/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.lang.java.ParserTst;
public class ParserCornersTest extends ParserTst {
/**
* #1107 PMD 5.0.4 couldn't parse call of parent outer java class method
* from inner class.
*/
@Test
public void testInnerOuterClass() {
parseJava17("/**\n" + " * @author azagorulko\n" + " *\n" + " */\n"
+ "public class TestInnerClassCallsOuterParent {\n" + "\n" + " public void test() {\n"
+ " new Runnable() {\n" + " @Override\n" + " public void run() {\n"
+ " TestInnerClassCallsOuterParent.super.toString();\n" + " }\n"
+ " };\n" + " }\n" + "}\n");
}
@Test
public final void testGetFirstASTNameImageNull() {
parseJava14(ABSTRACT_METHOD_LEVEL_CLASS_DECL);
}
@Test
public final void testCastLookaheadProblem() {
parseJava14(CAST_LOOKAHEAD_PROBLEM);
}
/**
* Tests a specific generic notation for calling methods. See:
* https://jira.codehaus.org/browse/MPMD-139
*/
@Test
public void testGenericsProblem() {
parseJava15(GENERICS_PROBLEM);
parseJava17(GENERICS_PROBLEM);
}
@Test
public void testParsersCases15() {
String test15 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases.java");
parseJava15(test15);
}
@Test
public void testParsersCases17() {
String test17 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases17.java");
parseJava17(test17);
}
@Test
public void testParsersCases18() throws Exception {
String test18 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases18.java");
ASTCompilationUnit cu = parseJava18(test18);
Assert.assertEquals(21, cu.findChildNodesWithXPath("//FormalParameter").size());
Assert.assertEquals(4,
cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='true']").size());
Assert.assertEquals(17,
cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='false']").size());
}
/**
* Test for https://sourceforge.net/p/pmd/bugs/1333/
*/
@Test
public void testLambdaBug1333() {
parseJava18("final class Bug1333 {\n"
+ " private static final Logger LOG = LoggerFactory.getLogger(Foo.class);\n" + "\n"
+ " public void deleteDirectoriesByNamePattern() {\n"
+ " delete(path -> deleteDirectory(path));\n" + " }\n" + "\n"
+ " private void delete(Consumer<? super String> consumer) {\n"
+ " LOG.debug(consumer.toString());\n" + " }\n" + "\n"
+ " private void deleteDirectory(String path) {\n" + " LOG.debug(path);\n" + " }\n" + "}");
}
@Test
public void testLambdaBug1470() throws Exception {
String code = IOUtils.toString(ParserCornersTest.class.getResourceAsStream("LambdaBug1470.java"), "UTF-8");
parseJava18(code);
}
/**
* Test for https://sourceforge.net/p/pmd/bugs/1355/
*/
@Test
public void emptyFileJustComment() {
parseJava18("// just a comment");
}
@Test
public void testMultipleExceptionCatching() {
String code = "public class Foo { public void bar() { "
+ "try { System.out.println(); } catch (RuntimeException | IOException e) {} } }";
try {
parseJava15(code);
fail("Expected exception");
} catch (ParseException e) {
assertEquals(
"Line 1, Column 94: Cannot catch multiple exceptions when running in JDK inferior to 1.7 mode!",
e.getMessage());
}
try {
parseJava17(code);
// no exception expected
} catch (ParseException e) {
fail();
}
}
@Test
public void testBug1429ParseError() throws Exception {
String c = IOUtils.toString(this.getClass().getResourceAsStream("Bug1429.java"));
parseJava18(c);
}
@Test
public void testBug1530ParseError() throws Exception {
String c = IOUtils.toString(this.getClass().getResourceAsStream("Bug1530.java"));
parseJava18(c);
}
@Test
public void testGitHubBug207() throws Exception {
String c = IOUtils.toString(this.getClass().getResourceAsStream("GitHubBug207.java"));
parseJava18(c);
}
@Test
public void testBug206() throws Exception {
String code = "public @interface Foo {" + PMD.EOL
+ "static final ThreadLocal<Interner<Integer>> interner =" + PMD.EOL
+ " ThreadLocal.withInitial(Interners::newStrongInterner);" + PMD.EOL
+ "}";
parseJava18(code);
}
@Test
public void testGitHubBug208ParseError() throws Exception {
String c = IOUtils.toString(this.getClass().getResourceAsStream("GitHubBug208.java"));
parseJava15(c);
}
@Test
public void testGitHubBug257NonExistingCast() throws Exception {
String code = "public class Test {" + PMD.EOL
+ " public static void main(String[] args) {" + PMD.EOL
+ " double a = 4.0;" + PMD.EOL
+ " double b = 2.0;" + PMD.EOL
+ " double result = Math.sqrt((a) - b);" + PMD.EOL
+ " System.out.println(result);" + PMD.EOL
+ " }" + PMD.EOL
+ "}";
ASTCompilationUnit compilationUnit = parseJava15(code);
assertEquals("A cast was found when none expected", 0, compilationUnit.findDescendantsOfType(ASTCastExpression.class).size());
}
@Test
public void testGitHubBug309() throws Exception {
String code = readAsString("GitHubBug309.java");
ASTCompilationUnit compilationUnit = parseJava18(code);
assertNotNull(compilationUnit);
}
/**
* This triggered bug #1484 UnusedLocalVariable - false positive -
* parenthesis
*
* @throws Exception
*/
@Test
public void stringConcatentationShouldNotBeCast() throws Exception {
String code = "public class Test {\n" + " public static void main(String[] args) {\n"
+ " System.out.println(\"X\" + (args) + \"Y\");\n" + " }\n" + "}";
ASTCompilationUnit cu = parseJava18(code);
Assert.assertEquals(0, cu.findDescendantsOfType(ASTCastExpression.class).size());
}
private String readAsString(String resource) {
InputStream in = ParserCornersTest.class.getResourceAsStream(resource);
try {
return IOUtils.toString(in);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(in);
}
}
private static final String GENERICS_PROBLEM = "public class Test {" + PMD.EOL + " public void test() {" + PMD.EOL
+ " String o = super.<String> doStuff(\"\");" + PMD.EOL + " }" + PMD.EOL + "}";
private static final String ABSTRACT_METHOD_LEVEL_CLASS_DECL = "public class Test {" + PMD.EOL + " void bar() {"
+ PMD.EOL + " abstract class X { public abstract void f(); }" + PMD.EOL
+ " class Y extends X { public void f() {" + PMD.EOL + " new Y().f();" + PMD.EOL + " }}" + PMD.EOL
+ " }" + PMD.EOL + "}";
private static final String CAST_LOOKAHEAD_PROBLEM = "public class BadClass {" + PMD.EOL + " public Class foo() {"
+ PMD.EOL + " return (byte[].class);" + PMD.EOL + " }" + PMD.EOL + "}";
}