Merge branch 'grammar-isolate-version-checks' into java-grammar
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,11 @@ import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
|
||||
*/
|
||||
public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, AccessNode, JavaNode {
|
||||
|
||||
|
||||
default String getSimpleName() {
|
||||
return getImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the type kind of this declaration.
|
||||
*
|
||||
|
@ -80,6 +80,12 @@ public final class ASTConstructorCall extends AbstractJavaExpr implements ASTPri
|
||||
return (ASTArgumentList) jjtGetChild(idx);
|
||||
}
|
||||
|
||||
/** Returns true if type arguments to the constructed instance's type are inferred. */
|
||||
public boolean usesDiamondTypeArgs() {
|
||||
ASTTypeArguments targs = getTypeNode().getTypeArguments();
|
||||
return targs != null && targs.isDiamond();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type node.
|
||||
|
@ -130,7 +130,19 @@ public final class ASTNumericLiteral extends AbstractLiteral implements ASTLiter
|
||||
return getImage().replaceAll("_++", "");
|
||||
}
|
||||
|
||||
private int getIntBase() {
|
||||
/**
|
||||
* Returns true if this is an integral literal, ie either a long or
|
||||
* an integer literal. Otherwise, this is a floating point literal.
|
||||
*/
|
||||
public boolean isIntegral() {
|
||||
return isIntegral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base of the literal, eg 8 for an octal literal,
|
||||
* 10 for a decimal literal, etc.
|
||||
*/
|
||||
public int getBase() {
|
||||
final String image = getImage().toLowerCase(Locale.ROOT);
|
||||
if (image.startsWith("0x")) {
|
||||
return 16;
|
||||
@ -161,7 +173,7 @@ public final class ASTNumericLiteral extends AbstractLiteral implements ASTLiter
|
||||
public long getValueAsLong() {
|
||||
if (isIntegral) {
|
||||
// Using BigInteger to allow parsing 0x8000000000000000+ numbers as negative instead of a NumberFormatException
|
||||
BigInteger bigInt = new BigInteger(stripIntValue(), getIntBase());
|
||||
BigInteger bigInt = new BigInteger(stripIntValue(), getBase());
|
||||
return bigInt.longValue();
|
||||
} else {
|
||||
return (long) getValueAsDouble();
|
||||
|
@ -4,8 +4,13 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.internal.util.IteratorUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Try statement node.
|
||||
@ -51,6 +56,16 @@ public final class ASTTryStatement extends AbstractJavaNode {
|
||||
return jjtGetChild(0) instanceof ASTResourceList;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTResourceList getResourceList() {
|
||||
return AstImplUtil.getChildAs(this, 0, ASTResourceList.class);
|
||||
}
|
||||
|
||||
public List<ASTResource> getResources() {
|
||||
ASTResourceList list = getResourceList();
|
||||
return list == null ? Collections.emptyList() : IteratorUtil.toList(list.iterator());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the catch statement nodes of this try statement.
|
||||
|
@ -10,6 +10,7 @@ import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.ParserOptions;
|
||||
import net.sourceforge.pmd.lang.ast.AbstractTokenManager;
|
||||
import net.sourceforge.pmd.lang.ast.JavaCharStream;
|
||||
import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker;
|
||||
import net.sourceforge.pmd.lang.java.qname.JavaOperationQualifiedName;
|
||||
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
|
||||
@ -63,18 +64,19 @@ public final class InternalApiBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static ASTCompilationUnit parseInternal(String fileName, Reader source, int jdkVersion, boolean preview, ParserOptions options) {
|
||||
public static ASTCompilationUnit parseInternal(String fileName, Reader source, LanguageLevelChecker<?> checker, ParserOptions options) {
|
||||
JavaParser parser = new JavaParser(new JavaCharStream(source));
|
||||
String suppressMarker = options.getSuppressMarker();
|
||||
if (suppressMarker != null) {
|
||||
parser.setSuppressMarker(suppressMarker);
|
||||
}
|
||||
parser.setJdkVersion(jdkVersion);
|
||||
parser.setPreview(preview);
|
||||
parser.setJdkVersion(checker.getJdkVersion());
|
||||
parser.setPreview(checker.isPreviewEnabled());
|
||||
|
||||
AbstractTokenManager.setFileName(fileName);
|
||||
ASTCompilationUnit acu = parser.CompilationUnit();
|
||||
acu.setNoPmdComments(parser.getSuppressMap());
|
||||
checker.check(acu);
|
||||
return acu;
|
||||
}
|
||||
|
||||
|
@ -13,4 +13,35 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class SideEffectingVisitorAdapter<T> implements SideEffectingVisitor<T> {
|
||||
|
||||
|
||||
public void visit(ASTAnnotation node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTSingleMemberAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTNormalAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTMarkerAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
// TODO delegation
|
||||
|
||||
|
||||
public void visit(ASTSwitchLabeledRule node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
public void visit(ASTAnyTypeDeclaration node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast.internal;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ParseException;
|
||||
|
||||
/**
|
||||
* Strategy for reporting language-feature violations, for use by a
|
||||
* {@link LanguageLevelChecker}. For example, {@link ReportingStrategy#reporterThatThrows()}
|
||||
* produces a checker that throws a parse exception. It would be trivial
|
||||
* to make eg a checker that eg collects all warnings instead of failing
|
||||
* on the first one.
|
||||
*
|
||||
* @param <T> Type of object accumulating violations
|
||||
*/
|
||||
public interface ReportingStrategy<T> {
|
||||
|
||||
/** Create a blank accumulator before performing the check. */
|
||||
T createAccumulator();
|
||||
|
||||
|
||||
/** Consume the accumulator, after all violations have been reported. */
|
||||
void done(T accumulator);
|
||||
|
||||
|
||||
/**
|
||||
* Report that a node violates a language feature. This doesn't have
|
||||
* to throw an exception, we could also just warn, or accumulate into
|
||||
* the parameter.
|
||||
*/
|
||||
void report(Node node, String message, T acc);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a reporter that throws a {@link ParseException} when the
|
||||
* first error is reported.
|
||||
*/
|
||||
static ReportingStrategy<Void> reporterThatThrows() {
|
||||
return new ReportingStrategy<Void>() {
|
||||
@Override
|
||||
public Void createAccumulator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(Void accumulator) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(Node node, String message, Void acc) {
|
||||
throw new ParseException(
|
||||
"Line " + node.getBeginLine() + ", Column " + node.getBeginColumn() + ": " + message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -21,6 +21,8 @@ import net.sourceforge.pmd.lang.java.JavaLanguageModule;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.MethodLikeNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker;
|
||||
import net.sourceforge.pmd.lang.java.ast.internal.ReportingStrategy;
|
||||
import net.sourceforge.pmd.lang.java.dfa.DataFlowFacade;
|
||||
import net.sourceforge.pmd.lang.java.dfa.JavaDFAGraphRule;
|
||||
import net.sourceforge.pmd.lang.java.metrics.JavaMetricsComputer;
|
||||
@ -46,8 +48,7 @@ import net.sf.saxon.sxpath.IndependentContext;
|
||||
|
||||
public class JavaLanguageHandler extends AbstractPmdLanguageVersionHandler {
|
||||
|
||||
private final int jdkVersion;
|
||||
private final boolean preview;
|
||||
private final LanguageLevelChecker<?> levelChecker;
|
||||
private final LanguageMetricsProvider<ASTAnyTypeDeclaration, MethodLikeNode> myMetricsProvider = new JavaMetricsProvider();
|
||||
|
||||
public JavaLanguageHandler(int jdkVersion) {
|
||||
@ -56,14 +57,13 @@ public class JavaLanguageHandler extends AbstractPmdLanguageVersionHandler {
|
||||
|
||||
public JavaLanguageHandler(int jdkVersion, boolean preview) {
|
||||
super(JavaProcessingStage.class);
|
||||
this.jdkVersion = jdkVersion;
|
||||
this.preview = preview;
|
||||
this.levelChecker = new LanguageLevelChecker<>(jdkVersion, preview, ReportingStrategy.reporterThatThrows());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Parser getParser(ParserOptions parserOptions) {
|
||||
return new JavaLanguageParser(jdkVersion, preview, parserOptions);
|
||||
return new JavaLanguageParser(levelChecker, parserOptions);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.lang.java.internal;
|
||||
|
||||
import java.io.Reader;
|
||||
@ -14,6 +13,7 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.JavaTokenManager;
|
||||
import net.sourceforge.pmd.lang.java.ast.InternalApiBridge;
|
||||
import net.sourceforge.pmd.lang.java.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker;
|
||||
|
||||
/**
|
||||
* Adapter for the JavaParser, using the specified grammar version.
|
||||
@ -23,13 +23,11 @@ import net.sourceforge.pmd.lang.java.ast.ParseException;
|
||||
*/
|
||||
public class JavaLanguageParser extends AbstractParser {
|
||||
|
||||
private final int jdkVersion;
|
||||
private final boolean preview;
|
||||
private final LanguageLevelChecker<?> checker;
|
||||
|
||||
public JavaLanguageParser(int jdkVersion, boolean preview, ParserOptions parserOptions) {
|
||||
JavaLanguageParser(LanguageLevelChecker<?> checker, ParserOptions parserOptions) {
|
||||
super(parserOptions);
|
||||
this.jdkVersion = jdkVersion;
|
||||
this.preview = preview;
|
||||
this.checker = checker;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -40,6 +38,6 @@ public class JavaLanguageParser extends AbstractParser {
|
||||
|
||||
@Override
|
||||
public Node parse(String fileName, Reader source) throws ParseException {
|
||||
return InternalApiBridge.parseInternal(fileName, source, jdkVersion, preview, getParserOptions());
|
||||
return InternalApiBridge.parseInternal(fileName, source, checker, getParserOptions());
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import static net.sourceforge.pmd.lang.java.ParserTstUtil.getNodes;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.java.JavaLanguageModule;
|
||||
|
||||
public class ASTAnnotationTest {
|
||||
|
||||
@Test
|
||||
public void testAnnotationSucceedsWithDefaultMode() {
|
||||
getNodes(ASTAnnotation.class, TEST1);
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public void testAnnotationFailsWithJDK14() {
|
||||
getNodes(LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.4"), ASTAnnotation.class, TEST1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationSucceedsWithJDK15() {
|
||||
getNodes(LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.5"), ASTAnnotation.class, TEST1);
|
||||
}
|
||||
|
||||
private static final String TEST1 = "public class Foo extends Buz {" + PMD.EOL + " @Override" + PMD.EOL
|
||||
+ " void bar() {" + PMD.EOL + " // overrides a superclass method" + PMD.EOL + " }" + PMD.EOL + "}";
|
||||
}
|
@ -156,7 +156,7 @@ public class ParserCornersTest {
|
||||
fail("Expected exception");
|
||||
} catch (ParseException e) {
|
||||
assertEquals(
|
||||
"Line 1, Column 94: Cannot catch multiple exceptions when running in JDK inferior to 1.7 mode!",
|
||||
"Line 1, Column 70: Composite catch clauses are a feature of Java 1.7, you should select your language version accordingly",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
package net.sourceforge.pmd.lang.java.ast
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Earliest
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.J1_3
|
||||
import net.sourceforge.pmd.lang.java.ast.ParserTestCtx.Companion.AnnotationParsingCtx
|
||||
|
||||
/**
|
||||
@ -13,6 +15,15 @@ import net.sourceforge.pmd.lang.java.ast.ParserTestCtx.Companion.AnnotationParsi
|
||||
*/
|
||||
class ASTAnnotationTest : ParserTestSpec({
|
||||
|
||||
|
||||
parserTest("Test annot fails before JDK 1.4", javaVersions = Earliest..J1_3) {
|
||||
|
||||
inContext(AnnotationParsingCtx) {
|
||||
"@F" shouldNot parse()
|
||||
"@F(a=1)" shouldNot parse()
|
||||
}
|
||||
}
|
||||
|
||||
parserTest("Marker annotations") {
|
||||
|
||||
inContext(AnnotationParsingCtx) {
|
||||
|
@ -12,7 +12,7 @@ class ASTCatchStatementTest : ParserTestSpec({
|
||||
|
||||
parserTest("Test crash on multicatch", javaVersions = Earliest..J1_6) {
|
||||
|
||||
expectParseException("Cannot catch multiple exceptions when running in JDK inferior to 1.7 mode") {
|
||||
expectParseException("Composite catch clauses are a feature of Java 1.7, you should select your language version accordingly") {
|
||||
parseAstStatement("try { } catch (IOException | AssertionError e) { }")
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user