Merge branch 'master' into issue4912-java-grammar-fix

This commit is contained in:
Juan Martín Sotuyo Dodero
2024-04-16 17:38:03 -03:00
committed by GitHub
31 changed files with 819 additions and 291 deletions

View File

@ -7453,6 +7453,15 @@
"contributions": [
"code"
]
},
{
"login": "mkolesnikov",
"name": "Michael Kolesnikov",
"avatar_url": "https://avatars.githubusercontent.com/u/754163?v=4",
"profile": "https://github.com/mkolesnikov",
"contributions": [
"bug"
]
}
],
"contributorsPerLine": 7,

View File

@ -36,7 +36,7 @@ function build() {
if pmd_ci_utils_is_fork_or_pull_request; then
pmd_ci_log_group_start "Build with mvnw"
./mvnw clean install --show-version --errors --batch-mode "${PMD_MAVEN_EXTRA_OPTS[@]}"
./mvnw clean install --show-version --errors --batch-mode -Pgenerate-rule-docs "${PMD_MAVEN_EXTRA_OPTS[@]}"
pmd_ci_log_group_end
# Execute danger and dogfood only for pull requests in our own repository

File diff suppressed because it is too large Load Diff

View File

@ -210,19 +210,34 @@ more violations than expected.
Another example, to suppress violations occurring in classes whose name contains `Bean`:
```xml
<property name="violationSuppressXPath" value="./ancestor::ClassDeclaration[contains(@Image, 'Bean')]"/>
<property name="violationSuppressXPath" value="./ancestor-or-self::ClassDeclaration[contains(@SimpleName, 'Bean')]"/>
```
And an example to suppress violations occurring in `equals` or `hashCode` methods:
```xml
<property name="violationSuppressXPath" value="./ancestor-or-self::MethodDeclaration[@Name = ('equals', 'hashCode')]"/>
```
Note the use of a sequence comparison, which tests for true if any member of one sequence matches any other member of the other.
Here this test is true if the `@Name` attribute is any of the given names.
You can also use regex for string comparison. The next example suppresses violations in classes ending with `Bean`:
```xml
<property name="violationSuppressXPath" value="./ancestor::ClassDeclaration[matches(@Image, '^.*Bean$')]"/>
<property name="violationSuppressXPath" value="./ancestor-or-self::ClassDeclaration[matches(@SimpleName, '^.*Bean$')]"/>
```
Note here the usage of the `./ancestor::` axis instead of `//`. The latter would match
Note here the usage of the `./ancestor-or-self::` axis instead of `//`. The latter would match
any ClassDeclaration in the file, while the former matches only class
declaration nodes that *enclose the violation node*, which is usually what you'd want.
Note the context node in this expression is the node the violation was reported on. Different
rules report on different nodes, for instance, {% rule java/bestpractices/UnusedFormalParameter %} reports
on the `ASTVariableId` for the parameter, and {% rule java/bestpractices/MissingOverride %} reports on
the `ASTMethodDeclaration` node. You have to take this into account when using the context node directly,
although many `violationSuppressXPath` expressions will check for some ancestor node like an enclosing class or method,
instead of testing the context node directly.
The nodes which a rule reports on can only be determined by looking at the implementation of the rule.
Note for XPath based suppression to work, you must know how to write
an XPath query that matches the AST structure of the nodes of the
violations you wish to suppress. XPath queries are explained in

View File

@ -26,10 +26,17 @@ This is a {{ site.pmd.release_type }} release.
* cli
* [#4791](https://github.com/pmd/pmd/issues/4791): \[cli] Could not find or load main class
* [#4913](https://github.com/pmd/pmd/issues/4913): \[cli] cpd-gui closes immediately
* doc
* [#4901](https://github.com/pmd/pmd/issues/4901): \[doc] Improve documentation on usage of violationSuppressXPath
* apex
* [#4418](https://github.com/pmd/pmd/issues/4418): \[apex] ASTAnnotation.getImage() does not return value as written in the class
* apex-errorprone
* [#3953](https://github.com/pmd/pmd/issues/3953): \[apex] EmptyCatchBlock false positive with formal (doc) comments
* java
* [#4899](https://github.com/pmd/pmd/issues/4899): \[java] Parsing failed in ParseLock#doParse() java.io.IOException: Stream closed
* [#4902](https://github.com/pmd/pmd/issues/4902): \[java] "Bad intersection, unrelated class types" for Constable\[] and Enum\[]
* [#4912](https://github.com/pmd/pmd/issues/4912): \[java] Unable to parse some Java9+ resource references
* [#4947](https://github.com/pmd/pmd/issues/4947): \[java] Broken TextBlock parser
* java-bestpractices
* [#1084](https://github.com/pmd/pmd/issues/1084): \[java] Allow JUnitTestsShouldIncludeAssert to configure verification methods
* [#4435](https://github.com/pmd/pmd/issues/4435): \[java] \[7.0-rc1] UnusedAssignment for used field
@ -38,6 +45,7 @@ This is a {{ site.pmd.release_type }} release.
* java-codestyle
* [#4602](https://github.com/pmd/pmd/issues/4602): \[java] UnnecessaryImport: false positives with static imports
* [#4785](https://github.com/pmd/pmd/issues/4785): \[java] False Positive: PMD Incorrectly report violation for UnnecessaryImport
* [#4779](https://github.com/pmd/pmd/issues/4779): \[java] Examples in documentation of MethodArgumentCanBeFinal do not trigger the rule
* [#4881](https://github.com/pmd/pmd/issues/4881): \[java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0)
* java-design
* [#3694](https://github.com/pmd/pmd/issues/3694): \[java] SingularField ignores static variables

View File

@ -13,8 +13,8 @@ public final class ASTAnnotation extends AbstractApexNode.Single<AnnotationModif
/**
* Valid annotations in the Apex language.
* <p>
* Includes all annotations from the <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation.htm">official
*
* <p>Includes all annotations from the <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation.htm">official
* documentation</a>, plus
* <ul>
* <li>{@code AllowCertifiedApex}</li>
@ -71,21 +71,38 @@ public final class ASTAnnotation extends AbstractApexNode.Single<AnnotationModif
return visitor.visit(this, data);
}
/**
* Returns the normalized annotation name for known, valid annotations.
* The normalized name is in PascalCase. If an unknown annotation is used,
* the raw name (as in the source code) is returned.
*
* @see #getRawName()
*/
public String getName() {
// If resolvable to a known name, return the case-normalized name.
String rawName = node.getName().getString();
String rawName = getRawName();
if (NORMALIZED_ANNOTATION_NAMES.contains(rawName)) {
return NORMALIZED_ANNOTATION_NAMES.floor(rawName);
}
return rawName;
}
/**
* Returns the annotation name as it appears in the source code.
* This allows to verify the casing.
*
* @since 7.1.0
*/
public String getRawName() {
return node.getName().getString();
}
@Override
public String getImage() {
return getName();
}
public boolean isResolved() {
return NORMALIZED_ANNOTATION_NAMES.contains(node.getName().getString());
return NORMALIZED_ANNOTATION_NAMES.contains(getRawName());
}
}

View File

@ -0,0 +1,30 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import net.sourceforge.pmd.lang.document.Chars;
class ASTAnnotationTest extends ApexParserTestBase {
@Test
void caseSensitiveName() {
ASTUserClassOrInterface<?> parsed = parse("public with sharing class Example {\n"
+ "\n"
+ " @istest\n"
+ " private static void fooShouldBar() {\n"
+ " }\n"
+ " \n"
+ "}");
ASTAnnotation annotation = parsed.descendants(ASTAnnotation.class).first();
assertEquals("IsTest", annotation.getName());
assertEquals("istest", annotation.getRawName());
Chars text = annotation.getTextDocument().sliceOriginalText(annotation.getTextRegion());
assertEquals("@istest", text.toString());
}
}

View File

@ -53,6 +53,16 @@ public class ClasspathClassLoader extends URLClassLoader {
static {
registerAsParallelCapable();
// Disable caching for jar files to prevent issues like #4899
try {
// Uses a pseudo URL to be able to call URLConnection#setDefaultUseCaches
// with Java9+ there is a static method for that per protocol:
// https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/URLConnection.html#setDefaultUseCaches(java.lang.String,boolean)
URI.create("jar:file:file.jar!/").toURL().openConnection().setDefaultUseCaches(false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public ClasspathClassLoader(List<File> files, ClassLoader parent) throws IOException {

View File

@ -17,6 +17,11 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -60,27 +65,111 @@ class ClasspathClassLoaderTest {
}
}
@Test
void loadFromJar() throws IOException {
final String RESOURCE_NAME = "net/sourceforge/pmd/Sample.txt";
final String TEST_CONTENT = "Test\n";
private static final String CUSTOM_JAR_RESOURCE = "net/sourceforge/pmd/Sample.txt";
private static final String CUSTOM_JAR_RESOURCE2 = "net/sourceforge/pmd/Sample2.txt";
private static final String CUSTOM_JAR_RESOURCE_CONTENT = "Test\n";
private Path prepareCustomJar() throws IOException {
Path jarPath = tempDir.resolve("custom.jar");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(jarPath))) {
out.putNextEntry(new ZipEntry(RESOURCE_NAME));
out.write(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
out.putNextEntry(new ZipEntry(CUSTOM_JAR_RESOURCE));
out.write(CUSTOM_JAR_RESOURCE_CONTENT.getBytes(StandardCharsets.UTF_8));
out.putNextEntry(new ZipEntry(CUSTOM_JAR_RESOURCE2));
out.write(CUSTOM_JAR_RESOURCE_CONTENT.getBytes(StandardCharsets.UTF_8));
}
return jarPath;
}
@Test
void loadFromJar() throws IOException {
Path jarPath = prepareCustomJar();
String classpath = jarPath.toString();
try (ClasspathClassLoader loader = new ClasspathClassLoader(classpath, null)) {
try (InputStream in = loader.getResourceAsStream(RESOURCE_NAME)) {
try (InputStream in = loader.getResourceAsStream(CUSTOM_JAR_RESOURCE)) {
assertNotNull(in);
String s = IOUtil.readToString(in, StandardCharsets.UTF_8);
assertEquals(TEST_CONTENT, s);
assertEquals(CUSTOM_JAR_RESOURCE_CONTENT, s);
}
}
}
/**
* @see <a href="https://github.com/pmd/pmd/issues/4899">[java] Parsing failed in ParseLock#doParse() java.io.IOException: Stream closed #4899</a>
*/
@Test
void loadMultithreadedFromJar() throws IOException, InterruptedException {
Path jarPath = prepareCustomJar();
String classpath = jarPath.toString();
int numberOfThreads = 2;
final CyclicBarrier waitForClosed = new CyclicBarrier(numberOfThreads);
final Semaphore grabResource = new Semaphore(1);
final List<Exception> caughtExceptions = new ArrayList<>();
class ThreadRunnable extends Thread {
private final int number;
ThreadRunnable(int number) {
super("Thread" + number);
this.number = number;
}
@Override
public void run() {
try (ClasspathClassLoader loader = new ClasspathClassLoader(classpath, null)) {
// Make sure, the threads get the resource stream one after another, so that the
// underlying Jar File is definitively cached (if caching is enabled).
grabResource.acquire();
InputStream stream;
try {
stream = loader.getResourceAsStream(CUSTOM_JAR_RESOURCE);
} finally {
grabResource.release();
}
try (InputStream in = stream) {
assertNotNull(in);
if (number > 0) {
// all except the first thread should wait until the first thread is finished
// and has closed the ClasspathClassLoader
waitForClosed.await();
}
String s = IOUtil.readToString(in, StandardCharsets.UTF_8);
assertEquals(CUSTOM_JAR_RESOURCE_CONTENT, s);
}
} catch (Exception e) {
caughtExceptions.add(e);
throw new RuntimeException(e);
} finally {
try {
if (number == 0) {
// signal the other waiting threads to continue. Here, we have closed
// already the ClasspathClassLoader.
waitForClosed.await();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
}
}
List<Thread> threads = new ArrayList<>(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
threads.add(new ThreadRunnable(i));
}
threads.forEach(Thread::start);
for (Thread thread : threads) {
thread.join();
}
assertTrue(caughtExceptions.isEmpty());
}
/**
* Verifies, that we load the class files from the runtime image of the correct java home.
* This tests multiple versions, in order to avoid that the test accidentally is successful when

View File

@ -656,7 +656,7 @@ public class RuleDocGenerator {
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
String path = file.toString();
String path = RuleSetUtils.normalizeForwardSlashes(file.toString());
if (path.contains("src")) {
String foundRuleClass = null;

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.annotation.Experimental;
/**
* This is a Java 21/22 Preview feature.
* The template of a {@link ASTTemplateExpression}. This is a Java 21/22 Preview feature.
*
* <pre class="grammar">
*

View File

@ -8,12 +8,11 @@ import net.sourceforge.pmd.annotation.Experimental;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
/**
* This is a Java 21/22 Preview feature.
* A string template expression. This is a Java 21/22 Preview feature.
*
* <pre class="grammar">
*
* TemplateExpression ::= ({@link ASTVariableAccess VariableAccess} | {@link ASTFieldAccess FieldAccess})
* ({@link ASTTemplate Template} | {@link ASTStringLiteral StringLiteral})
* TemplateExpression ::= ({@link ASTVariableAccess VariableAccess} | {@link ASTFieldAccess FieldAccess}) {@link ASTTemplate Template}
*
* </pre>
*

View File

@ -21,7 +21,6 @@ import net.sourceforge.pmd.annotation.Experimental;
*/
@Experimental("String templates is a Java 21/22 Preview feature")
public final class ASTTemplateFragment extends AbstractJavaNode {
private String content;
ASTTemplateFragment(int i) {
super(i);
@ -33,11 +32,7 @@ public final class ASTTemplateFragment extends AbstractJavaNode {
}
public String getContent() {
return content;
}
void setContent(String content) {
this.content = content;
return getText().toString();
}
}

View File

@ -99,6 +99,9 @@ final class ClassStub implements JClassSymbol, AsmStub, AnnotationOwner {
} else {
return false;
}
} catch (IOException e) {
// add a bit more info to the exception
throw new IOException("While loading class from " + loader, e);
}
}

View File

@ -50,7 +50,7 @@ abstract class Loader {
@Override
public String toString() {
return "(StreamLoader for " + name + ")";
return "StreamLoader(for " + name + ")";
}
}
}

View File

@ -4,10 +4,11 @@
package net.sourceforge.pmd.lang.java.types;
import static net.sourceforge.pmd.util.CollectionUtil.setOf;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
@ -319,34 +320,48 @@ final class Lub {
return mostSpecific.iterator().next();
}
List<JTypeMirror> bounds = new ArrayList<>(mostSpecific);
List<JTypeMirror> bounds = new ArrayList<>(mostSpecific.size());
bounds.add(null); // first element will be replaced with primary bound
JTypeMirror primaryBound = null;
for (int i = 0; i < bounds.size(); i++) {
JTypeMirror ci = bounds.get(i);
for (JTypeMirror ci : mostSpecific) {
if (isExclusiveIntersectionBound(ci)) {
// either Ci is an array, or Ci is a class, or Ci is a type var (possibly captured)
// Ci is not unresolved
if (primaryBound == null) {
primaryBound = ci;
// move primary bound first
Collections.swap(bounds, 0, i);
} else if (ci.isArray() && primaryBound.isArray()) {
// A[] & B[] = (A & B)[]
// Note that since we're after mostSpecific, we already know
// that A is unrelated to B. Therefore if both B and A are classes,
// then A & B cannot exist and so (A & B)[] similarly does not exist.
JTypeMirror componentGlb = glb(ts, setOf(((JArrayType) ci).getComponentType(),
((JArrayType) primaryBound).getComponentType()));
primaryBound = ts.arrayType(componentGlb);
} else {
throw new IllegalArgumentException(
"Bad intersection, unrelated class types " + ci + " and " + primaryBound + " in " + types
);
}
} else {
bounds.add(ci);
}
}
if (primaryBound == null) {
if (bounds.size() == 1) {
return bounds.get(0);
}
primaryBound = ts.OBJECT;
}
bounds.set(0, primaryBound); // set the primary bound
if (primaryBound == ts.OBJECT) {
// if primary bound is object, it does not appear in the bounds
bounds = bounds.subList(1, bounds.size());
}
if (bounds.size() == 1) {
return bounds.get(0); // not an intersection
}
return new JIntersectionType(ts, primaryBound, bounds);
}

View File

@ -580,6 +580,11 @@ public final class TypeOps {
return this == UNCHECKED_WARNING;
}
/** True if this is {@link #SUBTYPING} or {@link #UNCHECKED_NO_WARNING}. */
public boolean withoutWarnings() {
return this == SUBTYPING || this == UNCHECKED_NO_WARNING;
}
// package:
@ -1733,8 +1738,15 @@ public final class TypeOps {
vLoop:
for (JTypeMirror v : set) {
for (JTypeMirror w : set) {
if (!w.equals(v) && !hasUnresolvedSymbol(w) && isSubtypePure(w, v).bySubtyping()) {
continue vLoop;
if (!w.equals(v) && !hasUnresolvedSymbol(w)) {
Convertibility isConvertible = isSubtypePure(w, v);
if (isConvertible.bySubtyping()
// This last case covers unchecked conversion. It is made antisymmetric by the
// test for a symbol. eg |G| <~> G<?> so it would fail.
// However, |G| ~> S if |G| <: |S|, so we should consider |G| more specific than S.
|| isConvertible.withoutWarnings() && !Objects.equals(w.getSymbol(), v.getSymbol())) {
continue vLoop;
}
}
}
result.add(v);

View File

@ -697,12 +697,20 @@ public final class TypeSystem {
* <li>The intersection has a single component that is a
* class, array, or type variable. If all components are interfaces,
* then that component is {@link #OBJECT}.
* <li>If several components are arrays, then their components
* are intersected: {@code A[] & B[] = (A & B)[]}
* </ul>
*
* <p>If after these transformations, only a single component remains,
* then that is the returned type. Otherwise a {@link JIntersectionType}
* is created. Note that the intersection may be unsatisfiable (eg {@code A[] & Runnable}),
* but we don't attempt to minimize this to {@link #NULL_TYPE}.
* but we don't attempt to minimize this to {@link #NULL_TYPE}. Similarly,
* we do not attempt to minimize valid intersections. For instance {@code List<?> & Collection<Number>}
* can technically be minimized to {@code List<Number>}, but doing this
* requires inference of a fitting parameterization in general, which is
* complex, and not necessary in the internal tasks where intersection types are
* useful. In fact intersection types are precisely useful because they are
* simple to build.
*
* <p>See also JLS§4.9 (Intersection types).
*

View File

@ -1034,17 +1034,27 @@ public class MissingTheProperSuffix implements SessionBean {} // non-standard
class="net.sourceforge.pmd.lang.java.rule.codestyle.MethodArgumentCouldBeFinalRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#methodargumentcouldbefinal">
<description>
A method argument that is never re-assigned within the method can be declared final.
Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method.
This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}.
It will also ignore the parameters of abstract methods.
</description>
<priority>3</priority>
<example>
<![CDATA[
public void foo1 (String param) { // do stuff with param never assigning it
}
public void foo2 (final String param) { // better, do stuff with param never assigning it
class Foo {
// reported, parameter can be declared final
public String foo1(String param) {
return param;
}
// not reported, parameter is declared final
public String foo2(final String param) {
return param.trim();
}
// not reported because param is unused
public String unusedParam(String param) {
return "abc";
}
}
]]>
</example>

View File

@ -357,4 +357,14 @@ class ParserCornersTest extends BaseJavaTreeDumpTest {
void testGitHubBug3642() {
doTest("GitHubBug3642");
}
@Test
void testGitHubBug1780() {
doTest("GitHubBug1780OuterClass");
}
@Test
void testGithubBug4947() {
java15.parseResource("testdata/Issue4947TextBlock.java");
}
}

View File

@ -46,5 +46,19 @@ public class LubTestData {
public static class GenericSub2<T> extends GenericSuper<T> implements I2<I3>, I4 {
}
public interface EnumSuperItf {
}
public enum Enum1 implements EnumSuperItf {
}
public enum Enum2 implements EnumSuperItf {
}
// unrelated
public static class C1 {
}
public static class C2 {
}
}

View File

@ -5,7 +5,6 @@
package net.sourceforge.pmd.lang.java.ast
import io.kotest.matchers.shouldBe
import net.sourceforge.pmd.lang.test.ast.shouldBe
import net.sourceforge.pmd.lang.java.ast.JavaVersion.*
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Earliest
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Latest
@ -15,6 +14,7 @@ import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind
import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind.*
import net.sourceforge.pmd.lang.test.ast.NodeSpec
import net.sourceforge.pmd.lang.test.ast.ValuedNodeSpec
import net.sourceforge.pmd.lang.test.ast.shouldBe
import net.sourceforge.pmd.lang.test.ast.shouldHaveText
/**
@ -135,6 +135,12 @@ $delim
$delim
""".testTextBlock()
"""
$delim
x$delim
""".testTextBlock()
}
}

View File

@ -7,11 +7,13 @@ package net.sourceforge.pmd.lang.java.types
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.shouldBe
import io.kotest.property.checkAll
import net.sourceforge.pmd.lang.test.ast.shouldBeA
import net.sourceforge.pmd.lang.java.symbols.internal.asm.createUnresolvedAsmSymbol
import net.sourceforge.pmd.lang.java.types.testdata.LubTestData
import net.sourceforge.pmd.lang.test.ast.shouldBeA
/**
* Tests "the greatest lower bound" (glb).
@ -71,6 +73,32 @@ class GlbTest : FunSpec({
}
test("Test GLB of arrays") {
glb(ts.SERIALIZABLE.toArray(), t_ArrayList.toArray()) shouldBe t_ArrayList.toArray()
glb(t_ArrayList.toArray(), ts.SERIALIZABLE.toArray()) shouldBe t_ArrayList.toArray()
glb(t_List.toArray(), `t_List{?}`.toArray()) shouldBe `t_List{?}`.toArray()
}
test("Test GLB of arrays of unrelated type") {
// C1 & C2 does not exist as they are both unrelated classes
shouldThrow<IllegalArgumentException> {
glb(LubTestData.C1::class.decl, LubTestData.C2::class.decl)
}
// C1[] & C2[] = (C1 & C2)[] equally does not exist
shouldThrow<IllegalArgumentException> {
glb(LubTestData.C1::class.decl.toArray(), LubTestData.C2::class.decl.toArray())
}
// but C1[] & I1[] = (C1 & I1)[] exists because I1 is an interface.
glb(LubTestData.C1::class.decl.toArray(), LubTestData.I1::class.decl.toArray())
.shouldBe((LubTestData.C1::class.decl * LubTestData.I1::class.decl).toArray())
}
test("Test lub of zero types") {
shouldThrow<IllegalArgumentException> {
@ -89,28 +117,60 @@ class GlbTest : FunSpec({
}
}
test("test corner case") {
TypeOps.mostSpecific(
setOf(
t_Collection[`?` extends t_Number],
`t_List{?}`,
t_List
)
) shouldBe setOf(t_Collection[`?` extends t_Number], `t_List{?}`)
}
test("Test GLB corner cases") {
// note: intersections are not minimized, or reduced to the null type if they are unsatisfiable.
// note also that in this test we test the components explicitly instead of using the DSL,
// because the DSL operator to create intersections actually calls GLB.
glb(t_Iterable[`?` extends t_Number], t_Iterable[t_String]).shouldBeA<JIntersectionType> {
it.components.shouldContainExactly(t_Iterable[`?` extends t_Number], t_Iterable[t_String])
}
glb(`t_ArrayList{Integer}`, ts.NULL_TYPE) shouldBe ts.NULL_TYPE
glb(`t_ArrayList{Integer}`, t_Iterable[`?` extends t_Number], t_Iterable[t_String]).shouldBeA<JIntersectionType> {
it.components.shouldContainExactly(`t_ArrayList{Integer}`, t_Iterable[t_String])
it.components.shouldContainExactlyInAnyOrder(`t_ArrayList{Integer}`, t_Iterable[t_String])
}
glb(`t_List{? extends Number}`, `t_Collection{Integer}`).shouldBeA<JIntersectionType> {
it.components.shouldContainExactly(`t_List{? extends Number}`, `t_Collection{Integer}`)
it.components.shouldContainExactlyInAnyOrder(`t_List{? extends Number}`, `t_Collection{Integer}`)
}
glb(t_List.toArray(), t_Iterable).shouldBeA<JIntersectionType> {
it.components.shouldContainExactly(t_List.toArray(), t_Iterable)
it.components.shouldContainExactlyInAnyOrder(t_List.toArray(), t_Iterable)
it.inducedClassType.shouldBeNull()
}
glb(`t_List{? extends Number}`, `t_Collection{Integer}`, `t_ArrayList{Integer}`) shouldBe `t_ArrayList{Integer}`
glb(`t_List{? extends Number}`, `t_List{String}`, `t_Enum{JPrimitiveType}`).shouldBeA<JIntersectionType> {
it.components.shouldContainExactly(`t_Enum{JPrimitiveType}`, `t_List{String}`, `t_List{? extends Number}`)
it.components.shouldContainExactlyInAnyOrder(`t_Enum{JPrimitiveType}`, `t_List{String}`, `t_List{? extends Number}`)
}
glb(
t_Collection[`?` extends t_Number],
`t_List{?}`,
t_List
).shouldBeA<JIntersectionType> {
it.components.shouldContainExactlyInAnyOrder(t_Collection[`?` extends t_Number], `t_List{?}`)
}
glb(t_List, `t_List{?}`) shouldBe `t_List{?}`
glb(
t_Collection[`?` extends t_Number],
`t_List{?}`
).shouldBeA<JIntersectionType> {
it.components.shouldContainExactlyInAnyOrder(t_Collection[`?` extends t_Number], `t_List{?}`)
}
}
test("Test GLB with unresolved things") {

View File

@ -140,6 +140,22 @@ class LubTest : FunSpec({
lub(t_List[Sub1::class.decl], t_List[Sub2::class.decl]) shouldBe result
}
test("Test lub of related arrays") {
// the component type
lub(
Enum1::class.decl,
Enum2::class.decl,
) shouldBe t_Enum[`?` extends t_Enum[`?`] * EnumSuperItf::class.decl] * EnumSuperItf::class.decl
// let's try arrays
lub(
Enum1::class.decl.toArray(),
Enum2::class.decl.toArray(),
) shouldBe (t_Enum * EnumSuperItf::class.decl).toArray()
}
}
}

View File

@ -7,13 +7,13 @@
package net.sourceforge.pmd.lang.java.types.internal.infer
import io.kotest.matchers.shouldBe
import net.sourceforge.pmd.lang.java.ast.*
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol
import net.sourceforge.pmd.lang.java.types.*
import net.sourceforge.pmd.lang.test.ast.NodeSpec
import net.sourceforge.pmd.lang.test.ast.shouldBe
import net.sourceforge.pmd.lang.test.ast.shouldBeA
import net.sourceforge.pmd.lang.test.ast.shouldMatchN
import net.sourceforge.pmd.lang.java.ast.*
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol
import net.sourceforge.pmd.lang.java.types.*
import java.util.*
/**
@ -384,4 +384,37 @@ class Foo {
}
parserTest("#4902 bad intersection") {
val (acu, spy) = parser.parseWithTypeInferenceSpy("""
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BadIntersection {
interface Animal { }
enum Bird implements Animal { PARROT, CHICKEN }
enum Fish implements Animal { GOLDFISH, MACKEREL }
private static List<Animal> combineAnimals() {
return Stream.of(
Bird.values(),
Fish.values()
)
.flatMap(Arrays::stream)
.collect(Collectors.toList());
}
}
""".trimIndent())
val (_, t_Animal) = acu.declaredTypeSignatures()
spy.shouldBeOk {
acu.firstMethodCall() shouldHaveType java.util.List::class[t_Animal]
}
}
})

View File

@ -0,0 +1,21 @@
package com.pmd.test;
public class GitHubBug1780OuterClass {
public GitHubBug1780OuterClass() {
System.out.println("Inner Class AdapterClass");
}
public class InnerClass {
public InnerClass() {
System.out.println("Inner Class Constructor");
}
}
private static class StaticInnerClass extends InnerClass {
public StaticInnerClass() {
new GitHubBug1780OuterClass().super();
System.out.println("StaticInnerClass Constructor");
}
}
public static void main(String args[]) {
new GitHubBug1780OuterClass.StaticInnerClass();
}
}

View File

@ -0,0 +1,68 @@
+- CompilationUnit[@PackageName = "com.pmd.test"]
+- PackageDeclaration[@Name = "com.pmd.test"]
| +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
+- ClassDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "com.pmd.test.GitHubBug1780OuterClass", @CanonicalName = "com.pmd.test.GitHubBug1780OuterClass", @EffectiveVisibility = Visibility.V_PUBLIC, @Enum = false, @Final = false, @Interface = false, @Local = false, @Nested = false, @PackageName = "com.pmd.test", @Record = false, @RegularClass = true, @RegularInterface = false, @SimpleName = "GitHubBug1780OuterClass", @Static = false, @TopLevel = true, @Visibility = Visibility.V_PUBLIC]
+- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"]
+- ClassBody[@Empty = false, @Size = 4]
+- ConstructorDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PUBLIC, @Final = false, @Image = "GitHubBug1780OuterClass", @Name = "GitHubBug1780OuterClass", @Static = false, @Varargs = false, @Visibility = Visibility.V_PUBLIC, @containsComment = false]
| +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- ExpressionStatement[]
| +- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ClassType[@FullyQualified = false, @SimpleName = "System"]
| +- ArgumentList[@Empty = false, @Size = 1]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Inner Class AdapterClass", @Empty = false, @Image = "\"Inner Class AdapterClass\"", @Length = 24, @LiteralText = "\"Inner Class AdapterClass\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- ClassDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "com.pmd.test.GitHubBug1780OuterClass$InnerClass", @CanonicalName = "com.pmd.test.GitHubBug1780OuterClass.InnerClass", @EffectiveVisibility = Visibility.V_PUBLIC, @Enum = false, @Final = false, @Interface = false, @Local = false, @Nested = true, @PackageName = "com.pmd.test", @Record = false, @RegularClass = true, @RegularInterface = false, @SimpleName = "InnerClass", @Static = false, @TopLevel = false, @Visibility = Visibility.V_PUBLIC]
| +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"]
| +- ClassBody[@Empty = false, @Size = 1]
| +- ConstructorDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PUBLIC, @Final = false, @Image = "InnerClass", @Name = "InnerClass", @Static = false, @Varargs = false, @Visibility = Visibility.V_PUBLIC, @containsComment = false]
| +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- ExpressionStatement[]
| +- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ClassType[@FullyQualified = false, @SimpleName = "System"]
| +- ArgumentList[@Empty = false, @Size = 1]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Inner Class Constructor", @Empty = false, @Image = "\"Inner Class Constructor\"", @Length = 23, @LiteralText = "\"Inner Class Constructor\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- ClassDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "com.pmd.test.GitHubBug1780OuterClass$StaticInnerClass", @CanonicalName = "com.pmd.test.GitHubBug1780OuterClass.StaticInnerClass", @EffectiveVisibility = Visibility.V_PRIVATE, @Enum = false, @Final = false, @Interface = false, @Local = false, @Nested = true, @PackageName = "com.pmd.test", @Record = false, @RegularClass = true, @RegularInterface = false, @SimpleName = "StaticInnerClass", @Static = true, @TopLevel = false, @Visibility = Visibility.V_PRIVATE]
| +- ModifierList[@EffectiveModifiers = "{private, static}", @ExplicitModifiers = "{private, static}"]
| +- ExtendsList[@Empty = false, @Size = 1]
| | +- ClassType[@FullyQualified = false, @SimpleName = "InnerClass"]
| +- ClassBody[@Empty = false, @Size = 1]
| +- ConstructorDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PRIVATE, @Final = false, @Image = "StaticInnerClass", @Name = "StaticInnerClass", @Static = false, @Varargs = false, @Visibility = Visibility.V_PUBLIC, @containsComment = false]
| +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 2, @containsComment = false]
| +- ExplicitConstructorInvocation[@ArgumentCount = 0, @MethodName = "new", @Qualified = true, @Super = true, @This = false]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "GitHubBug1780OuterClass"]
| | | +- ArgumentList[@Empty = true, @Size = 0]
| | +- ArgumentList[@Empty = true, @Size = 0]
| +- ExpressionStatement[]
| +- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ClassType[@FullyQualified = false, @SimpleName = "System"]
| +- ArgumentList[@Empty = false, @Size = 1]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "StaticInnerClass Constructor", @Empty = false, @Image = "\"StaticInnerClass Constructor\"", @Length = 28, @LiteralText = "\"StaticInnerClass Constructor\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- MethodDeclaration[@Abstract = false, @Arity = 1, @EffectiveVisibility = Visibility.V_PUBLIC, @Final = false, @MainMethod = true, @Name = "main", @Overridden = false, @Static = true, @Varargs = false, @Visibility = Visibility.V_PUBLIC, @Void = true]
+- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"]
+- VoidType[]
+- FormalParameters[@Empty = false, @Size = 1]
| +- FormalParameter[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Varargs = false, @Visibility = Visibility.V_LOCAL]
| +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| +- VariableId[@ArrayType = true, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = true, @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- ArrayDimensions[@Empty = false, @Size = 1]
| +- ArrayTypeDim[@Varargs = false]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- ExpressionStatement[]
+- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
+- ClassType[@FullyQualified = false, @SimpleName = "StaticInnerClass"]
| +- ClassType[@FullyQualified = false, @SimpleName = "GitHubBug1780OuterClass"]
+- ArgumentList[@Empty = true, @Size = 0]

View File

@ -308,7 +308,7 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 7, @containsComment = false]
| +- Block[@Empty = false, @Size = 10, @containsComment = true]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
@ -353,20 +353,87 @@
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "address", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "1 Maple Drive, Anytown", @Empty = false, @Image = "\"1 Maple Drive, Anytown\"", @Length = 22, @LiteralText = "\"1 Maple Drive, Anytown\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| | +- VariableDeclarator[@Initializer = true, @Name = "json"]
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "json", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- Template[]
| | +- TemplateFragment[@Content = "\"\"\"\n {\n \"name\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\",\n \"phone\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "phone", @Name = "phone", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\",\n \"address\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "address", @Name = "address", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\"\n }\n \"\"\""]
| +- LocalClassStatement[]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep430_StringTemplates$1Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{static, final}", @ExplicitModifiers = "{}"]
| | +- RecordComponentList[@Empty = false, @Size = 3, @Varargs = false]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| | | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "name", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "width", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "height", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | +- RecordBody[@Empty = false, @Size = 1]
| | +- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Name = "area", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = false]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | +- FormalParameters[@Empty = true, @Size = 0]
| | +- Block[@Empty = false, @Size = 1, @containsComment = false]
| | +- ReturnStatement[]
| | +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.MUL, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "width", @Name = "width", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "height", @Name = "height", @ParenthesisDepth = 0, @Parenthesized = false]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ArrayType[@ArrayDepth = 1]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArrayDimensions[@Empty = false, @Size = 1]
| | | +- ArrayTypeDim[@Varargs = false]
| | +- VariableDeclarator[@Initializer = true, @Name = "zone"]
| | +- VariableId[@ArrayType = true, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "zone", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ArrayAllocation[@ArrayDepth = 1, @CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ArrayType[@ArrayDepth = 1]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArrayDimensions[@Empty = false, @Size = 1]
| | | +- ArrayTypeDim[@Varargs = false]
| | +- ArrayInitializer[@CompileTimeConstant = false, @Length = 3, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArgumentList[@Empty = false, @Size = 3]
| | | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Alfa", @Empty = false, @Image = "\"Alfa\"", @Length = 4, @LiteralText = "\"Alfa\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "17.8", @IntLiteral = false, @Integral = false, @LiteralText = "17.8", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 17.8, @ValueAsFloat = 17.8, @ValueAsInt = 17, @ValueAsLong = 17]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "31.4", @IntLiteral = false, @Integral = false, @LiteralText = "31.4", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 31.4, @ValueAsFloat = 31.4, @ValueAsInt = 31, @ValueAsLong = 31]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArgumentList[@Empty = false, @Size = 3]
| | | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Bravo", @Empty = false, @Image = "\"Bravo\"", @Length = 5, @LiteralText = "\"Bravo\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "9.6", @IntLiteral = false, @Integral = false, @LiteralText = "9.6", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 9.6, @ValueAsFloat = 9.6, @ValueAsInt = 9, @ValueAsLong = 9]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "12.4", @IntLiteral = false, @Integral = false, @LiteralText = "12.4", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 12.4, @ValueAsFloat = 12.4, @ValueAsInt = 12, @ValueAsLong = 12]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | +- ArgumentList[@Empty = false, @Size = 3]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Charlie", @Empty = false, @Image = "\"Charlie\"", @Length = 7, @LiteralText = "\"Charlie\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "7.1", @IntLiteral = false, @Integral = false, @LiteralText = "7.1", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 7.1, @ValueAsFloat = 7.1, @ValueAsInt = 7, @ValueAsLong = 7]
| | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "11.23", @IntLiteral = false, @Integral = false, @LiteralText = "11.23", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 11.23, @ValueAsFloat = 11.23, @ValueAsInt = 11, @ValueAsLong = 11]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| +- VariableDeclarator[@Initializer = true, @Name = "json"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "json", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- VariableDeclarator[@Initializer = true, @Name = "table"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "table", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| +- Template[]
| +- TemplateFragment[@Content = "\"\"\"\n {\n \"name\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\",\n \"phone\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "phone", @Name = "phone", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\",\n \"address\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "address", @Name = "address", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\"\n }\n \"\"\";\n /*\n | \"\"\"\n | {\n | \"name\": \"Joan Smith\",\n | \"phone\": \"555-123-4567\",\n | \"address\": \"1 Maple Drive, Anytown\"\n | }\n | \"\"\"\n */\n\n record Rectangle(String name, double width, double height) {\n double area() {\n return width * height;\n }\n }\n Rectangle[] zone = new Rectangle[] {\n new Rectangle(\"Alfa\", 17.8, 31.4),\n new Rectangle(\"Bravo\", 9.6, 12.4),\n new Rectangle(\"Charlie\", 7.1, 11.23),\n };\n String table = STR.\"\"\"\n Description Width Height Area\n \\{"]
| +- TemplateFragment[@Content = "\"\"\"\n Description Width Height Area\n \\{"]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ArrayAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "zone", @Name = "zone", @ParenthesisDepth = 0, @Parenthesized = false]
@ -452,9 +519,9 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 4, @containsComment = false]
| +- Block[@Empty = false, @Size = 4, @containsComment = true]
| +- LocalClassStatement[]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep430_StringTemplates$1Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep430_StringTemplates$2Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{static, final}", @ExplicitModifiers = "{}"]
| | +- RecordComponentList[@Empty = false, @Size = 3, @Varargs = false]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
@ -654,7 +721,7 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 3, @containsComment = false]
| +- Block[@Empty = false, @Size = 3, @containsComment = true]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
@ -662,7 +729,8 @@
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "s1", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Welcome to your account", @Empty = false, @Image = "\"Welcome to your account\"", @Length = 23, @LiteralText = "\"Welcome to your account\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | +- Template[]
| | +- TemplateFragment[@Content = "\"Welcome to your account\""]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "User"]

View File

@ -308,7 +308,7 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 7, @containsComment = false]
| +- Block[@Empty = false, @Size = 10, @containsComment = true]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
@ -353,20 +353,87 @@
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "address", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "1 Maple Drive, Anytown", @Empty = false, @Image = "\"1 Maple Drive, Anytown\"", @Length = 22, @LiteralText = "\"1 Maple Drive, Anytown\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| | +- VariableDeclarator[@Initializer = true, @Name = "json"]
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "json", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- Template[]
| | +- TemplateFragment[@Content = "\"\"\"\n {\n \"name\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\",\n \"phone\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "phone", @Name = "phone", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\",\n \"address\": \"\\{"]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "address", @Name = "address", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TemplateFragment[@Content = "}\"\n }\n \"\"\""]
| +- LocalClassStatement[]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep459_StringTemplates$1Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{static, final}", @ExplicitModifiers = "{}"]
| | +- RecordComponentList[@Empty = false, @Size = 3, @Varargs = false]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| | | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "name", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "width", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
| | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"]
| | | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = true, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "height", @PatternBinding = false, @RecordComponent = true, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_PRIVATE]
| | +- RecordBody[@Empty = false, @Size = 1]
| | +- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Name = "area", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = false]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- PrimitiveType[@Kind = PrimitiveTypeKind.DOUBLE]
| | +- FormalParameters[@Empty = true, @Size = 0]
| | +- Block[@Empty = false, @Size = 1, @containsComment = false]
| | +- ReturnStatement[]
| | +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.MUL, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "width", @Name = "width", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "height", @Name = "height", @ParenthesisDepth = 0, @Parenthesized = false]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ArrayType[@ArrayDepth = 1]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArrayDimensions[@Empty = false, @Size = 1]
| | | +- ArrayTypeDim[@Varargs = false]
| | +- VariableDeclarator[@Initializer = true, @Name = "zone"]
| | +- VariableId[@ArrayType = true, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "zone", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ArrayAllocation[@ArrayDepth = 1, @CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ArrayType[@ArrayDepth = 1]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArrayDimensions[@Empty = false, @Size = 1]
| | | +- ArrayTypeDim[@Varargs = false]
| | +- ArrayInitializer[@CompileTimeConstant = false, @Length = 3, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArgumentList[@Empty = false, @Size = 3]
| | | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Alfa", @Empty = false, @Image = "\"Alfa\"", @Length = 4, @LiteralText = "\"Alfa\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "17.8", @IntLiteral = false, @Integral = false, @LiteralText = "17.8", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 17.8, @ValueAsFloat = 17.8, @ValueAsInt = 17, @ValueAsLong = 17]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "31.4", @IntLiteral = false, @Integral = false, @LiteralText = "31.4", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 31.4, @ValueAsFloat = 31.4, @ValueAsInt = 31, @ValueAsLong = 31]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | | +- ArgumentList[@Empty = false, @Size = 3]
| | | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Bravo", @Empty = false, @Image = "\"Bravo\"", @Length = 5, @LiteralText = "\"Bravo\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "9.6", @IntLiteral = false, @Integral = false, @LiteralText = "9.6", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 9.6, @ValueAsFloat = 9.6, @ValueAsInt = 9, @ValueAsLong = 9]
| | | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "12.4", @IntLiteral = false, @Integral = false, @LiteralText = "12.4", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 12.4, @ValueAsFloat = 12.4, @ValueAsInt = 12, @ValueAsLong = 12]
| | +- ConstructorCall[@AnonymousClass = false, @CompileTimeConstant = false, @DiamondTypeArgs = false, @MethodName = "new", @ParenthesisDepth = 0, @Parenthesized = false, @QualifiedInstanceCreation = false]
| | +- ClassType[@FullyQualified = false, @SimpleName = "Rectangle"]
| | +- ArgumentList[@Empty = false, @Size = 3]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Charlie", @Empty = false, @Image = "\"Charlie\"", @Length = 7, @LiteralText = "\"Charlie\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "7.1", @IntLiteral = false, @Integral = false, @LiteralText = "7.1", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 7.1, @ValueAsFloat = 7.1, @ValueAsInt = 7, @ValueAsLong = 7]
| | +- NumericLiteral[@Base = 10, @CompileTimeConstant = true, @DoubleLiteral = true, @FloatLiteral = false, @Image = "11.23", @IntLiteral = false, @Integral = false, @LiteralText = "11.23", @LongLiteral = false, @ParenthesisDepth = 0, @Parenthesized = false, @ValueAsDouble = 11.23, @ValueAsFloat = 11.23, @ValueAsInt = 11, @ValueAsLong = 11]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| +- ClassType[@FullyQualified = false, @SimpleName = "String"]
| +- VariableDeclarator[@Initializer = true, @Name = "json"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "json", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- VariableDeclarator[@Initializer = true, @Name = "table"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "table", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| +- Template[]
| +- TemplateFragment[@Content = "\"\"\"\n {\n \"name\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\",\n \"phone\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "phone", @Name = "phone", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\",\n \"address\": \"\\{"]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "address", @Name = "address", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TemplateFragment[@Content = "}\"\n }\n \"\"\";\n /*\n | \"\"\"\n | {\n | \"name\": \"Joan Smith\",\n | \"phone\": \"555-123-4567\",\n | \"address\": \"1 Maple Drive, Anytown\"\n | }\n | \"\"\"\n */\n\n record Rectangle(String name, double width, double height) {\n double area() {\n return width * height;\n }\n }\n Rectangle[] zone = new Rectangle[] {\n new Rectangle(\"Alfa\", 17.8, 31.4),\n new Rectangle(\"Bravo\", 9.6, 12.4),\n new Rectangle(\"Charlie\", 7.1, 11.23),\n };\n String table = STR.\"\"\"\n Description Width Height Area\n \\{"]
| +- TemplateFragment[@Content = "\"\"\"\n Description Width Height Area\n \\{"]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "name", @Name = "name", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ArrayAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "zone", @Name = "zone", @ParenthesisDepth = 0, @Parenthesized = false]
@ -452,9 +519,9 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 4, @containsComment = false]
| +- Block[@Empty = false, @Size = 4, @containsComment = true]
| +- LocalClassStatement[]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep459_StringTemplates$1Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "Jep459_StringTemplates$2Rectangle", @CanonicalName = null, @EffectiveVisibility = Visibility.V_LOCAL, @Enum = false, @Final = true, @Interface = false, @Local = true, @Nested = false, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Rectangle", @Static = true, @TopLevel = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{static, final}", @ExplicitModifiers = "{}"]
| | +- RecordComponentList[@Empty = false, @Size = 3, @Varargs = false]
| | | +- RecordComponent[@EffectiveVisibility = Visibility.V_LOCAL, @Varargs = false, @Visibility = Visibility.V_PRIVATE]
@ -654,7 +721,7 @@
| +- ModifierList[@EffectiveModifiers = "{static}", @ExplicitModifiers = "{static}"]
| +- VoidType[]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 3, @containsComment = false]
| +- Block[@Empty = false, @Size = 3, @containsComment = true]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "String"]
@ -662,7 +729,8 @@
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = true, @Name = "s1", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- TemplateExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false, @StringTemplate = true]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "STR", @Name = "STR", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Welcome to your account", @Empty = false, @Image = "\"Welcome to your account\"", @Length = 23, @LiteralText = "\"Welcome to your account\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| | +- Template[]
| | +- TemplateFragment[@Content = "\"Welcome to your account\""]
| +- LocalVariableDeclaration[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @TypeInferred = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"]
| | +- ClassType[@FullyQualified = false, @SimpleName = "User"]

Some files were not shown because too many files have changed in this diff Show More