简体   繁体   中英

Syntax check on a java file

For a given java file, I'd like to check if it's syntactically correct. ie. If it has semi-colons in the right places, matching parenthesis etc. Importantly, I need to check the file in isolation from all of its dependencies.

This other answer is promising, however it's really doing a semantic check rather than a syntactic check. It does what a compiler would do - check all the imports statements as well as verify external classes that are referenced in the code.

Is there a way to do a true syntax check? (A check that only inspects the raw text against Java's formal grammar)

Create or use a Java source code parser. For some parser generators there are public Java grammars available - you could use it to generate the parser.

Eg Java 8 grammar for ANTLR (no idea about quality of that grammar though, you'd have to do your evaluation - but the grammar is written by the author of ANTLR, so should be OK I guess).

As Jiri suggested, use the ANTLR library to put together a syntax checker.

  1. Download and extract the ANTLR grammars from here

  2. Download the ANTLR4 jar from here

  3. Run the following command to generate classes from the Java 8 grammar:

    java -jar antlr-4.5.3-complete.jar ~/Downloads/grammars-v4-master/java8/Java8.g4

  4. Copy the .java files that were created into your project

Then you can write your syntax checker:

public static void main(String[] args) throws SAXException, IOException {

    ANTLRInputStream input = new ANTLRFileStream(args[0]);
    Java8Lexer lexer = new Java8Lexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    Java8Parser parser = new Java8Parser(tokens);

    final StringBuilder errorMessages = new StringBuilder();
    parser.addErrorListener(new BaseErrorListener() {
        @Override
        public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
            String err = String.format("Failed to parse at line %d:%d due to %s", line, charPositionInLine + 1, msg);
            errorMessages.append(err);
            errorMessages.append(System.lineSeparator());
        }
    });

    parser.compilationUnit();
    int syntaxErrors = parser.getNumberOfSyntaxErrors();

    if (syntaxErrors == 0) {
        System.out.println(args[0] + ": PASS");
    } else {
        System.out.println(args[0] + ": FAILED (" + syntaxErrors + " syntax errors");
    }
}

I was researching how to do a quick java syntax-checker for usage in vim. I inspired by @Fidel 's answer (thanks for the example checker!) but it didn't suffice me as I needed it to work in a standalone way.

Here is a step by step process of what had to be done in order to have runnable command:

  • Run:
# download and generate .java classes
wget https://repo1.maven.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar -O antlr4-4.5.3.jar
wget https://raw.githubusercontent.com/antlr/grammars-v4/master/java8/Java8.g4 -O Java8.g4
java -jar antlr4-4.5.3.jar ./Java8.g4
  • Then write a syntax checker, perhaps similar to @Fidel 's one and place it under package checker; place it directly under ./checker directory

  • Also place all of the generated .java classes under that package (ie. put package checker; to the first line of all the files)

  • Run:

# prepare directory structure and compile
mkdir -p checker && mv *.java ./checker/
javac -cp antlr4-4.5.3.jar ./checker/*.java
  • Prepare a Manifest file that will look similarly to:
Class-Path: antlr4-4.5.3.jar
Main-Class: checker.<name-of-your-checker-class>
  • Run:
# package into a jar file and run to test everything works
jar cfm checker.jar Manifest.txt checker/*.class
java -jar ./checker.jar <filename-you-want-to-run-syntax-check-against>

For my usage in vim I then created a simple shell script to wrap execution of the process of running the java jar that looks like this:

#!/bin/bash

DIR=$(readlink -f $0)
DIR=${DIR:0:(-3)}            # put the length of the script name here instead of '3'

java -jar ${DIR}checker.jar $@

Then make it executable and symlink it under $PATH :

chmod a+x <file-name>
sudo ln -s /path/to/the/script /usr/bin/java-syntax

And finally added a keybinding like this into a .vimrc file (ie. to map running the syntax-check when F10 key is pressed):

" java syntax validation                                                        
map <F10> :!java-syntax % <CR>

I also stored the process into a github repository , where all the commands are prepared in a makefile and it suffices to run make in order to build and package the checker. Feel free to use it as an inspiration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM