I also noticed this, and agree some improvement is needed in this area.
I have some concerns about how to make this work with the current LSP spec though. Headers are by nature going to be included multiple times, and could have different set of diagnostics for each time they are included. The LSP doesn't deal well with that, it assumes that a single file has a single set of diagnostics. If we emit two publishDiagnostics (one for the main file and one for the header file), we have these problems:
- If both a.c and b.c include header.h, let's say you open a.c and we emit some diagnostics for header.h. Then you open b.c and we produce a new set of diagnostics for header.h, which will overwrite the previous ones. Then as you edit the two files, more publishDiagnostics are sent, so the diagnostics for header.h will switch back and forth between the two.
- When reading compiler output in the terminal, the order is very important. You usually read the first message, since the rest may just be a consequence of that first error. If we emit two publishDiagnostics, most IDEs will probably display them in an arbitrary order. For example, my IDE groups the diagnostics by file in a "problems" view:
** error: Unknown type 'zzz'
** error: ...
... lots of other files ...
** error: Syntax error that causes the zzz type not to be defined.
In a normal compiler output, you would see the error in zzz.h first and deal with that). But here, when you see the error in main.c and there is nothing that tips you that the error in zzz.h may be the actual cause.
What we might need in the protocol is a way to publish diagnostics in file X that were encountered when building file Y. Like by adding an optional uri field to the Diagnostic interface. It would essentially say, when building the file for which I am providing diagnostics, I encountered an error in this other file. In the publishDiagnostics notification regarding a.c, we could then notify about an error in header.h. Then, when analyzing b.c, we could emit a distinct error in header.h. In the IDEs, we could then group them like this:
** header.h: error: some error
** a.c: error: some error caused by the previous one
** header.h: error: some other error
** b.c: error: some error caused by the previous one
This could also help for .c files that are generated, for example from .y files. The compiler will emit when compiling the .c file, but the error will be about the .y file, because of #line directives.