/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; import static net.sourceforge.pmd.lang.apex.ast.ApexParserTestHelpers.parse; import static org.junit.Assert.assertEquals; import java.io.File; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.lang.ast.Node; import apex.jorje.semantic.ast.compilation.Compilation; public class ApexParserTest { @Test public void understandsSimpleFile() { // Setup String code = "@isTest\n public class SimpleClass {\n" + " @isTest\n public static void testAnything() {\n" + " \n" + " }\n" + "}"; // Exercise ApexNode<Compilation> rootNode = parse(code); // Verify List<ASTMethod> methods = rootNode.findDescendantsOfType(ASTMethod.class); assertEquals(4, methods.size()); } private String testCodeForLineNumbers = "public class SimpleClass {\n" // line 1 + " public void method1() {\n" // line 2 + " System.out.println(\"abc\");\n" // line 3 + " // this is a comment\n" // line 4 + " }\n" // line 5 + "}\n"; // line 6 @Test public void verifyLineColumNumbers() { ApexNode<Compilation> rootNode = parse(testCodeForLineNumbers); assertLineNumbersForTestCode(rootNode); } @Test public void verifyLineColumNumbersWithWindowsLineEndings() { String windowsLineEndings = testCodeForLineNumbers.replaceAll(" \n", "\r\n"); ApexNode<Compilation> rootNode = parse(windowsLineEndings); assertLineNumbersForTestCode(rootNode); } private void assertLineNumbersForTestCode(ApexNode<Compilation> rootNode) { // whole source code, well from the beginning of the class // name Modifier of the class - doesn't work. This node just // sees the identifier ("SimpleClass") // assertPosition(rootNode.jjtGetChild(0), 1, 1, 1, 6); // "public" assertPosition(rootNode, 1, 14, 6, 2); // "method1" - starts with identifier until end of its block statement Node method1 = rootNode.jjtGetChild(1); assertPosition(method1, 2, 17, 5, 5); // Modifier of method1 - doesn't work. This node just sees the // identifier ("method1") // assertPosition(method1.jjtGetChild(0), 2, 17, 2, 20); // "public" for // method1 // BlockStatement - the whole method body Node blockStatement = method1.jjtGetChild(1); assertPosition(blockStatement, 2, 27, 5, 5); // the expression ("System.out...") Node expressionStatement = blockStatement.jjtGetChild(0); assertPosition(expressionStatement, 3, 9, 3, 34); } @Test public void verifyEndLine() { String code = "public class SimpleClass {\n" // line 1 + " public void method1() {\n" // line 2 + " }\n" // line 3 + " public void method2() {\n" // line 4 + " }\n" // line 5 + "}\n"; // line 6 ApexNode<Compilation> rootNode = parse(code); Node method1 = rootNode.jjtGetChild(1); assertEquals("Wrong begin line", 2, method1.getBeginLine()); assertEquals("Wrong end line", 3, method1.getEndLine()); Node method2 = rootNode.jjtGetChild(2); assertEquals("Wrong begin line", 4, method2.getBeginLine()); assertEquals("Wrong end line", 5, method2.getEndLine()); } @Test public void parsesRealWorldClasses() throws Exception { File directory = new File("src/test/resources"); File[] fList = directory.listFiles(); for (File file : fList) { if (file.isFile() && file.getName().endsWith(".cls")) { String sourceCode = FileUtils.readFileToString(file); ApexNode<Compilation> rootNode = parse(sourceCode); Assert.assertNotNull(rootNode); } } } /** * See bug #1485 * * @see <a href="https://sourceforge.net/p/pmd/bugs/1485/">#1485</a> */ @Test public void stackOverflowDuringClassParsing() throws Exception { String source = IOUtils.toString(ApexParserTest.class.getResourceAsStream("StackOverflowClass.cls")); ApexNode<Compilation> rootNode = parse(source); Assert.assertNotNull(rootNode); int count = visitPosition(rootNode, 0); Assert.assertEquals(586, count); } private int visitPosition(Node node, int count) { int result = count + 1; Assert.assertTrue(node.getBeginLine() > 0); Assert.assertTrue(node.getBeginColumn() > 0); Assert.assertTrue(node.getEndLine() > 0); Assert.assertTrue(node.getEndColumn() > 0); for (int i = 0; i < node.jjtGetNumChildren(); i++) { result = visitPosition(node.jjtGetChild(i), result); } return result; } // TEST HELPER private static void assertPosition(Node node, int beginLine, int beginColumn, int endLine, int endColumn) { assertEquals("Wrong begin line", beginLine, node.getBeginLine()); assertEquals("Wrong begin column", beginColumn, node.getBeginColumn()); assertEquals("Wrong end line", endLine, node.getEndLine()); assertEquals("Wrong end column", endColumn, node.getEndColumn()); } }