Home | History | Annotate | Download | only in jsdoc
      1 package org.chromium.devtools.jsdoc;
      2 
      3 import com.google.javascript.jscomp.Compiler;
      4 import com.google.javascript.jscomp.NodeTraversal;
      5 import com.google.javascript.jscomp.parsing.Config;
      6 import com.google.javascript.jscomp.parsing.Config.LanguageMode;
      7 import com.google.javascript.jscomp.parsing.ParserRunner;
      8 import com.google.javascript.rhino.ErrorReporter;
      9 import com.google.javascript.rhino.Node;
     10 
     11 import org.chromium.devtools.jsdoc.checks.ContextTrackingValidationCheck;
     12 
     13 import java.io.FileNotFoundException;
     14 import java.io.IOException;
     15 import java.nio.ByteBuffer;
     16 import java.nio.charset.StandardCharsets;
     17 import java.nio.file.FileSystems;
     18 import java.nio.file.Files;
     19 import java.util.ArrayList;
     20 import java.util.List;
     21 import java.util.concurrent.Callable;
     22 
     23 public class FileCheckerCallable implements Callable<ValidatorContext> {
     24 
     25     private final String fileName;
     26 
     27     public FileCheckerCallable(String fileName) {
     28         this.fileName = fileName;
     29     }
     30 
     31     @Override
     32     public ValidatorContext call() {
     33         try {
     34             ValidatorContext context = new ValidatorContext(readScriptText(), fileName);
     35             ValidationCheckDispatcher dispatcher = new ValidationCheckDispatcher(context);
     36             dispatcher.registerCheck(new ContextTrackingValidationCheck());
     37             NodeTraversal.traverse(new Compiler(), parseScript(context), dispatcher);
     38             return context;
     39         } catch (FileNotFoundException e) {
     40             logError("File not found: " + fileName);
     41         } catch (IOException e) {
     42             logError("Failed to read file " + fileName);
     43         }
     44         return null;
     45     }
     46 
     47     private String readScriptText() throws IOException {
     48         byte[] encoded = Files.readAllBytes(FileSystems.getDefault().getPath(fileName));
     49         String text = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(encoded)).toString();
     50         return text;
     51     }
     52 
     53     private static Node parseScript(final ValidatorContext context) {
     54         Config config = ParserRunner.createConfig(true, LanguageMode.ECMASCRIPT5_STRICT, true);
     55         ErrorReporter errorReporter = new ErrorReporter() {
     56             @Override
     57             public void warning(String message, String sourceName, int line, int lineOffset) {
     58                 // Ignore.
     59             }
     60 
     61             @Override
     62             public void error(String message, String sourceName, int line, int lineOffset) {
     63                 logError("at " + sourceName + ":" + line + ":" + lineOffset);
     64             }
     65         };
     66         try {
     67             return ParserRunner.parse(
     68                     context.sourceFile, context.sourceFile.getCode(), config, errorReporter).ast;
     69         } catch (IOException e) {
     70             // Does not happen with preloaded files.
     71             return null;
     72         }
     73     }
     74 
     75     private static void logError(String message) {
     76         System.err.println("ERROR: " + message);
     77     }
     78 
     79     private static class ValidationCheckDispatcher extends DoDidVisitorAdapter {
     80         private final List<ValidationCheck> checks = new ArrayList<>(2);
     81         private final ValidatorContext context;
     82 
     83         public ValidationCheckDispatcher(ValidatorContext context) {
     84             this.context = context;
     85         }
     86 
     87         public void registerCheck(ValidationCheck check) {
     88             check.setContext(context);
     89             checks.add(check);
     90         }
     91 
     92         @Override
     93         public void doVisit(Node node) {
     94             for (DoDidNodeVisitor visitor : checks) {
     95                 visitor.doVisit(node);
     96             }
     97         }
     98 
     99         @Override
    100         public void didVisit(Node node) {
    101             for (ValidationCheck check : checks) {
    102                 check.didVisit(node);
    103             }
    104         }
    105     }
    106 }
    107