[java] Improve module grammar
Type names in "provides" directives are disambiguated like any other type name. ASTName is made redundant and removed for good.
This commit is contained in:
@ -1,4 +1,9 @@
|
||||
/**
|
||||
* Improve module grammar.
|
||||
* Type names in "provides" directives are disambiguated like any other type name.
|
||||
* ASTName is made redundant and removed for good.
|
||||
* Clément Fournier 03/2022
|
||||
*====================================================================
|
||||
* Support "JEP 420: Pattern Matching for switch (Second Preview)" for Java 18 Preview
|
||||
* There were no grammar changes between 18-preview and 17-preview
|
||||
* Remove support for Java 16 preview language features
|
||||
@ -2734,40 +2739,34 @@ void DefaultValue():
|
||||
}
|
||||
|
||||
void ModuleDeclaration():
|
||||
{}
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
JavaccToken t;
|
||||
}
|
||||
{
|
||||
( Annotation() )* [LOOKAHEAD({isKeyword("open")}) <IDENTIFIER> {jjtThis.setOpen(true);}] LOOKAHEAD({isKeyword("module")}) <IDENTIFIER>
|
||||
t=<IDENTIFIER> { s.append(t.getImage()); }
|
||||
( "." t=<IDENTIFIER> { s.append('.').append(t.getImage()); } )* { jjtThis.setImage(s.toString()); }
|
||||
AnnotationList()
|
||||
[LOOKAHEAD({isKeyword("open")}) <IDENTIFIER> {jjtThis.setOpen(true);}]
|
||||
LOOKAHEAD({isKeyword("module")}) <IDENTIFIER>
|
||||
ModuleName()
|
||||
"{" (ModuleDirective())* "}"
|
||||
}
|
||||
|
||||
void ModuleDirective():
|
||||
{}
|
||||
void ModuleDirective() #void:
|
||||
{String packageName;}
|
||||
{
|
||||
( LOOKAHEAD({isKeyword("requires")}) <IDENTIFIER> { jjtThis.setType(ASTModuleDirective.DirectiveType.REQUIRES); }
|
||||
(LOOKAHEAD({isKeyword("transitive")}) <IDENTIFIER> { jjtThis.setRequiresModifier(ASTModuleDirective.RequiresModifier.TRANSITIVE); } |
|
||||
"static" { jjtThis.setRequiresModifier(ASTModuleDirective.RequiresModifier.STATIC); } )?
|
||||
ModuleName() ";" )
|
||||
| ( LOOKAHEAD({isKeyword("exports")}) <IDENTIFIER> { jjtThis.setType(ASTModuleDirective.DirectiveType.EXPORTS); } Name() [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())*] ";" )
|
||||
| ( LOOKAHEAD({isKeyword("opens")}) <IDENTIFIER> { jjtThis.setType(ASTModuleDirective.DirectiveType.OPENS); } Name() [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())*] ";" )
|
||||
| ( LOOKAHEAD({isKeyword("uses")}) <IDENTIFIER> { jjtThis.setType(ASTModuleDirective.DirectiveType.USES); } Name() ";" )
|
||||
| ( LOOKAHEAD({isKeyword("provides")}) <IDENTIFIER> { jjtThis.setType(ASTModuleDirective.DirectiveType.PROVIDES); } Name() LOOKAHEAD({isKeyword("with")}) <IDENTIFIER> Name() ("," Name() )* ";" )
|
||||
( LOOKAHEAD({isKeyword("requires")}) <IDENTIFIER>
|
||||
[
|
||||
LOOKAHEAD({isKeyword("transitive")}) <IDENTIFIER> { jjtThis.setTransitive(); }
|
||||
| "static" { jjtThis.setStatic(); }
|
||||
]
|
||||
ModuleName() ";" ) #ModuleRequiresDirective
|
||||
| ( LOOKAHEAD({isKeyword("exports")}) <IDENTIFIER> packageName=VoidNameNoLookahead() {jjtThis.setPackageName(packageName);} [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())* ] ";" ) #ModuleExportsDirective
|
||||
| ( LOOKAHEAD({isKeyword("opens")}) <IDENTIFIER> packageName=VoidNameNoLookahead() {jjtThis.setPackageName(packageName);} [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())* ] ";" ) #ModuleOpensDirective
|
||||
| ( LOOKAHEAD({isKeyword("uses")}) <IDENTIFIER> packageName=VoidNameNoLookahead() {jjtThis.setPackageName(packageName);} ";" ) #ModuleUsesDirective
|
||||
| ( LOOKAHEAD({isKeyword("provides")}) <IDENTIFIER> ClassName() LOOKAHEAD({isKeyword("with")}) <IDENTIFIER> ClassName() ("," ClassName() )* ";" ) #ModuleProvidesDirective
|
||||
}
|
||||
|
||||
void ModuleName():
|
||||
{ String name; }
|
||||
{
|
||||
name=VoidName() { jjtThis.setImage(name); }
|
||||
}
|
||||
|
||||
void Name():
|
||||
{ String name; }
|
||||
{
|
||||
name=VoidName() { jjtThis.setImage(name); }
|
||||
name=VoidNameNoLookahead() { jjtThis.setImage(name); }
|
||||
}
|
||||
|
||||
void AmbiguousName():
|
||||
@ -2793,6 +2792,18 @@ String VoidName() #void:
|
||||
{return s.toString();}
|
||||
}
|
||||
|
||||
|
||||
String VoidNameNoLookahead() #void:
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
JavaccToken t;
|
||||
}
|
||||
{
|
||||
t=<IDENTIFIER> { s.append(t.getImage()); }
|
||||
( "." t=<IDENTIFIER> { s.append('.').append(t.getImage()); } )*
|
||||
{return s.toString();}
|
||||
}
|
||||
|
||||
// Produces a ClassOrInterfaceType, possibly with an ambiguous LHS
|
||||
void ClassName() #void:
|
||||
{}
|
||||
|
@ -73,8 +73,7 @@ public final class ASTCompilationUnit extends AbstractJavaTypeNode implements Ja
|
||||
* Returns the package name of this compilation unit. If there is no
|
||||
* package declaration, then returns the empty string.
|
||||
*/
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
public @NonNull String getPackageName() {
|
||||
ASTPackageDeclaration pack = getPackageDeclaration();
|
||||
return pack == null ? "" : pack.getName();
|
||||
}
|
||||
@ -88,6 +87,13 @@ public final class ASTCompilationUnit extends AbstractJavaTypeNode implements Ja
|
||||
return children(ASTAnyTypeDeclaration.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module declaration, if this is a modular compilation unit.
|
||||
*/
|
||||
public @Nullable ASTModuleDeclaration getModuleDeclaration() {
|
||||
return firstChild(ASTModuleDeclaration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull JSymbolTable getSymbolTable() {
|
||||
assert symbolTable != null : "Symbol table wasn't set";
|
||||
|
@ -4,7 +4,21 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
public final class ASTModuleDeclaration extends AbstractJavaNode {
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* A module declaration. This is found at the top-level of a
|
||||
* {@linkplain ASTCompilationUnit modular compilation unit}.
|
||||
*
|
||||
* <pre clas="grammar">
|
||||
*
|
||||
* ModuleDeclaration ::= {@linkplain ASTModifierList AnnotationList} "open"?
|
||||
* "module" {@linkplain ASTModuleName ModuleName}
|
||||
* "{" {@linkplain ASTModuleDirective ModuleDirective}* "}"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleDeclaration extends AbstractJavaNode implements Annotatable {
|
||||
|
||||
private boolean open;
|
||||
|
||||
@ -18,6 +32,20 @@ public final class ASTModuleDeclaration extends AbstractJavaNode {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the declared module. Module names look
|
||||
* like package names, eg {@code java.base}.
|
||||
*/
|
||||
public String getName() {
|
||||
return firstChild(ASTModuleName.class).getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream with all directives declared by the module.
|
||||
*/
|
||||
public NodeStream<ASTModuleDirective> getDirectives() {
|
||||
return children(ASTModuleDirective.class);
|
||||
}
|
||||
|
||||
void setOpen(boolean open) {
|
||||
this.open = open;
|
||||
|
@ -4,44 +4,47 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
public final class ASTModuleDirective extends AbstractJavaNode {
|
||||
|
||||
import net.sourceforge.pmd.lang.rule.xpath.NoAttribute;
|
||||
|
||||
/**
|
||||
* A directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
* Implementations provide more specific attributes.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleDirective ::= {@linkplain ASTModuleRequiresDirective ModuleRequiresDirective}
|
||||
* | {@linkplain ASTModuleOpensDirective ModuleOpensDirective}
|
||||
* | {@linkplain ASTModuleExportsDirective ModuleExportsDirective}
|
||||
* | {@linkplain ASTModuleProvidesDirective ModuleProvidesDirective}
|
||||
* | {@linkplain ASTModuleUsesDirective ModuleUsesDirective}
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class ASTModuleDirective extends AbstractJavaNode {
|
||||
|
||||
private final DirectiveType type;
|
||||
|
||||
|
||||
ASTModuleDirective(int id, DirectiveType type) {
|
||||
super(id);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind of the directive.
|
||||
*/
|
||||
@NoAttribute
|
||||
public DirectiveType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind of a module directive. Specific kinds are represented by
|
||||
* specific subclasses.
|
||||
*/
|
||||
public enum DirectiveType {
|
||||
REQUIRES, EXPORTS, OPENS, USES, PROVIDES
|
||||
}
|
||||
|
||||
public enum RequiresModifier {
|
||||
STATIC, TRANSITIVE
|
||||
}
|
||||
|
||||
private DirectiveType type;
|
||||
|
||||
private RequiresModifier requiresModifier;
|
||||
|
||||
ASTModuleDirective(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
void setType(DirectiveType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return String.valueOf(type);
|
||||
}
|
||||
|
||||
void setRequiresModifier(RequiresModifier requiresModifier) {
|
||||
this.requiresModifier = requiresModifier;
|
||||
}
|
||||
|
||||
public String getRequiresModifier() {
|
||||
return requiresModifier == null ? null : requiresModifier.name();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* An "exports" directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleExportsDirective ::=
|
||||
* "exports" <PACKAGE_NAME>
|
||||
* ( "to" {@linkplain ASTModuleName ModuleName} ( "," {@linkplain ASTModuleName ModuleName})* )?
|
||||
* ";"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleExportsDirective extends AbstractPackageNameModuleDirective {
|
||||
|
||||
ASTModuleExportsDirective(int id) {
|
||||
super(id, DirectiveType.EXPORTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of the module names that are found after the "to" keyword.
|
||||
* May be empty
|
||||
*/
|
||||
public NodeStream<ASTModuleName> getTargetModules() {
|
||||
return children(ASTModuleName.class);
|
||||
}
|
||||
}
|
@ -4,6 +4,10 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* The name of a module. Module names look like package names, eg
|
||||
* {@code java.base}.
|
||||
*/
|
||||
public final class ASTModuleName extends AbstractJavaNode {
|
||||
|
||||
ASTModuleName(int id) {
|
||||
@ -15,4 +19,19 @@ public final class ASTModuleName extends AbstractJavaNode {
|
||||
public <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String getImage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the declared module. Module names look
|
||||
* like package names, eg {@code java.base}.
|
||||
*/
|
||||
public String getName() {
|
||||
return super.getImage();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* An "opens" directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleOpensDirective ::=
|
||||
* "opens" <PACKAGE_NAME>
|
||||
* ( "to" {@linkplain ASTModuleName ModuleName} ( "," {@linkplain ASTModuleName ModuleName})* )?
|
||||
* ";"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleOpensDirective extends AbstractPackageNameModuleDirective {
|
||||
|
||||
ASTModuleOpensDirective(int id) {
|
||||
super(id, DirectiveType.OPENS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of the module names that are found after the "to" keyword.
|
||||
* May be empty
|
||||
*/
|
||||
public NodeStream<ASTModuleName> getTargetModules() {
|
||||
return children(ASTModuleName.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* A "provides" directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleProvidesDirective ::=
|
||||
* "provides" {@linkplain ASTClassOrInterfaceType ClassType}
|
||||
* "with" {@linkplain ASTClassOrInterfaceType ClassType} ( "," {@linkplain ASTClassOrInterfaceType ClassType} )*
|
||||
* ";"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleProvidesDirective extends ASTModuleDirective {
|
||||
|
||||
ASTModuleProvidesDirective(int id) {
|
||||
super(id, DirectiveType.PROVIDES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
public ASTClassOrInterfaceType getProvidedInterface() {
|
||||
return firstChild(ASTClassOrInterfaceType.class);
|
||||
}
|
||||
|
||||
public NodeStream<ASTClassOrInterfaceType> getImplementations() {
|
||||
return children(ASTClassOrInterfaceType.class).drop(1);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* A "requires" directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleRequiresDirective ::=
|
||||
* "requires" ( "transitive" | "static" )? {@linkplain ASTModuleName ModuleName} ";"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleRequiresDirective extends ASTModuleDirective {
|
||||
|
||||
private boolean isStatic;
|
||||
private boolean isTransitive;
|
||||
|
||||
ASTModuleRequiresDirective(int id) {
|
||||
super(id, DirectiveType.REQUIRES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the required module.
|
||||
*/
|
||||
public @NonNull ASTModuleName getRequiredModule() {
|
||||
return Objects.requireNonNull(firstChild(ASTModuleName.class));
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
public boolean isTransitive() {
|
||||
return isTransitive;
|
||||
}
|
||||
|
||||
void setTransitive() {
|
||||
isTransitive = true;
|
||||
}
|
||||
|
||||
void setStatic() {
|
||||
isStatic = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* A "uses" directive of a {@linkplain ASTModuleDeclaration module declaration}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ModuleUsesDirective ::= "uses" <PACKAGE_NAME> ";"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTModuleUsesDirective extends AbstractPackageNameModuleDirective {
|
||||
|
||||
ASTModuleUsesDirective(int id) {
|
||||
super(id, DirectiveType.USES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
|
||||
public class ASTName extends AbstractJavaTypeNode {
|
||||
|
||||
private NameDeclaration nd;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for a synthetic node.
|
||||
* @param image Image of the new node
|
||||
*/
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTName(String image, AbstractJavaNode parent) {
|
||||
super(JavaParserImplTreeConstants.JJTNAME);
|
||||
setImage(image);
|
||||
setParent(parent);
|
||||
}
|
||||
|
||||
ASTName(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public void setNameDeclaration(NameDeclaration nd) {
|
||||
this.nd = nd;
|
||||
}
|
||||
|
||||
public NameDeclaration getNameDeclaration() {
|
||||
return this.nd;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
@ -6,8 +6,7 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* Package declaration at the top of a {@linkplain ASTCompilationUnit source file}.
|
||||
* Since 7.0, there is no {@linkplain ASTName Name} node anymore. Use
|
||||
* {@link #getName()} instead.
|
||||
* Since 7.0, there is no Name node anymore. Use {@link #getName()} instead.
|
||||
*
|
||||
*
|
||||
* <pre class="grammar">
|
||||
|
@ -30,15 +30,6 @@ public class ASTYieldStatement extends AbstractStatement {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImage() {
|
||||
String result = super.getImage();
|
||||
if (result == null && hasDescendantOfType(ASTName.class)) {
|
||||
result = getFirstDescendantOfType(ASTName.class).getImage();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the yielded expression. */
|
||||
public ASTExpression getExpr() {
|
||||
|
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
public abstract class AbstractPackageNameModuleDirective extends ASTModuleDirective {
|
||||
|
||||
AbstractPackageNameModuleDirective(int id, DirectiveType type) {
|
||||
super(id, type);
|
||||
}
|
||||
|
||||
public final String getPackageName() {
|
||||
return super.getImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final String getImage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
final void setPackageName(String name) {
|
||||
super.setImage(name);
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTExtendsList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTModuleProvidesDirective;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTThisExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression;
|
||||
@ -62,6 +63,7 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule {
|
||||
|| parent instanceof ASTExtendsList // extends AbstractMap<...>
|
||||
|| parent instanceof ASTThisExpression // Enclosing.this
|
||||
|| parent instanceof ASTSuperExpression // Enclosing.super
|
||||
|| parent instanceof ASTModuleProvidesDirective // provides <interface> with <implementation>
|
||||
|| parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLambdaParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodReference;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTNumericLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPattern;
|
||||
@ -152,11 +151,6 @@ public final class LazyTypeResolver extends JavaVisitorBase<TypingContext, @NonN
|
||||
return ts.NO_TYPE; // TODO shouldn't be a typenode (do you mean type of variable, or type of initializer?)
|
||||
}
|
||||
|
||||
@Override
|
||||
public JTypeMirror visit(ASTName node, TypingContext ctx) {
|
||||
return ts.NO_TYPE; // TODO shouldn't be a typenode (basically an AmbiguousName)
|
||||
}
|
||||
|
||||
@Override
|
||||
public JTypeMirror visit(ASTCompilationUnit node, TypingContext ctx) {
|
||||
return ts.NO_TYPE; // TODO shouldn't be a typenode
|
||||
|
@ -1,14 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* 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.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@ -17,51 +13,11 @@ import net.sourceforge.pmd.lang.java.BaseParserTest;
|
||||
public class ASTModuleDeclarationTest extends BaseParserTest {
|
||||
|
||||
@Test
|
||||
public final void jdk9ModuleInfo() {
|
||||
ASTCompilationUnit ast = java9.parseResource("jdkversiontests/jdk9_module_info.java");
|
||||
ASTModuleDeclaration module = ast.descendants(ASTModuleDeclaration.class).firstOrThrow();
|
||||
assertTrue(module.isOpen());
|
||||
assertEquals("com.example.foo", module.getImage());
|
||||
assertEquals(7, module.getNumChildren());
|
||||
List<ASTModuleDirective> directives = module.children(ASTModuleDirective.class).toList();
|
||||
assertEquals(7, directives.size());
|
||||
|
||||
// requires com.example.foo.http;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.REQUIRES.name(), directives.get(0).getType());
|
||||
assertNull(directives.get(0).getRequiresModifier());
|
||||
assertEquals("com.example.foo.http", directives.get(0).getFirstChildOfType(ASTModuleName.class).getImage());
|
||||
|
||||
// requires java.logging;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.REQUIRES.name(), directives.get(1).getType());
|
||||
assertNull(directives.get(1).getRequiresModifier());
|
||||
assertEquals("java.logging", directives.get(1).getFirstChildOfType(ASTModuleName.class).getImage());
|
||||
|
||||
// requires transitive com.example.foo.network;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.REQUIRES.name(), directives.get(2).getType());
|
||||
assertEquals(ASTModuleDirective.RequiresModifier.TRANSITIVE.name(), directives.get(2).getRequiresModifier());
|
||||
assertEquals("com.example.foo.network", directives.get(2).getFirstChildOfType(ASTModuleName.class).getImage());
|
||||
|
||||
// exports com.example.foo.bar;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.EXPORTS.name(), directives.get(3).getType());
|
||||
assertNull(directives.get(3).getRequiresModifier());
|
||||
assertEquals("com.example.foo.bar", directives.get(3).getFirstChildOfType(ASTName.class).getImage());
|
||||
|
||||
// exports com.example.foo.internal to com.example.foo.probe;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.EXPORTS.name(), directives.get(4).getType());
|
||||
assertNull(directives.get(4).getRequiresModifier());
|
||||
assertEquals("com.example.foo.internal", directives.get(4).getFirstChildOfType(ASTName.class).getImage());
|
||||
assertEquals("com.example.foo.probe", directives.get(4).getFirstChildOfType(ASTModuleName.class).getImage());
|
||||
|
||||
// uses com.example.foo.spi.Intf;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.USES.name(), directives.get(5).getType());
|
||||
assertNull(directives.get(5).getRequiresModifier());
|
||||
assertEquals("com.example.foo.spi.Intf", directives.get(5).getFirstChildOfType(ASTName.class).getImage());
|
||||
|
||||
// provides com.example.foo.spi.Intf with com.example.foo.Impl;
|
||||
assertEquals(ASTModuleDirective.DirectiveType.PROVIDES.name(), directives.get(6).getType());
|
||||
assertNull(directives.get(6).getRequiresModifier());
|
||||
assertEquals("com.example.foo.spi.Intf", directives.get(6).getFirstChildOfType(ASTName.class).getImage());
|
||||
assertEquals("com.example.foo.Impl", directives.get(6).findChildrenOfType(ASTName.class).get(1).getImage());
|
||||
public void testAnnotatable() {
|
||||
ASTCompilationUnit root = java9.parse("@A @B module foo { } ");
|
||||
ASTModuleDeclaration mod = root.getModuleDeclaration();
|
||||
assertTrue(mod.isAnnotationPresent("A"));
|
||||
assertTrue(mod.isAnnotationPresent("B"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,12 +11,15 @@ import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
|
||||
import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest;
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
|
||||
public class JDKVersionTest {
|
||||
public class JDKVersionTest extends BaseJavaTreeDumpTest {
|
||||
|
||||
private final JavaParsingHelper java3 = JavaParsingHelper.DEFAULT
|
||||
.withDefaultVersion("1.3")
|
||||
@ -210,7 +213,7 @@ public class JDKVersionTest {
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public final void jdk9PrivateInterfaceMethodsInJava18() {
|
||||
java8.parseResource("jdk9_private_interface_methods.java");
|
||||
java8.parseResource("java9/jdk9_private_interface_methods.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -225,52 +228,52 @@ public class JDKVersionTest {
|
||||
|
||||
@Test
|
||||
public final void jdk9PrivateInterfaceMethods() {
|
||||
java9.parseResource("jdk9_private_interface_methods.java");
|
||||
java9.parseResource("java9/jdk9_private_interface_methods.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void jdk9InvalidIdentifierInJava18() {
|
||||
java8.parseResource("jdk9_invalid_identifier.java");
|
||||
java8.parseResource("java9/jdk9_invalid_identifier.java");
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public final void jdk9InvalidIdentifier() {
|
||||
java9.parseResource("jdk9_invalid_identifier.java");
|
||||
java9.parseResource("java9/jdk9_invalid_identifier.java");
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public final void jdk9AnonymousDiamondInJava8() {
|
||||
java8.parseResource("jdk9_anonymous_diamond.java");
|
||||
java8.parseResource("java9/jdk9_anonymous_diamond.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void jdk9AnonymousDiamond() {
|
||||
java9.parseResource("jdk9_anonymous_diamond.java");
|
||||
java9.parseResource("java9/jdk9_anonymous_diamond.java");
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public final void jdk9ModuleInfoInJava8() {
|
||||
java8.parseResource("jdk9_module_info.java");
|
||||
java8.parseResource("java9/jdk9_module_info.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void jdk9ModuleInfo() {
|
||||
java9.parseResource("jdk9_module_info.java");
|
||||
java9.parseResource("java9/jdk9_module_info.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotatedModule() {
|
||||
java9.parseResource("jdk9_module_info_with_annot.java");
|
||||
java9.parseResource("java9/jdk9_module_info_with_annot.java");
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
public final void jdk9TryWithResourcesInJava8() {
|
||||
java8.parseResource("jdk9_try_with_resources.java");
|
||||
java8.parseResource("java9/jdk9_try_with_resources.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void jdk9TryWithResources() {
|
||||
java9.parseResource("jdk9_try_with_resources.java");
|
||||
java9.parseResource("java9/jdk9_try_with_resources.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -292,4 +295,9 @@ public class JDKVersionTest {
|
||||
assertTrue(e.getMessage().startsWith("Line 19"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BaseParsingHelper<?, ?> getParser() {
|
||||
return java9;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
|
||||
import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest;
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
|
||||
public class Java9TreeDumpTest extends BaseJavaTreeDumpTest {
|
||||
|
||||
private final JavaParsingHelper java9 = JavaParsingHelper.DEFAULT
|
||||
.withDefaultVersion("9")
|
||||
.withResourceContext(Java9TreeDumpTest.class, "jdkversiontests/java9");
|
||||
|
||||
@Test
|
||||
public void testModule() {
|
||||
doTest("jdk9_module_info");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotatedModule() {
|
||||
doTest("jdk9_module_info_with_annot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BaseParsingHelper<?, ?> getParser() {
|
||||
return java9;
|
||||
}
|
||||
}
|
@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
@ -66,27 +64,6 @@ public class SimpleNodeTest extends BaseParserTest {
|
||||
assertFalse(ucd.getChild(0) instanceof ASTImplementsList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnsOnQualifiedName() {
|
||||
for (Node node : java.getNodes(ASTName.class, QUALIFIED_NAME)) {
|
||||
if (node.getImage().equals("java.io.File")) {
|
||||
TestUtilsKt.assertPosition(node, 1, 8, 1, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLineNumbersForNameSplitOverTwoLines() {
|
||||
for (Node node : java.getNodes(ASTName.class, BROKEN_LINE_IN_NAME)) {
|
||||
if (node.getImage().equals("java.io.File")) {
|
||||
TestUtilsKt.assertPosition(node, 1, 8, 2, 5);
|
||||
}
|
||||
if (node.getImage().equals("Foo")) {
|
||||
TestUtilsKt.assertPosition(node, 2, 15, 2, 19);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testLineNumbersAreSetOnAllSiblings() {
|
||||
// for (ASTBlock b : java.getNodes(ASTBlock.class, LINE_NUMBERS_ON_SIBLINGS)) {
|
||||
@ -172,22 +149,6 @@ public class SimpleNodeTest extends BaseParserTest {
|
||||
// assertEquals(x2, n);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testParentMethods() {
|
||||
ASTCompilationUnit u = java.parse(TEST1);
|
||||
|
||||
ASTMethodDeclarator d = u.getFirstDescendantOfType(ASTMethodDeclarator.class);
|
||||
assertSame("getFirstParentOfType ASTMethodDeclaration", d.getParent(),
|
||||
d.getFirstParentOfType(ASTMethodDeclaration.class));
|
||||
assertNull("getFirstParentOfType ASTName", d.getFirstParentOfType(ASTName.class));
|
||||
|
||||
assertSame("getNthParent 1", d.getParent(), d.getNthParent(1));
|
||||
assertSame("getNthParent 2", d.getParent().getParent(), d.getNthParent(2));
|
||||
assertSame("getNthParent 6", u, d.getNthParent(6));
|
||||
assertNull("getNthParent 7", d.getNthParent(7));
|
||||
assertNull("getNthParent 8", d.getNthParent(8));
|
||||
}
|
||||
|
||||
private static final String TEST1 = "public class Test {\n void bar(String s) {\n s = s.toLowerCase();\n }\n}";
|
||||
|
||||
@Ignore
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast
|
||||
|
||||
import io.kotest.matchers.collections.shouldBeEmpty
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
||||
import net.sourceforge.pmd.lang.ast.test.*
|
||||
@ -70,6 +72,30 @@ class TypeDisambiguationTest : ParserTestSpec({
|
||||
}
|
||||
}
|
||||
|
||||
parserTest("Package names in module") {
|
||||
|
||||
val code = """
|
||||
module java.base {
|
||||
opens java.util;
|
||||
provides java.util.Map with java.util.HashMap;
|
||||
// ^^^^^^^^^ ^^^^^^^^^
|
||||
}
|
||||
"""
|
||||
|
||||
doTest("test without disambig") {
|
||||
val acu = parser.parse(code)
|
||||
|
||||
acu.descendants(ASTAmbiguousName::class.java).toList().shouldHaveSize(2)
|
||||
}
|
||||
|
||||
doTest("test with disambig") {
|
||||
enableProcessing()
|
||||
val acu = parser.parse(code)
|
||||
|
||||
acu.descendants(ASTAmbiguousName::class.java).toList().shouldBeEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parserTest("Failures") {
|
||||
val logger = enableProcessing()
|
||||
|
@ -12,4 +12,5 @@ open module com.example.foo {
|
||||
uses com.example.foo.spi.Intf;
|
||||
|
||||
provides com.example.foo.spi.Intf with com.example.foo.Impl;
|
||||
}
|
||||
provides com.example.foo.spi.Intf2 with com.example.foo.Impl, com.example.foo.Impl2;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
+- CompilationUnit[@PackageName = ""]
|
||||
+- ModuleDeclaration[@Name = "com.example.foo", @Open = "true"]
|
||||
+- ModuleName[@Name = "com.example.foo"]
|
||||
+- ModuleRequiresDirective[@Static = "false", @Transitive = "false"]
|
||||
| +- ModuleName[@Name = "com.example.foo.http"]
|
||||
+- ModuleRequiresDirective[@Static = "false", @Transitive = "false"]
|
||||
| +- ModuleName[@Name = "java.logging"]
|
||||
+- ModuleRequiresDirective[@Static = "false", @Transitive = "true"]
|
||||
| +- ModuleName[@Name = "com.example.foo.network"]
|
||||
+- ModuleExportsDirective[@PackageName = "com.example.foo.bar"]
|
||||
+- ModuleExportsDirective[@PackageName = "com.example.foo.internal"]
|
||||
| +- ModuleName[@Name = "com.example.foo.probe"]
|
||||
+- ModuleUsesDirective[@PackageName = "com.example.foo.spi.Intf"]
|
||||
+- ModuleProvidesDirective[]
|
||||
| +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Intf"]
|
||||
| +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Impl"]
|
||||
+- ModuleProvidesDirective[]
|
||||
+- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Intf2"]
|
||||
+- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Impl"]
|
||||
+- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Impl2"]
|
@ -0,0 +1,10 @@
|
||||
+- CompilationUnit[@PackageName = ""]
|
||||
+- ModuleDeclaration[@Name = "jdk.pack", @Open = "false"]
|
||||
+- Annotation[@SimpleName = "Deprecated"]
|
||||
| +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Deprecated"]
|
||||
| +- AnnotationMemberList[@Empty = "false", @Size = "2"]
|
||||
| +- MemberValuePair[@Image = "since", @Name = "since", @Shorthand = "false"]
|
||||
| | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "11", @Empty = "false", @Image = "\"11\"", @Length = "2", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"]
|
||||
| +- MemberValuePair[@Image = "forRemoval", @Name = "forRemoval", @Shorthand = "false"]
|
||||
| +- BooleanLiteral[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @True = "true"]
|
||||
+- ModuleName[@Name = "jdk.pack"]
|
@ -1,3 +1,7 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
public class InputJava9TryWithResources {
|
||||
public static void main() {
|
||||
MyResource resource1 = new MyResource();
|
Reference in New Issue
Block a user