diff --git a/.github/workflows/create_github_release.yml b/.github/workflows/create_github_release.yml index a7a531948d..12a4e0cf2c 100644 --- a/.github/workflows/create_github_release.yml +++ b/.github/workflows/create_github_release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.6.0 - name: Create Release id: create_release diff --git a/.github/workflows/maven_tests.yml b/.github/workflows/maven_tests.yml index 66281f5504..16e5fc5d75 100644 --- a/.github/workflows/maven_tests.yml +++ b/.github/workflows/maven_tests.yml @@ -46,7 +46,7 @@ jobs: steps: ## Checkout the current version of the code from the repo. - name: Checkout latest code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.6.0 with: fetch-depth: "0" @@ -85,7 +85,7 @@ jobs: - name: CodeCov - JavaParser Core - uses: codecov/codecov-action@v3.1.3 + uses: codecov/codecov-action@v3.1.4 timeout-minutes: 10 with: files: javaparser-core-testing/target/site/jacoco/jacoco.xml,javaparser-core-testing-bdd/target/site/jacoco/jacoco.xml @@ -95,7 +95,7 @@ jobs: env_vars: OS,JDK - name: CodeCov - JavaParser Symbol Solver - uses: codecov/codecov-action@v3.1.3 + uses: codecov/codecov-action@v3.1.4 timeout-minutes: 10 with: file: javaparser-symbol-solver-testing/target/site/jacoco/jacoco.xml @@ -110,7 +110,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout latest code - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.6.0 with: fetch-depth: "0" - name: Set up JDK 11 diff --git a/.github/workflows/prepare_release_changelog.yml b/.github/workflows/prepare_release_changelog.yml index 03da6ca7ab..59029b9a7a 100644 --- a/.github/workflows/prepare_release_changelog.yml +++ b/.github/workflows/prepare_release_changelog.yml @@ -15,7 +15,7 @@ jobs: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.6.0 # Setup Java 11 environment for the next steps - name: Setup Java @@ -39,11 +39,13 @@ jobs: RELEASE_TITLE="SNAPSHOT - $SHA_SHORT" RELEASE_TAG_NAME="v_snapshot_$SHA_SHORT" - echo "::set-output name=sha_long::$SHA_LONG" - echo "::set-output name=sha_short::$SHA_SHORT" - echo "::set-output name=changelog::$CHANGELOG" - echo "::set-output name=release_title::$RELEASE_TITLE" - echo "::set-output name=release_tag_name::$RELEASE_TAG_NAME" + echo "sha_long=$SHA_LONG" >> $GITHUB_OUTPUT + echo "sha_short=$SHA_SHORT" >> $GITHUB_OUTPUT + echo "changelog<> $GITHUB_OUTPUT + echo "$CHANGELOG" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "release_title=$RELEASE_TITLE" >> $GITHUB_OUTPUT + echo "release_tag_name=$RELEASE_TAG_NAME" >> $GITHUB_OUTPUT - name: Output variables diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index d8b2495a1e..ac184013fc 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/changelog.md b/changelog.md index 701343bd05..db50c4d2af 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,7 @@ -Next Release (Version 3.25.4-snapshot) +Next Release (Version 3.25.6-snapshot) -------------------------------------- -[issues resolved](https://github.com/javaparser/javaparser/milestone/200?closed=1) +[issues resolved](https://github.com/javaparser/javaparser/milestone/202?closed=1) ### Added ### Changed @@ -11,10 +11,106 @@ Next Release (Version 3.25.4-snapshot) ### Security +Version 3.25.5 +-------------- +[issues resolved](https://github.com/javaparser/javaparser/milestone/201?closed=1) + +### Added + +* fix: issue 4115 ResolvedUnionType should give access to a list of resolved types (PR [#4119](https://github.com/javaparser/javaparser/pull/4119) by [@jlerbsc](https://github.com/jlerbsc)) +* Support getting more annotation default values using reflection (PR [#4103](https://github.com/javaparser/javaparser/pull/4103) by [@freya022](https://github.com/freya022)) + +### Changed + +* Minor refactoring: Simplifies how to group deleted tokens by extracting a method into an independent class (PR [#4134](https://github.com/javaparser/javaparser/pull/4134) by [@jlerbsc](https://github.com/jlerbsc)) +* Replace deprecated command with environment file (PR [#4122](https://github.com/javaparser/javaparser/pull/4122) by [@70825](https://github.com/70825)) +* Fixes missing named constructor in Modifier.java (PR [#4092](https://github.com/javaparser/javaparser/pull/4092) by [@Auties00](https://github.com/Auties00)) + +### Fixed + +* Fix: issue 4133 Top-level class containerType() throws an exception instead of Optional.empty() (PR [#4135](https://github.com/javaparser/javaparser/pull/4135) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: apply multiline strings (PR [#4130](https://github.com/javaparser/javaparser/pull/4130) by [@70825](https://github.com/70825)) +* Fix: issue 3976 Issue resolving implicit generic types (PR [#4128](https://github.com/javaparser/javaparser/pull/4128) by [@jlerbsc](https://github.com/jlerbsc)) +* Add unit test for PR 4091 Fixed missing permits in pretty printer (PR [#4126](https://github.com/javaparser/javaparser/pull/4126) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue 4124 UnsupportedOperationException: 'T' is thrown in MethodCallExpr resolve (PR [#4125](https://github.com/javaparser/javaparser/pull/4125) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue 4051 Switched upperBounds and lowerBounds on ResolvedTypeP… (PR [#4123](https://github.com/javaparser/javaparser/pull/4123) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix failing test on JDK 17 (PR [#4121](https://github.com/javaparser/javaparser/pull/4121) by [@mahesh-hegde](https://github.com/mahesh-hegde)) +* Fix: issue 3673 isAssignableBy method StackOverflowError (PR [#4118](https://github.com/javaparser/javaparser/pull/4118) by [@jlerbsc](https://github.com/jlerbsc)) +* Orphan comment added when using lexical preservation is not printed (PR [#4114](https://github.com/javaparser/javaparser/pull/4114) by [@jlerbsc](https://github.com/jlerbsc)) +* Fixed missing permits in pretty printer (PR [#4091](https://github.com/javaparser/javaparser/pull/4091) by [@Auties00](https://github.com/Auties00)) + +### Developer Changes + +* chore(deps): update actions/checkout action to v3.6.0 (PR [#4127](https://github.com/javaparser/javaparser/pull/4127) by [@renovate[bot]](https://github.com/apps/renovate)) +* chore(deps): bump com.google.guava:guava from 32.1.1-jre to 32.1.2-jre (PR [#4109](https://github.com/javaparser/javaparser/pull/4109) by [@dependabot[bot]](https://github.com/apps/dependabot)) + +### Uncategorised + +* Fix: issue 4104 LPP doesn't handle new switch entries well (PR [#4106](https://github.com/javaparser/javaparser/pull/4106) by [@jlerbsc](https://github.com/jlerbsc)) + +### :heart: Contributors + +Thank You to all contributors who worked on this release! + +* [@freya022](https://github.com/freya022) +* [@Auties00](https://github.com/Auties00) +* [@mahesh-hegde](https://github.com/mahesh-hegde) +* [@jlerbsc](https://github.com/jlerbsc) +* [@70825](https://github.com/70825) + + +Version 3.25.4 +-------------- +[issues resolved](https://github.com/javaparser/javaparser/milestone/200?closed=1) + +### Changed + +* Nested 'if' statements should be simplified (PR [#4085](https://github.com/javaparser/javaparser/pull/4085) by [@jlerbsc](https://github.com/jlerbsc)) +* BDD tests: migarte to JBehave 5 (PR [#4028](https://github.com/javaparser/javaparser/pull/4028) by [@valfirst](https://github.com/valfirst)) + +### Fixed + +* Fix: issue 4077 After building JavaParser (with tests) on MacOS multi… (PR [#4086](https://github.com/javaparser/javaparser/pull/4086) by [@jlerbsc](https://github.com/jlerbsc)) +* fix line separators of selected test files (PR [#4083](https://github.com/javaparser/javaparser/pull/4083) by [@abego](https://github.com/abego)) +* Fix: issue 3978 typesolver can't parse in parallel (PR [#4073](https://github.com/javaparser/javaparser/pull/4073) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix #4056 isDeclaredInInterface() returns true for fields declared inside enumerations contained in an interface (PR [#4057](https://github.com/javaparser/javaparser/pull/4057) by [@Elewyth](https://github.com/Elewyth)) +* Fix: issue 4037 ArrayIndexOutOfBoundsException throws when method param is variadic (PR [#4046](https://github.com/javaparser/javaparser/pull/4046) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue 4016 Failed to parse variable with name 'sealed' or 'permits' (PR [#4039](https://github.com/javaparser/javaparser/pull/4039) by [@jlerbsc](https://github.com/jlerbsc)) + +### Developer Changes + +* chore(deps): bump guava from 32.1.0-jre to 32.1.1-jre (PR [#4089](https://github.com/javaparser/javaparser/pull/4089) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump guava from 32.0.0-jre to 32.1.0-jre (PR [#4087](https://github.com/javaparser/javaparser/pull/4087) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump checkstyle from 10.12.0 to 10.12.1 (PR [#4084](https://github.com/javaparser/javaparser/pull/4084) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump versions-maven-plugin from 2.15.0 to 2.16.0 (PR [#4055](https://github.com/javaparser/javaparser/pull/4055) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump maven-release-plugin from 3.0.0 to 3.0.1 (PR [#4053](https://github.com/javaparser/javaparser/pull/4053) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump guava from 31.1-jre to 32.0.0-jre (PR [#4042](https://github.com/javaparser/javaparser/pull/4042) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump maven-dependency-plugin from 3.5.0 to 3.6.0 (PR [#4035](https://github.com/javaparser/javaparser/pull/4035) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump maven-checkstyle-plugin from 3.2.2 to 3.3.0 (PR [#4033](https://github.com/javaparser/javaparser/pull/4033) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump maven-scm-plugin from 2.0.0 to 2.0.1 (PR [#4031](https://github.com/javaparser/javaparser/pull/4031) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump codecov/codecov-action from 3.1.3 to 3.1.4 (PR [#4030](https://github.com/javaparser/javaparser/pull/4030) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump build-helper-maven-plugin from 3.3.0 to 3.4.0 (PR [#4026](https://github.com/javaparser/javaparser/pull/4026) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): update dependency maven to v3.9.2 (PR [#4024](https://github.com/javaparser/javaparser/pull/4024) by [@renovate[bot]](https://github.com/apps/renovate)) + +### :heart: Contributors + +Thank You to all contributors who worked on this release! + +* [@valfirst](https://github.com/valfirst) +* [@abego](https://github.com/abego) +* [@Elewyth](https://github.com/Elewyth) +* [@jlerbsc](https://github.com/jlerbsc) + + Version 3.25.3 -------------- [issues resolved](https://github.com/javaparser/javaparser/milestone/199?closed=1) + +### Added + +* add Java 17 sealed/non-sealed classes (PR [#3997](https://github.com/javaparser/javaparser/pull/3997) by [@kris-scheibe](https://github.com/kris-scheibe)) + ### Changed * Minor simplification of the Difference class (PR [#4008](https://github.com/javaparser/javaparser/pull/4008) by [@jlerbsc](https://github.com/jlerbsc)) diff --git a/javaparser-core-generators/pom.xml b/javaparser-core-generators/pom.xml index 5026710358..74cbfed6e0 100644 --- a/javaparser-core-generators/pom.xml +++ b/javaparser-core-generators/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/utils/CodeUtils.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/utils/CodeUtils.java index 7f002d241e..a9d537c215 100644 --- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/utils/CodeUtils.java +++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/utils/CodeUtils.java @@ -49,10 +49,9 @@ private CodeUtils() { public static String castValue(String value, Type requiredType, String valueType) { String requiredTypeName = requiredType.asString(); - if (requiredTypeName.equals(valueType)) - return value; - else - return String.format("(%s) %s", requiredTypeName, value); + if (requiredTypeName.equals(valueType)) + return value; + return String.format("(%s) %s", requiredTypeName, value); } } diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java index 8c75799f1a..9169b3b755 100644 --- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java +++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java @@ -62,8 +62,8 @@ protected void generateVisitMethodBody(BaseNodeMetaModel node, MethodDeclaration if (propertyMetaModels.size() == 1) { builder.append("0"); break; - } else - continue; + } + continue; } // Is this field another AST node? Visit it. if (field.getNodeReference().isPresent()) { diff --git a/javaparser-core-metamodel-generator/pom.xml b/javaparser-core-metamodel-generator/pom.xml index 192c0d5df4..4040390a58 100644 --- a/javaparser-core-metamodel-generator/pom.xml +++ b/javaparser-core-metamodel-generator/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-core-serialization/pom.xml b/javaparser-core-serialization/pom.xml index b240d7489b..476d1fdfe5 100644 --- a/javaparser-core-serialization/pom.xml +++ b/javaparser-core-serialization/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-core-testing-bdd/pom.xml b/javaparser-core-testing-bdd/pom.xml index beaea91e21..38559c5b9c 100644 --- a/javaparser-core-testing-bdd/pom.xml +++ b/javaparser-core-testing-bdd/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 @@ -119,13 +119,13 @@ org.jbehave jbehave-core - 4.8.3 + 5.1.1 test - com.github.valfirst - jbehave-junit-runner - 2.3.2 + org.hamcrest + hamcrest + 2.2 test diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java index 73a32da063..eb91df2479 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java @@ -22,12 +22,12 @@ package com.github.javaparser; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; import org.jbehave.core.configuration.Configuration; import org.jbehave.core.configuration.MostUsefulConfiguration; import org.jbehave.core.failures.FailingUponPendingStep; import org.jbehave.core.io.LoadFromClasspath; import org.jbehave.core.io.StoryFinder; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.junit.JUnitStories; import org.jbehave.core.reporters.Format; import org.jbehave.core.reporters.StoryReporterBuilder; @@ -42,7 +42,7 @@ abstract class BasicJBehaveTest extends JUnitStories { BasicJBehaveTest(String storiesPath) { this.storiesPath = storiesPath; - JUnitReportingRunner.recommendedControls(configuredEmbedder()); + JUnit4StoryRunner.recommendedControls(configuredEmbedder()); } @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java index 737f56e57f..9a1a54b3e7 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java @@ -22,12 +22,12 @@ package com.github.javaparser; import com.github.javaparser.steps.CommentParsingSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class CommentParsingTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java index 37d4f83cf0..49b9067a3c 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java @@ -23,7 +23,7 @@ import com.github.javaparser.steps.ComparingSteps; import com.github.javaparser.steps.SharedSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class ComparingTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java index 7d00606718..b9637fa05d 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java @@ -23,7 +23,7 @@ import com.github.javaparser.steps.ManipulationSteps; import com.github.javaparser.steps.SharedSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class ManipulationTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java index 044c9fd93d..6cd778dc49 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java @@ -23,7 +23,7 @@ import com.github.javaparser.steps.ParsingSteps; import com.github.javaparser.steps.SharedSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class ParsingTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java index 32753e6f4e..abd183069d 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java @@ -23,7 +23,7 @@ import com.github.javaparser.steps.PositionRangeSteps; import com.github.javaparser.steps.SharedSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class PositionRangeTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java index 2968185abe..a2e9101d12 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java @@ -22,12 +22,12 @@ package com.github.javaparser; import com.github.javaparser.steps.PrettyPrintingSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class PrettyPrintingTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java index aee1441f6e..6d3c03887e 100644 --- a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java +++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java @@ -23,7 +23,7 @@ import com.github.javaparser.steps.SharedSteps; import com.github.javaparser.steps.VisitorSteps; -import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner; +import org.jbehave.core.junit.JUnit4StoryRunner; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.junit.runner.RunWith; @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -@RunWith(JUnitReportingRunner.class) +@RunWith(JUnit4StoryRunner.class) public class VisitorTest extends BasicJBehaveTest { @Override diff --git a/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story index a55d6af5fe..c3724cedea 100644 --- a/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story +++ b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story @@ -158,7 +158,7 @@ Then class 1 has 4 total contained comments Then class 1 has 1 orphan comment Then class 1 orphan comment 1 is "Case 1" Then field 1 in class 1 contains 0 comments -!--Then field 2 in class 1 contains 0 comments +!-- Then field 2 in class 1 contains 0 comments Then field 1 in class 1 is commented "field1" Then field 2 in class 1 is commented "Case 2" Then variable 1 value of field 2 in class 1 is commented "field2" @@ -180,7 +180,7 @@ When the class is parsed by the Java parser Then the compilation unit has 2 contained comments Then class 1 has 2 total contained comments Then field 1 in class 1 contains 0 comments -!--Then field 2 in class 1 contains 0 comments +!-- Then field 2 in class 1 contains 0 comments Then field 1 in class 1 is commented "field1" Then variable 1 value of field 2 in class 1 is commented "field2" diff --git a/javaparser-core-testing/pom.xml b/javaparser-core-testing/pom.xml index 3a053e7da7..cef19e1e08 100644 --- a/javaparser-core-testing/pom.xml +++ b/javaparser-core-testing/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java index 7c43f42436..0d7fc9fb97 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java @@ -21,6 +21,22 @@ package com.github.javaparser; +import static com.github.javaparser.ParseStart.COMPILATION_UNIT; +import static com.github.javaparser.ParserConfiguration.LanguageLevel.BLEEDING_EDGE; +import static com.github.javaparser.ParserConfiguration.LanguageLevel.CURRENT; +import static com.github.javaparser.Providers.provider; +import static com.github.javaparser.Range.range; +import static com.github.javaparser.StaticJavaParser.*; +import static com.github.javaparser.utils.TestUtils.assertInstanceOf; +import static com.github.javaparser.utils.Utils.SYSTEM_EOL; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Optional; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.AnnotationMemberDeclaration; @@ -34,21 +50,6 @@ import com.github.javaparser.ast.type.IntersectionType; import com.github.javaparser.ast.type.Type; import com.github.javaparser.printer.YamlPrinter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Optional; - -import static com.github.javaparser.ParseStart.COMPILATION_UNIT; -import static com.github.javaparser.ParserConfiguration.LanguageLevel.BLEEDING_EDGE; -import static com.github.javaparser.ParserConfiguration.LanguageLevel.CURRENT; -import static com.github.javaparser.Providers.provider; -import static com.github.javaparser.Range.range; -import static com.github.javaparser.StaticJavaParser.*; -import static com.github.javaparser.utils.TestUtils.assertInstanceOf; -import static com.github.javaparser.utils.Utils.SYSTEM_EOL; -import static org.junit.jupiter.api.Assertions.*; class JavaParserTest { @@ -142,7 +143,7 @@ void parseErrorContainsLocation() { Problem problem = result.getProblem(0); assertEquals(range(1, 9, 1, 17), problem.getLocation().get().toRange().get()); - assertEquals("Parse error. Found , expected one of \";\" \"<\" \"@\" \"abstract\" \"boolean\" \"byte\" \"char\" \"class\" \"default\" \"double\" \"enum\" \"exports\" \"final\" \"float\" \"int\" \"interface\" \"long\" \"module\" \"native\" \"non-sealed\" \"open\" \"opens\" \"private\" \"protected\" \"provides\" \"public\" \"record\" \"requires\" \"sealed\" \"short\" \"static\" \"strictfp\" \"synchronized\" \"to\" \"transient\" \"transitive\" \"uses\" \"void\" \"volatile\" \"with\" \"yield\" \"{\" \"}\" ", problem.getMessage()); + assertEquals("Parse error. Found , expected one of \";\" \"<\" \"@\" \"abstract\" \"boolean\" \"byte\" \"char\" \"class\" \"default\" \"double\" \"enum\" \"exports\" \"final\" \"float\" \"int\" \"interface\" \"long\" \"module\" \"native\" \"non-sealed\" \"open\" \"opens\" \"permits\" \"private\" \"protected\" \"provides\" \"public\" \"record\" \"requires\" \"sealed\" \"short\" \"static\" \"strictfp\" \"synchronized\" \"to\" \"transient\" \"transitive\" \"uses\" \"void\" \"volatile\" \"with\" \"yield\" \"{\" \"}\" ", problem.getMessage()); assertInstanceOf(ParseException.class, problem.getCause().get()); } diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java index c6f2e309bf..ebc08dae01 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java @@ -21,12 +21,6 @@ package com.github.javaparser.ast; -import com.github.javaparser.JavaParser; -import com.github.javaparser.ParseResult; -import com.github.javaparser.ParserConfiguration; -import com.github.javaparser.Problem; -import org.junit.jupiter.api.Test; - import static com.github.javaparser.ParseStart.COMPILATION_UNIT; import static com.github.javaparser.Providers.provider; import static com.github.javaparser.ast.Node.Parsedness.PARSED; @@ -34,6 +28,13 @@ import static com.github.javaparser.utils.Utils.SYSTEM_EOL; import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParseResult; +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.Problem; + class ParseResultTest { private final JavaParser javaParser = new JavaParser(new ParserConfiguration()); @@ -57,7 +58,7 @@ void whenParsingFailsThenWeGetProblemsAndABadResult() { assertThat(result.getProblems().size()).isEqualTo(1); Problem problem = result.getProblem(0); - assertThat(problem.getMessage()).isEqualTo("Parse error. Found \"{\", expected one of \"enum\" \"exports\" \"module\" \"open\" \"opens\" \"provides\" \"record\" \"requires\" \"strictfp\" \"to\" \"transitive\" \"uses\" \"with\" \"yield\" "); + assertThat(problem.getMessage()).isEqualTo("Parse error. Found \"{\", expected one of \"enum\" \"exports\" \"module\" \"open\" \"opens\" \"permits\" \"provides\" \"record\" \"requires\" \"sealed\" \"strictfp\" \"to\" \"transitive\" \"uses\" \"with\" \"yield\" "); assertThat(result.toString()).startsWith("Parsing failed:" + SYSTEM_EOL + "(line 1,col 1) Parse error."); } diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java index a1bed1c52a..89da70cefb 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java @@ -21,17 +21,19 @@ package com.github.javaparser.ast.body; +import static com.github.javaparser.StaticJavaParser.parse; +import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.opentest4j.AssertionFailedError; + import com.github.javaparser.ParserConfiguration; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier; import com.github.javaparser.utils.TestParser; -import org.junit.jupiter.api.Test; - -import static com.github.javaparser.StaticJavaParser.parse; -import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; class ClassOrInterfaceDeclarationTest { @Test @@ -109,4 +111,36 @@ void nonSealedClass() { assertTrue(x.hasModifier(Modifier.Keyword.NON_SEALED)); } + @ParameterizedTest + @EnumSource(value = ParserConfiguration.LanguageLevel.class, names = {"JAVA_8","JAVA_9","JAVA_10","JAVA_11","JAVA_12","JAVA_13","JAVA_14", "JAVA_15", "JAVA_16"}) + void sealedFieldNamePermitted(ParserConfiguration.LanguageLevel languageLevel) { + assertDoesNotThrow(() -> { + TestParser.parseVariableDeclarationExpr(languageLevel, "boolean sealed"); + }); + } + + @ParameterizedTest + @EnumSource(value = ParserConfiguration.LanguageLevel.class, names = {"JAVA_17"}) + void sealedFieldNameNotPermitted(ParserConfiguration.LanguageLevel languageLevel) { + assertThrows(AssertionFailedError.class, () -> { + TestParser.parseVariableDeclarationExpr(languageLevel, "boolean sealed"); + }); + } + + @ParameterizedTest + @EnumSource(value = ParserConfiguration.LanguageLevel.class, names = {"JAVA_8","JAVA_9","JAVA_10","JAVA_11","JAVA_12","JAVA_13","JAVA_14", "JAVA_15", "JAVA_16"}) + void permitsFieldNamePermitted(ParserConfiguration.LanguageLevel languageLevel) { + assertDoesNotThrow(() -> { + TestParser.parseVariableDeclarationExpr(languageLevel, "boolean permits"); + }); + } + + @ParameterizedTest + @EnumSource(value = ParserConfiguration.LanguageLevel.class, names = {"JAVA_17"}) + void permitsFieldNameNotPermitted(ParserConfiguration.LanguageLevel languageLevel) { + assertThrows(AssertionFailedError.class, () -> { + TestParser.parseVariableDeclarationExpr(languageLevel, "boolean permits"); + }); + } + } diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java index d2c2369ca8..96e9d8e63f 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java @@ -21,6 +21,7 @@ package com.github.javaparser.ast.body; +import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.Modifier.Keyword; @@ -30,8 +31,7 @@ import static com.github.javaparser.StaticJavaParser.parse; import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class FieldDeclarationTest { @Test @@ -100,4 +100,32 @@ void interfaceFieldTest() { } } + /** + * Regression test for issue #4056. + */ + @Test + void testEnumWithPrivateFieldInsideInterface() { + String source = "interface Outer {\n" + + " enum Numbers {\n" + + " ONE(1),\n" + + " TWO(2),\n" + + " THREE(3);\n" + + "\n" + + " Numbers(int i) {\n" + + " this.i = i;\n" + + " }\n" + + "\n" + + " private int i;\n" + + " }\n" + + "}"; + CompilationUnit cu = StaticJavaParser.parse(source); + FieldDeclaration i = cu.getTypes().get(0).asClassOrInterfaceDeclaration() + .getMembers().get(0).asEnumDeclaration() + .getFields().get(0); + assertAll( + () -> assertFalse(i.isPublic()), + () -> assertFalse(i.isStatic()), + () -> assertFalse(i.isFinal()) + ); + } } diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java index 1c57a9f405..c478786b2a 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java @@ -21,6 +21,15 @@ package com.github.javaparser.printer; +import static com.github.javaparser.StaticJavaParser.parse; +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; +import static com.github.javaparser.utils.Utils.SYSTEM_EOL; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; + import com.github.javaparser.ParserConfiguration; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; @@ -38,14 +47,6 @@ import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration.ConfigOption; import com.github.javaparser.printer.configuration.PrinterConfiguration; import com.github.javaparser.utils.TestParser; -import org.junit.jupiter.api.Test; - -import java.util.Optional; - -import static com.github.javaparser.StaticJavaParser.parse; -import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; -import static com.github.javaparser.utils.Utils.SYSTEM_EOL; -import static org.junit.jupiter.api.Assertions.assertEquals; class PrettyPrintVisitorTest extends TestParser { @@ -521,4 +522,18 @@ void innerClassWithConstructorReceiverParameterTest() { CompilationUnit cu = parseCompilationUnit(innerClassWithConstructorReceiverParam); assertEqualsStringIgnoringEol(innerClassWithConstructorReceiverParam, print(cu)); } + + @Test + void printPermitsKeyworld() { + CompilationUnit cu = parseCompilationUnit( + ParserConfiguration.LanguageLevel.JAVA_17, + "public sealed interface I1 permits I2, C, D {}" + ); + String expected = + "public sealed interface I1 permits I2, C, D {\n" + + "}\n"; + + + assertEqualsStringIgnoringEol(expected, cu.toString()); + } } diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue4104Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue4104Test.java new file mode 100755 index 0000000000..4498b777e0 --- /dev/null +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue4104Test.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.printer.lexicalpreservation; + +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.expr.IntegerLiteralExpr; +import com.github.javaparser.ast.stmt.BreakStmt; +import com.github.javaparser.ast.stmt.SwitchEntry; +import com.github.javaparser.ast.stmt.SwitchStmt; + +public class Issue4104Test extends AbstractLexicalPreservingTest { + + @Test + void test() { + considerCode( + "class Foo {\n" + + " void foo() {\n" + + " switch(bar) {\n" + + " default:\n" + + " break;\n" + + " }\n" + + " }\n" + + "}"); + // should be this +// String expected = +// "class Foo {\n" +// + " void foo() {\n" +// + " switch(bar) {\n" +// + " default:\n" +// + " break;\n" +// + " case 0:\n" +// + " break;\n" +// + " }\n" +// + " }\n" +// + "}"; + + String expected = + "class Foo {\n" + + " void foo() {\n" + + " switch(bar) {\n" + + " default:\n" + + " break;\n" + + " case 0:\n" + + " break;\n" + + " }\n" + + " }\n" + + "}"; + + SwitchStmt switchStmt = cu.findAll(SwitchStmt.class).stream().findFirst().get(); + + SwitchEntry newEntry = new SwitchEntry(); + newEntry.setLabels(NodeList.nodeList(new IntegerLiteralExpr(0))); + newEntry.setStatements(NodeList.nodeList(new BreakStmt())); + switchStmt.getEntries().addLast(newEntry); + + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } +} diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java index 94db84c39c..48366704b3 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java @@ -21,11 +21,24 @@ package com.github.javaparser.printer.lexicalpreservation; +import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType; +import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC; +import static com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter.NODE_TEXT_DATA; +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; +import static com.github.javaparser.utils.Utils.SYSTEM_EOL; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + import com.github.javaparser.GeneratedJavaParserConstants; import com.github.javaparser.JavaParser; import com.github.javaparser.ParserConfiguration; import com.github.javaparser.StaticJavaParser; -import com.github.javaparser.ParserConfiguration.LanguageLevel; import com.github.javaparser.ast.*; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.comments.LineComment; @@ -37,19 +50,6 @@ import com.github.javaparser.ast.visitor.ModifierVisitor; import com.github.javaparser.ast.visitor.Visitable; import com.github.javaparser.utils.TestUtils; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType; -import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC; -import static com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter.NODE_TEXT_DATA; -import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; -import static com.github.javaparser.utils.Utils.SYSTEM_EOL; -import static org.junit.jupiter.api.Assertions.*; class LexicalPreservingPrinterTest extends AbstractLexicalPreservingTest { private NodeText getTextForNode(Node node) { @@ -1742,6 +1742,86 @@ void removedIndentationJavaDocCommentsPrinted() { assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); } + @Test + void addingOrphanCommentToType() { + String actual = + "public class Foo {\n" + + "}" ; + + String expected = + "//added comment\n" + + "public class Foo {\n" + + "}"; + + considerCode(actual); + cu.getTypes().get(0).addOrphanComment(new LineComment("added comment")); + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } + + @Test + void addingOrphanCommentToBlock() { + String actual = + "public class Foo {\n" + + "}" ; + + String expected = + "//added comment\n" + + "public class Foo {\n" + + "}"; + + considerCode(actual); + cu.getTypes().get(0).getChildNodes().get(0).addOrphanComment(new LineComment("added comment")); + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } + + @Test + void addingOrphanCommentToBlockInMethodDeclaration() { + String actual = + "public class Foo {\n" + + " boolean m() {\n" + + " return true;\n" + + " }\n" + + "}" ; + + // that's probably not what we want, + // but this is what is implemented in LexicalPreservingPrinter.Observer.concretePropertyChange(..) + String expected = + "public class Foo {\n" + + " boolean m() //added comment\n" + + "{\n" + + " return true;\n" + + " }\n" + + "}"; + + considerCode(actual); + cu.findAll(BlockStmt.class).get(0).addOrphanComment(new LineComment("added comment")); + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } + + @Test + void addingOrphanCommentToBlockInMethodDeclaration2() { + String actual = + "public class Foo {\n" + + " boolean m() \n" + + " {\n" + + " return true;\n" + + " }\n" + + "}" ; + + String expected = + "public class Foo {\n" + + " boolean m() \n" + + " //added comment\n" + + " {\n" + + " return true;\n" + + " }\n" + + "}"; + + considerCode(actual); + cu.findAll(BlockStmt.class).get(0).addOrphanComment(new LineComment("added comment")); + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } + // issue 3800 determine whether active @Test void checkLPPIsAvailableOnNode() { diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/PeekingIteratorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/PeekingIteratorTest.java new file mode 100755 index 0000000000..3e77c97a95 --- /dev/null +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/PeekingIteratorTest.java @@ -0,0 +1,126 @@ +package com.github.javaparser.printer.lexicalpreservation; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; + +import org.junit.jupiter.api.*; + +class PeekingIteratorTest { + + private static final List EMPTY_LIST = new ArrayList(); + + private static List NON_EMPTY_LIST ; + + private PeekingIterator peekingIterator; + + @BeforeAll + static void setUpBeforeClass() throws Exception { + } + + @AfterAll + static void tearDownAfterClass() throws Exception { + } + + @BeforeEach + void setUp() throws Exception { + NON_EMPTY_LIST = Arrays.asList("A", "B", "C"); + } + + @AfterEach + void tearDown() throws Exception { + } + + @Test + void testHasNext() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertFalse(peekingIterator.hasNext()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertTrue(peekingIterator.hasNext()); + } + + @Test + void testPeek() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertEquals(null, peekingIterator.peek()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertEquals("A", peekingIterator.peek()); + assertEquals("A", peekingIterator.next()); + } + + @Test + void testElement() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertEquals(null, peekingIterator.peek()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertEquals("A", peekingIterator.peek()); + assertEquals(1, peekingIterator.nextIndex()); + } + + @Test + void testNext() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertThrows(NoSuchElementException.class, () -> peekingIterator.next()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertEquals("A", peekingIterator.next()); + } + + @Test + void testRemove() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertThrows(IllegalStateException.class, () -> peekingIterator.remove()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertThrows(IllegalStateException.class, () -> peekingIterator.remove()); + String result = peekingIterator.next(); + assertThrows(UnsupportedOperationException.class, () -> peekingIterator.remove()); + } + + @Test + void testHasPrevious() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertFalse(peekingIterator.hasPrevious()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertFalse(peekingIterator.hasPrevious()); + String result = peekingIterator.next(); + assertTrue(peekingIterator.hasPrevious()); + } + + @Test + void testPrevious() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertThrows(NoSuchElementException.class, () -> peekingIterator.previous()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertThrows(NoSuchElementException.class, () -> peekingIterator.previous()); + } + + @Test + void testNextIndex() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertEquals(0, peekingIterator.nextIndex()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertEquals(0, peekingIterator.nextIndex()); + } + + @Test + void testPreviousIndex() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertEquals(-1, peekingIterator.previousIndex()); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertEquals(-1, peekingIterator.previousIndex()); + } + + @Test + void testSet() { + peekingIterator = new PeekingIterator(EMPTY_LIST.listIterator()); + assertThrows(IllegalStateException.class, () -> peekingIterator.set("D")); + peekingIterator = new PeekingIterator(NON_EMPTY_LIST.listIterator()); + assertThrows(IllegalStateException.class, () -> peekingIterator.set("D")); + peekingIterator.next(); + peekingIterator.set("D"); + assertEquals(3, NON_EMPTY_LIST.size()); + } + +} diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java index c8a7f60301..6d47658418 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java @@ -21,14 +21,7 @@ package com.github.javaparser.utils; -import com.github.javaparser.ParseProblemException; -import com.github.javaparser.ParseResult; -import com.github.javaparser.ParserConfiguration; -import com.github.javaparser.ast.CompilationUnit; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; +import static org.junit.jupiter.api.Assertions.*; import java.io.IOException; import java.nio.file.Files; @@ -36,15 +29,30 @@ import java.nio.file.Paths; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import com.github.javaparser.ParseProblemException; +import com.github.javaparser.ParseResult; +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.printer.DefaultPrettyPrinter; +import com.github.javaparser.printer.Printer; +import com.github.javaparser.printer.configuration.DefaultConfigurationOption; +import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration.ConfigOption; class SourceRootTest { private final Path root = CodeGenerationUtils.mavenModuleRoot(SourceRootTest.class).resolve("src/test/resources/com/github/javaparser/utils/"); private final SourceRoot sourceRoot = new SourceRoot(root); + private Printer printer; @BeforeEach void before() { sourceRoot.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.BLEEDING_EDGE); + printer = new DefaultPrettyPrinter(); + sourceRoot.setPrinter(printer::print); } @Test @@ -59,11 +67,13 @@ void parseTestDirectory() throws IOException { @Test void saveInCallback() throws IOException { + printer.getConfiguration().addOption(new DefaultConfigurationOption(ConfigOption.END_OF_LINE_CHARACTER, LineSeparator.LF.asRawString())); sourceRoot.parse("", sourceRoot.getParserConfiguration(), (localPath, absolutePath, result) -> SourceRoot.Callback.Result.SAVE); } @Test void saveInCallbackParallelized() { + printer.getConfiguration().addOption(new DefaultConfigurationOption(ConfigOption.END_OF_LINE_CHARACTER, LineSeparator.LF.asRawString())); sourceRoot.parseParallelized("", sourceRoot.getParserConfiguration(), ((localPath, absolutePath, result) -> SourceRoot.Callback.Result.SAVE)); } diff --git a/javaparser-core/pom.xml b/javaparser-core/pom.xml index ef836fb6ef..fadd6ab72f 100644 --- a/javaparser-core/pom.xml +++ b/javaparser-core/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java b/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java index f3ae005dba..b3a4b33035 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java +++ b/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java @@ -97,17 +97,14 @@ private static List cleanLines(String content) { int asteriskIndex = startsWithAsterisk(l); if (asteriskIndex == -1) { return l; - } else { - // if a line starts with space followed by an asterisk drop to the asterisk - // if there is a space immediately after the asterisk drop it also - if (l.length() > (asteriskIndex + 1)) { + } + if (l.length() > (asteriskIndex + 1)) { char c = l.charAt(asteriskIndex + 1); if (c == ' ' || c == '\t') { return l.substring(asteriskIndex + 2); } } - return l.substring(asteriskIndex + 1); - } + return l.substring(asteriskIndex + 1); }).collect(Collectors.toList()); // lines containing only whitespace are normalized to empty lines cleanedLines = cleanedLines.stream().map(l -> l.trim().isEmpty() ? "" : l).collect(Collectors.toList()); @@ -129,15 +126,14 @@ private static List cleanLines(String content) { static int startsWithAsterisk(String line) { if (line.startsWith("*")) { return 0; - } else if ((line.startsWith(" ") || line.startsWith("\t")) && line.length() > 1) { + } + if ((line.startsWith(" ") || line.startsWith("\t")) && line.length() > 1) { int res = startsWithAsterisk(line.substring(1)); if (res == -1) { return -1; - } else { - return 1 + res; } - } else { - return -1; + return 1 + res; } + return -1; } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/LineEndingProcessingProvider.java b/javaparser-core/src/main/java/com/github/javaparser/LineEndingProcessingProvider.java index a9d4c3763a..9be75cdf30 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/LineEndingProcessingProvider.java +++ b/javaparser-core/src/main/java/com/github/javaparser/LineEndingProcessingProvider.java @@ -115,13 +115,12 @@ public int read(char[] buffer, final int offset, int len) throws IOException { if (pos == offset) { // Nothing read yet, this is the end of the stream. return EOF; - } else { - break; } - } else { - String str = String.valueOf((char) ch); - Optional lookup = LineSeparator.lookup(str); - if (lookup.isPresent()) { + break; + } + String str = String.valueOf((char) ch); + Optional lookup = LineSeparator.lookup(str); + if (lookup.isPresent()) { LineSeparator lineSeparator = lookup.get(); // Track the number of times this character is found.. eolCounts.putIfAbsent(lineSeparator, 0); @@ -140,9 +139,7 @@ public int read(char[] buffer, final int offset, int len) throws IOException { // If "this" (current) char is not a line separator, set the next loop's "previous" to null previousLineSeparator = null; } - // Move to next character - buffer[pos++] = (char) ch; - } + buffer[pos++] = (char) ch; } return pos - offset; } diff --git a/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java b/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java index de5be427cf..c6dd55f7f7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java +++ b/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java @@ -99,13 +99,11 @@ public int read(char[] buffer, final int offset, int len) throws IOException { if (pos == offset) { // Nothing read yet, this is the end of the stream. return EOF; - } else { - break; } - } else { - _mappingBuilder.update(); - buffer[pos++] = (char) ch; + break; } + _mappingBuilder.update(); + buffer[pos++] = (char) ch; } return pos - offset; } @@ -129,9 +127,8 @@ private int nextOutputChar() throws IOException { { if (_backslashSeen) { return clearBackSlashSeen(next); - } else { - return backSlashSeen(); } + return backSlashSeen(); } default: { @@ -348,17 +345,13 @@ public PositionUpdate lookup(Position position) { int result = Collections.binarySearch(_deltas, position); if (result >= 0) { return _deltas.get(result); - } else { - int insertIndex = -result - 1; - if (insertIndex == 0) { + } + int insertIndex = -result - 1; + if (insertIndex == 0) { // Before the first delta info, identity mapping. return PositionUpdate.NONE; - } else { - // The relevant update is the one with the position smaller - // than the requested position. - return _deltas.get(insertIndex - 1); } - } + return _deltas.get(insertIndex - 1); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java b/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java index 7f2a18dc03..18bcb081d1 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/CompilationUnit.java @@ -302,10 +302,8 @@ private boolean isImplicitImport(ImportDeclaration importDeclaration) { return currentPackageName.equals(importPackageName.get()); } return false; - } else { - // imports of unnamed package are not allowed - return true; } + return true; } private static Optional getImportPackageName(ImportDeclaration importDeclaration) { @@ -397,9 +395,9 @@ public CompilationUnit addImport(Class clazz) { if (clazz.isArray()) { return addImport(clazz.getComponentType()); } - if (ClassUtils.isPrimitiveOrWrapper(clazz) || JAVA_LANG.equals(clazz.getPackage().getName())) + if (ClassUtils.isPrimitiveOrWrapper(clazz) || JAVA_LANG.equals(clazz.getPackage().getName())) return this; - else if (clazz.isAnonymousClass() || clazz.isLocalClass()) + if (clazz.isAnonymousClass() || clazz.isLocalClass()) throw new IllegalArgumentException(clazz.getName() + " is an anonymous or local class therefore it can't be added with addImport"); return addImport(clazz.getCanonicalName()); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java index fc788cd916..21441ab9d6 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java @@ -86,6 +86,14 @@ public static Modifier transitiveModifier() { return new Modifier(Keyword.TRANSITIVE); } + public static Modifier sealedModifier() { + return new Modifier(Keyword.SEALED); + } + + public static Modifier nonSealedModifier() { + return new Modifier(Keyword.NON_SEALED); + } + /** * The Java modifier keywords. */ diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java index d13fbc7fcc..b4fdaa020f 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java @@ -366,6 +366,7 @@ public List getChildNodes() { } public void addOrphanComment(Comment comment) { + notifyPropertyChange(ObservableProperty.COMMENT, null, comment); orphanComments.add(comment); comment.setParentNode(this); } @@ -793,9 +794,8 @@ public SymbolResolver getSymbolResolver() { return findCompilationUnit().map(cu -> { if (cu.containsData(SYMBOL_RESOLVER_KEY)) { return cu.getData(SYMBOL_RESOLVER_KEY); - } else { - throw new IllegalStateException("Symbol resolution not configured: to configure consider setting a SymbolResolver in the ParserConfiguration"); } + throw new IllegalStateException("Symbol resolution not configured: to configure consider setting a SymbolResolver in the ParserConfiguration"); }).orElseThrow(() -> new IllegalStateException("The node is not inserted in a CompilationUnit")); } @@ -1116,15 +1116,14 @@ public Node next() { Node node = nodes.get(cursor); fillStackToLeaf(node); return nextFromLevel(); - } else { - nodesStack.pop(); - cursorStack.pop(); - hasNext = !nodesStack.empty(); - if (hasNext) { + } + nodesStack.pop(); + cursorStack.pop(); + hasNext = !nodesStack.empty(); + if (hasNext) { return nextFromLevel(); } - return root; - } + return root; } private Node nextFromLevel() { diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java b/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java index 46c7b2b376..d78ed2ad5c 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java @@ -319,9 +319,8 @@ public T[] toArray(T[] a) { public boolean remove(Object o) { if (o instanceof Node) { return remove((Node) o); - } else { - return false; } + return false; } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java index 3c7cf1c49c..31b583b350 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java @@ -267,8 +267,12 @@ public boolean isPublic() { * Returns true if the field is declared in an interface */ private boolean isDeclaredInInterface() { - Optional parentClass = findAncestor(ClassOrInterfaceDeclaration.class); - return parentClass.map(parent -> parent.isInterface()).orElse(false); + Optional parentType = findAncestor(TypeDeclaration.class); + return parentType + .filter(BodyDeclaration::isClassOrInterfaceDeclaration) + .map(BodyDeclaration::asClassOrInterfaceDeclaration) + .map(ClassOrInterfaceDeclaration::isInterface) + .orElse(false); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java index 04e36db6a1..c91424de4c 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java @@ -143,15 +143,15 @@ public Node setComment(final Comment comment) { @Override public boolean remove() { - // the other are orphan comments and remove should work with them + if (this.commentedNode != null) { this.commentedNode.setComment(null); return true; - } else if (this.getParentNode().isPresent()) { + } + if (this.getParentNode().isPresent()) { return this.getParentNode().get().removeOrphanComment(this); - } else { - return false; } + return false; } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java index c8f9d8129f..2428dc468e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java @@ -141,9 +141,8 @@ public InstanceOfExpr(TokenRange tokenRange, Expression expression, ReferenceTyp public Optional getName() { if (pattern == null) { return Optional.empty(); - } else { - return Optional.of(pattern.getName()); } + return Optional.of(pattern.getName()); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java index 0180b24d5e..d86f6b2ab8 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java @@ -128,17 +128,11 @@ public int asInt() { * @return the literal value as a number while respecting different number representations */ public Number asNumber() { - /* - * we need to handle the special case for the literal 2147483648, which is used to - * represent Integer.MIN_VALUE (-2147483648) as a combination of a UnaryExpr and an - * IntegerLiteralExpr. However 2147483648 cannot be represented in an integer, so we - * need to return a long - */ + if (Objects.equals(value, MAX_31_BIT_UNSIGNED_VALUE_AS_STRING) && hasUnaryMinusAsParent(this)) { return MAX_31_BIT_UNSIGNED_VALUE_AS_LONG; - } else { - return asInt(); } + return asInt(); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java index 2413d74e45..95d46f00a5 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java @@ -208,9 +208,8 @@ public boolean remove(Node node) { public Optional getExpressionBody() { if (body.isExpressionStmt()) { return Optional.of(body.asExpressionStmt().getExpression()); - } else { - return Optional.empty(); } + return Optional.empty(); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java index 223b7f441c..c39062cc37 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java @@ -135,16 +135,11 @@ public long asLong() { * @return the literal value as a number while respecting different number representations */ public Number asNumber() { - /* we need to handle the special case for the literal 9223372036854775808L, which is used to - * represent Integer.MIN_VALUE (-9223372036854775808L) as a combination of a UnaryExpr and a - * LongLiteralExpr. However 9223372036854775808L cannot be represented in a long, so we need - * to return a BigInteger - */ + if (Objects.equals(value, MAX_63_BIT_UNSIGNED_VALUE_AS_STRING) && hasUnaryMinusAsParent(this)) { return MAX_63_BIT_UNSIGNED_VALUE_AS_BIG_INTEGER; - } else { - return asLong(); } + return asLong(); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java index 35fdc68cfe..c178f0b558 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java @@ -72,9 +72,8 @@ default N removeModifier(Modifier.Keyword... modifiersToRemove) { default N setModifier(Modifier.Keyword m, boolean set) { if (set) { return addModifier(m); - } else { - return removeModifier(m); } + return removeModifier(m); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java index 2f888cee1d..873961a139 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java @@ -159,9 +159,8 @@ public static ObservableProperty fromCamelCaseName(String camelCaseName) { Optional observableProperty = Arrays.stream(values()).filter(v -> v.camelCaseName().equals(camelCaseName)).findFirst(); if (observableProperty.isPresent()) { return observableProperty.get(); - } else { - throw new IllegalArgumentException("No property found with the given camel case name: " + camelCaseName); } + throw new IllegalArgumentException("No property found with the given camel case name: " + camelCaseName); } ObservableProperty(Type type) { @@ -207,16 +206,15 @@ public Node getValueAsSingleReference(Node node) { try { if (rawValue instanceof Node) { return (Node) rawValue; - } else if (rawValue instanceof Optional) { + } + if (rawValue instanceof Optional) { Optional opt = (Optional) rawValue; if (opt.isPresent()) { return opt.get(); - } else { - return null; } - } else { - throw new RuntimeException(String.format("Property %s returned %s (%s)", this.name(), rawValue.toString(), rawValue.getClass().getCanonicalName())); + return null; } + throw new RuntimeException(String.format("Property %s returned %s (%s)", this.name(), rawValue.toString(), rawValue.getClass().getCanonicalName())); } catch (ClassCastException e) { throw new RuntimeException(e); } @@ -239,14 +237,12 @@ public NodeList getValueAsMultipleReference(Node node) { } if (rawValue instanceof NodeList) { return (NodeList) rawValue; - } else { - Optional opt = (Optional) rawValue; - if (opt.isPresent()) { + } + Optional opt = (Optional) rawValue; + if (opt.isPresent()) { return opt.get(); - } else { - return null; } - } + return null; } catch (ClassCastException e) { throw new RuntimeException("Unable to get list value for " + this.name() + " from " + node + " (class: " + node.getClass().getSimpleName() + ")", e); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java index e3038dff55..6e36e68d67 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VarType.java @@ -183,8 +183,7 @@ private Optional forEachStmtWithVariableDeclarator( node = node.get().getParentNode(); if (!node.isPresent() || !(node.get() instanceof ForEachStmt)) { return Optional.empty(); - } else { - return Optional.of((ForEachStmt)node.get()); } + return Optional.of((ForEachStmt)node.get()); } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/language_level_validations/Java17Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/language_level_validations/Java17Validator.java index 256d49c1dc..f131ed3b11 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/language_level_validations/Java17Validator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/language_level_validations/Java17Validator.java @@ -20,6 +20,9 @@ */ package com.github.javaparser.ast.validator.language_level_validations; +import com.github.javaparser.ast.validator.ReservedKeywordValidator; +import com.github.javaparser.ast.validator.Validator; + /** * This validator validates according to Java 17 syntax rules. * @@ -27,10 +30,15 @@ */ public class Java17Validator extends Java16Validator { + final Validator sealedNotAllowedAsIdentifier = new ReservedKeywordValidator("sealed"); + final Validator permitsNotAllowedAsIdentifier = new ReservedKeywordValidator("permits"); + public Java17Validator() { super(); // Released Language Features // Sealed Classes - https://openjdk.java.net/jeps/409 + add(sealedNotAllowedAsIdentifier); + add(permitsNotAllowedAsIdentifier); remove(noSealedClasses); remove(noPermitsListInClasses); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java index f80297d23e..6e479243f7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/EqualsVisitor.java @@ -64,7 +64,8 @@ private boolean commonNodeEquality(Node n, Node n2) { private boolean nodesEquals(final List nodes1, final List nodes2) { if (nodes1 == null) { return nodes2 == null; - } else if (nodes2 == null) { + } + if (nodes2 == null) { return false; } if (nodes1.size() != nodes2.size()) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/DefaultPrettyPrinterVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/printer/DefaultPrettyPrinterVisitor.java index 60b93baee7..e5a181538e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/DefaultPrettyPrinterVisitor.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/DefaultPrettyPrinterVisitor.java @@ -302,6 +302,16 @@ public void visit(final ClassOrInterfaceDeclaration n, final Void arg) { } } } + if(!n.getPermittedTypes().isEmpty()){ + printer.print(" permits "); + for (final Iterator i = n.getPermittedTypes().iterator(); i.hasNext(); ) { + final ClassOrInterfaceType c = i.next(); + c.accept(this, arg); + if (i.hasNext()) { + printer.print(", "); + } + } + } printer.println(" {"); printer.indent(); if (!isNullOrEmpty(n.getMembers())) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java index fe32d335b4..6bebed3ba8 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrintVisitor.java @@ -310,6 +310,16 @@ public void visit(final ClassOrInterfaceDeclaration n, final Void arg) { } } } + if(!n.getPermittedTypes().isEmpty()){ + printer.print(" permits "); + for (final Iterator i = n.getPermittedTypes().iterator(); i.hasNext(); ) { + final ClassOrInterfaceType c = i.next(); + c.accept(this, arg); + if (i.hasNext()) { + printer.print(", "); + } + } + } printer.println(" {"); printer.indent(); if (!isNullOrEmpty(n.getMembers())) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmElement.java index a46ec56915..43cfaa8a34 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmElement.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmElement.java @@ -20,18 +20,19 @@ */ package com.github.javaparser.printer.concretesyntaxmodel; +import static com.github.javaparser.TokenTypes.eolTokenKind; +import static com.github.javaparser.TokenTypes.spaceTokenKind; + +import java.util.Arrays; +import java.util.List; + import com.github.javaparser.GeneratedJavaParserConstants; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.observer.ObservableProperty; import com.github.javaparser.printer.SourcePrinter; +import com.github.javaparser.printer.lexicalpreservation.TextElement; import com.github.javaparser.utils.LineSeparator; -import java.util.Arrays; -import java.util.List; - -import static com.github.javaparser.TokenTypes.eolTokenKind; -import static com.github.javaparser.TokenTypes.spaceTokenKind; - public interface CsmElement { void prettyPrint(Node node, SourcePrinter printer); @@ -72,10 +73,6 @@ static CsmElement token(int tokenType) { return new CsmToken(tokenType); } - static CsmElement token(int tokenType, CsmToken.TokenContentCalculator tokenContentCalculator) { - return new CsmToken(tokenType, tokenContentCalculator); - } - static CsmElement conditional(ObservableProperty property, CsmConditional.Condition condition, CsmElement thenElement) { return new CsmConditional(property, condition, thenElement); } @@ -152,4 +149,11 @@ static CsmElement unindent() { static CsmElement block(CsmElement content) { return sequence(token(GeneratedJavaParserConstants.LBRACE), indent(), content, unindent(), token(GeneratedJavaParserConstants.RBRACE)); } + + /* + * Verifies if the content of the {@code CsmElement} is the same as the provided {@code TextElement} + */ + default boolean isCorrespondingElement(TextElement textElement) { + return false; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmIndent.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmIndent.java index 761ee1e7df..5397a0cf15 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmIndent.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmIndent.java @@ -22,6 +22,8 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.printer.SourcePrinter; +import com.github.javaparser.printer.lexicalpreservation.TextElement; +import com.github.javaparser.printer.lexicalpreservation.TokenTextElement; public class CsmIndent implements CsmElement { @@ -30,6 +32,15 @@ public void prettyPrint(Node node, SourcePrinter printer) { printer.indent(); } + /* + * Verifies if the content of the {@code CsmElement} is the same as the provided {@code TextElement} + */ + @Override + public boolean isCorrespondingElement(TextElement textElement) { + return (textElement instanceof TokenTextElement) + && ((TokenTextElement)textElement).isSpaceOrTab(); + } + @Override public int hashCode() { return 1; diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmToken.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmToken.java index c60f7c6dba..f676360bda 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmToken.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmToken.java @@ -20,36 +20,28 @@ */ package com.github.javaparser.printer.concretesyntaxmodel; +import static com.github.javaparser.TokenTypes.isEndOfLineToken; +import static com.github.javaparser.TokenTypes.isWhitespaceButNotEndOfLine; + import com.github.javaparser.GeneratedJavaParserConstants; import com.github.javaparser.TokenTypes; import com.github.javaparser.ast.Node; import com.github.javaparser.printer.SourcePrinter; +import com.github.javaparser.printer.lexicalpreservation.TextElement; +import com.github.javaparser.printer.lexicalpreservation.TokenTextElement; import com.github.javaparser.utils.LineSeparator; -import static com.github.javaparser.TokenTypes.isEndOfLineToken; -import static com.github.javaparser.TokenTypes.isWhitespaceButNotEndOfLine; - public class CsmToken implements CsmElement { private final int tokenType; private String content; - private TokenContentCalculator tokenContentCalculator; - - public interface TokenContentCalculator { - - String calculate(Node node); - } - public int getTokenType() { return tokenType; } - public String getContent(Node node) { - if (tokenContentCalculator != null) { - return tokenContentCalculator.calculate(node); - } + public String getContent() { return content; } @@ -74,17 +66,12 @@ public CsmToken(int tokenType, String content) { this.content = content; } - public CsmToken(int tokenType, TokenContentCalculator tokenContentCalculator) { - this.tokenType = tokenType; - this.tokenContentCalculator = tokenContentCalculator; - } - @Override public void prettyPrint(Node node, SourcePrinter printer) { if (isEndOfLineToken(tokenType)) { printer.println(); } else { - printer.print(getContent(node)); + printer.print(getContent()); } } @@ -104,21 +91,20 @@ public boolean equals(Object o) { return false; if (content != null ? !content.equals(csmToken.content) : csmToken.content != null) return false; - return tokenContentCalculator != null ? tokenContentCalculator.equals(csmToken.tokenContentCalculator) : csmToken.tokenContentCalculator == null; + return true; } @Override public int hashCode() { int result = tokenType; result = 31 * result + (content != null ? content.hashCode() : 0); - result = 31 * result + (tokenContentCalculator != null ? tokenContentCalculator.hashCode() : 0); return result; } public boolean isWhiteSpace() { return TokenTypes.isWhitespace(tokenType); } - + public boolean isWhiteSpaceNotEol() { return isWhiteSpace() && !isNewLine(); } @@ -126,4 +112,14 @@ public boolean isWhiteSpaceNotEol() { public boolean isNewLine() { return TokenTypes.isEndOfLineToken(tokenType); } + + /* + * Verifies if the content of the {@code CsmElement} is the same as the provided {@code TextElement} + */ + @Override + public boolean isCorrespondingElement(TextElement textElement) { + return (textElement instanceof TokenTextElement) + && ((TokenTextElement)textElement).getTokenKind() == getTokenType() + && ((TokenTextElement)textElement).getText().equals(getContent()); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java index e9769b58ee..572a9c2fee 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java @@ -88,11 +88,11 @@ private boolean isToken() { public TextElement toTextElement() { if (element instanceof LexicalDifferenceCalculator.CsmChild) { return new ChildTextElement(((LexicalDifferenceCalculator.CsmChild) element).getChild()); - } else if (element instanceof CsmToken) { - return new TokenTextElement(((CsmToken) element).getTokenType(), ((CsmToken) element).getContent(null)); - } else { - throw new UnsupportedOperationException(element.getClass().getSimpleName()); } + if (element instanceof CsmToken) { + return new TokenTextElement(((CsmToken) element).getTokenType(), ((CsmToken) element).getContent()); + } + throw new UnsupportedOperationException(element.getClass().getSimpleName()); } /* diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java index 390a0a9131..caf84d9850 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java @@ -20,16 +20,16 @@ */ package com.github.javaparser.printer.lexicalpreservation; +import java.util.Optional; + import com.github.javaparser.Range; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.comments.Comment; -import java.util.Optional; - /** * Represent the position of a child node in the NodeText of its parent. */ -class ChildTextElement extends TextElement { +public class ChildTextElement extends TextElement { private final Node child; @@ -37,21 +37,22 @@ class ChildTextElement extends TextElement { this.child = child; } - String expand() { + @Override + public String expand() { return LexicalPreservingPrinter.print(child); } - Node getChild() { + public Node getChild() { return child; } @Override - boolean isToken(int tokenKind) { + public boolean isToken(int tokenKind) { return false; } @Override - boolean isNode(Node node) { + public boolean isNode(Node node) { return node == child; } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java index 045d43d85e..6d2a955c0e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java @@ -37,7 +37,9 @@ import com.github.javaparser.ast.type.ArrayType; import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.ast.type.Type; -import com.github.javaparser.printer.concretesyntaxmodel.*; +import com.github.javaparser.printer.concretesyntaxmodel.CsmElement; +import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent; +import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent; import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild; /** @@ -80,7 +82,7 @@ public class Difference { /* * Returns the indentation used after the last line break */ - private List processIndentation(List indentation, List prevElements) { + List processIndentation(List indentation, List prevElements) { int eolIndex = lastIndexOfEol(prevElements); // Return "indentation" as is if no EOL element was found if (eolIndex < 0) @@ -123,7 +125,7 @@ int lastIndexOfEol(List source) { private int posOfNextComment(int fromIndex, List elements) { if (!isValidIndex(fromIndex, elements)) return -1; - ReadOnlyListIterator iterator = new ReadOnlyListIterator(elements, fromIndex); + ArrayIterator iterator = new ArrayIterator<>(elements, fromIndex); // search for the next consecutive space characters while (iterator.hasNext()) { TextElement element = iterator.next(); @@ -155,7 +157,7 @@ private void removeElements(int fromIndex, int toIndex, List elemen // removing elements int count = fromIndex; while (iterator.hasNext() && count <= toIndex) { - TextElement element = iterator.next(); + iterator.next(); iterator.remove(); count++; } @@ -169,10 +171,10 @@ private boolean isValidIndex(int index, List elements) { * Returns the position of the last new line character or -1 if there is no eol in the specified list of TextElement */ int lastIndexOfEolWithoutGPT(List source) { - ListIterator listIterator = source.listIterator(source.size()); + ListIterator listIterator = source.listIterator(source.size()); int lastIndex = source.size() - 1; while (listIterator.hasPrevious()) { - TextElement elem = (TextElement) listIterator.previous(); + TextElement elem = listIterator.previous(); if (elem.isNewline()) { return lastIndex; } @@ -215,7 +217,7 @@ private boolean isAfterLBrace(NodeText nodeText, int nodeTextIndex) { * [ ][ ]void[ ]m{} * } */ - private int considerEnforcingIndentation(NodeText nodeText, int nodeTextIndex) { + int considerEnforcingIndentation(NodeText nodeText, int nodeTextIndex) { return considerIndentation(nodeText, nodeTextIndex, indentation.size()); } @@ -316,7 +318,7 @@ private EnforcingIndentationContext defineEnforcingIndentationContext(NodeText n } } // compute space after the deleted element - if (isSpaceOrTabElement(nodeText, startIndex)) { + if (startIndex < nodeText.numberOfElements() && isSpaceOrTabElement(nodeText, startIndex)) { // int startingFromIndex = startIndex == 0 ? startIndex : startIndex + 1; for (int i = startIndex; i >= 0 && i < nodeText.numberOfElements(); i++) { if (nodeText.getTextElement(i).isNewline()) { @@ -344,7 +346,7 @@ private boolean isSpaceOrTabElement(NodeText nodeText, int i) { * to the difference (adding and removing the elements provided). */ void apply() { - extractReshuffledDiffElements(diffElements); + ReshuffledDiffElementExtractor.of(nodeText).extract(diffElements); Map removedGroups = combineRemovedElementsToRemovedGroups(); do { boolean isLeftOverDiffElement = applyLeftOverDiffElements(); @@ -404,90 +406,6 @@ private boolean applyLeftOverDiffElements() { return isLeftOverElement; } - private void extractReshuffledDiffElements(List diffElements) { - for (int index = 0; index < diffElements.size(); index++) { - DifferenceElement diffElement = diffElements.get(index); - if (diffElement instanceof Reshuffled) { - Reshuffled reshuffled = (Reshuffled) diffElement; - // First, let's see how many tokens we need to attribute to the previous version of the of the CsmMix - CsmMix elementsFromPreviousOrder = reshuffled.getPreviousOrder(); - CsmMix elementsFromNextOrder = reshuffled.getNextOrder(); - // This contains indexes from elementsFromNextOrder to indexes from elementsFromPreviousOrder - Map correspondanceBetweenNextOrderAndPreviousOrder = getCorrespondanceBetweenNextOrderAndPreviousOrder(elementsFromPreviousOrder, elementsFromNextOrder); - // We now find out which Node Text elements corresponds to the elements in the original CSM - List nodeTextIndexOfPreviousElements = findIndexOfCorrespondingNodeTextElement(elementsFromPreviousOrder.getElements(), nodeText, originalIndex, node); - Map nodeTextIndexToPreviousCSMIndex = new HashMap<>(); - for (int i = 0; i < nodeTextIndexOfPreviousElements.size(); i++) { - int value = nodeTextIndexOfPreviousElements.get(i); - if (value != -1) { - nodeTextIndexToPreviousCSMIndex.put(value, i); - } - } - int lastNodeTextIndex = nodeTextIndexOfPreviousElements.stream().max(Integer::compareTo).orElse(-1); - // Elements to be added at the end - List elementsToBeAddedAtTheEnd = new LinkedList<>(); - List nextOrderElements = elementsFromNextOrder.getElements(); - Map> elementsToAddBeforeGivenOriginalCSMElement = new HashMap<>(); - for (int ni = 0; ni < nextOrderElements.size(); ni++) { - // If it has a mapping, then it is kept - if (!correspondanceBetweenNextOrderAndPreviousOrder.containsKey(ni)) { - // Ok, it is something new. Where to put it? Let's see what is the first following - // element that has a mapping - int originalCsmIndex = -1; - for (int nj = ni + 1; nj < nextOrderElements.size() && originalCsmIndex == -1; nj++) { - if (correspondanceBetweenNextOrderAndPreviousOrder.containsKey(nj)) { - originalCsmIndex = correspondanceBetweenNextOrderAndPreviousOrder.get(nj); - if (!elementsToAddBeforeGivenOriginalCSMElement.containsKey(originalCsmIndex)) { - elementsToAddBeforeGivenOriginalCSMElement.put(originalCsmIndex, new LinkedList<>()); - } - elementsToAddBeforeGivenOriginalCSMElement.get(originalCsmIndex).add(nextOrderElements.get(ni)); - } - } - // it does not preceed anything, so it goes at the end - if (originalCsmIndex == -1) { - elementsToBeAddedAtTheEnd.add(nextOrderElements.get(ni)); - } - } - } - // We go over the original node text elements, in the order they appear in the NodeText. - // Considering an original node text element (ONE) - // * we verify if it corresponds to a CSM element. If it does not we just move on, otherwise - // we find the correspond OCE (Original CSM Element) - // * we first add new elements that are marked to be added before OCE - // * if OCE is marked to be present also in the "after" CSM we add a kept element, - // otherwise we add a removed element - // Remove the whole Reshuffled element - diffElements.remove(index); - int diffElIterator = index; - if (lastNodeTextIndex != -1) { - for (int ntIndex = originalIndex; ntIndex <= lastNodeTextIndex; ntIndex++) { - if (nodeTextIndexToPreviousCSMIndex.containsKey(ntIndex)) { - int indexOfOriginalCSMElement = nodeTextIndexToPreviousCSMIndex.get(ntIndex); - if (elementsToAddBeforeGivenOriginalCSMElement.containsKey(indexOfOriginalCSMElement)) { - for (CsmElement elementToAdd : elementsToAddBeforeGivenOriginalCSMElement.get(indexOfOriginalCSMElement)) { - diffElements.add(diffElIterator++, new Added(elementToAdd)); - } - } - CsmElement originalCSMElement = elementsFromPreviousOrder.getElements().get(indexOfOriginalCSMElement); - boolean toBeKept = correspondanceBetweenNextOrderAndPreviousOrder.containsValue(indexOfOriginalCSMElement); - if (toBeKept) { - diffElements.add(diffElIterator++, new Kept(originalCSMElement)); - } else { - diffElements.add(diffElIterator++, new Removed(originalCSMElement)); - } - } - // else we have a simple node text element, without associated csm element, just keep ignore it - } - } - // Finally we look for the remaining new elements that were not yet added and - // add all of them - for (CsmElement elementToAdd : elementsToBeAddedAtTheEnd) { - diffElements.add(diffElIterator++, new Added(elementToAdd)); - } - } - } - } - /** * Maps all Removed elements as keys to their corresponding RemovedGroup. * A RemovedGroup contains all consecutive Removed elements. @@ -854,7 +772,7 @@ private int getIndexToNextTokenElement(TokenTextElement element, int nestedDiamo JavaToken nextToken = next.get(); Kind kind = Kind.valueOf(nextToken.getKind()); if (isDiamondOperator(kind)) { - if (kind.GT.equals(kind)) + if (Kind.GT.equals(kind)) nestedDiamondOperator--; else nestedDiamondOperator++; @@ -883,7 +801,7 @@ private int getIndexToNextTokenElementInArrayType(TokenTextElement element, int JavaToken nextToken = next.get(); Kind kind = Kind.valueOf(nextToken.getKind()); if (isBracket(kind)) { - if (kind.RBRACKET.equals(kind)) + if (Kind.RBRACKET.equals(kind)) arrayLevel--; } // manage the fact where the first token is not a diamond operator but a whitespace @@ -899,45 +817,14 @@ private int getIndexToNextTokenElementInArrayType(TokenTextElement element, int * Returns true if the token is possibly a diamond operator */ private boolean isDiamondOperator(Kind kind) { - return kind.GT.equals(kind) || kind.LT.equals(kind); + return Kind.GT.equals(kind) || Kind.LT.equals(kind); } /* * Returns true if the token is a bracket */ private boolean isBracket(Kind kind) { - return kind.LBRACKET.equals(kind) || kind.RBRACKET.equals(kind); - } - - private boolean openBraceWasOnSameLine() { - int index = originalIndex; - while (index >= 0 && !nodeText.getTextElement(index).isNewline()) { - if (nodeText.getTextElement(index).isToken(LBRACE)) { - return true; - } - index--; - } - return false; - } - - private boolean wasSpaceBetweenBraces() { - return nodeText.getTextElement(originalIndex).isToken(RBRACE) && doWeHaveLeftBraceFollowedBySpace(originalIndex - 1) && (diffIndex < 2 || !diffElements.get(diffIndex - 2).isRemoved()); - } - - private boolean doWeHaveLeftBraceFollowedBySpace(int index) { - index = rewindSpace(index); - return nodeText.getTextElement(index).isToken(LBRACE); - } - - private int rewindSpace(int index) { - if (index <= 0) { - return index; - } - if (nodeText.getTextElement(index).isWhiteSpace()) { - return rewindSpace(index - 1); - } else { - return index; - } + return Kind.LBRACKET.equals(kind) || Kind.RBRACKET.equals(kind); } private boolean nextIsRightBrace(int index) { @@ -1050,6 +937,9 @@ private void applyAddedDiffElement(Added added) { if (!isPreviousElementNewline && !isFirstElement && !previousIsWhiteSpace) { // Insert after the new line originalIndex++; + // We want to adjust the indentation while considering the new element that we + // added + originalIndex = adjustIndentation(indentation, nodeText, originalIndex, false); } nodeText.addElement(originalIndex, addedTextElement); originalIndex++; @@ -1069,113 +959,69 @@ private void applyAddedDiffElement(Added added) { diffIndex++; } - private String tokenDescription(int kind) { - return GeneratedJavaParserConstants.tokenImage[kind]; - } - - /* - * Considering that the lists of elements are ordered, We can find the common - * elements by starting with the list before the modifications and, for each - * element, by going through the list of elements containing the modifications. - * - * We can find the common elements by starting with the list before the - * modifications (L1) and, for each element, by going through the list of elements - * containing the modifications (L2). - * - * If element A in list L1 is not found in list L2, it is a deleted element. - * If element A of list L1 is found in list L2, it is a kept element. In this - * case the search for the next element of the list L1 must start from the - * position of the last element kept {@code syncNextIndex}. - */ - private Map getCorrespondanceBetweenNextOrderAndPreviousOrder(CsmMix elementsFromPreviousOrder, - CsmMix elementsFromNextOrder) { - Map correspondanceBetweenNextOrderAndPreviousOrder = new HashMap<>(); - ReadOnlyListIterator previousOrderElementsIterator = new ReadOnlyListIterator( - elementsFromPreviousOrder.getElements()); - int syncNextIndex = 0; - while (previousOrderElementsIterator.hasNext()) { - CsmElement pe = previousOrderElementsIterator.next(); - ReadOnlyListIterator nextOrderElementsIterator = new ReadOnlyListIterator( - elementsFromNextOrder.getElements(), syncNextIndex); - while (nextOrderElementsIterator.hasNext()) { - CsmElement ne = nextOrderElementsIterator.next(); - if (!correspondanceBetweenNextOrderAndPreviousOrder.values().contains(previousOrderElementsIterator.index()) - && DifferenceElementCalculator.matching(ne, pe)) { - correspondanceBetweenNextOrderAndPreviousOrder.put(nextOrderElementsIterator.index(), - previousOrderElementsIterator.index()); - // set the position to start on the next {@code nextOrderElementsIterator} iteration - syncNextIndex = nextOrderElementsIterator.index(); - break; - } - } - } - return correspondanceBetweenNextOrderAndPreviousOrder; - } - /* - * A list iterator which does not allow to modify the list - * and which provides a method to know the current positioning + * A list iterator which provides a method to know the current positioning */ - private class ReadOnlyListIterator implements ListIterator { - ListIterator elements; - public ReadOnlyListIterator(List elements) { + public static class ArrayIterator implements ListIterator { + ListIterator iterator; + public ArrayIterator(List elements) { this(elements, 0); } - public ReadOnlyListIterator(List elements, int index) { - this.elements = elements.listIterator(index); + public ArrayIterator(List elements, int index) { + this.iterator = elements.listIterator(index); } @Override public boolean hasNext() { - return elements.hasNext(); + return iterator.hasNext(); } @Override public T next() { - return elements.next(); + return iterator.next(); } @Override public boolean hasPrevious() { - return elements.hasPrevious(); + return iterator.hasPrevious(); } @Override public T previous() { - return elements.previous(); + return iterator.previous(); } @Override public int nextIndex() { - return elements.nextIndex(); + return iterator.nextIndex(); } @Override public int previousIndex() { - return elements.previousIndex(); + return iterator.previousIndex(); } /* * Returns the current index in the underlying list */ public int index() { - return elements.nextIndex() - 1; + return iterator.nextIndex() - 1; } @Override public void remove() { - throw new UnsupportedOperationException(); + iterator.remove();; } @Override public void set(T e) { - throw new UnsupportedOperationException(); + iterator.set(e); } @Override public void add(T e) { - throw new UnsupportedOperationException(); + iterator.add(e);; } } @@ -1188,100 +1034,6 @@ private boolean isFollowedByUnindent(List diffElements, int d return (nextIndexValue) < diffElements.size() && diffElements.get(nextIndexValue).isAdded() && diffElements.get(nextIndexValue).getElement() instanceof CsmUnindent; } - private List findIndexOfCorrespondingNodeTextElement(List elements, NodeText nodeText, int startIndex, Node node) { - List correspondingIndices = new ArrayList<>(); - for (ListIterator csmElementListIterator = elements.listIterator(); csmElementListIterator.hasNext(); ) { - int previousCsmElementIndex = csmElementListIterator.previousIndex(); - CsmElement csmElement = csmElementListIterator.next(); - int nextCsmElementIndex = csmElementListIterator.nextIndex(); - Map potentialMatches = new EnumMap<>(MatchClassification.class); - for (int i = startIndex; i < nodeText.numberOfElements(); i++) { - if (!correspondingIndices.contains(i)) { - TextElement textElement = nodeText.getTextElement(i); - boolean isCorresponding = isCorrespondingElement(textElement, csmElement, node); - if (isCorresponding) { - boolean hasSamePreviousElement = false; - if (i > 0 && previousCsmElementIndex > -1) { - TextElement previousTextElement = nodeText.getTextElement(i - 1); - hasSamePreviousElement = isCorrespondingElement(previousTextElement, elements.get(previousCsmElementIndex), node); - } - boolean hasSameNextElement = false; - if (i < nodeText.numberOfElements() - 1 && nextCsmElementIndex < elements.size()) { - TextElement nextTextElement = nodeText.getTextElement(i + 1); - hasSameNextElement = isCorrespondingElement(nextTextElement, elements.get(nextCsmElementIndex), node); - } - if (hasSamePreviousElement && hasSameNextElement) { - potentialMatches.putIfAbsent(MatchClassification.ALL, i); - } else if (hasSamePreviousElement) { - potentialMatches.putIfAbsent(MatchClassification.PREVIOUS_AND_SAME, i); - } else if (hasSameNextElement) { - potentialMatches.putIfAbsent(MatchClassification.NEXT_AND_SAME, i); - } else { - potentialMatches.putIfAbsent(MatchClassification.SAME_ONLY, i); - } - } else if (isAlmostCorrespondingElement(textElement, csmElement, node)) { - potentialMatches.putIfAbsent(MatchClassification.ALMOST, i); - } - } - } - // Prioritize the matches from best to worst - Optional bestMatchKey = potentialMatches.keySet().stream().min(Comparator.comparing(MatchClassification::getPriority)); - if (bestMatchKey.isPresent()) { - correspondingIndices.add(potentialMatches.get(bestMatchKey.get())); - } else { - correspondingIndices.add(-1); - } - } - return correspondingIndices; - } - - private enum MatchClassification { - - ALL(1), PREVIOUS_AND_SAME(2), NEXT_AND_SAME(3), SAME_ONLY(4), ALMOST(5); - - private final int priority; - - MatchClassification(int priority) { - this.priority = priority; - } - - int getPriority() { - return priority; - } - } - - private boolean isCorrespondingElement(TextElement textElement, CsmElement csmElement, Node node) { - if (csmElement instanceof CsmToken) { - CsmToken csmToken = (CsmToken) csmElement; - if (textElement instanceof TokenTextElement) { - TokenTextElement tokenTextElement = (TokenTextElement) textElement; - return tokenTextElement.getTokenKind() == csmToken.getTokenType() && tokenTextElement.getText().equals(csmToken.getContent(node)); - } - } else if (csmElement instanceof CsmChild) { - CsmChild csmChild = (CsmChild) csmElement; - if (textElement instanceof ChildTextElement) { - ChildTextElement childTextElement = (ChildTextElement) textElement; - return childTextElement.getChild() == csmChild.getChild(); - } - } else if (csmElement instanceof CsmIndent) { - CsmIndent csmIndent = (CsmIndent) csmElement; - if (textElement instanceof TokenTextElement) { - TokenTextElement tokenTextElement = (TokenTextElement) textElement; - return tokenTextElement.isSpaceOrTab(); - } - } else { - throw new UnsupportedOperationException(); - } - return false; - } - - private boolean isAlmostCorrespondingElement(TextElement textElement, CsmElement csmElement, Node node) { - if (isCorrespondingElement(textElement, csmElement, node)) { - return false; - } - return textElement.isWhiteSpace() && csmElement instanceof CsmToken && ((CsmToken) csmElement).isWhiteSpace(); - } - private int adjustIndentation(List indentation, NodeText nodeText, int nodeTextIndex, boolean followedByUnindent) { List indentationAdj = processIndentation(indentation, nodeText.getElements().subList(0, nodeTextIndex - 1)); if (nodeTextIndex < nodeText.numberOfElements() && nodeText.getTextElement(nodeTextIndex).isToken(RBRACE)) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java index 200f9ecee4..b9481df29c 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java @@ -74,16 +74,19 @@ static boolean matching(CsmElement a, CsmElement b) { CsmChild childA = (CsmChild) a; CsmChild childB = (CsmChild) b; return childA.getChild().equals(childB.getChild()); - } else if (b instanceof CsmToken) { + } + if (b instanceof CsmToken) { return false; - } else if (b instanceof CsmIndent) { + } + if (b instanceof CsmIndent) { return false; - } else if (b instanceof CsmUnindent) { + } + if (b instanceof CsmUnindent) { return false; - } else { - throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); } - } else if (a instanceof CsmToken) { + throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); + } + if (a instanceof CsmToken) { if (b instanceof CsmToken) { // fix #2382: // Tokens are described by their type AND their content @@ -92,18 +95,22 @@ static boolean matching(CsmElement a, CsmElement b) { CsmToken childA = (CsmToken) a; CsmToken childB = (CsmToken) b; return childA.equals(childB); - } else if (b instanceof CsmChild) { + } + if (b instanceof CsmChild) { return false; - } else if (b instanceof CsmIndent) { + } + if (b instanceof CsmIndent) { return false; - } else if (b instanceof CsmUnindent) { + } + if (b instanceof CsmUnindent) { return false; - } else { - throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); } - } else if (a instanceof CsmIndent) { + throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); + } + if (a instanceof CsmIndent) { return b instanceof CsmIndent; - } else if (a instanceof CsmUnindent) { + } + if (a instanceof CsmUnindent) { return b instanceof CsmUnindent; } throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); @@ -118,17 +125,19 @@ private static boolean replacement(CsmElement a, CsmElement b) { CsmChild childA = (CsmChild) a; CsmChild childB = (CsmChild) b; return childA.getChild().getClass().equals(childB.getChild().getClass()); - } else if (b instanceof CsmToken) { + } + if (b instanceof CsmToken) { return false; - } else { - throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); } - } else if (a instanceof CsmToken) { + throw new UnsupportedOperationException(a.getClass().getSimpleName() + " " + b.getClass().getSimpleName()); + } + if (a instanceof CsmToken) { if (b instanceof CsmToken) { CsmToken childA = (CsmToken) a; CsmToken childB = (CsmToken) b; return childA.getTokenType() == childB.getTokenType(); - } else if (b instanceof CsmChild) { + } + if (b instanceof CsmChild) { return false; } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index cbca1d4822..7e08f9597c 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -20,6 +20,8 @@ */ package com.github.javaparser.printer.lexicalpreservation; +import java.util.*; + import com.github.javaparser.GeneratedJavaParserConstants; import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.Node; @@ -37,8 +39,6 @@ import com.github.javaparser.printer.lexicalpreservation.changes.*; import com.github.javaparser.utils.LineSeparator; -import java.util.*; - class LexicalDifferenceCalculator { /** @@ -71,7 +71,7 @@ void removeIndentationElements() { } } - static class CsmChild implements CsmElement { + public static class CsmChild implements CsmElement { private final Node child; @@ -88,6 +88,15 @@ public void prettyPrint(Node node, SourcePrinter printer) { throw new UnsupportedOperationException(); } + /* + * Verifies if the content of the {@code CsmElement} is the same as the provided {@code TextElement} + */ + @Override + public boolean isCorrespondingElement(TextElement textElement) { + return (textElement instanceof ChildTextElement) + && ((ChildTextElement)textElement).getChild() == getChild(); + } + @Override public String toString() { return "child(" + child.getClass().getSimpleName() + ")"; @@ -141,7 +150,7 @@ private void replaceEolTokens(List differenceElements, LineSe } /* - * Returns a new line token + * Returns a new line token */ private CsmElement getNewLineToken(LineSeparator lineSeparator) { return CsmElement.newline(lineSeparator); @@ -190,7 +199,7 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List N setup(N node) { }); return node; } - + /* * Returns true if the lexical preserving printer is initialized on the node */ @@ -138,9 +113,9 @@ public static boolean isAvailableOn(Node node) { return node.containsData(NODE_TEXT_DATA); } - // + // // Constructor and setup - // + // private static AstObserver createObserver() { return new LexicalPreservingPrinter.Observer(); } @@ -162,13 +137,33 @@ public void concretePropertyChange(Node observedNode, ObservableProperty propert orElse(getOrCreateNodeText(observedNode)); if (oldValue == null) { // this case corresponds to the addition of a comment int index = parentNode.isPresent() ? // Find the position of the comment node and put in front of it the [...] - nodeText.findChild(observedNode) : // + nodeText.findChild(observedNode) : // 0; - // Add the same indent depth of the comment to the following node - fixIndentOfMovedNode(nodeText, index); + /* Add the same indentation to the comment as the previous node + * for example if we want to add a comment on the body of the method declaration : + * Actual code + * {@code + * public class Foo { + * void visit(final UnknownType n, final Void arg) + * { + * } + * } + * } + * Expected result + * {@code + * public class Foo { + * void visit(final UnknownType n, final Void arg) + * //added comment <-- we should insert indentation before the comment + * { + * } + * } + * } + */ + fixIndentOfAddedNode(nodeText, index - 1); LineSeparator lineSeparator = observedNode.getLineEndingStyleOrDefault(LineSeparator.SYSTEM); - nodeText.addElement(index, makeCommentToken((Comment) newValue)); - nodeText.addToken(index + 1, eolTokenKind(lineSeparator), lineSeparator.asRawString()); + nodeText.addElement(index++, makeCommentToken((Comment) newValue)); + nodeText.addToken(index, eolTokenKind(lineSeparator), lineSeparator.asRawString()); + // code indentation after inserting an eol token may be wrong } else if (newValue == null) { // this case corresponds to a deletion of a comment if (oldValue instanceof Comment) { if (((Comment) oldValue).isOrphan()) { @@ -188,6 +183,7 @@ public void concretePropertyChange(Node observedNode, ObservableProperty propert throw new UnsupportedOperationException("Trying to remove something that is not a comment!"); } } else { + // this is a replacement of a comment List matchingTokens = findTokenTextElementForComment((Comment) oldValue, nodeText); if (matchingTokens.size() != 1) { throw new IllegalStateException("The matching comment to be replaced could not be found"); @@ -203,12 +199,12 @@ public void concretePropertyChange(Node observedNode, ObservableProperty propert } LEXICAL_DIFFERENCE_CALCULATOR.calculatePropertyChange(nodeText, observedNode, property, oldValue, newValue); } - + private boolean isCompleteLine(List elements , int index) { if (index <= 0 || index >= elements.size()) return false; boolean isCompleteLine=true; ListIterator iterator = elements.listIterator(index); - // verify if elements after the index are only spaces or tabs + // verify if elements after the index are only spaces or tabs while(iterator.hasNext()) { TextElement textElement = iterator.next(); if (textElement.isNewline()) break; @@ -216,7 +212,7 @@ private boolean isCompleteLine(List elements , int index) { isCompleteLine=false; break; } - // verify if elements before the index are only spaces or tabs + // verify if elements before the index are only spaces or tabs iterator = elements.listIterator(index); while(iterator.hasPrevious() && isCompleteLine) { TextElement textElement = iterator.previous(); @@ -224,10 +220,10 @@ private boolean isCompleteLine(List elements , int index) { if (textElement.isSpaceOrTab()) continue; isCompleteLine=false; } - + return isCompleteLine; } - + private void removeAllExtraCharacters(List elements , int index) { if (index < 0 || index >= elements.size()) return; removeAllExtraCharactersStartingFrom(elements.listIterator(index)); @@ -264,7 +260,7 @@ private void removeAllExtraCharactersStartingFrom(ListIterator iter break; } } - + private TokenTextElement makeCommentToken(Comment newComment) { if (newComment.isJavadocComment()) { return new TokenTextElement(JAVADOC_COMMENT, newComment.getHeader() + newComment.getContent() + newComment.getFooter()); @@ -302,7 +298,7 @@ private List findChildTextElementForComment(Comment oldValue, } return matchingChildElements; } - + private List selectMatchingChildElements(Comment oldValue, NodeText nodeText) { List result = new ArrayList<>(); List childTextElements = nodeText.getElements().stream().filter(e -> e.isChild()) @@ -322,7 +318,7 @@ private List selectMatchingChildElements(Comment oldValue, Nod } return result; } - + private boolean isSameComment(Comment childValue, Comment oldValue) { return childValue.getContent().equals(oldValue.getContent()); } @@ -350,27 +346,29 @@ private boolean isEqualRange(Optional range1, Optional range2) { return false; } - /** - * This method inserts new space tokens at the given {@code index}. If a new comment is added to the node - * at the position of {@code index}, the new comment and the node will have the same indent. - * - * @param nodeText The text of the node - * @param index The position where a new comment will be added to - */ - private void fixIndentOfMovedNode(NodeText nodeText, int index) { + /** + * This method inserts new space tokens at the given {@code index}. If a new + * comment is added to the token list at the position following {@code index}, + * the new comment and the node will have the same indent. + * + * @param nodeText The text of the node + * @param index The position at which the analysis should start + */ + private void fixIndentOfAddedNode(NodeText nodeText, int index) { if (index <= 0) { return; } TextElement currentSpaceCandidate = null; - for (int i = index - 1; i >= 0; i--) { + for (int i = index; i >= 0; i--) { TextElement spaceCandidate = nodeText.getTextElement(i); if (spaceCandidate.isSpaceOrTab()) { // save the current indentation char currentSpaceCandidate = nodeText.getTextElement(i); } if (!spaceCandidate.isSpaceOrTab()) { - if (spaceCandidate.isNewline() && i != index - 1) { - for (int j = 0; j < (index - 1) - i; j++) { + if (spaceCandidate.isNewline() && i != index) { + int numberOfIndentationCharacters = index - i; + for (int j = 0; j < numberOfIndentationCharacters; j++) { if (currentSpaceCandidate != null) { // use the current (or last) indentation character nodeText.addElement(index, new TokenTextElement(JavaToken.Kind.SPACE.getKind(), currentSpaceCandidate.expand())); @@ -435,7 +433,7 @@ public void process(Node node) { }.visitBreadthFirst(root); }); } - + private static Optional findNodeForToken(Node node, Range tokenRange) { if (node.isPhantom()) { return Optional.empty(); @@ -475,9 +473,9 @@ private static void storeInitialTextForOneNode(Node node, List nodeTo node.setData(NODE_TEXT_DATA, new NodeText(elements.stream().map(p -> p.b).collect(toList()))); } - // + // // Iterators - // + // private static Iterator tokensPreceeding(final Node node) { if (!node.getParentNode().isPresent()) { return new TextElementIteratorsFactory.EmptyIterator<>(); @@ -489,18 +487,15 @@ private static Iterator tokensPreceeding(final Node node) { if (index == NodeText.NOT_FOUND) { if (node.getParentNode().get() instanceof VariableDeclarator) { return tokensPreceeding(node.getParentNode().get()); - } else { - // comment node can be removed at this stage. - return new TextElementIteratorsFactory.EmptyIterator(); -// throw new IllegalArgumentException(String.format("I could not find child '%s' in parent '%s'. parentNodeText: %s", node, node.getParentNode().get(), parentNodeText)); } + return new TextElementIteratorsFactory.EmptyIterator(); } return new TextElementIteratorsFactory.CascadingIterator<>(TextElementIteratorsFactory.partialReverseIterator(parentNodeText, index - 1), () -> tokensPreceeding(node.getParentNode().get())); } - // + // // Printing methods - // + // /** * Print a Node into a String, preserving the lexical information. */ @@ -509,12 +504,12 @@ public static String print(Node node) { final NodeText nodeText = getOrCreateNodeText(node); nodeText.getElements().forEach(element -> element.accept(visitor)); return visitor.toString(); - + } - // + // // Methods to handle transformations - // + // private static void prettyPrintingTextNode(Node node, NodeText nodeText) { if (node instanceof PrimitiveType) { PrimitiveType primitiveType = (PrimitiveType) node; @@ -580,7 +575,7 @@ private static NodeText interpret(Node node, CsmElement csm, NodeText nodeText) boolean pendingIndentation = false; // Add a comment and line separator if necessary node.getComment().ifPresent(comment -> { - // new comment has no range so in this case we want to force the comment before the node + // new comment has no range so in this case we want to force the comment before the node if (!comment.hasRange()) { LineSeparator lineSeparator = node.getLineEndingStyleOrDefault(LineSeparator.SYSTEM); calculatedSyntaxModel.elements.add(0,new CsmToken(eolTokenKind(lineSeparator), lineSeparator.asRawString())); @@ -608,7 +603,7 @@ private static NodeText interpret(Node node, CsmElement csm, NodeText nodeText) nodeText.addChild(((LexicalDifferenceCalculator.CsmChild) element).getChild()); } else if (element instanceof CsmToken) { CsmToken csmToken = (CsmToken) element; - nodeText.addToken(csmToken.getTokenType(), csmToken.getContent(node)); + nodeText.addToken(csmToken.getTokenType(), csmToken.getContent()); if (csmToken.isNewLine()) { pendingIndentation = true; } @@ -656,9 +651,8 @@ static List findIndentation(Node node) { TokenTextElement tte = it.next(); if (tte.getTokenKind() == SINGLE_LINE_COMMENT || tte.isNewline()) { break; - } else { - followingNewlines.add(tte); } + followingNewlines.add(tte); } Collections.reverse(followingNewlines); for (int i = 0; i < followingNewlines.size(); i++) { @@ -669,9 +663,9 @@ static List findIndentation(Node node) { return followingNewlines; } - // + // // Helper methods - // + // private static boolean isReturningOptionalNodeList(Method m) { if (!m.getReturnType().getCanonicalName().equals(JAVA_UTIL_OPTIONAL)) { return false; diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LookaheadIterator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LookaheadIterator.java new file mode 100755 index 0000000000..9847fe9268 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LookaheadIterator.java @@ -0,0 +1,30 @@ +package com.github.javaparser.printer.lexicalpreservation; + +import java.util.NoSuchElementException; + +public interface LookaheadIterator { + + /** + * Returns the next element in iteration without advancing the underlying iterator. + * If the iterator is already exhausted, null will be returned. + *

