Closed TamaMcGlinn closed 1 year ago
As far as I can see, the pattern & input seems good to me.
so, does efm expect the linter to output a piece of json with a filename etc? I see that the filename is not complete; it doesn't include the directory from the root of the repository, but is instead just main.adb. Is that a problem?
I can't make sure what is wrong since I don't have gcc supported ada. Could you please try linter-stdin?
As far as I can see, the full path rather than just the filename is the only difference. So I am going to try wrapping gcc in a script to output the full path rather than just the filename.
Tue Nov 08-15:48:39 - tama@vm001954:~/code/ada/testit
$ gcc -c src/main.cpp
src/main.cpp:1:1: error: '::main' must return 'int'
1 | void main(){
| ^~~~
src/main.cpp: In function 'int main()':
src/main.cpp:2:10: error: 'something' was not declared in this scope
2 | return something;
| ^~~~~~~~~
Tue Nov 08-15:48:44 - tama@vm001954:~/code/ada/testit
$ gcc -c src/main.adb
main.adb:4:04: error: "procedure" should be "function"
main.adb:7:04: error: "end Foo;" expected
Ok, this works:
#!/usr/bin/env bash
FULLPATH=$(readlink -f "$1")
FILE_NAME=${FULLPATH##*/}
gcc -c "$@" 2>&1 | sed "s@${FILE_NAME}@${FULLPATH}@"
I've named the script gcc_lint, put it in $PATH and replaced gcc -c
with gcc_lint
and it works. So the problem is that gcc, specifically when compiling Ada files, outputs only the file's name, without any part of the path, whereas efm requires the full path to the file to be output.
For future readers, here is a more advanced version I call gprbuild_lint which also works for .ads specs:
#!/usr/bin/env bash
# Original reason for the script: gcc (and gprbuild) output only the filename,
# not the full path as required by efm-langserver
FULLPATH=$(readlink -f "$1")
FILE_NAME=${FULLPATH##*/}
# gcc -c only works on package bodies (*.adb)
if [[ $1 == *.adb ]]; then
# when treating a .adb file, we can pass -c [thefile] to only compile that file
# this is much quicker than compiling the whole project
COMPILE="-c $1"
else
CORRESPONDING_ADB="${1%%.ads}.adb"
if test -f $CORRESPONDING_ADB; then
# compile the corresponding .adb file
COMPILE="-c $CORRESPONDING_ADB"
else
# fallback: compile the whole project
COMPILE=""
fi
fi
# Find *.gpr upwards from source file
# TODO allow overriding GPRFILE from neovim, for multi-gpr projects - in that case, do not search
DIR=$(dirname "$FULLPATH")
while
GPRFILE=$(find "$DIR"/ -maxdepth 1 -type f -iname "*.gpr")
[[ -z $GPRFILE ]] && [[ "$DIR" != "/" ]]
do DIR=$(dirname "$DIR"); done
if [[ -n $GPRFILE ]]; then
PROJECT="-P $GPRFILE"
fi
COMMAND="gprbuild -k $PROJECT $COMPILE"
$COMMAND 2>&1 | sed "s@${FILE_NAME}@${FULLPATH}@"
# # Debugging line to get info directly from linter into file
# echo "src/testit-example.ads:02:00: Note: $COMMAND"
@mattn regarding the TODO; have you ever passed information before directly from NeoVim into a linter on each call? This is because the project file could change at any time (using the nvim-lsp-gpr-selector plugin). I could use neovim-remote in the linter to access a global in the NeoVim instance, but it would be a pretty horrible solution.
Sorry, I don't use NeoVim.
I am trying to use efm-langserver with this config in NeoVim:
After setting
~/.config/efm-langserver/config.yaml
accordingly to get debug output:And loading a single Ada file with two errors present:
My ~/efmlog.txt now correctly notes the two errors, but they still don't show up as lint messages.
Any ideas?