Merge branch 'pr/4038'
This commit is contained in:
41 files changed
+3311
-584
No files matched your search
@@ -7,33 +7,34 @@ permalink: pmd_languages_java.html
|
||||
|
||||
Usually the latest non-preview Java Version is the default version.
|
||||
|
||||
Java Version |Alias | Supported by PMD since |
|
||||
-------------|------|------------------------|
|
||||
18-preview | | 6.44.0 |
|
||||
18 (default) | | 6.44.0 |
|
||||
17-preview | | 6.37.0 |
|
||||
17 | | 6.37.0 |
|
||||
16 | | 6.32.0 |
|
||||
15 | | 6.27.0 |
|
||||
14 | | 6.22.0 |
|
||||
13 | | 6.18.0 |
|
||||
12 | | 6.13.0 |
|
||||
11 | | 6.6.0 |
|
||||
10 | 1.10 | 6.4.0 |
|
||||
9 | 1.9 | 6.0.0 |
|
||||
8 | 1.8 | 5.1.0 |
|
||||
7 | 1.7 | 5.0.0 |
|
||||
6 | 1.6 | 3.9 |
|
||||
5 | 1.5 | 3.0 |
|
||||
1.4 | | 1.2.2 |
|
||||
1.3 | | 1.0.0 |
|
||||
| Java Version | Alias | Supported by PMD since |
|
||||
|--------------|-------|------------------------|
|
||||
| 19-preview | | 6.48.0 |
|
||||
| 19 (default) | | 6.48.0 |
|
||||
| 18-preview | | 6.44.0 |
|
||||
| 18 | | 6.44.0 |
|
||||
| 17 | | 6.37.0 |
|
||||
| 16 | | 6.32.0 |
|
||||
| 15 | | 6.27.0 |
|
||||
| 14 | | 6.22.0 |
|
||||
| 13 | | 6.18.0 |
|
||||
| 12 | | 6.13.0 |
|
||||
| 11 | | 6.6.0 |
|
||||
| 10 | 1.10 | 6.4.0 |
|
||||
| 9 | 1.9 | 6.0.0 |
|
||||
| 8 | 1.8 | 5.1.0 |
|
||||
| 7 | 1.7 | 5.0.0 |
|
||||
| 6 | 1.6 | 3.9 |
|
||||
| 5 | 1.5 | 3.0 |
|
||||
| 1.4 | | 1.2.2 |
|
||||
| 1.3 | | 1.0.0 |
|
||||
|
||||
## Using Java preview features
|
||||
|
||||
In order to analyze a project with PMD that uses preview language features, you'll need to enable
|
||||
it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `18-preview`:
|
||||
it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `19-preview`:
|
||||
|
||||
export PMD_JAVA_OPTS=--enable-preview
|
||||
./run.sh pmd -language java -version 18-preview ...
|
||||
./run.sh pmd -language java -version 19-preview ...
|
||||
|
||||
Note: we only support preview language features for the latest two java versions.
|
||||
@@ -236,9 +236,10 @@ nested element. Possible values are:
|
||||
<sourceLanguage name="java" version="15"/>
|
||||
<sourceLanguage name="java" version="16"/>
|
||||
<sourceLanguage name="java" version="17"/>
|
||||
<sourceLanguage name="java" version="17-preview"/>
|
||||
<sourceLanguage name="java" version="18"/> <!-- this is the default -->
|
||||
<sourceLanguage name="java" version="18"/>
|
||||
<sourceLanguage name="java" version="18-preview"/>
|
||||
<sourceLanguage name="java" version="19"/> <!-- this is the default -->
|
||||
<sourceLanguage name="java" version="19-preview"/>
|
||||
<sourceLanguage name="jsp" version=""/>
|
||||
<sourceLanguage name="modelica" version=""/>
|
||||
<sourceLanguage name="pom" version=""/>
|
||||
|
||||
@@ -14,6 +14,22 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Java 19 Support
|
||||
|
||||
This release of PMD brings support for Java 19. There are no new standard language features.
|
||||
|
||||
PMD supports [JEP 427: Pattern Matching for switch (Third Preview)](https://openjdk.org/jeps/427) and
|
||||
[JEP 405: Record Patterns (Preview)](https://openjdk.org/jeps/405) as preview language features.
|
||||
|
||||
In order to analyze a project with PMD that uses these language features,
|
||||
you'll need to enable it via the environment variable `PMD_JAVA_OPTS` and select the new language
|
||||
version `19-preview`:
|
||||
|
||||
export PMD_JAVA_OPTS=--enable-preview
|
||||
./run.sh pmd -language java -version 19-preview ...
|
||||
|
||||
Note: Support for Java 17 preview language features have been removed. The version "17-preview" is no longer available.
|
||||
|
||||
#### Gherkin support
|
||||
Thanks to the contribution from [Anne Brouwers](https://github.com/ASBrouwers) PMD now has CPD support
|
||||
for the [Gherkin](https://cucumber.io/docs/gherkin/) language. It is used to defined test cases for the
|
||||
@@ -25,6 +41,8 @@ Being based on a proper Antlr grammar, CPD can:
|
||||
* honor [comment-based suppressions](pmd_userdocs_cpd.html#suppression)
|
||||
|
||||
### Fixed Issues
|
||||
* java
|
||||
* [#4015](https://github.com/pmd/pmd/issues/4015): \[java] Support JDK 19
|
||||
* java-bestpractices
|
||||
* [#3455](https://github.com/pmd/pmd/issues/3455): \[java] WhileLoopWithLiteralBoolean - false negative with complex expressions
|
||||
* java-design
|
||||
@@ -35,6 +53,20 @@ Being based on a proper Antlr grammar, CPD can:
|
||||
|
||||
### API Changes
|
||||
|
||||
#### Deprecated API
|
||||
|
||||
* The experimental Java AST class {% jdoc java::lang.java.ast.ASTGuardedPattern %} has been deprecated and
|
||||
will be removed. It was introduced for Java 17 and Java 18 Preview as part of pattern matching for switch,
|
||||
but it is no longer supported with Java 19 Preview.
|
||||
|
||||
#### Experimental APIs
|
||||
|
||||
* To support the Java preview language features "Pattern Matching for Switch" and "Record Patterns", the following
|
||||
AST nodes have been introduced as experimental:
|
||||
* {% jdoc java::lang.java.ast.ASTSwitchGuard %}
|
||||
* {% jdoc java::lang.java.ast.ASTRecordPattern %}
|
||||
* {% jdoc java::lang.java.ast.ASTComponentPatternList %}
|
||||
|
||||
### External Contributions
|
||||
* [#3984](https://github.com/pmd/pmd/pull/3984): \[java] Fix AddEmptyString false-negative issue - [@LiGaOg](https://github.com/LiGaOg)
|
||||
* [#3988](https://github.com/pmd/pmd/pull/3988): \[java] Modify WhileLoopWithLiteralBoolean to meet the missing case #3455 - [@VoidxHoshi](https://github.com/VoidxHoshi)
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
<!-- this file contains are parse error explicitly -->
|
||||
<exclude-pattern>.*/net/sourceforge/pmd/lang/java/ast/InfiniteLoopInLookahead.java</exclude-pattern>
|
||||
|
||||
<!-- the following files cannot be parsed with the latest java version (19 preview) anymore
|
||||
since java 18 preview grammar is different.
|
||||
-->
|
||||
<exclude-pattern>.*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.java</exclude-pattern>
|
||||
<exclude-pattern>.*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.java</exclude-pattern>
|
||||
|
||||
<rule ref="category/java/bestpractices.xml" />
|
||||
<rule ref="category/java/codestyle.xml" />
|
||||
<rule ref="category/java/design.xml" />
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
/**
|
||||
* Support "JEP 427: Pattern Matching for switch (Third Preview)" for Java 19 Preview
|
||||
* Note: GuardedPattern is deprecated and only valid for 17-preview and 18-preview
|
||||
* New AST node: ASTSwitchGuard (production "Guard") - used within switch case labels for refining a pattern
|
||||
* Support "JEP 405: Record Patterns (Preview)" for Java 19 Preview
|
||||
* New AST node: ASTRecordPattern and ASTComponentPatternList (production "RecordStructurePattern")
|
||||
* Remove support for Java 17 preview language features
|
||||
* Andreas Dangel 07/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
|
||||
@@ -534,30 +542,48 @@ public class JavaParser {
|
||||
}
|
||||
|
||||
private boolean isJEP406Supported() {
|
||||
return (jdkVersion == 17 || jdkVersion == 18) && preview;
|
||||
return (jdkVersion == 18 || jdkVersion == 19) && preview;
|
||||
}
|
||||
|
||||
private void checkForPatternMatchingInSwitch() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview.");
|
||||
throwParseException("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForNullCaseLabel() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview.");
|
||||
throwParseException("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForDefaultCaseLabel() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Default case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview.");
|
||||
throwParseException("Default case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForGuardedPatterns() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview.");
|
||||
if (!((jdkVersion == 18) && preview)) {
|
||||
throwParseException("Guarded patterns are only supported with JDK 18 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForParenthesizedInstanceOfPattern() {
|
||||
if (!((jdkVersion == 18) && preview)) {
|
||||
throwParseException("Parenthesized InstanceOf patterns are only supported with JDK 18 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForGuard() {
|
||||
if (!((jdkVersion == 19) && preview)) {
|
||||
throwParseException("Guards are only supported with JDK 19 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForRecordPatterns() {
|
||||
if (!((jdkVersion == 19) && preview)) {
|
||||
throwParseException("Record Patterns are only supported with JDK 19 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1761,7 +1787,9 @@ void EqualityExpression() #EqualityExpression(>1):
|
||||
void Pattern() #void:
|
||||
{}
|
||||
{
|
||||
PrimaryPattern() [ GuardedPatternCondition() #GuardedPattern(2) {checkForGuardedPatterns();} ]
|
||||
LOOKAHEAD(ReferenceType() "(") RecordPattern()
|
||||
| LOOKAHEAD("(") ParenthesizedPattern()
|
||||
| TypePattern() [ GuardedPatternCondition() #GuardedPattern(2) {checkForGuardedPatterns();} ]
|
||||
}
|
||||
|
||||
void GuardedPatternCondition() #void:
|
||||
@@ -1770,11 +1798,10 @@ void GuardedPatternCondition() #void:
|
||||
"&&" ConditionalAndExpression()
|
||||
}
|
||||
|
||||
void PrimaryPattern() #void:
|
||||
void ParenthesizedPattern() #void:
|
||||
{}
|
||||
{
|
||||
TypePattern()
|
||||
| "(" Pattern() ")" { AstImplUtil.bumpParenDepth((ASTPattern) jjtree.peekNode()); }
|
||||
"(" Pattern() ")" { AstImplUtil.bumpParenDepth((ASTPattern) jjtree.peekNode()); }
|
||||
}
|
||||
|
||||
void TypePattern():
|
||||
@@ -1785,15 +1812,35 @@ void TypePattern():
|
||||
VariableDeclaratorId()
|
||||
}
|
||||
|
||||
void RecordPattern():
|
||||
{ checkForRecordPatterns(); }
|
||||
{
|
||||
ReferenceType() RecordStructurePattern() [ VariableDeclaratorId() ]
|
||||
}
|
||||
|
||||
void RecordStructurePattern() #ComponentPatternList:
|
||||
{}
|
||||
{
|
||||
"(" [ RecordComponentPatternList() ] ")"
|
||||
}
|
||||
|
||||
void RecordComponentPatternList() #void:
|
||||
{}
|
||||
{
|
||||
Pattern() ( "," Pattern() )*
|
||||
}
|
||||
|
||||
void InstanceOfExpression() #InstanceOfExpression(>1):
|
||||
{}
|
||||
{
|
||||
RelationalExpression()
|
||||
[ "instanceof"
|
||||
(
|
||||
LOOKAHEAD("final" | "@") {checkforBadInstanceOfPattern();} PrimaryPattern()
|
||||
LOOKAHEAD("final" | "@") {checkforBadInstanceOfPattern();} Pattern()
|
||||
|
|
||||
LOOKAHEAD("(") Pattern() {checkforBadInstanceOfPattern();}
|
||||
LOOKAHEAD("(") Pattern() {checkForParenthesizedInstanceOfPattern();}
|
||||
|
|
||||
LOOKAHEAD(ReferenceType() "(") RecordPattern()
|
||||
|
|
||||
Type()
|
||||
[ {checkforBadInstanceOfPattern();} VariableDeclaratorId() #TypePattern(2) ]
|
||||
@@ -2275,7 +2322,7 @@ void CaseLabelElement(ASTSwitchLabel label) #void:
|
||||
{
|
||||
"default" {label.setDefault(); checkForDefaultCaseLabel();}
|
||||
|
|
||||
LOOKAHEAD(Pattern()) Pattern() {checkForPatternMatchingInSwitch();}
|
||||
LOOKAHEAD(Pattern()) Pattern() {checkForPatternMatchingInSwitch();} ( LOOKAHEAD({isKeyword("when")}) Guard() )*
|
||||
|
|
||||
ConditionalExpression() #Expression
|
||||
{
|
||||
@@ -2285,6 +2332,21 @@ void CaseLabelElement(ASTSwitchLabel label) #void:
|
||||
}
|
||||
}
|
||||
|
||||
void Guard() #SwitchGuard:
|
||||
{
|
||||
Token t;
|
||||
checkForGuard();
|
||||
}
|
||||
{
|
||||
t = <IDENTIFIER> {
|
||||
if (!"when".equals(t.image)) {
|
||||
throw new ParseException("ERROR: expected 'when'");
|
||||
}
|
||||
}
|
||||
|
||||
Expression()
|
||||
}
|
||||
|
||||
void YieldStatement() :
|
||||
{ checkForYieldStatement(); }
|
||||
{
|
||||
|
||||
@@ -31,9 +31,10 @@ public class JavaLanguageModule extends BaseLanguageModule {
|
||||
addVersion("15", new JavaLanguageHandler(15));
|
||||
addVersion("16", new JavaLanguageHandler(16));
|
||||
addVersion("17", new JavaLanguageHandler(17));
|
||||
addVersion("17-preview", new JavaLanguageHandler(17, true));
|
||||
addDefaultVersion("18", new JavaLanguageHandler(18)); // 18 is the default
|
||||
addVersion("18", new JavaLanguageHandler(18));
|
||||
addVersion("18-preview", new JavaLanguageHandler(18, true));
|
||||
addDefaultVersion("19", new JavaLanguageHandler(19)); // 19 is the default
|
||||
addVersion("19-preview", new JavaLanguageHandler(19, true));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.Experimental;
|
||||
|
||||
/**
|
||||
* Contains a potentially empty list of nested Patterns for {@linkplain ASTRecordPattern RecordPattern} (JDK 19).
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* ComponentPatternList ::= "(" {@linkplain ASTPattern Pattern} ( "," {@linkplain ASTPattern pattern} ) ")"
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href="https://openjdk.org/jeps/405">JEP 405: Record Patterns (Preview)</a>
|
||||
*/
|
||||
@Experimental
|
||||
public final class ASTComponentPatternList extends AbstractJavaNode {
|
||||
ASTComponentPatternList(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
ASTComponentPatternList(JavaParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,11 @@ import net.sourceforge.pmd.annotation.Experimental;
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href="https://openjdk.java.net/jeps/406">JEP 406: Pattern Matching for switch (Preview)</a>
|
||||
*
|
||||
* @deprecated This is not used with java 19 preview anymore. Only valid for java 18 preview.
|
||||
*/
|
||||
@Experimental
|
||||
@Deprecated
|
||||
public final class ASTGuardedPattern extends AbstractJavaNode implements ASTPattern {
|
||||
|
||||
private int parenDepth;
|
||||
|
||||
@@ -10,18 +10,16 @@ import net.sourceforge.pmd.annotation.Experimental;
|
||||
* A pattern (for pattern matching constructs like {@link ASTInstanceOfExpression InstanceOfExpression}
|
||||
* or within a {@link ASTSwitchLabel}). This is a JDK 16 feature.
|
||||
*
|
||||
* <p>This interface will be implemented by all forms of patterns. For
|
||||
* now, only type test patterns are supported. Record deconstruction
|
||||
* patterns is planned for a future JDK version.
|
||||
* <p>This interface is implemented by all forms of patterns.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* Pattern ::= {@link ASTTypePattern TypePattern}
|
||||
* | {@link ASTGuardedPattern GuardedPattern}
|
||||
* Pattern ::= {@linkplain ASTTypePattern TypePattern} | {@linkplain ASTRecordPattern RecordPattern}
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href="https://openjdk.java.net/jeps/394">JEP 394: Pattern Matching for instanceof</a>
|
||||
* @see <a href="https://openjdk.org/jeps/394">JEP 394: Pattern Matching for instanceof</a>
|
||||
* @see <a href="https://openjdk.org/jeps/405">JEP 405: Record Patterns (Preview)</a>
|
||||
*/
|
||||
public interface ASTPattern extends JavaNode {
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.Experimental;
|
||||
|
||||
/**
|
||||
* A record pattern (JDK19).
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* RecordPattern ::= {@linkplain ASTReferenceType ReferenceType} {@linkplain ASTComponentPatternList ComponentPatternList} [ {@linkplain ASTVariableDeclaratorId VariableDeclaratorId} ]
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href="https://openjdk.org/jeps/405">JEP 405: Record Patterns (Preview)</a>
|
||||
*/
|
||||
@Experimental
|
||||
public final class ASTRecordPattern extends AbstractJavaNode implements ASTPattern {
|
||||
|
||||
private int parenDepth;
|
||||
|
||||
ASTRecordPattern(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
ASTRecordPattern(JavaParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type against which the expression is tested.
|
||||
*/
|
||||
public ASTReferenceType getTypeNode() {
|
||||
return getFirstChildOfType(ASTReferenceType.class);
|
||||
}
|
||||
|
||||
/** Returns the declared variable. */
|
||||
public ASTVariableDeclaratorId getVarId() {
|
||||
return getFirstChildOfType(ASTVariableDeclaratorId.class);
|
||||
}
|
||||
|
||||
void bumpParenDepth() {
|
||||
parenDepth++;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Experimental
|
||||
public int getParenthesisDepth() {
|
||||
return parenDepth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.Experimental;
|
||||
|
||||
/**
|
||||
* A guard for refining a switch case in {@link ASTSwitchLabel}s.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* SwitchLabel := "case" {@linkplain ASTPattern Pattern} SwitchGuard?
|
||||
* SwitchGuard ::= "when" {@linkplain ASTExpression Expression}
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
@Experimental
|
||||
public final class ASTSwitchGuard extends AbstractJavaNode {
|
||||
|
||||
ASTSwitchGuard(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
ASTSwitchGuard(JavaParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
public ASTExpression getGuard() {
|
||||
return (ASTExpression) getChild(0);
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,15 @@ final class AstImplUtil {
|
||||
}
|
||||
|
||||
static void bumpParenDepth(ASTPattern pattern) {
|
||||
assert pattern instanceof ASTTypePattern || pattern instanceof ASTGuardedPattern
|
||||
assert pattern instanceof ASTTypePattern
|
||||
|| pattern instanceof ASTRecordPattern
|
||||
|| pattern instanceof ASTGuardedPattern
|
||||
: pattern.getClass() + " doesn't have parenDepth attribute!";
|
||||
|
||||
if (pattern instanceof ASTTypePattern) {
|
||||
((ASTTypePattern) pattern).bumpParenDepth();
|
||||
} else if (pattern instanceof ASTRecordPattern) {
|
||||
((ASTRecordPattern) pattern).bumpParenDepth();
|
||||
} else if (pattern instanceof ASTGuardedPattern) {
|
||||
((ASTGuardedPattern) pattern).bumpParenDepth();
|
||||
}
|
||||
|
||||
+22
@@ -944,9 +944,31 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor {
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Deprecated
|
||||
@Override
|
||||
public Object visit(ASTGuardedPattern node, Object data) {
|
||||
visitor.visit(node, data);
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTSwitchGuard node, Object data) {
|
||||
visitor.visit(node, data);
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTRecordPattern node, Object data) {
|
||||
visitor.visit(node, data);
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTComponentPatternList node, Object data) {
|
||||
visitor.visit(node, data);
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
}
|
||||
+19
@@ -664,8 +664,27 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor {
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Deprecated
|
||||
@Override
|
||||
public Object visit(ASTGuardedPattern node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTSwitchGuard node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTRecordPattern node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTComponentPatternList node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
}
|
||||
+19
@@ -796,8 +796,27 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Deprecated
|
||||
@Override
|
||||
public Object visit(ASTGuardedPattern node, Object data) {
|
||||
return visitor.visit(node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTSwitchGuard node, Object data) {
|
||||
return visitor.visit(node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTRecordPattern node, Object data) {
|
||||
return visitor.visit(node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTComponentPatternList node, Object data) {
|
||||
return visitor.visit(node, data);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompactConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTComponentPatternList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression;
|
||||
@@ -103,6 +104,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTRecordBody;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRecordComponent;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRecordComponentList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRecordDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRecordPattern;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTResource;
|
||||
@@ -116,6 +118,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTStatement;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpressionList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchGuard;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabeledBlock;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabeledExpression;
|
||||
@@ -874,11 +877,31 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
|
||||
@Experimental
|
||||
@Deprecated
|
||||
@Override
|
||||
public Object visit(ASTGuardedPattern node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTSwitchGuard node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTRecordPattern node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public Object visit(ASTComponentPatternList node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
// CPD-ON
|
||||
}
|
||||
+2
-2
@@ -13,9 +13,9 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
ParserCornersTest.class,
|
||||
Java15TreeDumpTest.class,
|
||||
Java16TreeDumpTest.class,
|
||||
Java17PreviewTreeDumpTest.class,
|
||||
Java17TreeDumpTest.class,
|
||||
Java18PreviewTreeDumpTest.class
|
||||
Java18PreviewTreeDumpTest.class,
|
||||
Java19PreviewTreeDumpTest.class
|
||||
})
|
||||
public class AllJavaAstTreeDumpTest {
|
||||
|
||||
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.function.ThrowingRunnable;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest;
|
||||
import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter;
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
|
||||
public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
private final JavaParsingHelper java17p =
|
||||
JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("17-preview")
|
||||
.withResourceContext(Java17PreviewTreeDumpTest.class, "jdkversiontests/java17p/");
|
||||
private final JavaParsingHelper java17 = java17p.withDefaultVersion("17");
|
||||
|
||||
public Java17PreviewTreeDumpTest() {
|
||||
super(new RelevantAttributePrinter(), ".java");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseParsingHelper<?, ?> getParser() {
|
||||
return java17p;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternMatchingForSwitchBeforeJava17Preview() {
|
||||
ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java17.parseResource("PatternsInSwitchLabels.java");
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternMatchingForSwitch() {
|
||||
doTest("PatternsInSwitchLabels");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enhancedTypeCheckingSwitch() {
|
||||
doTest("EnhancedTypeCheckingSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopeOfPatternVariableDeclarations() {
|
||||
doTest("ScopeOfPatternVariableDeclarations");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNullBeforeJava17Preview() {
|
||||
ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java17.parseResource("DealingWithNull.java");
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNull() {
|
||||
doTest("DealingWithNull");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatternsBeforeJava17Preview() {
|
||||
ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java17.parseResource("GuardedAndParenthesizedPatterns.java");
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatterns() {
|
||||
doTest("GuardedAndParenthesizedPatterns");
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest {
|
||||
private final JavaParsingHelper java17 =
|
||||
JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("17")
|
||||
.withResourceContext(Java17TreeDumpTest.class, "jdkversiontests/java17/");
|
||||
private final JavaParsingHelper java17p = java17.withDefaultVersion("17-preview");
|
||||
private final JavaParsingHelper java16 = java17.withDefaultVersion("16");
|
||||
|
||||
public Java17TreeDumpTest() {
|
||||
@@ -45,13 +44,11 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest {
|
||||
@Test
|
||||
public void sealedClass() {
|
||||
doTest("geometry/Shape");
|
||||
java17p.parseResource("geometry/Shape.java"); // make sure we can parse it with preview as well
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonSealedClass() {
|
||||
doTest("geometry/Square");
|
||||
java17p.parseResource("geometry/Square.java"); // make sure we can parse it with preview as well
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,7 +66,6 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest {
|
||||
@Test
|
||||
public void sealedInterface() {
|
||||
doTest("expression/Expr");
|
||||
java17p.parseResource("expression/Expr.java"); // make sure we can parse it with preview as well
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,7 +65,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
thrown.getMessage().contains("Guarded patterns are only supported with JDK 18 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,7 +82,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview."));
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.function.ThrowingRunnable;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
|
||||
import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest;
|
||||
import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter;
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
|
||||
public class Java19PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
private final JavaParsingHelper java19p =
|
||||
JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("19-preview")
|
||||
.withResourceContext(Java19PreviewTreeDumpTest.class, "jdkversiontests/java19p/");
|
||||
private final JavaParsingHelper java19 = java19p.withDefaultVersion("19");
|
||||
|
||||
public Java19PreviewTreeDumpTest() {
|
||||
super(new RelevantAttributePrinter(), ".java");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseParsingHelper<?, ?> getParser() {
|
||||
return java19p;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNullBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java19.parseResource("DealingWithNull.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNull() {
|
||||
doTest("DealingWithNull");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enhancedTypeCheckingSwitch() {
|
||||
doTest("EnhancedTypeCheckingSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exhaustiveSwitch() {
|
||||
doTest("ExhaustiveSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatternsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java19.parseResource("GuardedAndParenthesizedPatterns.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatterns() {
|
||||
doTest("GuardedAndParenthesizedPatterns");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternsInSwitchLabelsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java19.parseResource("PatternsInSwitchLabels.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternsInSwitchLabels() {
|
||||
doTest("PatternsInSwitchLabels");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refiningPatternsInSwitch() {
|
||||
doTest("RefiningPatternsInSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopeOfPatternVariableDeclarations() {
|
||||
doTest("ScopeOfPatternVariableDeclarations");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordPatterns() {
|
||||
doTest("RecordPatterns");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordPatternsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java19.parseResource("RecordPatterns.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Record Patterns are only supported with JDK 19 Preview."));
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,9 @@ enum class JavaVersion : Comparable<JavaVersion> {
|
||||
J14,
|
||||
J15,
|
||||
J16,
|
||||
J17, J17__PREVIEW,
|
||||
J18, J18__PREVIEW;
|
||||
J17,
|
||||
J18, J18__PREVIEW,
|
||||
J19, J19__PREVIEW;
|
||||
|
||||
/** Name suitable for use with e.g. [JavaParsingHelper.parse] */
|
||||
val pmdName: String = name.removePrefix("J").replaceFirst("__", "-").replace('_', '.').toLowerCase()
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.java.net/jeps/406">JEP 406: Pattern Matching for switch (Preview)</a>
|
||||
*/
|
||||
public class GuardedAndParenthesizedPatterns {
|
||||
|
||||
|
||||
static void test(Object o) {
|
||||
switch (o) {
|
||||
case String s && (s.length() == 1) -> System.out.println("single char string");
|
||||
case String s -> System.out.println("string");
|
||||
case (Integer i && i.intValue() == 1) -> System.out.println("integer 1");
|
||||
case (((Long l && l.longValue() == 1L))) -> System.out.println("long 1 with parens");
|
||||
case (((Double d))) -> System.out.println("double with parens");
|
||||
default -> System.out.println("default case");
|
||||
}
|
||||
}
|
||||
|
||||
static void instanceOfPattern(Object o) {
|
||||
if (o instanceof String s && s.length() > 2) {
|
||||
System.out.println("A string containing at least two characters");
|
||||
}
|
||||
if (o != null && (o instanceof String s && s.length() > 3)) {
|
||||
System.out.println("A string containing at least three characters");
|
||||
}
|
||||
if (o instanceof (String s && s.length() > 4)) {
|
||||
System.out.println("A string containing at least four characters");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test("a");
|
||||
test("fooo");
|
||||
test(1);
|
||||
test(1L);
|
||||
instanceOfPattern("abcde");
|
||||
test(null);
|
||||
}
|
||||
}
|
||||
-385
File diff suppressed because it is too large.
Load diff
+23
-1
@@ -3,10 +3,24 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.java.net/jeps/406">JEP 406: Pattern Matching for switch (Preview)</a>
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
public class DealingWithNull {
|
||||
|
||||
static void testFooBar(String s) {
|
||||
switch (s) {
|
||||
case null -> System.out.println("Oops");
|
||||
case "Foo", "Bar" -> System.out.println("Great");
|
||||
default -> System.out.println("Ok");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStringOrNull(Object o) {
|
||||
switch (o) {
|
||||
case null, String s -> System.out.println("String: " + s);
|
||||
case default -> System.out.print("default case");
|
||||
}
|
||||
}
|
||||
|
||||
static void test(Object o) {
|
||||
switch (o) {
|
||||
@@ -64,5 +78,13 @@ public class DealingWithNull {
|
||||
test3(3);
|
||||
test3("test");
|
||||
test3(null);
|
||||
|
||||
testFooBar(null);
|
||||
testFooBar("Foo");
|
||||
testFooBar("Bar");
|
||||
testFooBar("baz");
|
||||
|
||||
testStringOrNull(null);
|
||||
testStringOrNull("some string");
|
||||
}
|
||||
}
|
||||
+211
-3
@@ -2,6 +2,134 @@
|
||||
+- TypeDeclaration[]
|
||||
+- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "DealingWithNull", @Default = false, @Final = false, @Image = "DealingWithNull", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "DealingWithNull", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false]
|
||||
+- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false]
|
||||
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD]
|
||||
| +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testFooBar", @Modifiers = 16, @Name = "testFooBar", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false]
|
||||
| +- ResultType[@Void = true, @returnsArray = false]
|
||||
| +- MethodDeclarator[@Image = "testFooBar", @ParameterCount = 1]
|
||||
| | +- FormalParameters[@ParameterCount = 1, @Size = 1]
|
||||
| | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false]
|
||||
| | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"]
|
||||
| | | +- ReferenceType[@Array = false, @ArrayDepth = 0]
|
||||
| | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false]
|
||||
| | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
|
||||
| +- Block[@containsComment = false]
|
||||
| +- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "s"]
|
||||
| +- SwitchLabeledExpression[]
|
||||
| | +- SwitchLabel[@Default = false]
|
||||
| | | +- Expression[@StandAlonePrimitive = false]
|
||||
| | | +- PrimaryExpression[]
|
||||
| | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| | | +- NullLiteral[]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Name[@Image = "System.out.println"]
|
||||
| | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| | +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| | +- ArgumentList[@Size = 1]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Oops\"", @FloatLiteral = false, @Image = "\"Oops\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Oops\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| +- SwitchLabeledExpression[]
|
||||
| | +- SwitchLabel[@Default = false]
|
||||
| | | +- Expression[@StandAlonePrimitive = false]
|
||||
| | | | +- PrimaryExpression[]
|
||||
| | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Foo\"", @FloatLiteral = false, @Image = "\"Foo\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Foo\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| | | +- Expression[@StandAlonePrimitive = false]
|
||||
| | | +- PrimaryExpression[]
|
||||
| | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Bar\"", @FloatLiteral = false, @Image = "\"Bar\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Bar\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Name[@Image = "System.out.println"]
|
||||
| | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| | +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| | +- ArgumentList[@Size = 1]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Great\"", @FloatLiteral = false, @Image = "\"Great\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Great\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| +- SwitchLabeledExpression[]
|
||||
| +- SwitchLabel[@Default = true]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "System.out.println"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Ok\"", @FloatLiteral = false, @Image = "\"Ok\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Ok\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD]
|
||||
| +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testStringOrNull", @Modifiers = 16, @Name = "testStringOrNull", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false]
|
||||
| +- ResultType[@Void = true, @returnsArray = false]
|
||||
| +- MethodDeclarator[@Image = "testStringOrNull", @ParameterCount = 1]
|
||||
| | +- FormalParameters[@ParameterCount = 1, @Size = 1]
|
||||
| | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false]
|
||||
| | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"]
|
||||
| | | +- ReferenceType[@Array = false, @ArrayDepth = 0]
|
||||
| | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false]
|
||||
| | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"]
|
||||
| +- Block[@containsComment = false]
|
||||
| +- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "o"]
|
||||
| +- SwitchLabeledExpression[]
|
||||
| | +- SwitchLabel[@Default = false]
|
||||
| | | +- Expression[@StandAlonePrimitive = false]
|
||||
| | | | +- PrimaryExpression[]
|
||||
| | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| | | | +- NullLiteral[]
|
||||
| | | +- TypePattern[@ParenthesisDepth = 0]
|
||||
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"]
|
||||
| | | | +- ReferenceType[@Array = false, @ArrayDepth = 0]
|
||||
| | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false]
|
||||
| | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Name[@Image = "System.out.println"]
|
||||
| | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| | +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| | +- ArgumentList[@Size = 1]
|
||||
| | +- Expression[@StandAlonePrimitive = false]
|
||||
| | +- AdditiveExpression[@Image = "+", @Operator = "+"]
|
||||
| | +- PrimaryExpression[]
|
||||
| | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"String: \"", @FloatLiteral = false, @Image = "\"String: \"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"String: \"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| | +- PrimaryExpression[]
|
||||
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "s"]
|
||||
| +- SwitchLabeledExpression[]
|
||||
| +- SwitchLabel[@Default = true]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "System.out.print"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"default case\"", @FloatLiteral = false, @Image = "\"default case\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"default case\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD]
|
||||
| +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false]
|
||||
| +- ResultType[@Void = true, @returnsArray = false]
|
||||
@@ -413,17 +541,97 @@
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"test\"", @FloatLiteral = false, @Image = "\"test\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"test\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "test3"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| +- NullLiteral[]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "testFooBar"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| +- NullLiteral[]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "testFooBar"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Foo\"", @FloatLiteral = false, @Image = "\"Foo\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Foo\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "testFooBar"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"Bar\"", @FloatLiteral = false, @Image = "\"Bar\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"Bar\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "testFooBar"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"baz\"", @FloatLiteral = false, @Image = "\"baz\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"baz\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
| +- Statement[]
|
||||
| +- StatementExpression[]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| | +- Name[@Image = "testStringOrNull"]
|
||||
| +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
| +- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
| +- ArgumentList[@Size = 1]
|
||||
| +- Expression[@StandAlonePrimitive = false]
|
||||
| +- PrimaryExpression[]
|
||||
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
| +- NullLiteral[]
|
||||
+- BlockStatement[@Allocation = false]
|
||||
+- Statement[]
|
||||
+- StatementExpression[]
|
||||
+- PrimaryExpression[]
|
||||
+- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
| +- Name[@Image = "test3"]
|
||||
| +- Name[@Image = "testStringOrNull"]
|
||||
+- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false]
|
||||
+- Arguments[@ArgumentCount = 1, @Size = 1]
|
||||
+- ArgumentList[@Size = 1]
|
||||
+- Expression[@StandAlonePrimitive = false]
|
||||
+- PrimaryExpression[]
|
||||
+- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
|
||||
+- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+- NullLiteral[]
|
||||
+- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "\"some string\"", @FloatLiteral = false, @Image = "\"some string\"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "\"some string\"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.java.net/jeps/406">JEP 406: Pattern Matching for switch (Preview)</a>
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
public class EnhancedTypeCheckingSwitch {
|
||||
|
||||
File renamed without changes.
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
public class ExhaustiveSwitch {
|
||||
|
||||
static int coverage(Object o) {
|
||||
return switch (o) {
|
||||
case String s -> s.length();
|
||||
case Integer i -> i;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
static int coverageDefaultCase(Object o) {
|
||||
return switch (o) {
|
||||
case String s -> s.length();
|
||||
case Integer i -> i;
|
||||
case default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
static void coverageStatement(Object o) {
|
||||
switch (o) {
|
||||
case String s:
|
||||
System.out.println(s);
|
||||
break;
|
||||
case Integer i:
|
||||
System.out.println("Integer");
|
||||
break;
|
||||
default: // Now exhaustive!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface S permits A, B, C {}
|
||||
final static class A implements S {}
|
||||
final static class B implements S {}
|
||||
record C(int i) implements S {} // Implicitly final
|
||||
|
||||
static int testSealedExhaustive(S s) {
|
||||
return switch (s) {
|
||||
case A a -> 1;
|
||||
case B b -> 2;
|
||||
case C c -> 3;
|
||||
};
|
||||
}
|
||||
|
||||
static void switchStatementExhaustive(S s) {
|
||||
switch (s) {
|
||||
case A a :
|
||||
System.out.println("A");
|
||||
break;
|
||||
case C c :
|
||||
System.out.println("C");
|
||||
break;
|
||||
default:
|
||||
System.out.println("default case, should be B");
|
||||
break;
|
||||
};
|
||||
}
|
||||
sealed interface I<T> permits E, F {}
|
||||
final static class E<X> implements I<String> {}
|
||||
final static class F<Y> implements I<Y> {}
|
||||
|
||||
static int testGenericSealedExhaustive(I<Integer> i) {
|
||||
return switch (i) {
|
||||
// Exhaustive as no E case possible!
|
||||
case F<Integer> bi -> 42;
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(coverage("a string"));
|
||||
System.out.println(coverage(42));
|
||||
System.out.println(coverage(new Object()));
|
||||
|
||||
coverageStatement("a string");
|
||||
coverageStatement(21);
|
||||
coverageStatement(new Object());
|
||||
|
||||
System.out.println("A:" + testSealedExhaustive(new A()));
|
||||
System.out.println("B:" + testSealedExhaustive(new B()));
|
||||
System.out.println("C:" + testSealedExhaustive(new C(1)));
|
||||
|
||||
switchStatementExhaustive(new A());
|
||||
switchStatementExhaustive(new B());
|
||||
switchStatementExhaustive(new C(2));
|
||||
|
||||
System.out.println("F:" + testGenericSealedExhaustive(new F<Integer>()));
|
||||
}
|
||||
}
|
||||
+686
File diff suppressed because it is too large.
Load diff
Loaded 30 of 41 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user