109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)package org.chromium.devtools.jsdoc; 209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.jscomp.Compiler; 4197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.jscomp.NodeTraversal; 5197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.jscomp.parsing.Config; 6197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.jscomp.parsing.Config.LanguageMode; 7197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.jscomp.parsing.ParserRunner; 8197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.rhino.ErrorReporter; 9197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.rhino.Node; 1009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import org.chromium.devtools.jsdoc.checks.ContextTrackingValidationCheck; 1209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.io.FileNotFoundException; 1409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.io.IOException; 1509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.nio.ByteBuffer; 1609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.nio.charset.StandardCharsets; 1709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.nio.file.FileSystems; 1809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.nio.file.Files; 1909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.util.ArrayList; 2009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.util.List; 2109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)import java.util.concurrent.Callable; 2209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 2309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public class FileCheckerCallable implements Callable<ValidatorContext> { 2409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 2509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private final String fileName; 2609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) public FileCheckerCallable(String fileName) { 2809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) this.fileName = fileName; 2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 3009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) @Override 3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) public ValidatorContext call() { 3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) try { 3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ValidatorContext context = new ValidatorContext(readScriptText(), fileName); 3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ValidationCheckDispatcher dispatcher = new ValidationCheckDispatcher(context); 3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) dispatcher.registerCheck(new ContextTrackingValidationCheck()); 37197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch NodeTraversal.traverse(new Compiler(), parseScript(context), dispatcher); 3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return context; 3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } catch (FileNotFoundException e) { 4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) logError("File not found: " + fileName); 4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } catch (IOException e) { 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) logError("Failed to read file " + fileName); 4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return null; 4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 47197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch private String readScriptText() throws IOException { 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) byte[] encoded = Files.readAllBytes(FileSystems.getDefault().getPath(fileName)); 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) String text = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(encoded)).toString(); 50197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return text; 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch private static Node parseScript(final ValidatorContext context) { 54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Config config = ParserRunner.createConfig(true, LanguageMode.ECMASCRIPT5_STRICT, true); 55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ErrorReporter errorReporter = new ErrorReporter() { 56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch @Override 57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch public void warning(String message, String sourceName, int line, int lineOffset) { 58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Ignore. 59197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 60197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch @Override 62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch public void error(String message, String sourceName, int line, int lineOffset) { 63197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch logError("at " + sourceName + ":" + line + ":" + lineOffset); 64197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 65197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 66197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch try { 67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return ParserRunner.parse( 68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch context.sourceFile, context.sourceFile.getCode(), config, errorReporter).ast; 69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } catch (IOException e) { 70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Does not happen with preloaded files. 71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return null; 72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private static void logError(String message) { 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) System.err.println("ERROR: " + message); 7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private static class ValidationCheckDispatcher extends DoDidVisitorAdapter { 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private final List<ValidationCheck> checks = new ArrayList<>(2); 8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) private final ValidatorContext context; 8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) public ValidationCheckDispatcher(ValidatorContext context) { 8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) this.context = context; 8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) public void registerCheck(ValidationCheck check) { 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) check.setContext(context); 8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) checks.add(check); 9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) @Override 93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch public void doVisit(Node node) { 9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (DoDidNodeVisitor visitor : checks) { 9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) visitor.doVisit(node); 9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) @Override 100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch public void didVisit(Node node) { 10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (ValidationCheck check : checks) { 10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) check.didVisit(node); 10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 107