EcmascriptParser { public EcmascriptNode<AstRoot> parse(final Reader reader) { try { final List<ParseProblem> parseProblems = new ArrayList<>(); final String sourceCode = IOUtils.toString(reader); final AstRoot astRoot = parseEcmascript(sourceCode, parseProblems); final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(sourceCode, parseProblems); EcmascriptNode<AstRoot> tree = treeBuilder.build(astRoot); suppressMap = new HashMap<>(); if (astRoot.getComments() != null) { for (Comment comment : astRoot.getComments()) { int nopmd = comment.getValue().indexOf(suppressMarker); if (nopmd > -1) { String suppression = comment.getValue().substring(nopmd + suppressMarker.length()); EcmascriptNode<Comment> node = treeBuilder.build(comment); suppressMap.put(node.getBeginLine(), suppression); } } } return tree; } catch (IOException e) { throw new ParseException(e); } } EcmascriptParser(EcmascriptParserOptions parserOptions); EcmascriptNode<AstRoot> parse(final Reader reader); Map<Integer, String> getSuppressMap();  }
@Test public void testLineNumbers() { final String SOURCE_CODE = "function a() {" + PMD.EOL + " alert('hello');" + PMD.EOL + "}" + PMD.EOL; EcmascriptNode<AstRoot> node = js.parse(SOURCE_CODE); assertEquals(1, node.getBeginLine()); assertEquals(1, node.getBeginColumn()); assertEquals(3, node.getEndLine()); assertEquals(1, node.getEndColumn()); Node child = node.getFirstChildOfType(ASTFunctionNode.class); assertEquals(1, child.getBeginLine()); assertEquals(1, child.getBeginColumn()); assertEquals(3, child.getEndLine()); assertEquals(1, child.getEndColumn()); child = node.getFirstDescendantOfType(ASTFunctionCall.class); assertEquals(2, child.getBeginLine()); assertEquals(3, child.getBeginColumn()); assertEquals(2, child.getEndLine()); assertEquals(16, child.getEndColumn()); }
@Test public void testLineNumbersWithinEcmascriptRules() { String source = "function f(x){\n" + " if (x) {\n" + " return 1;\n" + " } else {\n" + " return 0;\n" + " }\n" + "}"; final List<String> output = new ArrayList<>(); class MyEcmascriptRule extends AbstractEcmascriptRule { public Object visit(ASTScope node, Object data) { output.add("Scope from " + node.getBeginLine() + " to " + node.getEndLine()); return super.visit(node, data); } } MyEcmascriptRule rule = new MyEcmascriptRule(); RuleContext ctx = new RuleContext(); rule.apply(Arrays.asList(js.parse(source)), ctx); assertEquals("Scope from 2 to 4", output.get(0)); assertEquals("Scope from 4 to 6", output.get(1)); }
@Test public void testArrayAccess() { EcmascriptNode<AstRoot> node = js.parse("function a() { b['a'] = 1; c[1] = 2; }"); List<ASTElementGet> arrays = node.findDescendantsOfType(ASTElementGet.class); assertEquals("b", arrays.get(0).getTarget().getImage()); assertEquals("a", arrays.get(0).getElement().getImage()); assertEquals("c", arrays.get(1).getTarget().getImage()); assertEquals("1", arrays.get(1).getElement().getImage()); }
@Test public void testArrayMethod() { EcmascriptNode<AstRoot> rootNode = js.parse( "function test(){\n" + " a(); + " e[0].f(); List<ASTFunctionCall> calls = rootNode.findDescendantsOfType(ASTFunctionCall.class); List<String> results = new ArrayList<>(); for (ASTFunctionCall f : calls) { Node node = f.getTarget(); results.add(getName(node)); } assertEquals("[a, b.c, d[], e[].f, y.z[]]", results.toString()); }
@Test public void testCaseAsIdentifier() { ASTAstRoot rootNode = js.parse("function f(a){\n" + " a.case.flag = 1;\n" + " return;\n" + "}"); ASTBlock block = rootNode.getFirstDescendantOfType(ASTBlock.class); assertFalse(block.getChild(0) instanceof ASTEmptyExpression); assertTrue(block.getChild(0) instanceof ASTExpressionStatement); assertTrue(block.getChild(0).getChild(0) instanceof ASTAssignment); }
@Test public void testVoidKeyword() { ASTAstRoot rootNode = js.parse("function f(matchFn, fieldval, n){\n" + " return (matchFn)?(matcharray = eval(matchFn+\"('\"+fieldval+\"','\"+n.id+\"')\")):void(0);\n" + "}\n"); ASTUnaryExpression unary = rootNode.getFirstDescendantOfType(ASTUnaryExpression.class); assertEquals("void", unary.getImage()); }
@Test public void testXorAssignment() { ASTAstRoot rootNode = js.parse("function f() { var x = 2; x ^= 2; x &= 2; x |= 2; " + "x &&= true; x ||= false; x *= 2; x /= 2; x %= 2; x += 2; x -= 2; " + "x <<= 2; x >>= 2; x >>>= 2; }"); ASTAssignment infix = rootNode.getFirstDescendantOfType(ASTAssignment.class); assertEquals("^=", infix.getImage()); }