3

I've just started to use Flycheck to improve the quality of my code, and I am grateful that it is helping me to do that by pointing out assignments to free variables, and by identifying possibly undefined functions on the last line of the error display. (Actually, these two are Warnings, not errors.)

I would like to see no warnings in my error display, of course.

So is there a way for me to tell Flycheck about the global variables that I use on my project, and that I reference in multiple files? I have the appropriate defvar statements in one file, but not in all files. And I don't want to put defvar statements in every file that references them (I think, unless that's really the proper Emacs Lisp way...)

And is there a way for me to tell Flycheck about all the functions (which are defined in other files) that I reference in many files? That way only the truly undefined functions will show up in the last line of the Flycheck output. (I have so many that I don't usually want to flog through the long list of functions that I already know are defined, just to find ones that are possibly not defined.

I looked at the Flycheck manual on the home website, but it said nothing about this sort of thing. Neither could I see any sort of config variables for Lisp "include" or "prefix" files where I could point Flycheck to the file containing all my defvar statements...

Kevin
  • 1,308
  • 8
  • 20

2 Answers2

3

For global variables, use (defvar foo) (with no initial value). See the Elisp manual, node Compiler Errors.

For functions, use (declare foo "myfile.el"). See the Elisp manual, node Declaring Functions.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thank you. I was kind of hoping there would be a way to tell Flycheck to prefix those declaration files to the buffer, before doing it's checking. That way I wouldn't have to maintain a pile of changing declarations in all my files. I'll play around with your suggestions, and maybe all I will need is a single declare reference at the top of each file. PS. If it helps any, I made sure that I read the entire Emacs and Elisp manuals from end to end a while ago, but was trying to solve the problem using a Flycheck feature (if one existed). Thank you again for your tireless help on this site.. – Kevin Jun 27 '16 at 15:52
  • As long as the byte-compiler sees such a vacuous `defvar` once, that silences it for that variable for any subsequent compilations (in that session). So if you byte-compile several files, it is enough to put the vacuous `defvar` in the first that you compile. Likewise, for function declarations. You can put all of them in the same file, which you byte-compile first. – Drew Jun 27 '16 at 15:55
  • I played around with `defvar`, `(declare...`, and `(declare-function ..`, but the only times they help Flycheck is when the declarations appear in the file explicitly. That means I would need to maintain a pile of them in every Lisp file that I use. Instead, I put a job on my TODO list to write some functions to insert a pile of such declarations into each buffer on the `find-file-hook` and to remove them on the `before-save-hook`. Maybe that approach will accomplish my goals (low maintenance) while keeping Flycheck happy. – Kevin Jun 27 '16 at 16:37
  • 1
    @kevin Another possibility is to `require` the files with the definitions. – npostavs Jun 27 '16 at 16:41
  • You mean put a list of `(require 'my-other-file-1)`, `(require 'file2)`, etc in each of my source files, and that would make Flycheck pick them up? I could try that. I get the sense that these suggestions are for the byte compiler more than Flycheck, but if Flycheck just calls the byte compiler (it might well do that, I don't know), then I should start to focus my thinking on the byte compiler, and not on Flycheck. I know that Flycheck calls external syntax checkers, but didn't connect that with the byte compiler until just now. – Kevin Jun 27 '16 at 18:16
  • I think @npostavs probably means to require a file that includes the `defvar` and `declare-function` sexps that are needed. – Drew Jun 27 '16 at 19:07
  • Ah, I see now. Thanks. I tried that method, and it works! It seems like I need an absolute pathname to the declarations file for Flycheck, but `(require 'dcls (concat default-directory "dcls.el"))` does the job. Thank you everyone. – Kevin Jun 27 '16 at 21:25
  • @kevin You can probably adjust `load-path` instead of passing path to `require`. – npostavs Jun 27 '16 at 22:36
  • Yes, thank you. I figured that out eventually, when I dug into the doc for require. I'm still working out a policy for what to name the declaration files for each project (I started out with them all the same), and where to put them on the load path, etc. But I know I'm on the right track thanks to the help from everyone here. It's a really basic thing, load paths and require, but still new to me.. :-) – Kevin Jun 28 '16 at 13:18
  • I'm still having some blues with Flycheck, because it seems to have a problem finding the declarations files that I put in `(require 'my-dcls)`, even though the declaration files are on the load-path. I amended the original post above to show the issue, rather than start up a new question. – Kevin Jun 28 '16 at 14:00
  • 1
    I googled "flycheck elisp load-path" and it showed me https://github.com/flycheck/flycheck/issues/174 among other explanations, including a duplicate here at E.S.: http://emacs.stackexchange.com/q/10244 – phils Jun 28 '16 at 14:29
  • Please do not change your question or add another question to it. Post a separate question instead. And this is not a discussion forum. Ask a single, clear question per post. One sign of a good question is it having an accepted answer, preferably more than one good answer, and little or no comment back-and-forth. – Drew Jun 28 '16 at 14:30
  • You know, it never ceases to amaze me how I can do my debugging and reading homework, read the manuals I can find, search the net, come up with nothing useful, post a question here, and then have someone here post a link to a duplicate question, or cite some variable that is usually _exactly_ on target. I am grateful for the help, although I suppose it makes me look and feel like I didn't do my homework at all. To say nothing of crossing SO posting conventions. I'll go back and unedit my original posting, since now the answer is complete. Thanks again. – Kevin Jun 28 '16 at 16:18
  • I still haven't solved this issue using `(require 'my-dcls)`, so I posted another question here http://emacs.stackexchange.com/questions/24261/flycheck-variable-warnings-despite-flycheck-load-path, and have entered a bug report on Github for Flycheck here https://github.com/flycheck/flycheck/issues/1002. Hopefully I will eventually find a solution. – Kevin Jun 30 '16 at 14:52
1

The outcome of this whole issue is that (defvar foo) syntax works fine if it is embedded in the source file being checked. But it fails if it is brought into the syntax check with a (require 'my-dcls) reference to an external file containing (defvar foo).

A value must be assigned to foo, such as (defvar foo nil), in the external file if the declaration is to remove free variable warnings in the source file being tested by Flycheck.

So for now, I conclude that there is no way in Emacs Lisp to "include" a reference list (with no values set in the declarations) of globally defined variables in each source file of a project.

So the choices are to live with the free variable warnings, embed declarations into every source file on the project (ugh), or ensure that all my globals are defined -- with values set -- in the external declarations file brought in by the (require 'my-dcls) statement. Of the three choices, #3 seems to be the best approach.

Kevin
  • 1,308
  • 8
  • 20