+ * Note: this method does not throw a {@link NoSuchElementException} if the iterator + * is already exhausted. If you want such a behavior, use {@link #element()} instead. + *

+ * The rationale behind this is to follow the {@link java.util.Queue} interface + * which uses the same terminology. + * + * @return the next element from the iterator + */ + public E peek(); + + /** + * Returns the next element in iteration without advancing the underlying iterator. + * If the iterator is already exhausted, null will be returned. + * + * @return the next element from the iterator + * @throws NoSuchElementException if the iterator is already exhausted according to {@link #hasNext()} + */ + public E element(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PeekingIterator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PeekingIterator.java new file mode 100755 index 0000000000..98fd0f5ad8 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PeekingIterator.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2011, 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser.printer.lexicalpreservation; + +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.Objects; + +/** + * Decorates an iterator to support one-element lookahead while iterating. + *

+ * The decorator supports the removal operation, but an {@link IllegalStateException} + * will be thrown if {@link #remove()}, {@link #add()}, {@link #set()}} is called directly after a call to + * {@link #peek()} or {@link #element()}. + * + * @param the type of elements returned by this iterator. + * @since 4.0 + */ +public class PeekingIterator implements ListIterator, LookaheadIterator { + + /** The iterator being decorated. */ + private final ListIterator iterator; + + /** Indicates that the decorated iterator is exhausted. */ + private boolean exhausted; + + /** Indicates if the lookahead slot is filled. */ + private boolean slotFilled; + + /** The current slot for lookahead. */ + private E slot; + + /** + * Decorates the specified iterator to support one-element lookahead. + *

+ * If the iterator is already a {@link PeekingIterator} it is returned directly. + * + * @param the element type + * @param iterator the iterator to decorate + * @return a new peeking iterator + * @throws NullPointerException if the iterator is null + */ + public PeekingIterator peekingIterator(final ListIterator iterator) { + Objects.requireNonNull(iterator, "iterator"); + if (iterator instanceof PeekingIterator) { + final PeekingIterator it = (PeekingIterator) iterator; + return it; + } + return new PeekingIterator<>(iterator); + } + + + /** + * Constructor. + * + * @param iterator the iterator to decorate + */ + public PeekingIterator(final ListIterator iterator) { + this.iterator = iterator; + } + + /** + * Constructor. + * + * @param list the provider of the iterator to decorate + */ + public PeekingIterator(final List list) { + this.iterator = list.listIterator(); + } + + private void fill() { + if (exhausted || slotFilled) { + return; + } + if (iterator.hasNext()) { + slot = iterator.next(); + slotFilled = true; + } else { + exhausted = true; + slot = null; + slotFilled = false; + } + } + + @Override + public boolean hasNext() { + if (exhausted) { + return false; + } + return slotFilled || iterator.hasNext(); + } + + /** + * Returns the next element in iteration without advancing the underlying iterator. + * If the iterator is already exhausted, null will be returned. + *

+ * Note: this method does not throw a {@link NoSuchElementException} if the iterator + * is already exhausted. If you want such a behavior, use {@link #element()} instead. + *

+ * The rationale behind this is to follow the {@link java.util.Queue} interface + * which uses the same terminology. + * + * @return the next element from the iterator + */ + @Override + public E peek() { + fill(); + return exhausted ? null : slot; + } + + /** + * Returns the next element in iteration without advancing the underlying iterator. + * If the iterator is already exhausted, null will be returned. + * + * @return the next element from the iterator + * @throws NoSuchElementException if the iterator is already exhausted according to {@link #hasNext()} + */ + @Override + public E element() { + fill(); + if (exhausted) { + throw new NoSuchElementException(); + } + return slot; + } + + @Override + public E next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + final E x = slotFilled ? slot : iterator.next(); + // reset the lookahead slot + slot = null; + slotFilled = false; + return x; + } + + /** + * {@inheritDoc} + * + * @throws IllegalStateException if {@link #peek()} or {@link #element()} has been called + * prior to the call to {@link #remove()} + */ + @Override + public void remove() { + if (slotFilled) { + throw new IllegalStateException("peek() or element() called before remove()"); + } + iterator.remove(); + } + + + @Override + public boolean hasPrevious() { + return iterator.hasPrevious(); + } + + + @Override + public E previous() { + return iterator.previous(); + } + + + @Override + public int nextIndex() { + return iterator.nextIndex(); + } + + /* + * Returns the index of the element that would be returned by the last call to next. + * Returns list size - 1 if the listiterator is at the end of the list. + * Returns -1 if the listiterator is at the beginning of the list. + */ + public int currentIndex() { + if (!hasPrevious()) return previousIndex(); + return nextIndex() - 1; + } + + + @Override + public int previousIndex() { + return iterator.previousIndex(); + } + + + @Override + public void set(E e) { + if (slotFilled) { + throw new IllegalStateException("peek() or element() called before set()"); + } + iterator.set(e); + } + + + @Override + public void add(E e) { + if (slotFilled) { + throw new IllegalStateException("peek() or element() called before add()"); + } + iterator.add(e); + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java index 1b813a703f..88895bbfc3 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java @@ -52,15 +52,14 @@ public void parentChange(Node observedNode, Node previousParent, Node newParent) static boolean isPhantomNode(Node node) { if (isPhantomNodeCache.containsKey(node)) { return isPhantomNodeCache.get(node); - } else { - if (node instanceof UnknownType) { + } + if (node instanceof UnknownType) { return true; } - boolean res = (node.getParentNode().isPresent() && node.getParentNode().get().hasRange() && node.hasRange() && !node.getParentNode().get().getRange().get().contains(node.getRange().get()) || inPhantomNode(node, LEVELS_TO_EXPLORE)); - isPhantomNodeCache.put(node, res); - node.register(cacheCleaner); - return res; - } + boolean res = (node.getParentNode().isPresent() && node.getParentNode().get().hasRange() && node.hasRange() && !node.getParentNode().get().getRange().get().contains(node.getRange().get()) || inPhantomNode(node, LEVELS_TO_EXPLORE)); + isPhantomNodeCache.put(node, res); + node.register(cacheCleaner); + return res; } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java index 2c6b3c6cf5..f676c44b2e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java @@ -179,11 +179,11 @@ private boolean hasOnlyWhiteSpaceForTokenFunction(JavaToken token, Function getIndentation() { if (previousToken.isPresent()) { if (TokenTypes.isEndOfLineToken(previousToken.get().getKind())) { return Optional.of(Integer.valueOf(indentation)); - } else { - return Optional.empty(); } - } else { - return Optional.of(Integer.valueOf(indentation)); + return Optional.empty(); } + return Optional.of(Integer.valueOf(indentation)); } } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ReshuffledDiffElementExtractor.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ReshuffledDiffElementExtractor.java new file mode 100755 index 0000000000..041ad5ef7e --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ReshuffledDiffElementExtractor.java @@ -0,0 +1,218 @@ +package com.github.javaparser.printer.lexicalpreservation; + +import java.util.*; + +import com.github.javaparser.printer.concretesyntaxmodel.CsmElement; +import com.github.javaparser.printer.concretesyntaxmodel.CsmMix; +import com.github.javaparser.printer.concretesyntaxmodel.CsmToken; +import com.github.javaparser.printer.lexicalpreservation.Difference.ArrayIterator; + +public class ReshuffledDiffElementExtractor { + + private final NodeText nodeText; + + private enum MatchClassification { + + ALL(1), PREVIOUS_AND_SAME(2), NEXT_AND_SAME(3), SAME_ONLY(4), ALMOST(5); + + private final int priority; + + MatchClassification(int priority) { + this.priority = priority; + } + + int getPriority() { + return priority; + } + } + + static ReshuffledDiffElementExtractor of(NodeText nodeText) { + return new ReshuffledDiffElementExtractor(nodeText); + } + + private ReshuffledDiffElementExtractor(NodeText nodeText) { + this.nodeText = nodeText; + } + + public void extract(List diffElements) { + ArrayIterator iterator = new ArrayIterator<>(diffElements); + while (iterator.hasNext()) { + DifferenceElement diffElement = iterator.next(); + if (diffElement instanceof Reshuffled) { + Reshuffled reshuffled = (Reshuffled) diffElement; + // First, let's see how many tokens we need to attribute to the previous version of the of the CsmMix + CsmMix elementsFromPreviousOrder = reshuffled.getPreviousOrder(); + CsmMix elementsFromNextOrder = reshuffled.getNextOrder(); + // This contains indexes from elementsFromNextOrder to indexes from elementsFromPreviousOrder + Map correspondanceBetweenNextOrderAndPreviousOrder = getCorrespondanceBetweenNextOrderAndPreviousOrder(elementsFromPreviousOrder, elementsFromNextOrder); + // We now find out which Node Text elements corresponds to the elements in the original CSM + List nodeTextIndexOfPreviousElements = findIndexOfCorrespondingNodeTextElement(elementsFromPreviousOrder.getElements(), nodeText); + PeekingIterator nodeTextIndexOfPreviousElementsIterator = new PeekingIterator<>(nodeTextIndexOfPreviousElements); + Map nodeTextIndexToPreviousCSMIndex = new HashMap<>(); + while (nodeTextIndexOfPreviousElementsIterator.hasNext()) { + int value = nodeTextIndexOfPreviousElementsIterator.next(); + if (value != -1) { + nodeTextIndexToPreviousCSMIndex.put(value, nodeTextIndexOfPreviousElementsIterator.currentIndex()); + } + } + int lastNodeTextIndex = nodeTextIndexOfPreviousElements.stream().max(Integer::compareTo).orElse(-1); + // Elements to be added at the end + List elementsToBeAddedAtTheEnd = new LinkedList<>(); + List nextOrderElements = elementsFromNextOrder.getElements(); + Map> elementsToAddBeforeGivenOriginalCSMElement = new HashMap<>(); + for (int ni = 0; ni < nextOrderElements.size(); ni++) { + // If it has a mapping, then it is kept + if (!correspondanceBetweenNextOrderAndPreviousOrder.containsKey(ni)) { + // Ok, it is something new. Where to put it? Let's see what is the first following + // element that has a mapping + int originalCsmIndex = -1; + for (int nj = ni + 1; nj < nextOrderElements.size() && originalCsmIndex == -1; nj++) { + if (correspondanceBetweenNextOrderAndPreviousOrder.containsKey(nj)) { + originalCsmIndex = correspondanceBetweenNextOrderAndPreviousOrder.get(nj); + if (!elementsToAddBeforeGivenOriginalCSMElement.containsKey(originalCsmIndex)) { + elementsToAddBeforeGivenOriginalCSMElement.put(originalCsmIndex, new LinkedList<>()); + } + elementsToAddBeforeGivenOriginalCSMElement.get(originalCsmIndex).add(nextOrderElements.get(ni)); + } + } + // it does not preceed anything, so it goes at the end + if (originalCsmIndex == -1) { + elementsToBeAddedAtTheEnd.add(nextOrderElements.get(ni)); + } + } + } + // We go over the original node text elements, in the order they appear in the NodeText. + // Considering an original node text element (ONE) + // * we verify if it corresponds to a CSM element. If it does not we just move on, otherwise + // we find the correspond OCE (Original CSM Element) + // * we first add new elements that are marked to be added before OCE + // * if OCE is marked to be present also in the "after" CSM we add a kept element, + // otherwise we add a removed element + // Remove the whole Reshuffled element + iterator.remove(); + if (lastNodeTextIndex != -1) { + for (int ntIndex = 0; ntIndex <= lastNodeTextIndex; ntIndex++) { + if (nodeTextIndexToPreviousCSMIndex.containsKey(ntIndex)) { + int indexOfOriginalCSMElement = nodeTextIndexToPreviousCSMIndex.get(ntIndex); + if (elementsToAddBeforeGivenOriginalCSMElement.containsKey(indexOfOriginalCSMElement)) { + for (CsmElement elementToAdd : elementsToAddBeforeGivenOriginalCSMElement.get(indexOfOriginalCSMElement)) { + iterator.add(new Added(elementToAdd)); + } + } + CsmElement originalCSMElement = elementsFromPreviousOrder.getElements().get(indexOfOriginalCSMElement); + boolean toBeKept = correspondanceBetweenNextOrderAndPreviousOrder.containsValue(indexOfOriginalCSMElement); + if (toBeKept) { + iterator.add(new Kept(originalCSMElement)); + } else { + iterator.add(new Removed(originalCSMElement)); + } + } + // else we have a simple node text element, without associated csm element, just keep ignore it + } + } + // Finally we look for the remaining new elements that were not yet added and + // add all of them + for (CsmElement elementToAdd : elementsToBeAddedAtTheEnd) { + iterator.add(new Added(elementToAdd)); + } + } + } + } + + /* + * Considering that the lists of elements are ordered, We can find the common + * elements by starting with the list before the modifications and, for each + * element, by going through the list of elements containing the modifications. + * + * We can find the common elements by starting with the list before the + * modifications (L1) and, for each element, by going through the list of elements + * containing the modifications (L2). + * + * If element A in list L1 is not found in list L2, it is a deleted element. + * If element A of list L1 is found in list L2, it is a kept element. In this + * case the search for the next element of the list L1 must start from the + * position of the last element kept {@code syncNextIndex}. + */ + private Map getCorrespondanceBetweenNextOrderAndPreviousOrder(CsmMix elementsFromPreviousOrder, + CsmMix elementsFromNextOrder) { + Map correspondanceBetweenNextOrderAndPreviousOrder = new HashMap<>(); + ArrayIterator previousOrderElementsIterator = new ArrayIterator<>( + elementsFromPreviousOrder.getElements()); + int syncNextIndex = 0; + while (previousOrderElementsIterator.hasNext()) { + CsmElement pe = previousOrderElementsIterator.next(); + ArrayIterator nextOrderElementsIterator = new ArrayIterator<>( + elementsFromNextOrder.getElements(), syncNextIndex); + while (nextOrderElementsIterator.hasNext()) { + CsmElement ne = nextOrderElementsIterator.next(); + if (!correspondanceBetweenNextOrderAndPreviousOrder.values().contains(previousOrderElementsIterator.index()) + && DifferenceElementCalculator.matching(ne, pe)) { + correspondanceBetweenNextOrderAndPreviousOrder.put(nextOrderElementsIterator.index(), + previousOrderElementsIterator.index()); + // set the position to start on the next {@code nextOrderElementsIterator} iteration + syncNextIndex = nextOrderElementsIterator.index(); + break; + } + } + } + return correspondanceBetweenNextOrderAndPreviousOrder; + } + + private List findIndexOfCorrespondingNodeTextElement(List elements, NodeText nodeText) { + List correspondingIndices = new ArrayList<>(); + PeekingIterator csmElementListIterator = new PeekingIterator<>(elements); + while ( csmElementListIterator.hasNext() ) { + boolean isFirstIterationOnCsmElements = !csmElementListIterator.hasPrevious(); + int previousCsmElementIndex = csmElementListIterator.previousIndex(); + CsmElement csmElement = csmElementListIterator.next(); + Map potentialMatches = new EnumMap<>(MatchClassification.class); + PeekingIterator nodeTextListIterator = new PeekingIterator<>(nodeText.getElements()); + while (nodeTextListIterator.hasNext()) { + boolean isFirstIterationOnNodeTextElements = !nodeTextListIterator.hasPrevious(); + TextElement textElement = nodeTextListIterator.next(); + int currentTextElementIndex = nodeTextListIterator.currentIndex(); + if (!correspondingIndices.contains(currentTextElementIndex)) { + boolean isCorresponding = csmElement.isCorrespondingElement(textElement); + if (isCorresponding) { + boolean hasSamePreviousElement = false; + if (!isFirstIterationOnNodeTextElements && !isFirstIterationOnCsmElements) { + TextElement previousTextElement = nodeText.getTextElement(currentTextElementIndex - 1); + hasSamePreviousElement = elements.get(previousCsmElementIndex).isCorrespondingElement(previousTextElement); + } + boolean hasSameNextElement = false; + if (csmElementListIterator.hasNext()) { + TextElement nextTextElement = nodeTextListIterator.peek(); + hasSameNextElement = elements.get(csmElementListIterator.nextIndex()).isCorrespondingElement(nextTextElement); + } + if (hasSamePreviousElement && hasSameNextElement) { + potentialMatches.putIfAbsent(MatchClassification.ALL, currentTextElementIndex); + } else if (hasSamePreviousElement) { + potentialMatches.putIfAbsent(MatchClassification.PREVIOUS_AND_SAME, currentTextElementIndex); + } else if (hasSameNextElement) { + potentialMatches.putIfAbsent(MatchClassification.NEXT_AND_SAME, currentTextElementIndex); + } else { + potentialMatches.putIfAbsent(MatchClassification.SAME_ONLY, currentTextElementIndex); + } + } else if (isAlmostCorrespondingElement(textElement, csmElement)) { + potentialMatches.putIfAbsent(MatchClassification.ALMOST, currentTextElementIndex); + } + } + } + // Prioritize the matches from best to worst + Optional bestMatchKey = potentialMatches.keySet().stream().min(Comparator.comparing(MatchClassification::getPriority)); + if (bestMatchKey.isPresent()) { + correspondingIndices.add(potentialMatches.get(bestMatchKey.get())); + } else { + correspondingIndices.add(-1); + } + } + return correspondingIndices; + } + + private boolean isAlmostCorrespondingElement(TextElement textElement, CsmElement csmElement) { + if (csmElement.isCorrespondingElement(textElement)) { + return false; + } + return textElement.isWhiteSpace() && csmElement instanceof CsmToken && ((CsmToken) csmElement).isWhiteSpace(); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementIteratorsFactory.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementIteratorsFactory.java index 44a8f57d7a..1f46839a97 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementIteratorsFactory.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementIteratorsFactory.java @@ -174,13 +174,13 @@ public void remove() { nodeText.removeElement(index); } }; - } else if (textElement instanceof ChildTextElement) { + } + if (textElement instanceof ChildTextElement) { ChildTextElement childTextElement = (ChildTextElement) textElement; NodeText textForChild = childTextElement.getNodeTextForWrappedNode(); return reverseIterator(textForChild); - } else { - throw new IllegalArgumentException(); } + throw new IllegalArgumentException(); } public static Iterator reverseIterator(NodeText nodeText) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java index 9f36952507..9533c62e59 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java @@ -20,14 +20,14 @@ */ package com.github.javaparser.printer.lexicalpreservation; +import java.util.Optional; + import com.github.javaparser.JavaToken; import com.github.javaparser.JavaToken.Kind; import com.github.javaparser.Range; import com.github.javaparser.ast.Node; -import java.util.Optional; - -class TokenTextElement extends TextElement { +public class TokenTextElement extends TextElement { private final JavaToken token; @@ -44,16 +44,16 @@ class TokenTextElement extends TextElement { } @Override - String expand() { + public String expand() { return token.getText(); } // Visible for testing - String getText() { + public String getText() { return token.getText(); } - int getTokenKind() { + public int getTokenKind() { return token.getKind(); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java index 029cd0de84..5ca5e74a24 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java @@ -62,9 +62,8 @@ public Object getValue(ObservableProperty property, Node node) { // Perform modification -- add to the list newNodeList.add(index, nodeAdded); return newNodeList; - } else { - return new NoChange().getValue(property, node); } + return new NoChange().getValue(property, node); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java index 888770b62e..047f2f5823 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java @@ -60,9 +60,8 @@ public Object getValue(ObservableProperty property, Node node) { // Perform modification -- remove an item from the list newNodeList.remove(index); return newNodeList; - } else { - return new NoChange().getValue(property, node); } + return new NoChange().getValue(property, node); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java index a63a7b5124..c405206c70 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java @@ -62,9 +62,8 @@ public Object getValue(ObservableProperty property, Node node) { // Perform modification -- replace an item in the list newNodeList.set(index, newValue); return newNodeList; - } else { - return new NoChange().getValue(property, node); } + return new NoChange().getValue(property, node); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java index 5040b6f913..c598796cf0 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java @@ -123,9 +123,8 @@ public MethodUsage replaceExceptionType(int i, ResolvedType replaced) { public MethodUsage replaceReturnType(ResolvedType returnType) { if (returnType == this.returnType) { return this; - } else { - return new MethodUsage(declaration, paramTypes, returnType, exceptionTypes, typeParametersMap); } + return new MethodUsage(declaration, paramTypes, returnType, exceptionTypes, typeParametersMap); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/TypeSolver.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/TypeSolver.java index d7bf5eb49d..9691331156 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/TypeSolver.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/TypeSolver.java @@ -40,9 +40,8 @@ public interface TypeSolver { default TypeSolver getRoot() { if (getParent() == null) { return this; - } else { - return getParent().getRoot(); } + return getParent().getRoot(); } /** @@ -68,9 +67,8 @@ default ResolvedReferenceTypeDeclaration solveType(String name) throws UnsolvedS SymbolReference ref = tryToSolveType(name); if (ref.isSolved()) { return ref.getCorrespondingDeclaration(); - } else { - throw new UnsolvedSymbolException(name, this.toString()); } + throw new UnsolvedSymbolException(name, this.toString()); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java index 1b71161116..dee38cce75 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java @@ -129,9 +129,8 @@ default List formalParameterTypes() { default boolean hasVariadicParameter() { if (getNumberOfParams() == 0) { return false; - } else { - return getParam(getNumberOfParams() - 1).isVariadic(); } + return getParam(getNumberOfParams() - 1).isVariadic(); } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java index e8183cf957..077e1bc8c0 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java @@ -56,8 +56,7 @@ default ResolvedParameterDeclaration asParameter() { default String describeType() { if (isVariadic()) { return getType().asArrayType().getComponentType().describe() + "..."; - } else { - return getType().describe(); } + return getType().describe(); } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java index 4e397f9f55..dd17402924 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java @@ -175,9 +175,8 @@ default ResolvedFieldDeclaration getField(String name) { Optional field = this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst(); if (field.isPresent()) { return field.get(); - } else { - throw new UnsolvedSymbolException("Field not found: " + name); } + throw new UnsolvedSymbolException("Field not found: " + name); } /** @@ -187,9 +186,8 @@ default ResolvedFieldDeclaration getVisibleField(String name) { Optional field = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst(); if (field.isPresent()) { return field.get(); - } else { - throw new IllegalArgumentException(); } + throw new IllegalArgumentException(); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java index 4044488f68..643ef83da5 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java @@ -192,7 +192,7 @@ default boolean hasBound() { */ default boolean hasLowerBound() { for (Bound b : getBounds()) { - if (b.isExtends()) { + if (b.isSuper()) { return true; } } @@ -204,7 +204,7 @@ default boolean hasLowerBound() { */ default boolean hasUpperBound() { for (Bound b : getBounds()) { - if (b.isSuper()) { + if (b.isExtends()) { return true; } } @@ -218,7 +218,7 @@ default boolean hasUpperBound() { */ default ResolvedType getLowerBound() { for (Bound b : getBounds()) { - if (b.isExtends()) { + if (b.isSuper()) { return b.getType(); } } @@ -232,7 +232,7 @@ default ResolvedType getLowerBound() { */ default ResolvedType getUpperBound() { for (Bound b : getBounds()) { - if (b.isSuper()) { + if (b.isExtends()) { return b.getType(); } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConstructorResolutionLogic.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConstructorResolutionLogic.java index 35346ced9c..d1437da5a9 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConstructorResolutionLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConstructorResolutionLogic.java @@ -168,11 +168,11 @@ public static SymbolReference findMostApplicable } if (applicableConstructors.size() == 1) { return SymbolReference.solved(applicableConstructors.get(0)); - } else { - ResolvedConstructorDeclaration winningCandidate = applicableConstructors.get(0); - ResolvedConstructorDeclaration other = null; - boolean possibleAmbiguity = false; - for (int i = 1; i < applicableConstructors.size(); i++) { + } + ResolvedConstructorDeclaration winningCandidate = applicableConstructors.get(0); + ResolvedConstructorDeclaration other = null; + boolean possibleAmbiguity = false; + for (int i = 1; i < applicableConstructors.size(); i++) { other = applicableConstructors.get(i); if (isMoreSpecific(winningCandidate, other, typeSolver)) { possibleAmbiguity = false; @@ -198,9 +198,7 @@ public static SymbolReference findMostApplicable } } } - - return SymbolReference.solved(winningCandidate); - } + return SymbolReference.solved(winningCandidate); } private static boolean isMoreSpecific(ResolvedConstructorDeclaration constructorA, diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java index c0579982d2..5718978ac7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java @@ -54,9 +54,8 @@ public static Optional getFunctionalMethod(ResolvedType type) { ResolvedReferenceTypeDeclaration typeDeclaration = optionalTypeDeclaration.get(); if (type.isReferenceType() && typeDeclaration.isInterface()) { return getFunctionalMethod(typeDeclaration); - } else { - return Optional.empty(); } + return Optional.empty(); } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java index cc0f76c6ee..d9563f2667 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java @@ -192,48 +192,56 @@ private ResolvedType placeInferenceVariables(ResolvedType type) { if (type.isWildcard()) { if (type.asWildcard().isExtends()) { return ResolvedWildcard.extendsBound(placeInferenceVariables(type.asWildcard().getBoundedType())); - } else if (type.asWildcard().isSuper()) { + } + if (type.asWildcard().isSuper()) { return ResolvedWildcard.superBound(placeInferenceVariables(type.asWildcard().getBoundedType())); - } else { - return type; } - } else if (type.isTypeVariable()) { + return type; + } + if (type.isTypeVariable()) { return inferenceVariableTypeForTp(type.asTypeParameter()); - } else if (type.isReferenceType()) { + } + if (type.isReferenceType()) { return type.asReferenceType().transformTypeParameters(tp -> placeInferenceVariables(tp)); - } else if (type.isArray()) { + } + if (type.isArray()) { return new ResolvedArrayType(placeInferenceVariables(type.asArrayType().getComponentType())); - } else if (type.isNull() || type.isPrimitive() || type.isVoid()) { + } + if (type.isNull() || type.isPrimitive() || type.isVoid()) { return type; - } else if (type.isConstraint()) { + } + if (type.isConstraint()) { return ResolvedLambdaConstraintType.bound(placeInferenceVariables(type.asConstraintType().getBound())); - } else if (type instanceof InferenceVariableType) { + } + if (type instanceof InferenceVariableType) { return type; - } else { - throw new UnsupportedOperationException(type.describe()); } + throw new UnsupportedOperationException(type.describe()); } public ResolvedType resolve(ResolvedType type) { if (type instanceof InferenceVariableType) { InferenceVariableType inferenceVariableType = (InferenceVariableType) type; return inferenceVariableType.equivalentType(); - } else if (type.isReferenceType()) { + } + if (type.isReferenceType()) { return type.asReferenceType().transformTypeParameters(tp -> resolve(tp)); - } else if (type.isNull() || type.isPrimitive() || type.isVoid()) { + } + if (type.isNull() || type.isPrimitive() || type.isVoid()) { return type; - } else if (type.isArray()) { + } + if (type.isArray()) { return new ResolvedArrayType(resolve(type.asArrayType().getComponentType())); - } else if (type.isWildcard()) { + } + if (type.isWildcard()) { if (type.asWildcard().isExtends()) { return ResolvedWildcard.extendsBound(resolve(type.asWildcard().getBoundedType())); - } else if (type.asWildcard().isSuper()) { + } + if (type.asWildcard().isSuper()) { return ResolvedWildcard.superBound(resolve(type.asWildcard().getBoundedType())); - } else { - return type; } - } else { - throw new UnsupportedOperationException(type.describe()); + return type; } + throw new UnsupportedOperationException(type.describe()); } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceVariableType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceVariableType.java index 8fc6c55173..1659c6c796 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceVariableType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceVariableType.java @@ -111,9 +111,8 @@ public ResolvedType equivalentType() { if (concreteEquivalent.isEmpty()) { if (correspondingTp == null) { return new ReferenceTypeImpl(typeSolver.getSolvedJavaLangObject()); - } else { - return new ResolvedTypeVariable(correspondingTp); } + return new ResolvedTypeVariable(correspondingTp); } if (concreteEquivalent.size() == 1) { return concreteEquivalent.iterator().next(); @@ -123,15 +122,14 @@ public ResolvedType equivalentType() { .collect(Collectors.toSet()); if (notTypeVariables.size() == 1) { return notTypeVariables.iterator().next(); - } else if (notTypeVariables.size() == 0 && !superTypes.isEmpty()) { + } + if (notTypeVariables.size() == 0 && !superTypes.isEmpty()) { if (superTypes.size() == 1) { return superTypes.iterator().next(); - } else { - throw new IllegalStateException("Super types are: " + superTypes); } - } else { - throw new IllegalStateException("Equivalent types are: " + equivalentTypes); + throw new IllegalStateException("Super types are: " + superTypes); } + throw new IllegalStateException("Equivalent types are: " + equivalentTypes); } private boolean hasInferenceVariables(ResolvedType type){ diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java index 9b68c78bf3..9d51840ebf 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java @@ -330,6 +330,9 @@ private static boolean isAssignableMatchTypeParametersMatchingQName(ResolvedRefe if (!actualParam.isTypeVariable() || !actualParam.asTypeParameter().getName().equals(expectedParamName)) { return matchTypeVariable(expectedParam.asTypeVariable(), actualParam, matchedParameters); } + // actualParam is a TypeVariable and actualParam has the same name as expectedParamName + // We should definitely consider that types are assignable + return true; } else if (expectedParam.isReferenceType()) { if (actualParam.isTypeVariable()) { return matchTypeVariable(actualParam.asTypeVariable(), expectedParam, matchedParameters); @@ -337,15 +340,15 @@ private static boolean isAssignableMatchTypeParametersMatchingQName(ResolvedRefe if (!expectedParam.equals(actualParam)) { return false; } - } else if (expectedParam.isWildcard()) { + } + if (expectedParam.isWildcard()) { if (expectedParam.asWildcard().isExtends()) { return isAssignableMatchTypeParameters(expectedParam.asWildcard().getBoundedType(), actual, matchedParameters); } // TODO verify super bound return true; - } else { - throw new UnsupportedOperationException(expectedParam.describe()); } + throw new UnsupportedOperationException(expectedParam.describe()); } return true; } @@ -356,7 +359,8 @@ private static boolean matchTypeVariable(ResolvedTypeVariable typeVariable, Reso ResolvedType matchedParameter = matchedParameters.get(typeParameterName); if (matchedParameter.isAssignableBy(type)) { return true; - } else if (type.isAssignableBy(matchedParameter)) { + } + if (type.isAssignableBy(matchedParameter)) { // update matchedParameters to contain the more general type matchedParameters.put(typeParameterName, type); return true; @@ -823,9 +827,9 @@ public static Optional findMostApplicableUsage(List me } if (applicableMethods.size() == 1) { return Optional.of(applicableMethods.get(0)); - } else { - MethodUsage winningCandidate = applicableMethods.get(0); - for (int i = 1; i < applicableMethods.size(); i++) { + } + MethodUsage winningCandidate = applicableMethods.get(0); + for (int i = 1; i < applicableMethods.size(); i++) { MethodUsage other = applicableMethods.get(i); if (isMoreSpecific(winningCandidate, other)) { // nothing to do @@ -842,8 +846,7 @@ public static Optional findMostApplicableUsage(List me } } } - return Optional.of(winningCandidate); - } + return Optional.of(winningCandidate); } private static boolean areOverride(MethodUsage winningCandidate, MethodUsage other) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java index 4150fd7f16..83c635298b 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java @@ -112,9 +112,8 @@ public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToRe ResolvedType baseTypeReplaced = baseType.replaceTypeVariables(tpToReplace, replaced, inferredTypes); if (baseTypeReplaced == baseType) { return this; - } else { - return new ResolvedArrayType(baseTypeReplaced); } + return new ResolvedArrayType(baseTypeReplaced); } // / diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java index 9c101b44c9..f590920622 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java @@ -20,11 +20,11 @@ */ package com.github.javaparser.resolution.types; -import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; - import java.util.*; import java.util.stream.Collectors; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + /** * An intersection type is defined in java as list of types separates by ampersands. * @@ -71,8 +71,14 @@ public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tp, Re List elementsReplaced = elements.stream().map(e -> e.replaceTypeVariables(tp, replaced, inferredTypes)).collect(Collectors.toList()); if (elementsReplaced.equals(elements)) { return this; - } else { - return new ResolvedIntersectionType(elementsReplaced); } + return new ResolvedIntersectionType(elementsReplaced); + } + + /* + * Returns the list of the resolved types + */ + public List getElements() { + return elements; } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java index d29e58fbde..3121c92bd4 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java @@ -140,7 +140,8 @@ public boolean isTypeVariable() { public boolean isAssignableBy(ResolvedType other) { if (other.isPrimitive()) { return this == other || promotionTypes.contains(other); - } else if (other.isReferenceType()) { + } + if (other.isReferenceType()) { if (other.asReferenceType().getQualifiedName().equals(getBoxTypeQName())) { return true; } @@ -150,9 +151,8 @@ public boolean isAssignableBy(ResolvedType other) { } } return false; - } else { - return other.isConstraint() && this.isAssignableBy(other.asConstraintType().getBound()); } + return other.isConstraint() && this.isAssignableBy(other.asConstraintType().getBound()); } public String getBoxTypeQName() { @@ -182,14 +182,16 @@ public boolean isBoolean() { * If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8). */ public ResolvedPrimitiveType bnp(ResolvedPrimitiveType other) { - // If either operand is of type double, the other is converted to double. + if (this == ResolvedPrimitiveType.DOUBLE || other == ResolvedPrimitiveType.DOUBLE) { return ResolvedPrimitiveType.DOUBLE; // Otherwise, if either operand is of type float, the other is converted to float. - } else if (this == ResolvedPrimitiveType.FLOAT || other == ResolvedPrimitiveType.FLOAT) { + } + if (this == ResolvedPrimitiveType.FLOAT || other == ResolvedPrimitiveType.FLOAT) { return ResolvedPrimitiveType.FLOAT; // Otherwise, if either operand is of type long, the other is converted to long. - } else if (this == ResolvedPrimitiveType.LONG || other == ResolvedPrimitiveType.LONG) { + } + if (this == ResolvedPrimitiveType.LONG || other == ResolvedPrimitiveType.LONG) { return ResolvedPrimitiveType.LONG; } // Otherwise, both operands are converted to type int. diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java index 4763c71eeb..d7538b0421 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java @@ -470,9 +470,11 @@ protected boolean compareConsideringTypeParameters(ResolvedReferenceType other) List thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds().stream().map(ResolvedTypeParameterDeclaration.Bound::getType).collect(Collectors.toList()); List otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds().stream().map(ResolvedTypeParameterDeclaration.Bound::getType).collect(Collectors.toList()); return thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds); - } else if (!(thisParam instanceof ResolvedTypeVariable) && otherParam instanceof ResolvedTypeVariable) { + } + if (!(thisParam instanceof ResolvedTypeVariable) && otherParam instanceof ResolvedTypeVariable) { return compareConsideringVariableTypeParameters(thisParam, (ResolvedTypeVariable) otherParam); - } else if (thisParam instanceof ResolvedTypeVariable && !(otherParam instanceof ResolvedTypeVariable)) { + } + if (thisParam instanceof ResolvedTypeVariable && !(otherParam instanceof ResolvedTypeVariable)) { return compareConsideringVariableTypeParameters(otherParam, (ResolvedTypeVariable) thisParam); } return false; diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java index 1c319dce78..f6ab1721ab 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java @@ -67,9 +67,8 @@ default boolean isArray() { default int arrayLevel() { if (isArray()) { return 1 + this.asArrayType().getComponentType().arrayLevel(); - } else { - return 0; } + return 0; } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java index e3c3d1d0d0..eb149825b5 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java @@ -80,9 +80,8 @@ public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToBe if (tpToBeReplaced.getName().equals(this.typeParameter.getName())) { inferredTypes.put(this.asTypeParameter(), replaced); return replaced; - } else { - return this; } + return this; } @Override @@ -114,9 +113,8 @@ public boolean isTypeVariable() { public boolean isAssignableBy(ResolvedType other) { if (other.isTypeVariable()) { return describe().equals(other.describe()); - } else { - return true; } + return true; } @Override diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java index b238be965a..44feaddfe8 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java @@ -20,11 +20,11 @@ */ package com.github.javaparser.resolution.types; -import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; - import java.util.*; import java.util.stream.Collectors; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; + /** * A union type is defined in java as list of types separates by pipes. * @@ -87,4 +87,11 @@ public boolean isUnionType() { public ResolvedUnionType asUnionType() { return this; } + + /* + * Returns the list of the resolved types + */ + public List getElements() { + return elements; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java index 37b7ef4e76..f89faacf65 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java @@ -102,13 +102,14 @@ public int hashCode() { public String describe() { if (type == null) { return "?"; - } else if (type == BoundType.SUPER) { + } + if (type == BoundType.SUPER) { return "? super " + boundedType.describe(); - } else if (type == BoundType.EXTENDS) { + } + if (type == BoundType.EXTENDS) { return "? extends " + boundedType.describe(); - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } public boolean isSuper() { @@ -135,13 +136,14 @@ public boolean isAssignableBy(ResolvedType other) { if (boundedType == null) { // return other.isReferenceType() && other.asReferenceType().getQualifiedName().equals(Object.class.getCanonicalName()); return false; - } else if (type == BoundType.SUPER) { + } + if (type == BoundType.SUPER) { return boundedType.isAssignableBy(other); - } else if (type == BoundType.EXTENDS) { + } + if (type == BoundType.EXTENDS) { return false; - } else { - throw new RuntimeException(); } + throw new RuntimeException(); } @Override @@ -158,9 +160,8 @@ public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToRe } if (boundedTypeReplaced != boundedType) { return new ResolvedWildcard(type, boundedTypeReplaced); - } else { - return this; } + return this; } @Override @@ -169,11 +170,11 @@ public boolean mention(List typeParameters) { } public boolean isUpperBounded() { - return isSuper(); + return isExtends(); } public boolean isLowerBounded() { - return isExtends(); + return isSuper(); } public enum BoundType { @@ -190,9 +191,8 @@ public ResolvedType solveGenericTypes(Context context) { ResolvedType boundResolved = getBoundedType().solveGenericTypes(context); if (isExtends()) { return ResolvedWildcard.extendsBound(boundResolved); - } else { - return ResolvedWildcard.superBound(boundResolved); } + return ResolvedWildcard.superBound(boundResolved); } return this; } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java index 14d2f88849..d3a5f27f71 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java @@ -54,9 +54,8 @@ default ResolvedType useThisTypeParametersOnTheGivenType(ResolvedType type) { if (type.isWildcard() && type.asWildcard().isBounded()) { if (type.asWildcard().isExtends()) { return ResolvedWildcard.extendsBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); - } else { - return ResolvedWildcard.superBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); } + return ResolvedWildcard.superBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); } if (type.isReferenceType()) { type = type.asReferenceType().transformTypeParameters(this::useThisTypeParametersOnTheGivenType); diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java index b7e03bd9a2..4ef48be77a 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java @@ -103,17 +103,15 @@ public ResolvedType getValue(ResolvedTypeParameterDeclaration typeParameter) { String qualifiedName = typeParameter.getQualifiedName(); if (nameToValue.containsKey(qualifiedName)) { return nameToValue.get(qualifiedName); - } else { - return new ResolvedTypeVariable(typeParameter); } + return new ResolvedTypeVariable(typeParameter); } public Optional getValueBySignature(String signature) { if (nameToValue.containsKey(signature)) { return Optional.of(nameToValue.get(signature)); - } else { - return Optional.empty(); } + return Optional.empty(); } public List getNames() { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java index bc4ca155a8..500891cf89 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java @@ -39,7 +39,8 @@ private CodeGenerationUtils() { public static String getterName(Class type, String name) { if (name.startsWith("is") && boolean.class.equals(type)) { return name; - } else if (Boolean.TYPE.equals(type)) { + } + if (Boolean.TYPE.equals(type)) { return "is" + capitalize(name); } return "get" + capitalize(name); @@ -48,9 +49,11 @@ public static String getterName(Class type, String name) { public static String getterToPropertyName(String getterName) { if (getterName.startsWith("is")) { return decapitalize(getterName.substring("is".length())); - } else if (getterName.startsWith("get")) { + } + if (getterName.startsWith("get")) { return decapitalize(getterName.substring("get".length())); - } else if (getterName.startsWith("has")) { + } + if (getterName.startsWith("has")) { return decapitalize(getterName.substring("has".length())); } throw new IllegalArgumentException("Unexpected getterName '" + getterName + "'"); @@ -66,9 +69,8 @@ public static String setterName(String fieldName) { public static String optionalOf(String text, boolean isOptional) { if (isOptional) { return f("Optional.of(%s)", text); - } else { - return "Optional.empty()"; } + return "Optional.empty()"; } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java index 1a48126ef9..d41947bc1a 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java @@ -55,16 +55,13 @@ default Optional getRoot(Path file) { return Optional.empty(); } return storage.map(CompilationUnit.Storage::getSourceRoot); - } else { - Log.info("Storage information not present -- an issue with providing a string rather than file reference?"); } - } else { - Log.info("Parse result not present"); + Log.info("Storage information not present -- an issue with providing a string rather than file reference?"); } - } else { - Log.info("Parsing was not successful."); - Log.info("There were (%d) problems parsing file: %s", () -> parseResult.getProblems().size(), parseResult::getProblems); + Log.info("Parse result not present"); } + Log.info("Parsing was not successful."); + Log.info("There were (%d) problems parsing file: %s", () -> parseResult.getProblems().size(), parseResult::getProblems); } catch (ParseProblemException e) { Log.info("Problem parsing file %s : %s", () -> file, () -> e.getLocalizedMessage()); } catch (RuntimeException e) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/LineSeparator.java b/javaparser-core/src/main/java/com/github/javaparser/utils/LineSeparator.java index 41fa775fa6..a27aa8aa11 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/LineSeparator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/LineSeparator.java @@ -122,25 +122,27 @@ public static LineSeparator getLineEnding(int countCr, int countLf, int countCrL public static Optional lookup(String ending) { if (CR.asRawString().equals(ending)) { return Optional.of(CR); - } else if (LF.asRawString().equals(ending)) { + } + if (LF.asRawString().equals(ending)) { return Optional.of(LF); - } else if (CRLF.asRawString().equals(ending)) { + } + if (CRLF.asRawString().equals(ending)) { return Optional.of(CRLF); - } else { - return Optional.empty(); } + return Optional.empty(); } public static Optional lookupEscaped(String ending) { if (CR.asEscapedString().equals(ending)) { return Optional.of(CR); - } else if (LF.asEscapedString().equals(ending)) { + } + if (LF.asEscapedString().equals(ending)) { return Optional.of(LF); - } else if (CRLF.asEscapedString().equals(ending)) { + } + if (CRLF.asEscapedString().equals(ending)) { return Optional.of(CRLF); - } else { - return Optional.empty(); } + return Optional.empty(); } public String describe() { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java index b2bdb6840d..88ccd0722d 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java @@ -76,18 +76,16 @@ private static int compare(Node a, Node b, boolean ignoringAnnotations) { int signLine = signum(beginLineWithoutConsideringAnnotation(a) - beginLineWithoutConsideringAnnotation(b)); if (signLine == 0) { return signum(beginColumnWithoutConsideringAnnotation(a) - beginColumnWithoutConsideringAnnotation(b)); - } else { - return signLine; } + return signLine; } Position aBegin = a.getBegin().get(); Position bBegin = b.getBegin().get(); int signLine = signum(aBegin.line - bBegin.line); if (signLine == 0) { return signum(aBegin.column - bBegin.column); - } else { - return signLine; } + return signLine; } public static AnnotationExpr getLastAnnotation(Node node) { @@ -98,9 +96,8 @@ public static AnnotationExpr getLastAnnotation(Node node) { } sortByBeginPosition(annotations); return annotations.get(annotations.size() - 1); - } else { - return null; } + return null; } private static int beginLineWithoutConsideringAnnotation(Node node) { @@ -112,37 +109,35 @@ private static int beginColumnWithoutConsideringAnnotation(Node node) { } private static Node firstNonAnnotationNode(Node node) { - // TODO: Consider the remaining "types" of thing that annotations can target ( https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html ) + if (node instanceof ClassOrInterfaceDeclaration) { // Modifiers appear before the class name -- ClassOrInterfaceDeclaration casted = (ClassOrInterfaceDeclaration) node; Modifier earliestModifier = casted.getModifiers().stream().filter(modifier -> modifier.hasRange()).min(Comparator.comparing(o -> o.getRange().get().begin)).orElse(null); if (earliestModifier == null) { return casted.getName(); - } else { - return earliestModifier; } - } else if (node instanceof MethodDeclaration) { + return earliestModifier; + } + if (node instanceof MethodDeclaration) { // Modifiers appear before the class name -- MethodDeclaration casted = (MethodDeclaration) node; Modifier earliestModifier = casted.getModifiers().stream().filter(modifier -> modifier.hasRange()).min(Comparator.comparing(o -> o.getRange().get().begin)).orElse(null); if (earliestModifier == null) { return casted.getType(); - } else { - return earliestModifier; } - } else if (node instanceof FieldDeclaration) { + return earliestModifier; + } + if (node instanceof FieldDeclaration) { // Modifiers appear before the class name -- FieldDeclaration casted = (FieldDeclaration) node; Modifier earliestModifier = casted.getModifiers().stream().filter(modifier -> modifier.hasRange()).min(Comparator.comparing(o -> o.getRange().get().begin)).orElse(null); if (earliestModifier == null) { return casted.getVariable(0).getType(); - } else { - return earliestModifier; } - } else { - return node; + return earliestModifier; } + return node; } /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java index 0d128592f2..af8058d160 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java @@ -595,9 +595,8 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th w.fork(); walks.add(w); return SKIP_SUBTREE; - } else { - return CONTINUE; } + return CONTINUE; } @Override diff --git a/javaparser-core/src/main/javacc/java.jj b/javaparser-core/src/main/javacc/java.jj index 876f724183..c3a076ce30 100644 --- a/javaparser-core/src/main/javacc/java.jj +++ b/javaparser-core/src/main/javacc/java.jj @@ -3087,7 +3087,7 @@ String Identifier(): // Make sure the module info keywords don't interfere with normal Java parsing by matching them as normal identifiers. | | | | | | | | | | // Make sure older Java versions parse - | | | | + | | | | | | // An actual plain old identifier ) { ret = token.image; setTokenKind(IDENTIFIER);} diff --git a/javaparser-symbol-solver-core/pom.xml b/javaparser-symbol-solver-core/pom.xml index 115bbe127d..e9b340a6c8 100644 --- a/javaparser-symbol-solver-core/pom.xml +++ b/javaparser-symbol-solver-core/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java index 7130e10807..95598959db 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java @@ -21,6 +21,8 @@ package com.github.javaparser.symbolsolver; +import static com.github.javaparser.resolution.Navigator.demandParentNode; + import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.*; @@ -39,8 +41,6 @@ import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*; -import static com.github.javaparser.resolution.Navigator.demandParentNode; - /** * This implementation of the SymbolResolver wraps the functionality of the library to make them easily usable * from JavaParser nodes. @@ -293,7 +293,7 @@ public T toResolvedType(Type javaparserType, Class resultClass) { public ResolvedType calculateType(Expression expression) { return JavaParserFacade.get(typeSolver).getType(expression); } - + @Override public ResolvedReferenceTypeDeclaration toTypeDeclaration(Node node) { if (node instanceof ClassOrInterfaceDeclaration) { @@ -312,7 +312,7 @@ public ResolvedReferenceTypeDeclaration toTypeDeclaration(Node node) { return new JavaParserAnnotationDeclaration((AnnotationDeclaration) node, typeSolver); } if (node instanceof EnumConstantDeclaration) { - return new JavaParserEnumDeclaration((EnumDeclaration) demandParentNode((EnumConstantDeclaration) node), typeSolver); + return new JavaParserEnumDeclaration((EnumDeclaration) demandParentNode(node), typeSolver); } throw new IllegalArgumentException("Cannot get a reference type declaration from " + node.getClass().getCanonicalName()); } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java index 82527a7911..22e86f6576 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java @@ -173,9 +173,8 @@ private String toString(MethodCallExpr node) { private String toString(SymbolReference methodDeclarationSymbolReference) { if (methodDeclarationSymbolReference.isSolved()) { return methodDeclarationSymbolReference.getCorrespondingDeclaration().getQualifiedSignature(); - } else { - return "UNSOLVED"; } + return "UNSOLVED"; } private List collectAllNodes(Node node) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/cache/InMemoryCache.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/cache/InMemoryCache.java index d20727ea32..4ef77a1b59 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/cache/InMemoryCache.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/cache/InMemoryCache.java @@ -21,6 +21,7 @@ package com.github.javaparser.symbolsolver.cache; +import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.WeakHashMap; @@ -47,7 +48,11 @@ public static InMemoryCache create( return new InMemoryCache<>(); } - private final Map mappedValues = new WeakHashMap<>(); + private final Map mappedValues; + + private InMemoryCache() { + mappedValues = Collections.synchronizedMap(new WeakHashMap<>()); + } @Override public void put(K key, V value) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java index 014fc34be6..3c80746e73 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -292,9 +292,8 @@ public SymbolReference solve(AnnotationExpr annot if (typeDeclarationSymbolReference.isSolved()) { ResolvedAnnotationDeclaration annotationDeclaration = (ResolvedAnnotationDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration(); return solved(annotationDeclaration); - } else { - return unsolved(); } + return unsolved(); } public SymbolReference solve(FieldAccessExpr fieldAccessExpr) { @@ -370,21 +369,20 @@ public ResolvedType getType(Node node, boolean solveLambdas) { Log.trace("getType on %s -> %s", () -> node, () -> res); } return node.getData(TYPE_WITH_LAMBDAS_RESOLVED); - } else { - Optional res = find(TYPE_WITH_LAMBDAS_RESOLVED, node); - if (res.isPresent()) { + } + Optional res = find(TYPE_WITH_LAMBDAS_RESOLVED, node); + if (res.isPresent()) { return res.get(); } - res = find(TYPE_WITHOUT_LAMBDAS_RESOLVED, node); - if (!res.isPresent()) { + res = find(TYPE_WITHOUT_LAMBDAS_RESOLVED, node); + if (!res.isPresent()) { ResolvedType resType = getTypeConcrete(node, solveLambdas); node.setData(TYPE_WITHOUT_LAMBDAS_RESOLVED, resType); Optional finalRes = res; Log.trace("getType on %s (no solveLambdas) -> %s", () -> node, () -> finalRes); return resType; } - return res.get(); - } + return res.get(); } private Optional find(DataKey dataKey, Node node) { @@ -560,10 +558,10 @@ protected Node findContainingTypeDeclOrObjectCreationExpr(Node node) { if (parent instanceof BodyDeclaration) { if (parent instanceof TypeDeclaration) { return parent; - } else { - detachFlag = true; } - } else if (parent instanceof ObjectCreationExpr) { + detachFlag = true; + } + if (parent instanceof ObjectCreationExpr) { if (detachFlag) { return parent; } @@ -583,10 +581,10 @@ protected Node findContainingTypeDeclOrObjectCreationExpr(Node node, String clas if (parent instanceof BodyDeclaration) { if (parent instanceof TypeDeclaration && ((TypeDeclaration) parent).getFullyQualifiedName().get().endsWith(className)) { return parent; - } else { - detachFlag = true; } - } else if (parent instanceof ObjectCreationExpr && ((ObjectCreationExpr) parent).getType().getName().asString().equals(className)) { + detachFlag = true; + } + if (parent instanceof ObjectCreationExpr && ((ObjectCreationExpr) parent).getType().getName().asString().equals(className)) { if (detachFlag) { return parent; } @@ -629,9 +627,8 @@ private Optional forEachStmtWithVariableDeclarator( node = node.get().getParentNode(); if (!node.isPresent() || !(node.get() instanceof ForEachStmt)) { return Optional.empty(); - } else { - return Optional.of((ForEachStmt)node.get()); } + return Optional.of((ForEachStmt)node.get()); } public ResolvedType convert(Type type, Node node) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java index 9c5eaafcc0..de9b56759b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java @@ -45,64 +45,90 @@ public static Context getContext(Node node, TypeSolver typeSolver) { throw new NullPointerException("Node should not be null"); } - // TODO: Is order important here? + if (node instanceof ArrayAccessExpr) { return new ArrayAccessExprContext((ArrayAccessExpr) node, typeSolver); - } else if (node instanceof AnnotationDeclaration) { + } + if (node instanceof AnnotationDeclaration) { return new AnnotationDeclarationContext((AnnotationDeclaration) node, typeSolver); - } else if (node instanceof BinaryExpr) { + } + if (node instanceof BinaryExpr) { return new BinaryExprContext((BinaryExpr) node, typeSolver); - } else if (node instanceof BlockStmt) { + } + if (node instanceof BlockStmt) { return new BlockStmtContext((BlockStmt) node, typeSolver); - } else if (node instanceof CompilationUnit) { + } + if (node instanceof CompilationUnit) { return new CompilationUnitContext((CompilationUnit) node, typeSolver); - } else if (node instanceof EnclosedExpr) { + } + if (node instanceof EnclosedExpr) { return new EnclosedExprContext((EnclosedExpr) node, typeSolver); - } else if (node instanceof ForEachStmt) { + } + if (node instanceof ForEachStmt) { return new ForEachStatementContext((ForEachStmt) node, typeSolver); - } else if (node instanceof ForStmt) { + } + if (node instanceof ForStmt) { return new ForStatementContext((ForStmt) node, typeSolver); - } else if (node instanceof IfStmt) { + } + if (node instanceof IfStmt) { return new IfStatementContext((IfStmt) node, typeSolver); - } else if (node instanceof InstanceOfExpr) { + } + if (node instanceof InstanceOfExpr) { return new InstanceOfExprContext((InstanceOfExpr) node, typeSolver); - } else if (node instanceof LambdaExpr) { + } + if (node instanceof LambdaExpr) { return new LambdaExprContext((LambdaExpr) node, typeSolver); - } else if (node instanceof MethodDeclaration) { + } + if (node instanceof MethodDeclaration) { return new MethodContext((MethodDeclaration) node, typeSolver); - } else if (node instanceof ConstructorDeclaration) { + } + if (node instanceof ConstructorDeclaration) { return new ConstructorContext((ConstructorDeclaration) node, typeSolver); - } else if (node instanceof ClassOrInterfaceDeclaration) { + } + if (node instanceof ClassOrInterfaceDeclaration) { return new ClassOrInterfaceDeclarationContext((ClassOrInterfaceDeclaration) node, typeSolver); - } else if (node instanceof MethodCallExpr) { + } + if (node instanceof MethodCallExpr) { return new MethodCallExprContext((MethodCallExpr) node, typeSolver); - } else if (node instanceof MethodReferenceExpr) { + } + if (node instanceof MethodReferenceExpr) { return new MethodReferenceExprContext((MethodReferenceExpr) node, typeSolver); - } else if (node instanceof EnumDeclaration) { + } + if (node instanceof EnumDeclaration) { return new EnumDeclarationContext((EnumDeclaration) node, typeSolver); - } else if (node instanceof FieldAccessExpr) { + } + if (node instanceof FieldAccessExpr) { return new FieldAccessContext((FieldAccessExpr) node, typeSolver); - } else if (node instanceof SwitchEntry) { + } + if (node instanceof SwitchEntry) { return new SwitchEntryContext((SwitchEntry) node, typeSolver); - } else if (node instanceof TryStmt) { + } + if (node instanceof TryStmt) { return new TryWithResourceContext((TryStmt) node, typeSolver); - } else if (node instanceof Statement) { + } + if (node instanceof Statement) { return new StatementContext<>((Statement) node, typeSolver); - } else if (node instanceof CatchClause) { + } + if (node instanceof CatchClause) { return new CatchClauseContext((CatchClause) node, typeSolver); - } else if (node instanceof UnaryExpr) { + } + if (node instanceof UnaryExpr) { return new UnaryExprContext((UnaryExpr) node, typeSolver); - } else if (node instanceof VariableDeclarator) { + } + if (node instanceof VariableDeclarator) { return new VariableDeclaratorContext((VariableDeclarator) node, typeSolver); - } else if (node instanceof VariableDeclarationExpr) { + } + if (node instanceof VariableDeclarationExpr) { return new VariableDeclarationExprContext((VariableDeclarationExpr) node, typeSolver); - } else if (node instanceof ObjectCreationExpr && + } + if (node instanceof ObjectCreationExpr && ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) { return new AnonymousClassDeclarationContext((ObjectCreationExpr) node, typeSolver); - } else if (node instanceof ObjectCreationExpr) { + } + if (node instanceof ObjectCreationExpr) { return new ObjectCreationContext((ObjectCreationExpr)node, typeSolver); - } else { - if (node instanceof NameExpr) { + } + if (node instanceof NameExpr) { // to resolve a name when in a fieldAccess context, we can go up until we get a node other than FieldAccessExpr, // in order to prevent a infinite loop if the name is the same as the field (ie x.x, x.y.x, or x.y.z.x) if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof FieldAccessExpr) { @@ -119,8 +145,8 @@ public static Context getContext(Node node, TypeSolver typeSolver) { return getContext(node.getParentNode().get().getParentNode().get(), typeSolver); } } - final Node parentNode = demandParentNode(node); - if (node instanceof ClassOrInterfaceType && parentNode instanceof ClassOrInterfaceDeclaration) { + final Node parentNode = demandParentNode(node); + if (node instanceof ClassOrInterfaceType && parentNode instanceof ClassOrInterfaceDeclaration) { ClassOrInterfaceDeclaration parentDeclaration = (ClassOrInterfaceDeclaration) parentNode; if (parentDeclaration.getImplementedTypes().contains(node) || parentDeclaration.getExtendedTypes().contains(node)) { @@ -129,8 +155,7 @@ public static Context getContext(Node node, TypeSolver typeSolver) { return new ClassOrInterfaceDeclarationExtendsContext(parentDeclaration, typeSolver); } } - return getContext(parentNode, typeSolver); - } + return getContext(parentNode, typeSolver); } public static SymbolDeclarator getSymbolDeclarator(Node node, TypeSolver typeSolver) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java index 9a999dc0fc..54528547dc 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java @@ -83,7 +83,8 @@ public TypeExtractor(TypeSolver typeSolver, JavaParserFacade facade) { public ResolvedType visit(VariableDeclarator node, Boolean solveLambdas) { if (demandParentNode(node) instanceof FieldDeclaration) { return facade.convertToUsage(node.getType()); - } else if (demandParentNode(node) instanceof VariableDeclarationExpr) { + } + if (demandParentNode(node) instanceof VariableDeclarationExpr) { return facade.convertToUsage(node.getType()); } throw new UnsupportedOperationException(demandParentNode(node).getClass().getCanonicalName()); @@ -213,16 +214,17 @@ public ResolvedType visit(EnclosedExpr node, Boolean solveLambdas) { */ private ResolvedType solveDotExpressionType(ResolvedReferenceTypeDeclaration parentType, FieldAccessExpr node) { // Fields and internal type declarations cannot have the same name. - // Thus, these checks will always be mutually exclusive. + if (parentType.isEnum() && parentType.asEnum().hasEnumConstant(node.getName().getId())) { return parentType.asEnum().getEnumConstant(node.getName().getId()).getType(); - } else if (parentType.hasField(node.getName().getId())) { + } + if (parentType.hasField(node.getName().getId())) { return parentType.getField(node.getName().getId()).getType(); - } else if (parentType.hasInternalType(node.getName().getId())) { + } + if (parentType.hasInternalType(node.getName().getId())) { return new ReferenceTypeImpl(parentType.getInternalType(node.getName().getId())); - } else { - throw new UnsolvedSymbolException(node.getName().getId()); } + throw new UnsolvedSymbolException(node.getName().getId()); } @Override @@ -333,9 +335,8 @@ public ResolvedType visit(NameExpr node, Boolean solveLambdas) { Optional value = createSolver().solveSymbolAsValue(node.getName().getId(), node); if (!value.isPresent()) { throw new UnsolvedSymbolException("Solving " + node, node.getName().getId()); - } else { - return value.get().getType(); } + return value.get().getType(); } @Override @@ -404,24 +405,22 @@ public ResolvedType visit(SuperExpr node, Boolean solveLambdas) { ResolvedTypeDeclaration resolvedTypeName = resolvedTypeNameRef.getCorrespondingDeclaration(); if (resolvedTypeName.isInterface()) { return new ReferenceTypeImpl(resolvedTypeName.asInterface()); - } else if (resolvedTypeName.isClass()) { + } + if (resolvedTypeName.isClass()) { // TODO: Maybe include a presence check? e.g. in the case of `java.lang.Object` there will be no superclass. return resolvedTypeName.asClass().getSuperClass().orElseThrow(() -> new RuntimeException("super class unexpectedly empty")); - } else { - throw new UnsupportedOperationException(node.getClass().getCanonicalName()); } - } else { - throw new UnsolvedSymbolException(className); + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); } + throw new UnsolvedSymbolException(className); } ResolvedTypeDeclaration typeOfNode = facade.getTypeDeclaration(facade.findContainingTypeDeclOrObjectCreationExpr(node)); if (typeOfNode instanceof ResolvedClassDeclaration) { // TODO: Maybe include a presence check? e.g. in the case of `java.lang.Object` there will be no superclass. return ((ResolvedClassDeclaration) typeOfNode).getSuperClass().orElseThrow(() -> new RuntimeException("super class unexpectedly empty")); - } else { - throw new UnsupportedOperationException(node.getClass().getCanonicalName()); } + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); } @Override @@ -496,8 +495,8 @@ public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) { result = resolveLambda(node, result); } return result; - } else if (demandParentNode(node) instanceof VariableDeclarator) - { + } + if (demandParentNode(node) instanceof VariableDeclarator) { VariableDeclarator decExpr = (VariableDeclarator) demandParentNode(node); ResolvedType result = decExpr.getType().resolve(); @@ -505,7 +504,8 @@ public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) { result = resolveLambda(node, result); } return result; - } else if (demandParentNode(node) instanceof AssignExpr) { + } + if (demandParentNode(node) instanceof AssignExpr) { AssignExpr assExpr = (AssignExpr) demandParentNode(node); ResolvedType result = assExpr.calculateResolvedType(); @@ -513,9 +513,8 @@ public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) { result = resolveLambda(node, result); } return result; - } else { - throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value"); } + throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value"); } private ResolvedType resolveLambda(LambdaExpr node, ResolvedType result) { @@ -635,7 +634,14 @@ public ResolvedType visit(MethodReferenceExpr node, Boolean solveLambdas) { return result; } - return refMethod.getCorrespondingDeclaration().getParam(pos).getType(); + // Since variable parameters are represented by an array, in case we deal with + // the variadic parameter we have to take into account the base type of the + // array. + ResolvedMethodDeclaration rmd = refMethod.getCorrespondingDeclaration(); + if (rmd.hasVariadicParameter() && pos >= rmd.getNumberOfParams() - 1) { + return rmd.getLastParam().getType().asArrayType().getComponentType(); + } + return rmd.getParam(pos).getType(); } throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value"); } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java index 6f6c60fe16..fc00797b6b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java @@ -157,10 +157,11 @@ public SymbolReference solveSymbolInParentCo .findFirst(); if (localResolutionResults.isPresent()) { - if(patternExprs.size() == 1) { + if (patternExprs.size() == 1) { JavaParserPatternDeclaration decl = JavaParserSymbolDeclaration.patternVar(localResolutionResults.get(), typeSolver); return SymbolReference.solved(decl); - } else if(patternExprs.size() > 1) { + } + if(patternExprs.size() > 1) { throw new IllegalStateException("Unexpectedly more than one reference in scope"); } } @@ -217,13 +218,14 @@ protected Collection findTypeDeclarations(Opti .getTypeDeclaration() .orElseThrow(() -> new RuntimeException("TypeDeclaration unexpectedly empty.")) ); - } else { - return singletonList(typeSolver.getSolvedJavaLangObject()); } - } else if (typeOfScope.isArray()) { + return singletonList(typeSolver.getSolvedJavaLangObject()); + } + if (typeOfScope.isArray()) { // method call on array are Object methods return singletonList(typeSolver.getSolvedJavaLangObject()); - } else if (typeOfScope.isTypeVariable()) { + } + if (typeOfScope.isTypeVariable()) { Collection result = new ArrayList<>(); for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { // TODO: Figure out if it is appropriate to remove the orElseThrow() -- if so, how... @@ -235,7 +237,8 @@ protected Collection findTypeDeclarations(Opti ); } return result; - } else if (typeOfScope.isConstraint()) { + } + if (typeOfScope.isConstraint()) { // TODO: Figure out if it is appropriate to remove the orElseThrow() -- if so, how... ResolvedType type = typeOfScope.asConstraintType().getBound(); if (type.isReferenceType()) { @@ -243,10 +246,10 @@ protected Collection findTypeDeclarations(Opti type.asReferenceType().getTypeDeclaration() .orElseThrow(() -> new RuntimeException("TypeDeclaration unexpectedly empty.")) ); - } else { - throw new UnsupportedOperationException("The type declaration cannot be found on constraint "+ type.describe()); } - } else if (typeOfScope.isUnionType()) { + throw new UnsupportedOperationException("The type declaration cannot be found on constraint "+ type.describe()); + } + if (typeOfScope.isUnionType()) { return typeOfScope.asUnionType().getCommonAncestor() .flatMap(ResolvedReferenceType::getTypeDeclaration) .map(Collections::singletonList) @@ -289,9 +292,8 @@ public Optional solveMethodAsUsage(String name, List MethodUsage methodUsage = ((TypeVariableResolutionCapability) methodDeclaration).resolveTypeVariables(this, argumentsTypes); return Optional.of(methodUsage); - } else { - return Optional.empty(); } + return Optional.empty(); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java index bfa3509ded..cce4dd8357 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java @@ -113,7 +113,8 @@ public final SymbolReference solveType(String name, Lis if (localType.getName().getId().equals(name)) { return SymbolReference.solved(JavaParserFacade.get(typeSolver) .getTypeDeclaration(localType)); - } else if (name.startsWith(String.format("%s.", localType.getName()))) { + } + if (name.startsWith(String.format("%s.", localType.getName()))) { return JavaParserFactory.getContext(localType, typeSolver) .solveType(name.substring(localType.getName().getId().length() + 1)); } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java index 61112b45fe..8a7be56cb2 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java @@ -81,9 +81,8 @@ public SymbolReference solveSymbol(String na SymbolReference type = this.solveType(typeName); if (type.isSolved()) { return new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName); - } else { - itName = typeName; } + itName = typeName; } // Look among statically imported values @@ -129,13 +128,16 @@ public SymbolReference solveType(String name, List qualified.equals(name)).orElse(false)) { if (type instanceof ClassOrInterfaceDeclaration) { return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type)); - } else if (type instanceof AnnotationDeclaration) { + } + + if (type instanceof AnnotationDeclaration) { return SymbolReference.solved(new JavaParserAnnotationDeclaration((AnnotationDeclaration) type, typeSolver)); - } else if (type instanceof EnumDeclaration) { + } + + if (type instanceof EnumDeclaration) { return SymbolReference.solved(new JavaParserEnumDeclaration((EnumDeclaration) type, typeSolver)); - } else { - throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } + throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } } @@ -223,28 +225,25 @@ public SymbolReference solveType(String name, List solveMethod(String name, List< SymbolReference method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true); if (method.isSolved()) { return method; - } else { - return SymbolReference.unsolved(); } + return SymbolReference.unsolved(); } } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java index 215ced0724..6d82865846 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java @@ -46,8 +46,7 @@ public static Optional solveMethodAsUsage(ResolvedTypeDeclaration t if (typeDeclaration instanceof MethodUsageResolutionCapability) { return ((MethodUsageResolutionCapability) typeDeclaration) .solveMethodAsUsage(name, argumentsTypes, invokationContext, typeParameters); - } else { - throw new UnsupportedOperationException(typeDeclaration.toString()); } + throw new UnsupportedOperationException(typeDeclaration.toString()); } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java index 4c804ad50d..54eed28196 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java @@ -88,14 +88,13 @@ public Optional solveSymbolAsValue(String name) { } if (typeOfScope.isReferenceType()) { return solveSymbolAsValue(name, typeOfScope.asReferenceType()); - } else if (typeOfScope.isConstraint()) { + } + if (typeOfScope.isConstraint()) { return solveSymbolAsValue(name, typeOfScope.asConstraintType().getBound().asReferenceType()); - } else { - return Optional.empty(); } - } else { - return solveSymbolAsValueInParentContext(name); + return Optional.empty(); } + return solveSymbolAsValueInParentContext(name); } /* diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java index cdb5feb315..378500f75e 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java @@ -51,13 +51,11 @@ public SymbolReference solveSymbol(String na VariableDeclarator variableDeclarator = wrappedNode.getVariable().getVariables().get(0); if (variableDeclarator.getName().getId().equals(name)) { return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver)); - } else { - if (demandParentNode(wrappedNode) instanceof BlockStmt) { + } + if (demandParentNode(wrappedNode) instanceof BlockStmt) { return StatementContext.solveInBlock(name, typeSolver, wrappedNode); - } else { - return solveSymbolInParentContext(name); } - } + return solveSymbolInParentContext(name); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java index 0e48055874..206074f635 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java @@ -61,9 +61,8 @@ public SymbolReference solveSymbol(String na if (demandParentNode(wrappedNode) instanceof NodeWithStatements) { return StatementContext.solveInBlock(name, typeSolver, wrappedNode); - } else { - return solveSymbolInParentContext(name); } + return solveSymbolInParentContext(name); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java index 0a99cd6950..8d7dce32e4 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java @@ -86,9 +86,11 @@ public SymbolReference solveType(String name, List internalType = member.asTypeDeclaration(); if (internalType.getName().getId().equals(name) && compareTypeParameters(internalType, typeArguments)) { return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType)); - } else if (name.startsWith(wrappedNode.getName().getId() + "." + internalType.getName().getId())) { + } + if (name.startsWith(wrappedNode.getName().getId() + "." + internalType.getName().getId())) { return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1), typeArguments); - } else if (name.startsWith(internalType.getName().getId() + ".")) { + } + if (name.startsWith(internalType.getName().getId() + ".")) { return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeArguments); } } @@ -185,9 +187,8 @@ private > boolean compareTypeParameters(T ty private boolean compareTypeParameters(TypeDeclaration typeDeclaration, List resolvedTypeArguments) { if (typeDeclaration instanceof NodeWithTypeParameters) { return compareTypeParameters((NodeWithTypeParameters) typeDeclaration, resolvedTypeArguments); - } else { - return true; } + return true; } /** @@ -215,9 +216,8 @@ private ResolvedTypeDeclaration checkAncestorsForType(String name, ResolvedRefer if (internalTypeDeclaration.getName().equals(name)) { if (visible) { return internalTypeDeclaration; - } else { - return null; // FIXME -- Avoid returning null. } + return null; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java index 5e9c133646..46841127a3 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java @@ -77,7 +77,7 @@ public Optional solveSymbolAsValue(String name) { // Get the functional method in order for us to resolve it's type arguments properly Optional functionalMethodOpt = FunctionalInterfaceLogic.getFunctionalMethod(lambdaType); - if (functionalMethodOpt.isPresent()){ + if (functionalMethodOpt.isPresent()) { MethodUsage functionalMethod = functionalMethodOpt.get(); InferenceContext inferenceContext = new InferenceContext(typeSolver); @@ -112,10 +112,10 @@ public Optional solveSymbolAsValue(String name) { } Value value = new Value(conType, name); return Optional.of(value); - } else{ - return Optional.empty(); } - } else if (parentNode instanceof VariableDeclarator) { + return Optional.empty(); + } + if (parentNode instanceof VariableDeclarator) { VariableDeclarator variableDeclarator = (VariableDeclarator) parentNode; ResolvedType t = JavaParserFacade.get(typeSolver).convertToUsage(variableDeclarator.getType()); Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t); @@ -137,10 +137,10 @@ public Optional solveSymbolAsValue(String name) { Value value = new Value(lambdaType, name); return Optional.of(value); - } else { - throw new UnsupportedOperationException(); } - } else if (parentNode instanceof ReturnStmt) { + throw new UnsupportedOperationException(); + } + if (parentNode instanceof ReturnStmt) { ReturnStmt returnStmt = (ReturnStmt) parentNode; Optional optDeclaration = returnStmt.findAncestor(MethodDeclaration.class); if (optDeclaration.isPresent()) { @@ -165,11 +165,11 @@ public Optional solveSymbolAsValue(String name) { Value value = new Value(lambdaType, name); return Optional.of(value); - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } - } else if (parentNode instanceof CastExpr) { + } + if (parentNode instanceof CastExpr) { CastExpr castExpr = (CastExpr) parentNode; ResolvedType t = JavaParserFacade.get(typeSolver).convertToUsage(castExpr.getType()); Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t); @@ -192,12 +192,10 @@ public Optional solveSymbolAsValue(String name) { Value value = new Value(lambdaType, name); return Optional.of(value); - } else { - throw new UnsupportedOperationException(); } - } else { throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java index 4909fbee3b..21b0a608c6 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java @@ -22,6 +22,7 @@ package com.github.javaparser.symbolsolver.javaparsermodel.contexts; import java.util.*; +import java.util.stream.Collectors; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; @@ -38,6 +39,7 @@ import com.github.javaparser.resolution.model.typesystem.ReferenceTypeImpl; import com.github.javaparser.resolution.types.*; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.resolution.typeinference.LeastUpperBoundLogic; import com.github.javaparser.utils.Pair; public class MethodCallExprContext extends AbstractJavaParserContext { @@ -90,10 +92,9 @@ public Optional solveMethodAsUsage(String name, List methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage); methodUsage = resolveMethodTypeParameters(methodUsage, argumentsTypes); return Optional.of(methodUsage); - } else { - throw new UnsolvedSymbolException(ref.getCorrespondingDeclaration().toString(), - "Method '" + name + "' with parameterTypes " + argumentsTypes); } + throw new UnsolvedSymbolException(ref.getCorrespondingDeclaration().toString(), + "Method '" + name + "' with parameterTypes " + argumentsTypes); } } @@ -229,9 +230,8 @@ private Optional solveMethodAsUsage(ResolvedReferenceType refType, methodUsage = methodUsage.replaceParamType(i, replaced); } return Optional.of(methodUsage); - } else { - return ref; } + return ref; } private void inferTypes(ResolvedType source, ResolvedType target, Map mappings) { @@ -410,14 +410,86 @@ private MethodUsage resolveMethodTypeParameters(MethodUsage methodUsage, List matchedTypeParameters) { + // first group all resolved types by type variable + Map> resolvedTypesByTypeVariable = groupResolvedTypeByTypeVariable(matchedTypeParameters); + // then reduce the list of resolved types with the least upper bound logic + Map reducedResolvedTypesByTypeVariable = reduceResolvedTypesByTypeVariable(resolvedTypesByTypeVariable); + // then replace resolved type by the reduced type for each type variable + convertTypesParameters(matchedTypeParameters, reducedResolvedTypesByTypeVariable); + // finally replace type parameters for (ResolvedTypeParameterDeclaration tp : matchedTypeParameters.keySet()) { methodUsage = methodUsage.replaceTypeParameter(tp, matchedTypeParameters.get(tp)); } return methodUsage; } + /* + * Update the matchedTypeParameters map from the types in reducedResolvedTypesByTypeVariable map. + */ + private void convertTypesParameters( + Map matchedTypeParameters, + Map reducedResolvedTypesByTypeVariable) { + for (ResolvedTypeParameterDeclaration tp : matchedTypeParameters.keySet()) { + String typeParameterName = tp.getName(); + boolean replacement = reducedResolvedTypesByTypeVariable.keySet().contains(typeParameterName); + if (replacement) { + matchedTypeParameters.put(tp, reducedResolvedTypesByTypeVariable.get(typeParameterName)); + } + } + } + + /* + * Group resolved type by the variable type. For example in Map.of("k0", 0, "k1", + * 1D) which is solved as static Map of(K k1, V v1, K k2, V v2) + * the type variable named V that represents the type of the first and fourth parameter + * must reference v1 (Integer type) and v2 (Double type). + */ + private Map> groupResolvedTypeByTypeVariable(Map typeParameters) { + Map> resolvedTypesByTypeVariable = new HashMap<>(); + for (ResolvedTypeParameterDeclaration tp : typeParameters.keySet()) { + String typeParameterName = tp.getName(); + boolean alreadyCollected = resolvedTypesByTypeVariable.keySet().contains(typeParameterName); + if (!alreadyCollected) { + Set resolvedTypes = findResolvedTypesByTypeVariable(typeParameterName, typeParameters); + resolvedTypesByTypeVariable.put(typeParameterName, resolvedTypes); + } + } + return resolvedTypesByTypeVariable; + } + + /* + * Collect all resolved type from a type variable name + */ + private Set findResolvedTypesByTypeVariable(String typeVariableName, Map typeParameters) { + return typeParameters.keySet().stream() + .filter(resolvedTypeParameterDeclaration -> resolvedTypeParameterDeclaration.getName().equals(typeVariableName)) + .map(resolvedTypeParameterDeclaration -> typeParameters.get(resolvedTypeParameterDeclaration)) + .collect(Collectors.toSet()); + } + + /* + * Reduce all set of resolved type with LUB + */ + private Map reduceResolvedTypesByTypeVariable(Map> typeParameters) { + Map reducedResolvedTypesList = new HashMap<>(); + for (String typeParameterName : typeParameters.keySet()) { + ResolvedType type = reduceResolvedTypesWithLub(typeParameters.get(typeParameterName)); + reducedResolvedTypesList.put(typeParameterName, type); + } + return reducedResolvedTypesList; + } + + private ResolvedType reduceResolvedTypesWithLub(Set resolvedTypes) { + return LeastUpperBoundLogic.of().lub(resolvedTypes); + } + private void matchTypeParameters(ResolvedType expectedType, ResolvedType actualType, Map matchedTypeParameters) { if (expectedType.isTypeVariable()) { ResolvedType type = actualType; @@ -491,35 +563,39 @@ private Optional solveMethodAsUsage(ResolvedTypeVariable tp, String private Optional solveMethodAsUsage(ResolvedType type, String name, List argumentsTypes, Context invokationContext) { if (type instanceof ResolvedReferenceType) { return solveMethodAsUsage((ResolvedReferenceType) type, name, argumentsTypes, invokationContext); - } else if (type instanceof LazyType) { + } + if (type instanceof LazyType) { return solveMethodAsUsage(type.asReferenceType(), name, argumentsTypes, invokationContext); - } else if (type instanceof ResolvedTypeVariable) { + } + if (type instanceof ResolvedTypeVariable) { return solveMethodAsUsage((ResolvedTypeVariable) type, name, argumentsTypes, invokationContext); - } else if (type instanceof ResolvedWildcard) { + } + if (type instanceof ResolvedWildcard) { ResolvedWildcard wildcardUsage = (ResolvedWildcard) type; if (wildcardUsage.isSuper()) { return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, invokationContext); - } else if (wildcardUsage.isExtends()) { + } + if (wildcardUsage.isExtends()) { return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, invokationContext); - } else { - return solveMethodAsUsage(new ReferenceTypeImpl(typeSolver.getSolvedJavaLangObject()), name, argumentsTypes, invokationContext); } - } else if (type instanceof ResolvedLambdaConstraintType){ + return solveMethodAsUsage(new ReferenceTypeImpl(typeSolver.getSolvedJavaLangObject()), name, argumentsTypes, invokationContext); + } + if (type instanceof ResolvedLambdaConstraintType){ ResolvedLambdaConstraintType constraintType = (ResolvedLambdaConstraintType) type; return solveMethodAsUsage(constraintType.getBound(), name, argumentsTypes, invokationContext); - } else if (type instanceof ResolvedArrayType) { + } + if (type instanceof ResolvedArrayType) { // An array inherits methods from Object not from it's component type return solveMethodAsUsage(new ReferenceTypeImpl(typeSolver.getSolvedJavaLangObject()), name, argumentsTypes, invokationContext); - } else if (type instanceof ResolvedUnionType) { + } + if (type instanceof ResolvedUnionType) { Optional commonAncestor = type.asUnionType().getCommonAncestor(); if (commonAncestor.isPresent()) { return solveMethodAsUsage(commonAncestor.get(), name, argumentsTypes, invokationContext); - } else { - throw new UnsupportedOperationException("no common ancestor available for " + type.describe()); } - } else { - throw new UnsupportedOperationException("type usage: " + type.getClass().getCanonicalName()); + throw new UnsupportedOperationException("no common ancestor available for " + type.describe()); } + throw new UnsupportedOperationException("type usage: " + type.getClass().getCanonicalName()); } private ResolvedType usingParameterTypesFromScope(ResolvedType scope, ResolvedType type, Map inferredTypes) { @@ -529,10 +605,8 @@ private ResolvedType usingParameterTypesFromScope(ResolvedType scope, ResolvedTy type = type.replaceTypeVariables(entry.a, scope.asReferenceType().getGenericParameterByName(entry.a.getName()).get(), inferredTypes); } } - return type; - } else { - return type; } + return type; } private ResolvedType applyInferredTypes(ResolvedType type, Map inferredTypes) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodReferenceExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodReferenceExprContext.java index b2d81b3a6a..36c84f804a 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodReferenceExprContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodReferenceExprContext.java @@ -21,6 +21,10 @@ package com.github.javaparser.symbolsolver.javaparsermodel.contexts; +import static com.github.javaparser.resolution.Navigator.demandParentNode; + +import java.util.*; + import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.Expression; @@ -41,10 +45,6 @@ import com.github.javaparser.resolution.types.ResolvedType; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; -import java.util.*; - -import static com.github.javaparser.resolution.Navigator.demandParentNode; - public class MethodReferenceExprContext extends AbstractJavaParserContext { /// @@ -81,14 +81,11 @@ public SymbolReference solveMethod(String name, List< SymbolReference firstResAttempt = MethodResolutionLogic.solveMethodInType(rrtd, name, argumentsTypes, false); if (firstResAttempt.isSolved()) { return firstResAttempt; - } else { - // If has not already been solved above then will be solved here if single argument type same as - // (or subclass of) rrtd, as call is actually performed on the argument itself with zero params - SymbolReference secondResAttempt = MethodResolutionLogic.solveMethodInType(rrtd, name, Collections.emptyList(), false); - if (secondResAttempt.isSolved()) { + } + SymbolReference secondResAttempt = MethodResolutionLogic.solveMethodInType(rrtd, name, Collections.emptyList(), false); + if (secondResAttempt.isSolved()) { return secondResAttempt; } - } } return SymbolReference.unsolved(); @@ -103,7 +100,13 @@ private List inferArgumentTypes() { MethodCallExpr methodCallExpr = (MethodCallExpr) demandParentNode(wrappedNode); MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(methodCallExpr); int pos = pos(methodCallExpr, wrappedNode); - ResolvedType lambdaType = methodUsage.getParamTypes().get(pos); + ResolvedMethodDeclaration rmd = methodUsage.getDeclaration(); + // Since variable parameters are represented by an array, in case we deal with + // the variadic parameter we have to take into account the base type of the + // array. + ResolvedType lambdaType = (rmd.hasVariadicParameter() && pos >= rmd.getNumberOfParams() - 1) ? + rmd.getLastParam().getType().asArrayType().getComponentType(): + methodUsage.getParamType(pos); // Get the functional method in order for us to resolve it's type arguments properly Optional functionalMethodOpt = FunctionalInterfaceLogic.getFunctionalMethod(lambdaType); @@ -133,10 +136,10 @@ private List inferArgumentTypes() { } return resolvedTypes; - } else { - throw new UnsupportedOperationException(); } - } else if (demandParentNode(wrappedNode) instanceof VariableDeclarator) { + throw new UnsupportedOperationException(); + } + if (demandParentNode(wrappedNode) instanceof VariableDeclarator) { VariableDeclarator variableDeclarator = (VariableDeclarator) demandParentNode(wrappedNode); ResolvedType t = JavaParserFacade.get(typeSolver).convertToUsage(variableDeclarator.getType()); Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t); @@ -159,10 +162,10 @@ private List inferArgumentTypes() { } return resolvedTypes; - } else { - throw new UnsupportedOperationException(); } - } else if (demandParentNode(wrappedNode) instanceof ReturnStmt) { + throw new UnsupportedOperationException(); + } + if (demandParentNode(wrappedNode) instanceof ReturnStmt) { ReturnStmt returnStmt = (ReturnStmt) demandParentNode(wrappedNode); Optional optDeclaration = returnStmt.findAncestor(MethodDeclaration.class); if (optDeclaration.isPresent()) { @@ -187,14 +190,12 @@ private List inferArgumentTypes() { } return resolvedTypes; - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } throw new UnsupportedOperationException(); - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } private int pos(MethodCallExpr callExpr, Expression param) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java index 58abcb62e3..fbc6bc85cb 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java @@ -142,12 +142,14 @@ public Optional solveSymbolAsValue(String name) { Node parentOfWrappedNode = optionalParentNode.get(); - // we should look in all the statements preceding, treating them as SymbolDeclarators + if (parentOfWrappedNode instanceof MethodDeclaration) { return parentContext.solveSymbolAsValue(name); - }else if (parentOfWrappedNode instanceof LambdaExpr) { + } + if (parentOfWrappedNode instanceof LambdaExpr) { return parentContext.solveSymbolAsValue(name); - } else if (!(parentOfWrappedNode instanceof NodeWithStatements)) { + } + if (!(parentOfWrappedNode instanceof NodeWithStatements)) { return parentContext.solveSymbolAsValue(name); } @@ -230,14 +232,17 @@ private SymbolReference solveSymbol(String n Node parentOfWrappedNode = optionalParentNode.get(); - // we should look in all the statements preceding, treating them as SymbolDeclarators + if (parentOfWrappedNode instanceof MethodDeclaration) { return solveSymbolInParentContext(name); - } else if (parentOfWrappedNode instanceof ConstructorDeclaration) { + } + if (parentOfWrappedNode instanceof ConstructorDeclaration) { return solveSymbolInParentContext(name); - } else if (parentOfWrappedNode instanceof LambdaExpr) { + } + if (parentOfWrappedNode instanceof LambdaExpr) { return solveSymbolInParentContext(name); - } else if (parentOfWrappedNode instanceof NodeWithStatements) { + } + if (parentOfWrappedNode instanceof NodeWithStatements) { // If we choose to not solve adjacent statements abort the solution process here. // In the calling context (the context that calls this) we will attempt to // resolve all prior adjacent statements, and then the common parent as the fallback. diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java index bc0e67e4a7..b4b4a1886c 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java @@ -65,9 +65,8 @@ public Optional solveSymbolAsValue(String name) { if (demandParentNode(wrappedNode) instanceof BlockStmt) { return StatementContext.solveInBlockAsValue(name, typeSolver, wrappedNode); - } else { - return solveSymbolAsValueInParentContext(name); } + return solveSymbolAsValueInParentContext(name); } @Override @@ -84,9 +83,8 @@ public SymbolReference solveSymbol(String na if (demandParentNode(wrappedNode) instanceof BlockStmt) { return StatementContext.solveInBlock(name, typeSolver, wrappedNode); - } else { - return solveSymbolInParentContext(name); } + return solveSymbolInParentContext(name); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java index d4e6b9ffae..ffa27592c1 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java @@ -71,26 +71,26 @@ static String getClassName(String base, Node container) { String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId(); if (b.isEmpty()) { return cn; - } else { - return b + "." + cn; } - } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) { + return b + "." + cn; + } + if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) { String b = getClassName(base, container.getParentNode().orElse(null)); String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId(); if (b.isEmpty()) { return cn; - } else { - return b + "." + cn; } - } else if (container instanceof com.github.javaparser.ast.body.AnnotationDeclaration) { + return b + "." + cn; + } + if (container instanceof com.github.javaparser.ast.body.AnnotationDeclaration) { String b = getClassName(base, container.getParentNode().orElse(null)); String cn = ((com.github.javaparser.ast.body.AnnotationDeclaration) container).getName().getId(); if (b.isEmpty()) { return cn; - } else { - return b + "." + cn; } - } else if (container != null) { + return b + "." + cn; + } + if (container != null) { return getClassName(base, container.getParentNode().orElse(null)); } return base; @@ -122,8 +122,7 @@ static List(container)); - } else { - return declared; } + return declared; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java index 405bac13ff..7df40f47a5 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java @@ -115,9 +115,8 @@ public String getQualifiedName() { String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null)); if (containerName.isEmpty()) { return wrappedNode.getName().getId(); - } else { - return containerName + "." + wrappedNode.getName(); } + return containerName + "." + wrappedNode.getName(); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java index 18b497aee1..7910da6373 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java @@ -86,9 +86,8 @@ public List findMembersOfKind(final Class memberClass) { .filter(node -> memberClass.isAssignableFrom(node.getClass())) .map(memberClass::cast) .collect(Collectors.toList()); - } else { - return Collections.emptyList(); } + return Collections.emptyList(); } public Context getContext() { @@ -233,9 +232,8 @@ public String getQualifiedName() { String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null)); if (containerName.isEmpty()) { return getName(); - } else { - return containerName + "." + getName(); } + return containerName + "." + getName(); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java index c73ab84457..f65179f5da 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java @@ -189,16 +189,15 @@ public String getName() { @Override public Optional getSuperClass() { - if(isJavaLangObject()) { + if (isJavaLangObject()) { // If this is java.lang.Object, it has no super class. return Optional.empty(); - } else if (wrappedNode.getExtendedTypes().isEmpty()) { + } + if (wrappedNode.getExtendedTypes().isEmpty()) { // All objects implicitly extend java.lang.Object -- inject it here (only when this isn't java.lang.Object) return Optional.of(object()); - } else { - // Otherwise, return the first ancestor (n.b.: we know it's not empty due to check above). - return Optional.of(toReferenceType(wrappedNode.getExtendedTypes().getFirst().get())); } + return Optional.of(toReferenceType(wrappedNode.getExtendedTypes().getFirst().get())); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java index 5264281b72..2aaf9170d1 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java @@ -341,11 +341,10 @@ public List getAncestors(boolean acceptIncompleteList) { public List getTypeParameters() { if (this.wrappedNode.getTypeParameters() == null) { return Collections.emptyList(); - } else { - return this.wrappedNode.getTypeParameters().stream().map( + } + return this.wrappedNode.getTypeParameters().stream().map( (tp) -> new JavaParserTypeParameter(tp, typeSolver) ).collect(Collectors.toList()); - } } /** diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java index 34bec36db4..c75e3b0c8b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java @@ -59,7 +59,8 @@ public static int getParamPos(Parameter parameter) { for (Node node : demandParentNode(parameter).getChildNodes()) { if (node == parameter) { return pos; - } else if (node instanceof Parameter) { + } + if (node instanceof Parameter) { pos++; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java index 5733080a7d..a3d4c48083 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java @@ -24,6 +24,7 @@ import java.util.*; import java.util.stream.Collectors; +import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.*; @@ -69,9 +70,8 @@ public String getQualifiedName() { String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null)); if (containerName.isEmpty()) { return wrappedNode.getName().getId(); - } else { - return containerName + "." + wrappedNode.getName().getId(); } + return containerName + "." + wrappedNode.getName().getId(); } public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { @@ -92,9 +92,8 @@ public boolean isAssignableBy(ResolvedType type) { if (type.isReferenceType()) { ResolvedReferenceTypeDeclaration other = typeSolver.solveType(type.describe()); return isAssignableBy(other); - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } /** @@ -125,30 +124,31 @@ public SymbolReference solveType(String name) { if (internalType instanceof ClassOrInterfaceDeclaration) { if (((ClassOrInterfaceDeclaration) internalType).isInterface()) { return SymbolReference.solved(new JavaParserInterfaceDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver)); - } else { - return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver)); } - } else if (internalType instanceof EnumDeclaration) { + return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver)); + } + if (internalType instanceof EnumDeclaration) { return SymbolReference.solved(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver)); - } else if (internalType instanceof AnnotationDeclaration) { + } + if (internalType instanceof AnnotationDeclaration) { return SymbolReference.solved(new JavaParserAnnotationDeclaration((com.github.javaparser.ast.body.AnnotationDeclaration) internalType, typeSolver)); - } else { - throw new UnsupportedOperationException(); } - } else if (name.startsWith(prefix) && name.length() > prefix.length()) { + throw new UnsupportedOperationException(); + } + if (name.startsWith(prefix) && name.length() > prefix.length()) { if (internalType instanceof ClassOrInterfaceDeclaration) { if (((ClassOrInterfaceDeclaration) internalType).isInterface()) { return new JavaParserInterfaceDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length())); - } else { - return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length())); } - } else if (internalType instanceof EnumDeclaration) { + return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length())); + } + if (internalType instanceof EnumDeclaration) { return new SymbolSolver(typeSolver).solveTypeInType(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver), name.substring(prefix.length())); - } else if (internalType instanceof AnnotationDeclaration) { + } + if (internalType instanceof AnnotationDeclaration) { return SymbolReference.solved(new JavaParserAnnotationDeclaration((com.github.javaparser.ast.body.AnnotationDeclaration) internalType, typeSolver)); - } else { - throw new UnsupportedOperationException(); } + throw new UnsupportedOperationException(); } } } @@ -158,6 +158,7 @@ public SymbolReference solveType(String name) { public Optional containerType() { return wrappedNode .getParentNode() + .filter(parentNode -> !(parentNode instanceof CompilationUnit)) .map(node -> node.getSymbolResolver().toTypeDeclaration(node)); } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java index ec36ebcad6..693ef20c5b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java @@ -96,11 +96,11 @@ public String getContainerQualifiedName() { ResolvedTypeParametrizable container = getContainer(); if (container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) container).getQualifiedName(); - } else if (container instanceof JavaParserConstructorDeclaration) { + } + if (container instanceof JavaParserConstructorDeclaration) { return ((JavaParserConstructorDeclaration) container).getQualifiedSignature(); - } else { - return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); } + return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); } @Override @@ -108,11 +108,11 @@ public String getContainerId() { ResolvedTypeParametrizable container = getContainer(); if (container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) container).getId(); - } else if (container instanceof JavaParserConstructorDeclaration) { + } + if (container instanceof JavaParserConstructorDeclaration) { return ((JavaParserConstructorDeclaration) container).getQualifiedSignature(); - } else { - return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); } + return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); } @Override @@ -121,7 +121,8 @@ public ResolvedTypeParametrizable getContainer() { if (parentNode instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) { com.github.javaparser.ast.body.ClassOrInterfaceDeclaration jpTypeDeclaration = (com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) parentNode; return JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration); - } else if (parentNode instanceof com.github.javaparser.ast.body.ConstructorDeclaration){ + } + if (parentNode instanceof com.github.javaparser.ast.body.ConstructorDeclaration){ com.github.javaparser.ast.body.ConstructorDeclaration jpConstructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) parentNode; Optional jpTypeDeclaration = jpConstructorDeclaration.findAncestor(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class); if (jpTypeDeclaration.isPresent()) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java index 3f1e1b88e9..1f74833c73 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java @@ -93,9 +93,8 @@ public ResolvedType getUsage(Node node) { public boolean isAssignableBy(ResolvedType type) { if (type.isTypeVariable()) { throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type.describe()); - } else { - throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type); } + throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type); } @Override @@ -125,9 +124,9 @@ public List getAncestors(boolean acceptIncompleteList) { // If no bound is declared for a type variable, Object is assumed. // https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.4 return Collections.singletonList(new ReferenceTypeImpl(typeSolver.getSolvedJavaLangObject())); - } else { - List ancestors = new ArrayList<>(); - for (ClassOrInterfaceType type : wrappedNode.getTypeBound()) { + } + List ancestors = new ArrayList<>(); + for (ClassOrInterfaceType type : wrappedNode.getTypeBound()) { try { ResolvedType resolvedType = JavaParserFacade.get(typeSolver).convertToUsage(type); ancestors.add(resolvedType.asReferenceType()); @@ -138,8 +137,7 @@ public List getAncestors(boolean acceptIncompleteList) { } } } - return ancestors; - } + return ancestors; } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java index 765ac44b69..a51bb497fc 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java @@ -72,9 +72,8 @@ public String getClassName() { String qualifiedName = getQualifiedName(); if (qualifiedName.contains(".")) { return qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1, qualifiedName.length()); - } else { - return qualifiedName; } + return qualifiedName; } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java index c56fd027c6..946aeaaf8d 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java @@ -92,7 +92,7 @@ public Set getDeclaredMethods() { @Override public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { - return isAssignableBy(new ReferenceTypeImpl(other)); + return javassistTypeDeclarationAdapter.isAssignableBy(other); } @Override @@ -194,30 +194,24 @@ public ResolvedType getUsage(Node node) { } @Override - public boolean isAssignableBy(ResolvedType type) { - if (type.isNull()) { - return true; - } - - if (type instanceof LambdaArgumentTypePlaceholder) { + public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + if (other instanceof LambdaArgumentTypePlaceholder) { return isFunctionalInterface(); } - - // TODO look into generics - if (type.describe().equals(this.getQualifiedName())) { + if (other.getQualifiedName().equals(getQualifiedName())) { return true; } - - Optional superClassOpt = getSuperClass(); - if (superClassOpt.isPresent()) { - ResolvedReferenceType superClass = superClassOpt.get(); - if (superClass.isAssignableBy(type)) { - return true; - } - } - - for (ResolvedReferenceType interfaceType : getInterfaces()) { - if (interfaceType.isAssignableBy(type)) { + Optional oSuperClass = javassistTypeDeclarationAdapter.getSuperClass(); + if (oSuperClass.isPresent()) { + ResolvedReferenceType superClass = oSuperClass.get(); + Optional oDecl = superClass.getTypeDeclaration(); + if (oDecl.isPresent() && oDecl.get().canBeAssignedTo(other)) { + return true; + } + } + + for (ResolvedReferenceType interfaze : javassistTypeDeclarationAdapter.getInterfaces()) { + if (interfaze.getTypeDeclaration().isPresent() && interfaze.getTypeDeclaration().get().canBeAssignedTo(other)) { return true; } } @@ -225,6 +219,11 @@ public boolean isAssignableBy(ResolvedType type) { return false; } + @Override + public boolean isAssignableBy(ResolvedType type) { + return javassistTypeDeclarationAdapter.isAssignableBy(type); + } + @Override public boolean isTypeParameter() { return false; diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java index 875e13b725..0a88c7e65f 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java @@ -43,21 +43,20 @@ public static ResolvedType typeUsageFor(CtClass ctClazz, TypeSolver typeSolver) try { if (ctClazz.isArray()) { return new ResolvedArrayType(typeUsageFor(ctClazz.getComponentType(), typeSolver)); - } else if (ctClazz.isPrimitive()) { + } + if (ctClazz.isPrimitive()) { if (ctClazz.getName().equals("void")) { return ResolvedVoidType.INSTANCE; - } else { - return ResolvedPrimitiveType.byName(ctClazz.getName()); } - } else { - if (ctClazz.isInterface()) { + return ResolvedPrimitiveType.byName(ctClazz.getName()); + } + if (ctClazz.isInterface()) { return new ReferenceTypeImpl(new JavassistInterfaceDeclaration(ctClazz, typeSolver)); - } else if (ctClazz.isEnum()) { + } + if (ctClazz.isEnum()) { return new ReferenceTypeImpl(new JavassistEnumDeclaration(ctClazz, typeSolver)); - } else { - return new ReferenceTypeImpl(new JavassistClassDeclaration(ctClazz, typeSolver)); } - } + return new ReferenceTypeImpl(new JavassistClassDeclaration(ctClazz, typeSolver)); } catch (NotFoundException e) { throw new RuntimeException(e); } @@ -66,27 +65,30 @@ public static ResolvedType typeUsageFor(CtClass ctClazz, TypeSolver typeSolver) public static ResolvedReferenceTypeDeclaration toTypeDeclaration(CtClass ctClazz, TypeSolver typeSolver) { if (ctClazz.isAnnotation()) { return new JavassistAnnotationDeclaration(ctClazz, typeSolver); - } else if (ctClazz.isInterface()) { + } + if (ctClazz.isInterface()) { return new JavassistInterfaceDeclaration(ctClazz, typeSolver); - } else if (ctClazz.isEnum()) { + } + if (ctClazz.isEnum()) { return new JavassistEnumDeclaration(ctClazz, typeSolver); - } else if (ctClazz.isArray()) { + } + if (ctClazz.isArray()) { throw new IllegalArgumentException("This method should not be called passing an array"); - } else { - return new JavassistClassDeclaration(ctClazz, typeSolver); } + return new JavassistClassDeclaration(ctClazz, typeSolver); } static AccessSpecifier modifiersToAccessLevel(final int modifiers) { if (Modifier.isPublic(modifiers)) { return AccessSpecifier.PUBLIC; - } else if (Modifier.isProtected(modifiers)) { + } + if (Modifier.isProtected(modifiers)) { return AccessSpecifier.PROTECTED; - } else if (Modifier.isPrivate(modifiers)) { + } + if (Modifier.isPrivate(modifiers)) { return AccessSpecifier.PRIVATE; - } else { - return AccessSpecifier.NONE; } + return AccessSpecifier.NONE; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java index 76ba87101d..d8459286ca 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java @@ -31,6 +31,7 @@ import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.*; import com.github.javaparser.resolution.logic.MethodResolutionCapability; +import com.github.javaparser.resolution.model.LambdaArgumentTypePlaceholder; import com.github.javaparser.resolution.model.SymbolReference; import com.github.javaparser.resolution.types.ResolvedReferenceType; import com.github.javaparser.resolution.types.ResolvedType; @@ -108,13 +109,13 @@ public SymbolReference solveMethod(String name, List< } @Override - public boolean isAssignableBy(ResolvedType type) { - return javassistTypeDeclarationAdapter.isAssignableBy(type); + public List getAllFields() { + return javassistTypeDeclarationAdapter.getDeclaredFields(); } @Override - public List getAllFields() { - return javassistTypeDeclarationAdapter.getDeclaredFields(); + public boolean isAssignableBy(ResolvedType type) { + return javassistTypeDeclarationAdapter.isAssignableBy(type); } @Override @@ -122,6 +123,37 @@ public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { return javassistTypeDeclarationAdapter.isAssignableBy(other); } + @Override + public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + if (other.isJavaLangObject()) { + // Everything can be assigned to {@code java.lang.Object} + return true; + } + + if (other instanceof LambdaArgumentTypePlaceholder) { + return isFunctionalInterface(); + } + if (other.getQualifiedName().equals(getQualifiedName())) { + return true; + } + Optional oSuperClass = javassistTypeDeclarationAdapter.getSuperClass(); + if (oSuperClass.isPresent()) { + ResolvedReferenceType superClass = oSuperClass.get(); + Optional oDecl = superClass.getTypeDeclaration(); + if (oDecl.isPresent() && oDecl.get().canBeAssignedTo(other)) { + return true; + } + } + for (ResolvedReferenceType interfaze : javassistTypeDeclarationAdapter.getInterfaces()) { + if (interfaze.getTypeDeclaration().isPresent() + && interfaze.getTypeDeclaration().get().canBeAssignedTo(other)) { + return true; + } + } + + return false; + } + @Override public List getAncestors(boolean acceptIncompleteList) { return javassistTypeDeclarationAdapter.getAncestors(acceptIncompleteList); diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java index ebbd8e82ec..4972032c8b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java @@ -30,7 +30,9 @@ import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.logic.FunctionalInterfaceLogic; import com.github.javaparser.resolution.model.LambdaArgumentTypePlaceholder; +import com.github.javaparser.resolution.model.typesystem.NullType; import com.github.javaparser.resolution.model.typesystem.ReferenceTypeImpl; import com.github.javaparser.resolution.types.ResolvedReferenceType; import com.github.javaparser.resolution.types.ResolvedType; @@ -84,17 +86,15 @@ public Optional getSuperClass() { return Optional.of(new ReferenceTypeImpl( typeSolver.solveType(JavassistUtils.internalNameToCanonicalName(ctClass.getClassFile().getSuperclass())) )); - } else { - // If there is a generic signature present, solve the types and return it. - SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature()); - return Optional.ofNullable( + } + SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature()); + return Optional.ofNullable( JavassistUtils.signatureTypeToType( classSignature.getSuperClass(), typeSolver, typeDeclaration ).asReferenceType() ); - } } catch (BadBytecode e) { throw new RuntimeException(e); } @@ -215,8 +215,8 @@ private String getAnnotationType(Object annotation) { public List getTypeParameters() { if (null == ctClass.getGenericSignature()) { return Collections.emptyList(); - } else { - try { + } + try { SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature()); return Arrays.stream(classSignature.getParameters()) @@ -225,7 +225,6 @@ public List getTypeParameters() { } catch (BadBytecode badBytecode) { throw new RuntimeException(badBytecode); } - } } public Optional containerType() { @@ -238,23 +237,41 @@ public Optional containerType() { } } - public boolean isAssignableBy(ResolvedType other) { + public boolean isAssignableBy(ResolvedType type) { - if (other.isNull()) { + if (type instanceof NullType) { return true; } - - if (other instanceof LambdaArgumentTypePlaceholder) { - return typeDeclaration.isFunctionalInterface(); + if (type instanceof LambdaArgumentTypePlaceholder) { + return isFunctionalInterface(); + } + if (type.isArray()) { + return false; + } + if (type.isPrimitive()) { + return false; + } + if (type.describe().equals(typeDeclaration.getQualifiedName())) { + return true; + } + if (type instanceof ReferenceTypeImpl) { + ReferenceTypeImpl otherTypeDeclaration = (ReferenceTypeImpl) type; + if(otherTypeDeclaration.getTypeDeclaration().isPresent()) { + return otherTypeDeclaration.getTypeDeclaration().get().canBeAssignedTo(typeDeclaration); + } } - return other.isAssignableBy(new ReferenceTypeImpl(typeDeclaration)); + return false; } public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { return isAssignableBy(new ReferenceTypeImpl(other)); } + private final boolean isFunctionalInterface() { + return FunctionalInterfaceLogic.getFunctionalMethod(typeDeclaration).isPresent(); + } + /** * Get the nested classes. *
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java index d1be24a2c4..22ef611492 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java @@ -91,7 +91,8 @@ public String getName() { public String getContainerQualifiedName() { if (this.container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) this.container).getQualifiedName(); - } else if (this.container instanceof ResolvedMethodLikeDeclaration) { + } + if (this.container instanceof ResolvedMethodLikeDeclaration) { return ((ResolvedMethodLikeDeclaration) this.container).getQualifiedName(); } throw new UnsupportedOperationException(); diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java index ff6cad8142..4c7b722f81 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java @@ -131,7 +131,8 @@ static ResolvedType signatureTypeToType(SignatureAttribute.Type signatureType, T ResolvedReferenceTypeDeclaration typeDeclaration = typeSolver.solveType( removeTypeArguments(internalNameToCanonicalName(getTypeName(classType)))); return new ReferenceTypeImpl(typeDeclaration, typeArguments); - } else if (signatureType instanceof SignatureAttribute.TypeVariable) { + } + if (signatureType instanceof SignatureAttribute.TypeVariable) { SignatureAttribute.TypeVariable typeVariableSignature = (SignatureAttribute.TypeVariable) signatureType; Optional typeParameterDeclarationOpt = typeParametrizable.findTypeParameter(typeVariableSignature.getName()); if (!typeParameterDeclarationOpt.isPresent()) { @@ -139,20 +140,20 @@ static ResolvedType signatureTypeToType(SignatureAttribute.Type signatureType, T } ResolvedTypeParameterDeclaration typeParameterDeclaration = typeParameterDeclarationOpt.get(); return new ResolvedTypeVariable(typeParameterDeclaration); - } else if (signatureType instanceof SignatureAttribute.ArrayType) { + } + if (signatureType instanceof SignatureAttribute.ArrayType) { SignatureAttribute.ArrayType arrayType = (SignatureAttribute.ArrayType) signatureType; ResolvedType baseType = signatureTypeToType(arrayType.getComponentType(), typeSolver, typeParametrizable); return getArrayType(baseType, arrayType.getDimension()); - } else if (signatureType instanceof SignatureAttribute.BaseType) { + } + if (signatureType instanceof SignatureAttribute.BaseType) { SignatureAttribute.BaseType baseType = (SignatureAttribute.BaseType) signatureType; if (baseType.toString().equals("void")) { return ResolvedVoidType.INSTANCE; - } else { - return ResolvedPrimitiveType.byName(baseType.toString()); } - } else { - throw new RuntimeException(signatureType.getClass().getCanonicalName()); + return ResolvedPrimitiveType.byName(baseType.toString()); } + throw new RuntimeException(signatureType.getClass().getCanonicalName()); } /* * Manage dimension of an array @@ -170,9 +171,8 @@ private static String getTypeName(SignatureAttribute.ClassType classType) { private static String removeTypeArguments(String typeName) { if (typeName.contains("<")) { return typeName.substring(0, typeName.indexOf('<')); - } else { - return typeName; } + return typeName; } static String internalNameToCanonicalName(String typeName) { @@ -182,12 +182,12 @@ static String internalNameToCanonicalName(String typeName) { private static ResolvedType objectTypeArgumentToType(SignatureAttribute.ObjectType typeArgument, TypeSolver typeSolver, ResolvedTypeParametrizable typeParametrizable) { if (typeArgument instanceof SignatureAttribute.ClassType) { return signatureTypeToType(typeArgument, typeSolver, typeParametrizable); - } else if (typeArgument instanceof SignatureAttribute.ArrayType) { + } + if (typeArgument instanceof SignatureAttribute.ArrayType) { return new ResolvedArrayType(signatureTypeToType(((SignatureAttribute.ArrayType) typeArgument).getComponentType(), typeSolver, typeParametrizable)); - } else { - String typeName = typeArgument.jvmTypeName(); - return getGenericParameterByName(typeName, typeParametrizable, typeSolver); } + String typeName = typeArgument.jvmTypeName(); + return getGenericParameterByName(typeName, typeParametrizable, typeSolver); } private static ResolvedType getGenericParameterByName(String typeName, ResolvedTypeParametrizable typeParametrizable, TypeSolver typeSolver) { @@ -200,16 +200,16 @@ private static ResolvedType typeArgumentToType(SignatureAttribute.TypeArgument t if (typeArgument.isWildcard()) { if (typeArgument.getType() == null) { return ResolvedWildcard.UNBOUNDED; - } else if (typeArgument.getKind() == '+') { + } + if (typeArgument.getKind() == '+') { return ResolvedWildcard.extendsBound(objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable)); - } else if (typeArgument.getKind() == '-') { + } + if (typeArgument.getKind() == '-') { return ResolvedWildcard.superBound(objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable)); - } else { - throw new UnsupportedOperationException(); } - } else { - return objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable); + throw new UnsupportedOperationException(); } + return objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable); } /** diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java index 5ee4aa678b..b59281efd0 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java @@ -83,11 +83,10 @@ public String getPackageName() { @Override public String getClassName() { String qualifiedName = getQualifiedName(); - if(qualifiedName.contains(".")) { + if (qualifiedName.contains(".")) { return qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1); - } else { - return qualifiedName; } + return qualifiedName; } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java index 82418c2db2..2e38f82c1b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java @@ -21,7 +21,9 @@ package com.github.javaparser.symbolsolver.reflectionmodel; +import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; @@ -30,7 +32,9 @@ import com.github.javaparser.resolution.types.ResolvedPrimitiveType; import com.github.javaparser.resolution.types.ResolvedType; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -40,14 +44,18 @@ */ public class ReflectionAnnotationMemberDeclaration implements ResolvedAnnotationMemberDeclaration { - private static Map, Function> valueAsExressionConverter = new HashMap<>(); + private static Map, Function> valueAsExpressionConverters = new HashMap<>(); static { - valueAsExressionConverter.put(Boolean.class, (value) -> new BooleanLiteralExpr(Boolean.class.cast(value))); - valueAsExressionConverter.put(Character.class, (value) -> new CharLiteralExpr(Character.class.cast(value))); - valueAsExressionConverter.put(Double.class, (value) -> new DoubleLiteralExpr(Double.class.cast(value))); - valueAsExressionConverter.put(Integer.class, (value) -> new IntegerLiteralExpr(Integer.class.cast(value))); - valueAsExressionConverter.put(Long.class, (value) -> new LongLiteralExpr(Long.class.cast(value))); - valueAsExressionConverter.put(String.class, (value) -> new StringLiteralExpr(String.class.cast(value))); + valueAsExpressionConverters.put(Boolean.class, (value) -> new BooleanLiteralExpr((Boolean) value)); + valueAsExpressionConverters.put(Character.class, (value) -> new CharLiteralExpr((Character) value)); + valueAsExpressionConverters.put(Double.class, (value) -> new DoubleLiteralExpr((Double) value)); + valueAsExpressionConverters.put(Integer.class, (value) -> new IntegerLiteralExpr((Integer) value)); + valueAsExpressionConverters.put(Long.class, (value) -> new LongLiteralExpr((Long) value)); + valueAsExpressionConverters.put(String.class, (value) -> new StringLiteralExpr((String) value)); + valueAsExpressionConverters.put(Class.class, (value) -> { + final ClassOrInterfaceType type = new ClassOrInterfaceType(null, ((Class) value).getSimpleName()); + return new ClassExpr(type); + }); } private Method annotationMember; @@ -61,8 +69,43 @@ public ReflectionAnnotationMemberDeclaration(Method annotationMember, TypeSolver @Override public Expression getDefaultValue() { Object value = annotationMember.getDefaultValue(); - Function fn = valueAsExressionConverter.get(value.getClass()); - if (fn == null) throw new UnsupportedOperationException(String.format("Obtaining the type of the annotation member %s is not supported yet.", annotationMember.getName())); + if (value == null) return null; + + if (value.getClass().isArray()) { + Object[] values = (Object[]) value; + final NodeList expressions = Arrays.stream(values) + .map(this::transformDefaultValue) + .collect(NodeList.toNodeList()); + return new ArrayInitializerExpr(expressions); + } + + return transformDefaultValue(value); + } + + private Expression transformDefaultValue(Object value) { + if (value instanceof Enum) { + final Class declaringClass = ((Enum) value).getDeclaringClass(); + final String name = ((Enum) value).name(); + return new FieldAccessExpr(new NameExpr(declaringClass.getSimpleName()), name); + } else if (value instanceof Annotation) { + final Class annotationType = ((Annotation) value).annotationType(); + final Method[] declaredMethods = annotationType.getDeclaredMethods(); + final NodeList pairs = Arrays.stream(declaredMethods) + .map(m -> { + final ReflectionAnnotationMemberDeclaration nestedMemberDeclaration = new ReflectionAnnotationMemberDeclaration(m, typeSolver); + return new MemberValuePair(m.getName(), nestedMemberDeclaration.getDefaultValue()); + }) + .collect(NodeList.toNodeList()); + + return new NormalAnnotationExpr(new Name(annotationType.getSimpleName()), pairs); + } + + Function fn = valueAsExpressionConverters.get(value.getClass()); + if (fn == null) + throw new UnsupportedOperationException( + String.format("Obtaining the default value of the annotation member %s (of type %s) is not supported yet.", + annotationMember.getName(), value.getClass().getSimpleName()) + ); return fn.apply(value); } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java index 2077f8b12f..51bbfd12e9 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java @@ -46,17 +46,20 @@ public class ReflectionFactory { public static ResolvedReferenceTypeDeclaration typeDeclarationFor(Class clazz, TypeSolver typeSolver) { if (clazz.isArray()) { throw new IllegalArgumentException("No type declaration available for an Array"); - } else if (clazz.isPrimitive()) { + } + if (clazz.isPrimitive()) { throw new IllegalArgumentException(); - } else if (clazz.isAnnotation()) { + } + if (clazz.isAnnotation()) { return new ReflectionAnnotationDeclaration(clazz, typeSolver); - } else if (clazz.isInterface()) { + } + if (clazz.isInterface()) { return new ReflectionInterfaceDeclaration(clazz, typeSolver); - } else if (clazz.isEnum()) { + } + if (clazz.isEnum()) { return new ReflectionEnumDeclaration(clazz, typeSolver); - } else { - return new ReflectionClassDeclaration(clazz, typeSolver); } + return new ReflectionClassDeclaration(clazz, typeSolver); } public static ResolvedType typeUsageFor(java.lang.reflect.Type type, TypeSolver typeSolver) { @@ -65,7 +68,8 @@ public static ResolvedType typeUsageFor(java.lang.reflect.Type type, TypeSolver boolean declaredOnClass = tv.getGenericDeclaration() instanceof java.lang.reflect.Type; ResolvedTypeParameterDeclaration typeParameter = new ReflectionTypeParameter(tv, declaredOnClass, typeSolver); return new ResolvedTypeVariable(typeParameter); - } else if (type instanceof ParameterizedType) { + } + if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; ResolvedReferenceType rawType = typeUsageFor(pt.getRawType(), typeSolver).asReferenceType(); List actualTypes = new ArrayList<>(); @@ -73,23 +77,25 @@ public static ResolvedType typeUsageFor(java.lang.reflect.Type type, TypeSolver // we consume the actual types rawType = rawType.transformTypeParameters(tp -> typeUsageFor(actualTypes.remove(0), typeSolver)).asReferenceType(); return rawType; - } else if (type instanceof Class) { + } + if (type instanceof Class) { Class c = (Class) type; if (c.isPrimitive()) { if (c.getName().equals(Void.TYPE.getName())) { return ResolvedVoidType.INSTANCE; - } else { - return ResolvedPrimitiveType.byName(c.getName()); } - } else if (c.isArray()) { + return ResolvedPrimitiveType.byName(c.getName()); + } + if (c.isArray()) { return new ResolvedArrayType(typeUsageFor(c.getComponentType(), typeSolver)); - } else { - return new ReferenceTypeImpl(typeDeclarationFor(c, typeSolver)); } - } else if (type instanceof GenericArrayType) { + return new ReferenceTypeImpl(typeDeclarationFor(c, typeSolver)); + } + if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; return new ResolvedArrayType(typeUsageFor(genericArrayType.getGenericComponentType(), typeSolver)); - } else if (type instanceof WildcardType) { + } + if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; if (wildcardType.getLowerBounds().length > 0 && wildcardType.getUpperBounds().length > 0) { if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].getTypeName().equals(JAVA_LANG_OBJECT)) { @@ -109,20 +115,20 @@ public static ResolvedType typeUsageFor(java.lang.reflect.Type type, TypeSolver return ResolvedWildcard.extendsBound(typeUsageFor(wildcardType.getUpperBounds()[0], typeSolver)); } return ResolvedWildcard.UNBOUNDED; - } else { - throw new UnsupportedOperationException(type.getClass().getCanonicalName() + " " + type); } + throw new UnsupportedOperationException(type.getClass().getCanonicalName() + " " + type); } static AccessSpecifier modifiersToAccessLevel(final int modifiers) { if (Modifier.isPublic(modifiers)) { return AccessSpecifier.PUBLIC; - } else if (Modifier.isProtected(modifiers)) { + } + if (Modifier.isProtected(modifiers)) { return AccessSpecifier.PROTECTED; - } else if (Modifier.isPrivate(modifiers)) { + } + if (Modifier.isPrivate(modifiers)) { return AccessSpecifier.PRIVATE; - } else { - return AccessSpecifier.NONE; } + return AccessSpecifier.NONE; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java index 6795800104..67e59ca33f 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java @@ -90,9 +90,8 @@ public ResolvedReferenceTypeDeclaration declaringType() { } if (method.getDeclaringClass().isEnum()) { return new ReflectionEnumDeclaration(method.getDeclaringClass(), typeSolver); - } else { - return new ReflectionClassDeclaration(method.getDeclaringClass(), typeSolver); } + return new ReflectionClassDeclaration(method.getDeclaringClass(), typeSolver); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java index d1657addfb..a5e0806038 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java @@ -96,18 +96,16 @@ public String getName() { public String getContainerQualifiedName() { if (container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) container).getQualifiedName(); - } else { - return ((ResolvedMethodLikeDeclaration) container).getQualifiedSignature(); } + return ((ResolvedMethodLikeDeclaration) container).getQualifiedSignature(); } @Override public String getContainerId() { if (container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) container).getId(); - } else { - return ((ResolvedMethodLikeDeclaration) container).getQualifiedSignature(); } + return ((ResolvedMethodLikeDeclaration) container).getQualifiedSignature(); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java index fe2aa018c9..3e458f286b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java @@ -118,9 +118,8 @@ public ResolvedTypeDeclaration solveType(Type type) { throw new UnsolvedSymbolException(JavaParserFactory.getContext(type, typeSolver).toString(), name); } return ref.getCorrespondingDeclaration(); - } else { - throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } + throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java index 01fd7549f6..4ab7d5057e 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java @@ -78,12 +78,11 @@ public static boolean isAName(Node node) { if (node instanceof FieldAccessExpr) { FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node; return isAName(fieldAccessExpr.getScope()); - } else { - return node instanceof SimpleName || + } + return node instanceof SimpleName || node instanceof Name || node instanceof ClassOrInterfaceType || node instanceof NameExpr; - } } private static Node getQualifier(Node node) { @@ -322,14 +321,13 @@ public static NameCategory classifyReference(Node name, TypeSolver typeSolver) { NameCategory first = syntacticClassificationAccordingToContext(name); // Second, a name that is initially classified by its context as an AmbiguousName or as a PackageOrTypeName is - // then reclassified to be a PackageName, TypeName, or ExpressionName. + if (first.isNeedingDisambiguation()) { NameCategory second = reclassificationOfContextuallyAmbiguousNames(name, first, typeSolver); assert !second.isNeedingDisambiguation(); return second; - } else { - return first; } + return first; } /** @@ -364,9 +362,8 @@ private static NameCategory reclassificationOfContextuallyAmbiguousPackageOrType if (isSimpleName(name)) { if (JavaParserFactory.getContext(name, typeSolver).solveType(nameAsString(name)).isSolved()) { return NameCategory.TYPE_NAME; - } else { - return NameCategory.PACKAGE_NAME; } + return NameCategory.PACKAGE_NAME; } // 6.5.4.2. Qualified PackageOrTypeNames @@ -381,9 +378,8 @@ private static NameCategory reclassificationOfContextuallyAmbiguousPackageOrType if (isQualifiedName(name)) { if (JavaParserFactory.getContext(name, typeSolver).solveType(nameAsString(name)).isSolved()) { return NameCategory.TYPE_NAME; - } else { - return NameCategory.PACKAGE_NAME; } + return NameCategory.PACKAGE_NAME; } throw new UnsupportedOperationException("This is unexpected: the name is neither simple or qualified"); @@ -410,9 +406,8 @@ private static NameCategory reclassificationOfContextuallyAmbiguousQualifiedAmbi if (leftNameCategory == NameCategory.PACKAGE_NAME) { if (typeSolver.hasType(nameAsString(nameNode))) { return NameCategory.TYPE_NAME; - } else { - return NameCategory.PACKAGE_NAME; } + return NameCategory.PACKAGE_NAME; } // * If the name to the left of the "." is reclassified as a TypeName, then: @@ -442,12 +437,10 @@ private static NameCategory reclassificationOfContextuallyAmbiguousQualifiedAmbi return NameCategory.TYPE_NAME; } return NameCategory.COMPILATION_ERROR; - } else { - throw new UnsupportedOperationException("The name is a type but it has been resolved to something that is not a reference type"); } - } else { - throw new UnsolvedSymbolException("Unable to solve context type: " + NameLogic.nameAsString(leftName)); + throw new UnsupportedOperationException("The name is a type but it has been resolved to something that is not a reference type"); } + throw new UnsolvedSymbolException("Unable to solve context type: " + NameLogic.nameAsString(leftName)); } // * If the name to the left of the "." is reclassified as an ExpressionName, then this AmbiguousName is @@ -983,23 +976,25 @@ public static String nameAsString(Node name) { } if (name instanceof Name) { return ((Name) name).asString(); - } else if (name instanceof SimpleName) { + } + if (name instanceof SimpleName) { return ((SimpleName) name).getIdentifier(); - } else if (name instanceof ClassOrInterfaceType) { + } + if (name instanceof ClassOrInterfaceType) { return ((ClassOrInterfaceType) name).asString(); - } else if (name instanceof FieldAccessExpr) { + } + if (name instanceof FieldAccessExpr) { FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) name; if (isAName(fieldAccessExpr.getScope())) { return nameAsString(fieldAccessExpr.getScope()) + "." + nameAsString(fieldAccessExpr.getName()); - } else { - throw new IllegalArgumentException(); } - } else if (name instanceof NameExpr) { + throw new IllegalArgumentException(); + } + if (name instanceof NameExpr) { return ((NameExpr) name).getNameAsString(); - } else { - throw new UnsupportedOperationException("Unknown type of name found: " + name + " (" - + name.getClass().getCanonicalName() + ")"); } + throw new UnsupportedOperationException("Unknown type of name found: " + name + " (" + + name.getClass().getCanonicalName() + ")"); } private interface PredicateOnParentAndChild

{ @@ -1017,9 +1012,8 @@ private static

boolean whenParentIs( if (child.getParentNode().isPresent()) { Node parent = child.getParentNode().get(); return parentClass.isInstance(parent) && predicate.isSatisfied(parentClass.cast(parent), child); - } else { - return false; } + return false; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/promotion/NumericConditionalExprHandler.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/promotion/NumericConditionalExprHandler.java index 2b61187906..8c1ff3a62b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/promotion/NumericConditionalExprHandler.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/promotion/NumericConditionalExprHandler.java @@ -111,7 +111,8 @@ public ResolvedType resolveType() { if (((ResolvedPrimitiveType)thenExpr).in(resolvedPrimitiveTypeSubList) && ((ResolvedPrimitiveType)elseExpr).equals(ResolvedPrimitiveType.INT)) { return thenExpr; - } else if (((ResolvedPrimitiveType)elseExpr).in(resolvedPrimitiveTypeSubList) + } + if (((ResolvedPrimitiveType)elseExpr).in(resolvedPrimitiveTypeSubList) && ((ResolvedPrimitiveType)thenExpr).equals(ResolvedPrimitiveType.INT)) { return elseExpr; } @@ -128,7 +129,8 @@ public ResolvedType resolveType() { && thenExpr.asReferenceType().toUnboxedType().get().in(resolvedPrimitiveTypeSubList) && ((ResolvedPrimitiveType)elseExpr).equals(ResolvedPrimitiveType.INT)) { return thenExpr.asReferenceType().toUnboxedType().get(); - } else if (elseExpr.isReference() && thenExpr.isPrimitive() + } + if (elseExpr.isReference() && thenExpr.isPrimitive() && elseExpr.asReferenceType().isUnboxable() && elseExpr.asReferenceType().toUnboxedType().get().in(resolvedPrimitiveTypeSubList) && ((ResolvedPrimitiveType)thenExpr).equals(ResolvedPrimitiveType.INT)) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/Bound.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/Bound.java index c432124dca..2849ed7257 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/Bound.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/Bound.java @@ -93,18 +93,16 @@ Optional isProperLowerBoundFor(InferenceVariable inferenceVari Optional partial = isProperLowerBound(); if (partial.isPresent() && partial.get().getInferenceVariable().equals(inferenceVariable)) { return partial; - } else { - return Optional.empty(); } + return Optional.empty(); } Optional isProperUpperBoundFor(InferenceVariable inferenceVariable) { Optional partial = isProperUpperBound(); if (partial.isPresent() && partial.get().getInferenceVariable().equals(inferenceVariable)) { return partial; - } else { - return Optional.empty(); } + return Optional.empty(); } /** diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/ControlFlowLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/ControlFlowLogic.java index 5bce7af578..1519504a1b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/ControlFlowLogic.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/ControlFlowLogic.java @@ -110,9 +110,8 @@ private List containedTryStmts(Statement statement) { private

boolean parentIs(Node node, Class

parentClass) { if (node.getParentNode().isPresent()) { return parentClass.isInstance(node.getParentNode().get()); - } else { - return false; } + return false; } // See JLS 14.21 @@ -167,10 +166,8 @@ public Boolean visit(IfStmt n, Void arg) { // An if-then-else statement can complete normally iff the then-statement can // complete normally or the else-statement can complete normally. return canCompleteNormally(n.getThenStmt()) || canCompleteNormally(n.getElseStmt().get()); - } else { - // An if-then statement can complete normally iff it is reachable. - return isReachable(n); } + return isReachable(n); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeHelper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeHelper.java index f9a67a80fb..4b7e654ff9 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeHelper.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeHelper.java @@ -66,9 +66,8 @@ public static boolean isProperType(ResolvedType type) { ResolvedWildcard wildcard = (ResolvedWildcard)type; if (wildcard.isBounded()) { return isProperType(wildcard.getBoundedType()); - } else { - return true; } + return true; } if (type.isPrimitive()) { return true; @@ -181,9 +180,8 @@ public static boolean areCompatibleThroughWideningReferenceConversion(ResolvedTy public static boolean areCompatibleThroughWideningPrimitiveConversion(ResolvedType s, ResolvedType t) { if (s.isPrimitive() && t.isPrimitive()) { return s.isAssignableBy(t); - } else { - return false; } + return false; } public static Set usedInferenceVariables(ResolvedType type) { @@ -229,13 +227,7 @@ public static Pair groundTargetTypeOfLambda(LambdaExpr la used18_5_3 = true; throw new UnsupportedOperationException(); } - - // - If T is a wildcard-parameterized functional interface type and the lambda expression is implicitly typed, - // then the ground target type is the non-wildcard parameterization (§9.9) of T. - - else { - return new Pair<>(nonWildcardParameterizationOf(T.asReferenceType(), typeSolver), used18_5_3); - } + return new Pair<>(nonWildcardParameterizationOf(T.asReferenceType(), typeSolver), used18_5_3); } // - Otherwise, the ground target type is T. @@ -314,9 +306,8 @@ public static MethodType getFunctionType(ResolvedType type) { Optional mu = FunctionalInterfaceLogic.getFunctionalMethod(type); if (mu.isPresent()) { return MethodType.fromMethodUsage(mu.get()); - } else { - throw new IllegalArgumentException(); } + throw new IllegalArgumentException(); } /** diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeInference.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeInference.java index 97dcdacdcd..6f6e72481a 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeInference.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/TypeInference.java @@ -66,9 +66,8 @@ public static MethodUsage toMethodUsage(MethodCallExpr call, ResolvedMethodDecla Optional instantiationSetOpt = typeInference.instantiationInference(call, methodDeclaration); if (instantiationSetOpt.isPresent()) { return instantiationSetToMethodUsage(methodDeclaration, instantiationSetOpt.get()); - } else { - throw new IllegalArgumentException(); } + throw new IllegalArgumentException(); } /// diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ExpressionCompatibleWithType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ExpressionCompatibleWithType.java index 7803ee241d..9a93b0f7d2 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ExpressionCompatibleWithType.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ExpressionCompatibleWithType.java @@ -68,9 +68,8 @@ public ReductionResult reduce(BoundSet currentBoundSet) { if (isProperType(T)) { if (isCompatibleInALooseInvocationContext(typeSolver, expression, T)) { return ReductionResult.trueResult(); - } else { - return ReductionResult.falseResult(); } + return ReductionResult.falseResult(); } // Otherwise, if the expression is a standalone expression (§15.2) of type S, the constraint reduces diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java index 5249bc9479..ce61e031a7 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java @@ -56,9 +56,8 @@ public ReductionResult reduce(BoundSet currentBoundSet) { if (isProperType(s) && isProperType(t)) { if (isCompatibleInALooseInvocationContext(s, t)) { return ReductionResult.trueResult(); - } else { - return ReductionResult.falseResult(); } + return ReductionResult.falseResult(); } // 2. Otherwise, if S is a primitive type, let S' be the result of applying boxing conversion (§5.1.7) to S. Then the constraint reduces to ‹S' → T›. diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSameAsType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSameAsType.java index cf688d4ef6..5329edad74 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSameAsType.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSameAsType.java @@ -56,9 +56,8 @@ public ReductionResult reduce(BoundSet currentBoundSet) { if (isProperType(S) && isProperType(T)) { if (S.equals(T)) { return ReductionResult.trueResult(); - } else { - return ReductionResult.falseResult(); } + return ReductionResult.falseResult(); } // - Otherwise, if S or T is the null type, the constraint reduces to false. diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSubtypeOfType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSubtypeOfType.java index e36511306d..3dc672f4bb 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSubtypeOfType.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeSubtypeOfType.java @@ -56,9 +56,8 @@ public ReductionResult reduce(BoundSet currentBoundSet) { if (isProperType(S) && isProperType(T)) { if (T.isAssignableBy(S)) { return ReductionResult.trueResult(); - } else { - return ReductionResult.falseResult(); } + return ReductionResult.falseResult(); } // - Otherwise, if S is the null type, the constraint reduces to true. diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java index cb0c6fe018..d9c70a4e31 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java @@ -92,20 +92,18 @@ public SymbolReference tryToSolveType(String n int lastDot = name.lastIndexOf('.'); if (lastDot == -1) { return SymbolReference.unsolved(); - } else { - String parentName = name.substring(0, lastDot); - String childName = name.substring(lastDot + 1); - SymbolReference parent = tryToSolveType(parentName); - if (parent.isSolved()) { + } + String parentName = name.substring(0, lastDot); + String childName = name.substring(lastDot + 1); + SymbolReference parent = tryToSolveType(parentName); + if (parent.isSolved()) { Optional innerClass = parent.getCorrespondingDeclaration() .internalTypes() .stream().filter(it -> it.getName().equals(childName)).findFirst(); return innerClass.map(SymbolReference::solved) .orElseGet(() -> SymbolReference.unsolved()); - } else { - return SymbolReference.unsolved(); } - } + return SymbolReference.unsolved(); } } else { return SymbolReference.unsolved(); diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java index 20950ffb19..124264178a 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java @@ -181,9 +181,8 @@ public ResolvedReferenceTypeDeclaration solveType(String name) throws UnsolvedSy SymbolReference res = tryToSolveType(name); if (res.isSolved()) { return res.getCorrespondingDeclaration(); - } else { - throw new UnsolvedSymbolException(name); } + throw new UnsolvedSymbolException(name); } /** diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java index 03948ccbd6..ff4aec107f 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java @@ -278,9 +278,8 @@ public ResolvedReferenceTypeDeclaration solveType(String name) throws UnsolvedSy SymbolReference ref = tryToSolveType(name); if (ref.isSolved()) { return ref.getCorrespondingDeclaration(); - } else { - throw new UnsolvedSymbolException(name); } + throw new UnsolvedSymbolException(name); } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java index 7a37222a7e..28f73d83d1 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java @@ -91,9 +91,8 @@ public void addDeclaration(String name, ResolvedReferenceTypeDeclaration typeDec public SymbolReference tryToSolveType(String name) { if (declarationMap.containsKey(name)) { return SymbolReference.solved(declarationMap.get(name)); - } else { - return SymbolReference.unsolved(); } + return SymbolReference.unsolved(); } } diff --git a/javaparser-symbol-solver-testing/pom.xml b/javaparser-symbol-solver-testing/pom.xml index 6f6d327605..5f36f4f28a 100644 --- a/javaparser-symbol-solver-testing/pom.xml +++ b/javaparser-symbol-solver-testing/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.3 + 3.25.5 4.0.0 diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3976Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3976Test.java new file mode 100755 index 0000000000..899adec21e --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3976Test.java @@ -0,0 +1,35 @@ +package com.github.javaparser.symbolsolver; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; + +import com.github.javaparser.JavaParserAdapter; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; + +public class Issue3976Test extends AbstractResolutionTest { + + @Test + @EnabledForJreRange(min = JRE.JAVA_9) + void test() { + String testCase = + "import java.util.Map;\n" + + "public class Foo {\n" + + " public Object m() {\n" + + " return Map.of(\"k0\", 0, \"k1\", 1D);\n" + + " }\n" + + "}"; + + CompilationUnit cu = JavaParserAdapter.of(createParserWithResolver(defaultTypeSolver())).parse(testCase); + + MethodCallExpr methodCallExpr = cu.findFirst(MethodCallExpr.class).get(); + + ResolvedType rt = methodCallExpr.calculateResolvedType(); + assertEquals("java.util.Map", rt.describe()); + } +} diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4037Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4037Test.java new file mode 100755 index 0000000000..338a85d2fb --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4037Test.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.symbolsolver; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.JavaParserAdapter; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodReferenceExpr; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; + +public class Issue4037Test extends AbstractResolutionTest { + + @Test + void test() { + + String code = + "public class Test1 {\n" + + " public static Integer getD2() { return null; }\n" + + " public static Integer getD1() { return null; }\n" + + " public void m(java.util.function.Supplier... rs) { }\n" + + "\n" + + " public void test() {\n" + + " new Test1().m(Test1::getD1, Test1::getD2); // exception throws\n" + + " }\n" + + " }"; + + JavaParserAdapter parser = JavaParserAdapter.of(createParserWithResolver(defaultTypeSolver())); + CompilationUnit cu = parser.parse(code); + + List exprs = cu.findAll(MethodReferenceExpr .class); + + exprs.forEach(expr -> { + assertDoesNotThrow(() -> expr.resolve()); + }); + } +} diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4124Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4124Test.java new file mode 100755 index 0000000000..1534531831 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue4124Test.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.symbolsolver; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.JavaParserAdapter; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; + +public class Issue4124Test extends AbstractResolutionTest { + + @Test + void issue4124_withDifferentTypeParameterName() { + + String code = + "import java.util.Collections;\n" + + "import java.util.List;\n" + + "public class Foo {\n" + + " public void test(List ls){\n" + + " Collections.synchronizedList(ls);\n" + + " }\n" + + "}\n"; + + CompilationUnit cu = JavaParserAdapter.of(createParserWithResolver(defaultTypeSolver())).parse(code); + + MethodCallExpr m = cu.findFirst(MethodCallExpr.class).get(); + ResolvedMethodDeclaration rmd = m.resolve(); + assertEquals("java.util.Collections.synchronizedList(java.util.List)", rmd.getQualifiedSignature()); + } + + @Test + void issue4124_withSameTypeParameterName() { + String code = + "import java.util.Collections;\n" + + "import java.util.List;\n" + + "public class Foo {\n" + + " public void test(List ls){\n" + + " Collections.synchronizedList(ls);\n" + + " }\n" + + "}\n"; + + CompilationUnit cu = JavaParserAdapter.of(createParserWithResolver(defaultTypeSolver())).parse(code); + + MethodCallExpr m = cu.findFirst(MethodCallExpr.class).get(); + ResolvedMethodDeclaration rmd = m.resolve(); + assertEquals("java.util.Collections.synchronizedList(java.util.List)", rmd.getQualifiedSignature()); + } +} diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java index 08fb1d0235..4ff72b79ed 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java @@ -34,6 +34,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.github.javaparser.JavaParserAdapter; import com.github.javaparser.ParserConfiguration; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.AccessSpecifier; @@ -49,10 +50,10 @@ import com.github.javaparser.resolution.types.ResolvedPrimitiveType; import com.github.javaparser.resolution.types.ResolvedReferenceType; import com.github.javaparser.resolution.types.ResolvedType; -import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest; import com.github.javaparser.symbolsolver.JavaSymbolSolver; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; @@ -61,7 +62,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -class JavaParserClassDeclarationTest extends AbstractSymbolResolutionTest { +class JavaParserClassDeclarationTest extends AbstractResolutionTest { private TypeSolver typeSolver; private TypeSolver typeSolverNewCode; @@ -957,7 +958,26 @@ void testHasInheritedAnnotation() throws IOException { // Set internalTypes() - // Optional containerType() + // issue #4133 + @Test + void testContainerType() { + String code = + "public class Foo {\n" + + " public static class Bar {\n" + + " public static class Baz {\n" + + " }\n" + + " }\n" + + "}\n"; + + JavaParserAdapter parser = JavaParserAdapter.of(createParserWithResolver(defaultTypeSolver())); + CompilationUnit cu = parser.parse(code); + + List declarations = cu.findAll(ClassOrInterfaceDeclaration.class); + // top level type + assertFalse(declarations.get(0).resolve().asReferenceType().containerType().isPresent()); + assertEquals("Foo", declarations.get(1).resolve().asReferenceType().containerType().get().getQualifiedName()); + assertEquals("Foo.Bar", declarations.get(2).resolve().asReferenceType().containerType().get().getQualifiedName()); + } @Test diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java index cb0eee4079..1b167ca664 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java @@ -539,7 +539,8 @@ void whenEqualTypeIsProvided() { void whenSuperClassIsProvided() { ResolvedReferenceTypeDeclaration node = newTypeSolver.solveType("com.github.javaparser.ast.Node"); JavassistClassDeclaration cu = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit"); - assertTrue(cu.isAssignableBy(node)); + assertFalse(cu.isAssignableBy(node)); + assertTrue(node.isAssignableBy(cu)); } @Test @@ -548,7 +549,8 @@ void whenInterfaceIsProvided() { "com.github.javaparser.ast.nodeTypes.NodeWithImplements"); JavassistClassDeclaration classDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType( "com.github.javaparser.ast.body.ClassOrInterfaceDeclaration"); - assertTrue(classDeclaration.isAssignableBy(nodeWithImplements)); + assertFalse(classDeclaration.isAssignableBy(nodeWithImplements)); + assertTrue(nodeWithImplements.isAssignableBy(classDeclaration)); } } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java index 6cffe3c671..d19abdbcde 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java @@ -225,8 +225,8 @@ void whenInterfaceIsProvided() { memoryTypeSolver.addDeclaration("B", declarationB); // Knowing that B extends A we expect: - assertFalse(declarationA.isAssignableBy(declarationB), "This should not be allowed: B variable = new A()"); - assertTrue(declarationB.isAssignableBy(declarationA), "This should be allowed: A variable = new B()"); + assertTrue(declarationA.isAssignableBy(declarationB), "This should not be allowed: A variable = new B()"); + assertFalse(declarationB.isAssignableBy(declarationA), "This should be allowed: B variable = new A()"); } } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java index def3dcac88..452a4ddab0 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java @@ -21,6 +21,24 @@ package com.github.javaparser.symbolsolver.model.typesystem; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; +import java.io.Serializable; +import java.net.ProtocolException; +import java.nio.Buffer; +import java.nio.CharBuffer; +import java.nio.file.FileSystemException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import com.github.javaparser.*; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; @@ -37,23 +55,6 @@ import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.io.Serializable; -import java.net.ProtocolException; -import java.nio.Buffer; -import java.nio.CharBuffer; -import java.nio.file.FileSystemException; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.junit.jupiter.api.Assertions.*; class ReferenceTypeTest extends AbstractSymbolResolutionTest { @@ -102,7 +103,7 @@ void setup() { new ReferenceTypeImpl(new ReflectionClassDeclaration(ClassCastException.class, typeSolver)), new ReferenceTypeImpl(new ReflectionClassDeclaration(AssertionError.class, typeSolver)) )); - + // minimal initialization of JavaParser ParserConfiguration configuration = new ParserConfiguration() .setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver())); @@ -267,7 +268,8 @@ public ResolvedReferenceTypeTester(ResolvedReferenceTypeDeclaration typeDeclarat super(typeDeclaration); } - public boolean isCorrespondingBoxingType(String name) { + @Override + public boolean isCorrespondingBoxingType(String name) { return super.isCorrespondingBoxingType(name); } @@ -335,7 +337,7 @@ void testIsAssignableByGenericsInheritance() { assertEquals(false, linkedListOfString.isAssignableBy(listOfStrings)); assertEquals(true, linkedListOfString.isAssignableBy(linkedListOfString)); } - + @Test void testIsAssignableByUnionType() { assertEquals(true, ioException.isAssignableBy(unionWithIOExceptionAsCommonAncestor)); @@ -852,7 +854,7 @@ void testGetAllFieldsVisibleToInheritors() { assertTrue(rtB.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("l"))); assertTrue(rtB.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("b"))); } - + @Test void erasure_non_generic_type() { List types = declaredTypes( @@ -860,7 +862,7 @@ void erasure_non_generic_type() { ResolvedType expected = types.get(0); assertEquals(expected, types.get(0).erasure()); } - + @Test // The erasure of a parameterized type void erasure_rawtype() { @@ -882,7 +884,7 @@ void erasure_arraytype() { String expected = "java.util.List[]"; assertEquals(expected, genericList.erasure().describe()); } - + @Test // The erasure of an array type T[] is |T|[]. void erasure_arraytype_with_bound() { @@ -892,7 +894,7 @@ void erasure_arraytype_with_bound() { String expected = "java.util.List[]"; assertEquals(expected, genericList.erasure().describe()); } - + @Test // The erasure of a type variable (§4.4) is the erasure of its leftmost bound. void erasure_type_variable() { @@ -902,7 +904,7 @@ void erasure_type_variable() { String expected = "A"; assertEquals(expected, rt.erasure().describe()); } - + @Test // The erasure of a nested type T.C is |T|.C. void erasure_nested_type() { @@ -926,17 +928,31 @@ void erasure_nested_type() { // assertEquals(expectedErasedAType, typeA.erasure()); assertEquals(expectedErasedCType, typeC.erasure()); } - + + @Test + void extend_type() { + ResolvedTypeVariable variable = parametrizedType("java.util.List", "java.lang.String"); + assertTrue(variable.asTypeParameter().hasUpperBound()); + assertFalse(variable.asTypeParameter().hasLowerBound()); + } + + @Test + void super_type() { + ResolvedTypeVariable variable = parametrizedTypeLowerBounded("java.util.List", "java.lang.String"); + assertTrue(variable.asTypeParameter().hasLowerBound()); + assertFalse(variable.asTypeParameter().hasUpperBound()); + } + // return a generic type with type arguments (arguments can be bounded) private ResolvedType genericType(String type, ResolvedType... parameterTypes) { return type(type, toList(parameterTypes)); } - + // return a generic type with type arguments private ResolvedType genericType(String type, String... parameterTypes) { return new ReferenceTypeImpl(typeSolver.solveType(type), types(parameterTypes)); } - + // return a list of types private List types(String... types) { return Arrays.stream(types).map(type -> type(type)).collect(Collectors.toList()); @@ -946,36 +962,50 @@ private List types(String... types) { private ResolvedType type(String type) { return type(type, new ArrayList<>()); } - + private ResolvedType type(String type, List typeArguments) { return new ReferenceTypeImpl(typeSolver.solveType(type), typeArguments); } - + // return a type parameter private ResolvedTypeVariable parametrizedType(String type, String parameterType) { + return parametrizedTypeUpperBounded(type, parameterType); + } + + private ResolvedTypeVariable parametrizedTypeUpperBounded(String type, String parameterType) { return new ResolvedTypeVariable(ResolvedTypeParameterDeclaration.onType(parameterType, type + "." + parameterType, Arrays.asList((extendBound(parameterType))))); } - // rturn an extend bound + private ResolvedTypeVariable parametrizedTypeLowerBounded(String type, String parameterType) { + return new ResolvedTypeVariable(ResolvedTypeParameterDeclaration.onType(parameterType, type + "." + parameterType, + Arrays.asList((superBound(parameterType))))); + } + + // return an extend bound private Bound extendBound(String type) { return Bound.extendsBound(type(type)); } + // return a super bound + private Bound superBound(String type) { + return Bound.superBound(type(type)); + } + private Set toSet(ResolvedType... resolvedTypes) { return new HashSet<>(toList(resolvedTypes)); } - + private List toList(ResolvedType... resolvedTypes) { return Arrays.asList(resolvedTypes); } - + // return an array type from the base type private ResolvedType array(ResolvedType baseType) { return new ResolvedArrayType(baseType); } - - // return a list of types from the declared types (using a static parser) + + // return a list of types from the declared types (using a static parser) private List declaredTypes(String... lines) { CompilationUnit tree = treeOf(lines); List results = Lists.newLinkedList(); @@ -992,5 +1022,5 @@ private CompilationUnit treeOf(String... lines) { } return StaticJavaParser.parse(builder.toString()); } - + } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java index 947f689130..33dca095da 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java @@ -23,8 +23,10 @@ import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.resolution.Navigator; import com.github.javaparser.resolution.declarations.ResolvedAnnotationDeclaration; import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration; @@ -57,7 +59,7 @@ class AnnotationsResolutionTest extends AbstractResolutionTest { void configureSymbolSolver() throws IOException { // configure symbol solver before parsing CombinedTypeSolver typeSolver = new CombinedTypeSolver(); - typeSolver.add(new ReflectionTypeSolver()); + typeSolver.add(new ReflectionTypeSolver(false)); typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar"))); StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver)); } @@ -359,4 +361,84 @@ void solveInnerClassAnnotationMember() throws IOException { assertEquals(am.getType().asReferenceType().getQualifiedName(), "foo.bar.MyAnnotationWithInnerClass.MyInnerClass"); } + @Test + void solveReflectionMarkerAnnotationWithDefaultArrayValue() throws IOException { + // parse compilation unit and get annotation expression + CompilationUnit cu = parseSample("Annotations"); + ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CI"); + + MarkerAnnotationExpr annotationExpr = clazz.getAnnotation(0).asMarkerAnnotationExpr(); + + // resolve annotation expression + ResolvedAnnotationDeclaration resolved = annotationExpr.resolve(); + + // Class[] - {} + Expression arrayExpr = findAnnotationMemberByName(resolved, "packagesOf").getDefaultValue(); + assertInstanceOf(ArrayInitializerExpr.class, arrayExpr); + final NodeList values = ((ArrayInitializerExpr) arrayExpr).getValues(); + assertTrue(values.isNonEmpty()); + assertTrue(values.get(0).isClassExpr()); + assertEquals("MethodHandle", values.get(0).asClassExpr().getType().asString()); + } + + @Test + void solveReflectionMarkerAnnotationWithDefaultClassValue() throws IOException { + // parse compilation unit and get annotation expression + CompilationUnit cu = parseSample("Annotations"); + ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CI"); + + MarkerAnnotationExpr annotationExpr = clazz.getAnnotation(0).asMarkerAnnotationExpr(); + + // resolve annotation expression + ResolvedAnnotationDeclaration resolved = annotationExpr.resolve(); + + // Class - LambdaMetafactory.class + ClassExpr classExpr = assertInstanceOf(ClassExpr.class, findAnnotationMemberByName(resolved, "clazz").getDefaultValue()); + final ClassOrInterfaceType type = assertInstanceOf(ClassOrInterfaceType.class, classExpr.getType()); + assertEquals("LambdaMetafactory", type.getNameAsString()); + } + + @Test + void solveReflectionMarkerAnnotationWithDefaultEnumValue() throws IOException { + // parse compilation unit and get annotation expression + CompilationUnit cu = parseSample("Annotations"); + ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CI"); + + MarkerAnnotationExpr annotationExpr = clazz.getAnnotation(0).asMarkerAnnotationExpr(); + + // resolve annotation expression + ResolvedAnnotationDeclaration resolved = annotationExpr.resolve(); + + // TimeUnit - TimeUnit.HOURS + Expression enumExpr = findAnnotationMemberByName(resolved, "unit").getDefaultValue(); + final FieldAccessExpr fieldAccessExpr = assertInstanceOf(FieldAccessExpr.class, enumExpr); + final NameExpr scopeNameExpr = assertInstanceOf(NameExpr.class, fieldAccessExpr.getScope()); + assertEquals("TimeUnit", scopeNameExpr.asNameExpr().getNameAsString()); + assertEquals("HOURS", fieldAccessExpr.getNameAsString()); + } + + @Test + void solveReflectionMarkerAnnotationWithDefaultNestedAnnotationValue() throws IOException { + // parse compilation unit and get annotation expression + CompilationUnit cu = parseSample("Annotations"); + ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CI"); + + MarkerAnnotationExpr annotationExpr = clazz.getAnnotation(0).asMarkerAnnotationExpr(); + + // resolve annotation expression + ResolvedAnnotationDeclaration resolved = annotationExpr.resolve(); + + // NestedAnnotation - @NestedAnnotation + Expression nestedExpr = findAnnotationMemberByName(resolved, "nestedAnnotation").getDefaultValue(); + assertInstanceOf(NormalAnnotationExpr.class, nestedExpr); + assertEquals("NestedAnnotation", nestedExpr.asNormalAnnotationExpr().getNameAsString()); + } + + private ResolvedAnnotationMemberDeclaration findAnnotationMemberByName(ResolvedAnnotationDeclaration resolved, String memberName) { + return resolved.getAnnotationMembers().stream() + .filter(a -> memberName.equals(a.getName())) + .findAny() + .orElseThrow(() -> new IllegalArgumentException(String.format("Could not find annotation member %s in %s", + memberName, resolved.getName()))); + } } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java index 8cac015477..8fb93be7f9 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java @@ -169,6 +169,7 @@ void solveMultiCatchType() { Type jpType = catchClause.getParameter().getType(); ResolvedType jssType = jpType.resolve(); assertTrue(jssType instanceof ResolvedUnionType); + assertTrue(jssType.asUnionType().getElements().size()==2); } @Test diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/LeastUpperBoundTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/LeastUpperBoundTest.java index 0a7c0788a2..a323664aac 100755 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/LeastUpperBoundTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/LeastUpperBoundTest.java @@ -2,12 +2,11 @@ import static org.junit.jupiter.api.Assertions.*; +import java.io.FileNotFoundException; import java.io.IOError; import java.io.IOException; import java.io.Serializable; -import java.rmi.AlreadyBoundException; -// "java.rmi.activation" package was removed from Java 17. -// import java.rmi.activation.UnknownGroupException; +import java.net.URISyntaxException; import java.util.*; import java.util.stream.Collectors; @@ -146,14 +145,12 @@ public void lub_approximation_inheritance_and_multiple_bounds() { @Test public void lub_approximation_with_complexe_inheritance() { ResolvedType expected = type(Exception.class.getCanonicalName()); - // java.lang.Object/java.lang.Throwable/java.lang.Exception/java.rmi.AlreadyBoundException - ResolvedType alreadyBoundException = type(AlreadyBoundException.class.getCanonicalName()); - /* "java.rmi.activation" package was removed from Java 17. - // java.lang.Object//java.lang.Throwable/java.lang.Exception/java.rmi.activation.ActivationException/java.rmi.activation.UnknownGroupException - ResolvedType unknownGroupException = type(UnknownGroupException.class.getCanonicalName()); - ResolvedType lub = leastUpperBound(alreadyBoundException, unknownGroupException); + // java.lang.Object/java.lang.Throwable/java.lang.Exception/java.net.URISyntaxException + ResolvedType uriSyntaxException = type(URISyntaxException.class.getCanonicalName()); + // java.lang.Object//java.lang.Throwable/java.lang.Exception/java.io.IOException/java.io.FileNotFoundException + ResolvedType fileNotFoundException = type(FileNotFoundException.class.getCanonicalName()); + ResolvedType lub = leastUpperBound(uriSyntaxException, fileNotFoundException); assertEquals(expected, lub); - */ } @Test diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/TargetType.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/TargetType.java new file mode 100644 index 0000000000..058404db94 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/TargetType.java @@ -0,0 +1,25 @@ +package com.github.javaparser.symbolsolver.testingclasses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.MethodHandle; +import java.util.concurrent.TimeUnit; + +@interface NestedAnnotation { + +} + +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR}) +@Retention(RetentionPolicy.SOURCE) +public @interface TargetType { + Class[] packagesOf() default {MethodHandle.class}; + + Class clazz() default LambdaMetafactory.class; + + TimeUnit unit() default TimeUnit.HOURS; + + NestedAnnotation nestedAnnotation() default @NestedAnnotation; +} \ No newline at end of file diff --git a/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt b/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt index 0f8e7d5bae..5377d7a66d 100644 --- a/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt +++ b/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt @@ -3,6 +3,7 @@ package foo.bar; import java.lang.annotation.*; import java.beans.*; import org.junit.*; +import com.github.javaparser.symbolsolver.testingclasses.TargetType; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @@ -76,6 +77,10 @@ class CH { @Transient public String field; } +@TargetType +class CI { +} + @Inherited public @interface InheritedAnnotation { } diff --git a/pom.xml b/pom.xml index b0d3f8720f..88ef44db59 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.github.javaparser javaparser-parent pom - 3.25.3 + 3.25.5 javaparser-parent https://github.com/javaparser @@ -200,7 +200,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.2.0 + 3.3.1 org.apache.maven.plugins @@ -210,7 +210,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 org.apache.maven.plugins @@ -231,7 +231,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0 + 3.0.1 true @@ -251,12 +251,12 @@ org.apache.maven.plugins maven-scm-plugin - 2.0.0 + 2.0.1 org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 org.eluder.coveralls @@ -307,7 +307,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.1.2 org.codehaus.mojo @@ -322,7 +322,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 org.codehaus.mojo @@ -332,12 +332,12 @@ org.apache.maven.plugins maven-dependency-plugin - 3.5.0 + 3.6.0 org.codehaus.mojo versions-maven-plugin - 2.15.0 + 2.16.0 false @@ -345,7 +345,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.2.2 + 3.3.0 dev-files/JavaParser-CheckStyle.xml true @@ -355,7 +355,7 @@ com.puppycrawl.tools checkstyle - 10.10.0 + 10.12.3 @@ -374,7 +374,7 @@ com.google.guava guava - 31.1-jre + 32.1.2-jre junit @@ -391,19 +391,19 @@ org.junit.jupiter junit-jupiter-engine - 5.9.3 + 5.10.0 test org.junit.jupiter junit-jupiter-params - 5.9.3 + 5.10.0 test org.junit.vintage junit-vintage-engine - 5.9.3 + 5.10.0 test @@ -503,7 +503,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts diff --git a/readme.md b/readme.md index e9e5a47840..7d54cb744f 100644 --- a/readme.md +++ b/readme.md @@ -115,7 +115,7 @@ The remainder of this README file is the original JavaParser README. [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2667378.svg)](https://doi.org/10.5281/zenodo.2667378) -This project contains a set of libraries implementing a Java 1.0 - Java 15 Parser with advanced analysis functionalities. This includes preview features to Java 13, with Java 14 preview features work-in-progress. +This project contains a set of libraries implementing a Java 1.0 - Java 17 Parser with advanced analysis functionalities. Our main site is at [JavaParser.org](http://javaparser.org) @@ -138,14 +138,14 @@ Just add the following to your maven configuration or tailor to your own depende com.github.javaparser javaparser-symbol-solver-core - 3.25.3 + 3.25.5 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.25.3' +implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.25.5' ``` Since Version 3.5.10, the JavaParser project includes the JavaSymbolSolver. @@ -160,14 +160,14 @@ Using the dependency above will add both JavaParser and JavaSymbolSolver to your com.github.javaparser javaparser-core - 3.25.3 + 3.25.5 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-core:3.25.3' +implementation 'com.github.javaparser:javaparser-core:3.25.5' ``` Since version 3.6.17 the AST can be serialized to JSON. @@ -179,14 +179,14 @@ There is a separate module for this: com.github.javaparser javaparser-core-serialization - 3.25.3 + 3.25.5 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-core-serialization:3.25.3' +implementation 'com.github.javaparser:javaparser-core-serialization:3.25.5' ``` ## How To Compile Sources @@ -222,7 +222,7 @@ Make sure that `javaparser-core` at least compiles before you run these. ## More information -#### [JavaParser.org](https://javaparser.org) is the main information site. +#### [JavaParser.org](https://javaparser.org) is the main information site or see the wiki page https://github.com/javaparser/javaparser/wiki. ## License