View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.ecmascript.ast;
5   
6   import java.io.IOException;
7   import java.io.Reader;
8   import java.util.ArrayList;
9   import java.util.HashMap;
10  import java.util.List;
11  import java.util.Map;
12  
13  import net.sourceforge.pmd.lang.ast.ParseException;
14  import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions;
15  
16  import org.apache.commons.io.IOUtils;
17  import org.mozilla.javascript.CompilerEnvirons;
18  import org.mozilla.javascript.Parser;
19  import org.mozilla.javascript.ast.AstRoot;
20  import org.mozilla.javascript.ast.Comment;
21  import org.mozilla.javascript.ast.ErrorCollector;
22  import org.mozilla.javascript.ast.ParseProblem;
23  
24  public class EcmascriptParser {
25      protected final EcmascriptParserOptions parserOptions;
26  
27      private Map<Integer, String> suppressMap;
28      private String suppressMarker = "NOPMD"; // that's the default value
29  
30      public EcmascriptParser(EcmascriptParserOptions parserOptions) {
31          this.parserOptions = parserOptions;
32          if (parserOptions.getSuppressMarker() != null) {
33              suppressMarker = parserOptions.getSuppressMarker();
34          }
35      }
36  
37      protected AstRoot parseEcmascript(final String sourceCode, final List<ParseProblem> parseProblems) throws ParseException {
38  	final CompilerEnvirons compilerEnvirons = new CompilerEnvirons();
39  	compilerEnvirons.setRecordingComments(parserOptions.isRecordingComments());
40  	compilerEnvirons.setRecordingLocalJsDocComments(parserOptions.isRecordingLocalJsDocComments());
41  	compilerEnvirons.setLanguageVersion(parserOptions.getRhinoLanguageVersion().getVersion());
42  	compilerEnvirons.setIdeMode(true); // Scope's don't appear to get set right without this
43  	compilerEnvirons.setWarnTrailingComma(true);
44          compilerEnvirons.setReservedKeywordAsIdentifier(true); // see bug #1150 "EmptyExpression" for valid statements!
45  
46  	// TODO We should do something with Rhino errors...
47  	final ErrorCollector errorCollector = new ErrorCollector();
48  	final Parser parser = new Parser(compilerEnvirons, errorCollector);
49  	// TODO Fix hardcode
50  	final String sourceURI = "unknown";
51  	final int beginLineno = 1;
52  	AstRoot astRoot = parser.parse(sourceCode, sourceURI, beginLineno);
53  	parseProblems.addAll(errorCollector.getErrors());
54  	return astRoot;
55      }
56  
57      public EcmascriptNode<AstRoot> parse(final Reader reader) {
58  	try {
59  	    final List<ParseProblem> parseProblems = new ArrayList<ParseProblem>();
60  	    final String sourceCode = IOUtils.toString(reader);
61  	    final AstRoot astRoot = parseEcmascript(sourceCode, parseProblems);
62  	    final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(sourceCode, parseProblems);
63  	    EcmascriptNode<AstRoot> tree = treeBuilder.build(astRoot);
64  
65              suppressMap = new HashMap<Integer, String>();
66              if (astRoot.getComments() != null) {
67                  for (Comment comment : astRoot.getComments()) {
68                      int nopmd = comment.getValue().indexOf(suppressMarker);
69                      if (nopmd > -1) {
70                          String suppression = comment.getValue().substring(nopmd + suppressMarker.length());
71                          EcmascriptNode<Comment> node = treeBuilder.build(comment);
72                          suppressMap.put(node.getBeginLine(), suppression);
73                      }
74                  }
75              }
76          return tree;
77  	} catch (IOException e) {
78  	    throw new ParseException(e);
79  	}
80      }
81  
82      public Map<Integer, String> getSuppressMap() {
83          return suppressMap;
84      }
85  }