Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to run GMQCC as a linter #203

Open
vkazanov opened this issue May 22, 2023 · 5 comments
Open

A way to run GMQCC as a linter #203

vkazanov opened this issue May 22, 2023 · 5 comments

Comments

@vkazanov
Copy link

vkazanov commented May 22, 2023

I am working on an Emacs mode for QuakeC projects. One useful things that's important to add to do is some kind of live code linting. A couple of things missing in gmqcc to make it convenient:

  1. lint a single file only.
  2. skip generating the resulting progs.dat file altogether.
  3. do not stop compiling on errors, go as far as possible.

Would GMQCC team be open to such changes?

Thank you

PS this is a sister Issue to this one.

@Blub
Copy link
Collaborator

Blub commented May 23, 2023

Open yes. Actively work on it... not sure.
I think simply skipping the codegen and limiting error/warning output to happen only for a specific file could be done rather easily. Note that you cannot just parse only a single file, since QC is context sensitive and uses no header files, that is, the whole source is one single translation unit, and you can't know if a b; is legal syntax without knowing what a is. However, given the compile times, I don't think that'll be much of an issue, but you will need to know which progs.src file to use (if any), and there will be a lot of shared code, so you can't always easily infer that from the file you're editing.
Also, xonotic uses a separate preprocessor step with cpp instead of using gmqcc's preprocessor, which makes this even more difficult to be useful for xonotic devs as well.

Other than that: making the output nice to understand (ie. using some sort of LSP protocol thing) would probably be doable if someone know how this works. I haven't looked into this myself at all.

The main usability issue will be continuing on errors. Touching the parser is a PITA, but on the other hand, for errors that happen later in the AST or IR stages this should be rather easy. But I don't know which of these happen more frequently ;-)

@vkazanov
Copy link
Author

vkazanov commented May 23, 2023

@Blub , I think I could work on this on my side with some guidance and comments on style of the PR (I am mostly do C these days, my C++ is rusty). The point is to get an approximation of what a linter would do. The plan is to:

  1. based on a compiler arg supress all compiler codegen - to avoid generating the *.dat file (-no-codegen). This should be easy.
  2. based on another flag see try to make the parser go as far as possible in the list of files provided by progs.src (-no-fail-on-error). Might require more involved tweaking. This is where linter parsers are different - they usually do some sort of error recovery.

My biggest problem with gmqcc right now is how it might not ever reach the file the editor is editing because of an error elsewhere.

Not limiting parsing to a single file is fine, I suppose, as I can do file path filtering on the editor side.

@Blub
Copy link
Collaborator

Blub commented May 23, 2023

My biggest problem with gmqcc right now is how it might not ever reach the file the editor is editing because of an error elsewhere.

Like I said, the parser is quite a PITA. But maybe it can be split up a bit. As a first step create a list of "items" where a function including its body as one item, a typedef is another item, and then the contents (mainly function bodies) are parsed in a 2nd step, that way, other functions don't depend on the internal code of every other function being correct.
Now of course, in the case where parens/quotes don't match up you can probably not do much of a recovery.

But that's probably a bigger and more involved change.

@vkazanov
Copy link
Author

@Blub hm. This sounds pretty involved.

Without looking at the code... Would something like skipping a file altogether work? I.e. fail a given file compilation on the first error but proceed with other files?

@Blub
Copy link
Collaborator

Blub commented May 23, 2023

Unlikely. The way QC code works is literally the same as if you just cat all files together into one big file.
I mean sure, you might get lucky, but you might also produce a lot of false "syntax errors".

I've been too far away from QC code and the parser for too long to really be confident about this, but it might not be as bad as I imagine for gmqcc, since we eg. don't have pointer support. So eg. we wouldn't need to know about a in a * b; to know what it's supposed to do. We might need some dummy nodes for things such as typedef unknown_thing foo; to be able to prevent later uses of foo from creating additional false errors...

And I mean, it's up to the user to interpret the errors. Eg. if an entity field is not found and you clearly see the code that declares it, you should be able to figure out that the syntax error way earlier might be the more important error to deal with ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants