1
2
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";
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);
43 compilerEnvirons.setWarnTrailingComma(true);
44 compilerEnvirons.setReservedKeywordAsIdentifier(true);
45
46
47 final ErrorCollector errorCollector = new ErrorCollector();
48 final Parser parser = new Parser(compilerEnvirons, errorCollector);
49
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 }