From 3766b36f2f0c49805777b27c310da10717e4500e Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 14:43:21 +0800
Subject: [PATCH 01/12] feat(CtType): add method `getMethodBySignature`
---
.../java/spoon/reflect/declaration/CtType.java | 8 ++++++++
.../support/reflect/declaration/CtTypeImpl.java | 15 +++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/src/main/java/spoon/reflect/declaration/CtType.java b/src/main/java/spoon/reflect/declaration/CtType.java
index c8d0f55d049..7b9c0ea4d4e 100644
--- a/src/main/java/spoon/reflect/declaration/CtType.java
+++ b/src/main/java/spoon/reflect/declaration/CtType.java
@@ -234,6 +234,14 @@ public interface CtType extends CtNamedElement, CtTypeInformation, CtTypeMemb
@PropertyGetter(role = METHOD)
CtMethod getMethod(String name, CtTypeReference... parameterTypes);
+ /**
+ * Gets a method from its signature.
+ *
+ * @return null if does not exit
+ */
+ @PropertyGetter(role = METHOD)
+ CtMethod getMethodBySignature(String signature);
+
/**
* Returns the methods that are directly declared by this class or
* interface.
diff --git a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java
index 8e4a5804c7f..818f72b2e3a 100644
--- a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java
+++ b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java
@@ -723,6 +723,21 @@ public CtMethod getMethod(String name, CtTypeReference... parameterTyp
return null;
}
+ @Override
+ @SuppressWarnings("unchecked")
+ public CtMethod getMethodBySignature(String signature) {
+ if (signature == null) {
+ return null;
+ }
+ String name = signature.substring(0, signature.indexOf('('));
+ for (CtMethod candidate : getMethodsByName(name)) {
+ if (candidate.getSignature().equals(signature)) {
+ return (CtMethod) candidate;
+ }
+ }
+ return null;
+ }
+
protected boolean hasSameParameters(CtExecutable candidate, CtTypeReference... parameterTypes) {
if (candidate.getParameters().size() != parameterTypes.length) {
return false;
From c7b28ac219419300fe2aecd496f9156237bc7d07 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 14:47:12 +0800
Subject: [PATCH 02/12] feat(CtClass): add method `getConstructorBySignature`
---
.../java/spoon/reflect/declaration/CtClass.java | 12 ++++++++++++
.../support/reflect/declaration/CtClassImpl.java | 14 ++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/src/main/java/spoon/reflect/declaration/CtClass.java b/src/main/java/spoon/reflect/declaration/CtClass.java
index 02d4948031b..19fe72dd52b 100644
--- a/src/main/java/spoon/reflect/declaration/CtClass.java
+++ b/src/main/java/spoon/reflect/declaration/CtClass.java
@@ -49,6 +49,18 @@ public interface CtClass extends CtType, CtStatement, CtSealable {
@PropertyGetter(role = CONSTRUCTOR)
CtConstructor getConstructor(CtTypeReference... parameterTypes);
+ /**
+ * Returns the constructor of the class that takes the given signature.
+ * e.g. java.util.HashSet has constructor with no parameters `()`
+ * e.g. java.util.HashSet has constructor with a int and a float parameters `(int,float)`
+ * e.g. java.util.HashSet has constructor with a java.util.Collection parameter `(java.util.Collection)`
+ *
+ * Derived from {@link #getTypeMembers()}
+ */
+ @DerivedProperty
+ @PropertyGetter(role = CONSTRUCTOR)
+ CtConstructor getConstructorBySignature(String signature);
+
/**
* Returns the constructors of this class. This includes the default
* constructor if this class has no constructors explicitly declared.
diff --git a/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java b/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java
index 3f946dbe526..266f50fb8d5 100644
--- a/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java
+++ b/src/main/java/spoon/support/reflect/declaration/CtClassImpl.java
@@ -88,6 +88,20 @@ public CtConstructor getConstructor(CtTypeReference... parameterTypes) {
return null;
}
+ @Override
+ public CtConstructor getConstructorBySignature(String signature) {
+ for (CtTypeMember typeMember : getTypeMembers()) {
+ if (!(typeMember instanceof CtConstructor)) {
+ continue;
+ }
+ CtConstructor c = (CtConstructor) typeMember;
+ if (c.getSignature().replaceAll(c.getDeclaringType().getQualifiedName(), "").equals(signature)) {
+ return c;
+ }
+ }
+ return null;
+ }
+
@Override
public Set> getConstructors() {
Set> constructors = new SignatureBasedSortedSet<>();
From 056b96c6872b17dfd5668772ccff8556a1fb885d Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 15:01:22 +0800
Subject: [PATCH 03/12] fix(CtPathStringBuilder): delete redundant ')'
when calling
`AbstractPathElement.getArguments([constructor with no parameters])`
will produce redundant ')'
---
src/main/java/spoon/reflect/path/CtPathStringBuilder.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/spoon/reflect/path/CtPathStringBuilder.java b/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
index 7082db76d81..2013757bf01 100644
--- a/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
+++ b/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
@@ -145,7 +145,8 @@ private String parseArgumentValue(Tokenizer tokenizer, String argName, CtPathEle
}
} else if ("]".equals(token) || ";".equals(token)) {
//finished reading of argument value
- pathElement.addArgument(argName, argValue.toString());
+ //[fix bug]:AbstractPathElement.getArguments([constructor with no parameters])
+ pathElement.addArgument(argName, argValue.toString().replace("())","()"));
return token;
}
argValue.append(token);
From f98231e9dd3a451bb1f782a78dfae95878f8b4fb Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 15:02:48 +0800
Subject: [PATCH 04/12] feat(CtPathImpl): add method `getJdkClass`
---
.../spoon/reflect/path/impl/CtPathImpl.java | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index a178f68c433..09381abe0cf 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -36,6 +36,32 @@ public List evaluateOn(CtElement... startNode) {
return (List) filtered;
}
+ private Class getJdkClass(String name) {
+ name = name.replaceAll("[\\[\\]]", "");
+ switch (name) {
+ case "byte":
+ return byte.class;
+ case "int":
+ return int.class;
+ case "long":
+ return long.class;
+ case "float":
+ return float.class;
+ case "double":
+ return double.class;
+ case "char":
+ return char.class;
+ case "boolean":
+ return boolean.class;
+ default:
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ }
+ }
+ return null;
+ }
+
@Override
public CtPath relativePath(CtElement parent) {
List roots = new ArrayList<>();
From 8a78406974a5bcdeb84109a6777919c71c1572e8 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 15:16:33 +0800
Subject: [PATCH 05/12] feat(CtPathImpl): rewrite method `evaluateOn`
Test cases have passed.
Now it supports to get JDK-element from CtPath(As String).
---
.../spoon/reflect/path/impl/CtPathImpl.java | 39 +++++++++++++
src/test/java/spoon/test/path/PathTest.java | 57 +++++++++++--------
2 files changed, 72 insertions(+), 24 deletions(-)
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index 09381abe0cf..4dc9ba82745 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -7,8 +7,12 @@
*/
package spoon.reflect.path.impl;
+import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
+import spoon.reflect.declaration.CtType;
+import spoon.reflect.factory.TypeFactory;
import spoon.reflect.path.CtPath;
+import spoon.reflect.path.CtRole;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,6 +37,41 @@ public List evaluateOn(CtElement... startNode) {
for (CtPathElement element : elements) {
filtered = element.getElements(filtered);
}
+ if (filtered.isEmpty()) {
+ List cls_name_list = new LinkedList<>();
+ CtType ctType = null;
+ for (CtPathElement element : elements) {
+ if (element instanceof CtRolePathElement) { // search by CtRolePathElement
+ Collection values = ((CtRolePathElement) element).getArguments().values();
+ String val = null;
+ if (values.iterator().hasNext()) val = values.iterator().next();
+ if (val != null) {
+ if (CtRole.SUB_PACKAGE.equals(((CtRolePathElement) element).getRole())
+ || CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole()))
+ cls_name_list.add(val);
+
+ Class cls = getJdkClass(String.join(".", cls_name_list));
+ if (cls != null) {
+ ctType = new TypeFactory().get(cls);
+ if (ctType != null) {
+ CtElement result = null;
+ if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole())) {
+ result = ctType.getMethodBySignature(val);
+ }
+ if (CtRole.CONSTRUCTOR.equals(((CtRolePathElement) element).getRole())) {
+ result = ((CtClass) ctType).getConstructorBySignature(val);
+ }
+ if (CtRole.FIELD.equals(((CtRolePathElement) element).getRole())) {
+ result = ctType.getField(val);
+ }
+ if (result != null) filtered.add(result);
+ }
+ }
+ }
+ }
+ }
+ if (filtered.isEmpty() && ctType != null) filtered.add(ctType);
+ }
return (List) filtered;
}
diff --git a/src/test/java/spoon/test/path/PathTest.java b/src/test/java/spoon/test/path/PathTest.java
index eccb2340265..25c48698cc9 100644
--- a/src/test/java/spoon/test/path/PathTest.java
+++ b/src/test/java/spoon/test/path/PathTest.java
@@ -17,12 +17,6 @@
package spoon.test.path;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import spoon.Launcher;
@@ -31,30 +25,18 @@
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtStatement;
-import spoon.reflect.declaration.CtClass;
-import spoon.reflect.declaration.CtConstructor;
-import spoon.reflect.declaration.CtElement;
-import spoon.reflect.declaration.CtMethod;
-import spoon.reflect.declaration.CtParameter;
-import spoon.reflect.declaration.CtType;
-import spoon.reflect.declaration.CtTypeMember;
+import spoon.reflect.declaration.*;
import spoon.reflect.factory.Factory;
-import spoon.reflect.path.CtElementPathBuilder;
-import spoon.reflect.path.CtPath;
-import spoon.reflect.path.CtPathBuilder;
-import spoon.reflect.path.CtPathException;
-import spoon.reflect.path.CtPathStringBuilder;
-import spoon.reflect.path.CtRole;
+import spoon.reflect.factory.TypeFactory;
+import spoon.reflect.path.*;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.NamedElementFilter;
import spoon.reflect.visitor.filter.TypeFilter;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
/**
* Created by nicolas on 10/06/2015.
@@ -409,4 +391,31 @@ public void testFieldOfArrayType() {
assertEquals(1, result.size());
assertSame(argType, result.get(0));
}
+
+ @Test
+ public void testGetJdkElementByCtPathString() {
+ CtPath path;
+ // test class
+ path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]");
+ assertTrue(path.evaluateOn().iterator().hasNext());
+ CtType class_HashSet = new TypeFactory().get(java.util.HashSet.class);
+ assertEquals(path.evaluateOn().iterator().next(), class_HashSet);
+ // if unable to get the method or the field, it will try to return the method.
+ // test method
+ path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#method[signature=contains(java.lang.Object)]");
+ assertTrue(path.evaluateOn().iterator().hasNext());
+ assertEquals(path.evaluateOn().iterator().next(), class_HashSet.getMethodBySignature("contains(java.lang.Object)"));
+ // test constructor
+ path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#constructor[signature=()]");
+ assertTrue(path.evaluateOn().iterator().hasNext());
+ assertEquals(path.evaluateOn().iterator().next(), ((CtClass) class_HashSet).getConstructorBySignature("()"));
+
+ path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#constructor[signature=(int)]");
+ assertTrue(path.evaluateOn().iterator().hasNext());
+ assertEquals(path.evaluateOn().iterator().next(), ((CtClass) class_HashSet).getConstructorBySignature("(int)"));
+ // test field
+ path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#field[name=map]");
+ assertTrue(path.evaluateOn().iterator().hasNext());
+ assertEquals(path.evaluateOn().iterator().next(), class_HashSet.getField("map"));
+ }
}
\ No newline at end of file
From ed960fbfd5f20148ff5aecda99f5ab54062856d4 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 16:47:06 +0800
Subject: [PATCH 06/12] docs(path.md): update doc
---
doc/path.md | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/doc/path.md b/doc/path.md
index 578651040b2..89ef5b0b845 100644
--- a/doc/path.md
+++ b/doc/path.md
@@ -13,13 +13,22 @@ For instance, a "then" branch in an if/then/else is a role (and not a node). All
### Evaluating AST paths
-Paths are used to find code elements, from a given root element.
+Paths are used to find code elements, from a given root element(e.g. `model.getRootPackage()`).
```java
path = new CtPathStringBuilder().fromString(".spoon.test.path.testclasses.Foo.foo#body#statement[index=0]");
List l = path.evaluateOn(root)
```
+If the root parameter is not given, spoon will try to find shadow elements(e.g. jdk classes).
+
+> If so, it can only supperts `CtType`, `CtMethod` and `CtField` for now.
+
+```java
+path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]");
+List l = path.evaluateOn()
+```
+
### Creating AST paths
#### From an existing element
From 0bfa2d43e08879a0566d1a4954329cd1a982c77c Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 17:10:15 +0800
Subject: [PATCH 07/12] refactor(CtPathImpl): optimization code
---
src/main/java/spoon/reflect/path/impl/CtPathImpl.java | 10 +++-------
src/test/java/spoon/test/path/PathTest.java | 2 +-
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index 4dc9ba82745..1432856d129 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -14,11 +14,7 @@
import spoon.reflect.path.CtPath;
import spoon.reflect.path.CtRole;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
/**
* Default implementation for a CtPath
@@ -52,8 +48,8 @@ public List evaluateOn(CtElement... startNode) {
Class cls = getJdkClass(String.join(".", cls_name_list));
if (cls != null) {
- ctType = new TypeFactory().get(cls);
- if (ctType != null) {
+ if (ctType == null) ctType = new TypeFactory().get(cls);
+ else {
CtElement result = null;
if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole())) {
result = ctType.getMethodBySignature(val);
diff --git a/src/test/java/spoon/test/path/PathTest.java b/src/test/java/spoon/test/path/PathTest.java
index 25c48698cc9..8ee4531b925 100644
--- a/src/test/java/spoon/test/path/PathTest.java
+++ b/src/test/java/spoon/test/path/PathTest.java
@@ -400,7 +400,7 @@ public void testGetJdkElementByCtPathString() {
assertTrue(path.evaluateOn().iterator().hasNext());
CtType class_HashSet = new TypeFactory().get(java.util.HashSet.class);
assertEquals(path.evaluateOn().iterator().next(), class_HashSet);
- // if unable to get the method or the field, it will try to return the method.
+ // if unable to get the method or the field, it will try to return the class.
// test method
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#method[signature=contains(java.lang.Object)]");
assertTrue(path.evaluateOn().iterator().hasNext());
From 120ac0dfd68a17be81094bac2e78344f5c9d0f26 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 18:58:12 +0800
Subject: [PATCH 08/12] refactor(PathTest): revert imports
---
src/test/java/spoon/test/path/PathTest.java | 29 +++++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/test/java/spoon/test/path/PathTest.java b/src/test/java/spoon/test/path/PathTest.java
index 8ee4531b925..bb323ad1a40 100644
--- a/src/test/java/spoon/test/path/PathTest.java
+++ b/src/test/java/spoon/test/path/PathTest.java
@@ -17,6 +17,12 @@
package spoon.test.path;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import spoon.Launcher;
@@ -25,18 +31,31 @@
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtStatement;
-import spoon.reflect.declaration.*;
+import spoon.reflect.declaration.CtClass;
+import spoon.reflect.declaration.CtConstructor;
+import spoon.reflect.declaration.CtElement;
+import spoon.reflect.declaration.CtMethod;
+import spoon.reflect.declaration.CtParameter;
+import spoon.reflect.declaration.CtType;
+import spoon.reflect.declaration.CtTypeMember;
import spoon.reflect.factory.Factory;
import spoon.reflect.factory.TypeFactory;
-import spoon.reflect.path.*;
+import spoon.reflect.path.CtElementPathBuilder;
+import spoon.reflect.path.CtPath;
+import spoon.reflect.path.CtPathBuilder;
+import spoon.reflect.path.CtPathException;
+import spoon.reflect.path.CtPathStringBuilder;
+import spoon.reflect.path.CtRole;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.NamedElementFilter;
import spoon.reflect.visitor.filter.TypeFilter;
-import java.util.*;
-
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* Created by nicolas on 10/06/2015.
From bbbbebabeb36110548ac503c81332027a825c9ab Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 19:09:26 +0800
Subject: [PATCH 09/12] docs(path.md): update doc as suggested
---
doc/path.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/path.md b/doc/path.md
index 89ef5b0b845..0c8281ec2a3 100644
--- a/doc/path.md
+++ b/doc/path.md
@@ -13,16 +13,16 @@ For instance, a "then" branch in an if/then/else is a role (and not a node). All
### Evaluating AST paths
-Paths are used to find code elements, from a given root element(e.g. `model.getRootPackage()`).
+Paths are used to find code elements, from a given root element.
```java
path = new CtPathStringBuilder().fromString(".spoon.test.path.testclasses.Foo.foo#body#statement[index=0]");
List l = path.evaluateOn(root)
```
-If the root parameter is not given, spoon will try to find shadow elements(e.g. jdk classes).
+If the root parameter is omitted, spoon will try to find shadow elements (e.g. jdk classes).
-> If so, it can only supperts `CtType`, `CtMethod` and `CtField` for now.
+> Querying shadow elements currently only supports types, methods and fields.
```java
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]");
From 3b779ee2edb6f96dc00cceb33233864d6ab22042 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Sun, 30 Oct 2022 19:39:28 +0800
Subject: [PATCH 10/12] refactor(CtPath): extract method
`evaluateOnShadowModel`
---
src/main/java/spoon/reflect/path/CtPath.java | 5 ++
.../spoon/reflect/path/impl/CtPathImpl.java | 56 +++++++++----------
src/test/java/spoon/test/path/PathTest.java | 21 +++----
3 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/src/main/java/spoon/reflect/path/CtPath.java b/src/main/java/spoon/reflect/path/CtPath.java
index e50a5d95530..adaf1a2c0b5 100644
--- a/src/main/java/spoon/reflect/path/CtPath.java
+++ b/src/main/java/spoon/reflect/path/CtPath.java
@@ -21,6 +21,11 @@ public interface CtPath {
*/
List evaluateOn(CtElement... startNode);
+ /**
+ * Search for elements matching this CtPatch from shadow model.
+ */
+ CtElement evaluateOnShadowModel();
+
/**
*
* Returns the path that is relative to the given element (subpath from it to the end of the path).
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index 1432856d129..8aabb12009c 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -33,42 +33,40 @@ public List evaluateOn(CtElement... startNode) {
for (CtPathElement element : elements) {
filtered = element.getElements(filtered);
}
- if (filtered.isEmpty()) {
- List cls_name_list = new LinkedList<>();
- CtType ctType = null;
- for (CtPathElement element : elements) {
- if (element instanceof CtRolePathElement) { // search by CtRolePathElement
- Collection values = ((CtRolePathElement) element).getArguments().values();
- String val = null;
- if (values.iterator().hasNext()) val = values.iterator().next();
- if (val != null) {
- if (CtRole.SUB_PACKAGE.equals(((CtRolePathElement) element).getRole())
- || CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole()))
- cls_name_list.add(val);
+ return (List) filtered;
+ }
+
+ @Override
+ public CtElement evaluateOnShadowModel() {
+ List cls_name_list = new LinkedList<>();
+ CtType ctType = null;
+ for (CtPathElement element : elements) {
+ if (element instanceof CtRolePathElement) { // search by CtRolePathElement
+ Collection values = ((CtRolePathElement) element).getArguments().values();
+ String val = null;
+ if (values.iterator().hasNext()) val = values.iterator().next();
+ if (val != null) {
+ if (CtRole.SUB_PACKAGE.equals(((CtRolePathElement) element).getRole())
+ || CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole()))
+ cls_name_list.add(val);
- Class cls = getJdkClass(String.join(".", cls_name_list));
- if (cls != null) {
- if (ctType == null) ctType = new TypeFactory().get(cls);
- else {
- CtElement result = null;
- if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole())) {
- result = ctType.getMethodBySignature(val);
- }
- if (CtRole.CONSTRUCTOR.equals(((CtRolePathElement) element).getRole())) {
- result = ((CtClass) ctType).getConstructorBySignature(val);
- }
- if (CtRole.FIELD.equals(((CtRolePathElement) element).getRole())) {
- result = ctType.getField(val);
- }
- if (result != null) filtered.add(result);
+ Class cls = getJdkClass(String.join(".", cls_name_list));
+ if (cls != null) {
+ if (ctType == null) ctType = new TypeFactory().get(cls);
+ else {
+ if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole()))
+ return ctType.getMethodBySignature(val);
+ if (CtRole.CONSTRUCTOR.equals(((CtRolePathElement) element).getRole()))
+ return ((CtClass) ctType).getConstructorBySignature(val);
+ if (CtRole.FIELD.equals(((CtRolePathElement) element).getRole())) {
+ return ctType.getField(val);
}
}
}
}
}
- if (filtered.isEmpty() && ctType != null) filtered.add(ctType);
}
- return (List) filtered;
+ return ctType;
}
private Class getJdkClass(String name) {
diff --git a/src/test/java/spoon/test/path/PathTest.java b/src/test/java/spoon/test/path/PathTest.java
index bb323ad1a40..d0b9041f27f 100644
--- a/src/test/java/spoon/test/path/PathTest.java
+++ b/src/test/java/spoon/test/path/PathTest.java
@@ -56,6 +56,7 @@
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* Created by nicolas on 10/06/2015.
@@ -416,25 +417,25 @@ public void testGetJdkElementByCtPathString() {
CtPath path;
// test class
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]");
- assertTrue(path.evaluateOn().iterator().hasNext());
+ assertNotNull(path.evaluateOnShadowModel());
CtType class_HashSet = new TypeFactory().get(java.util.HashSet.class);
- assertEquals(path.evaluateOn().iterator().next(), class_HashSet);
+ assertEquals(path.evaluateOnShadowModel(), class_HashSet);
// if unable to get the method or the field, it will try to return the class.
// test method
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#method[signature=contains(java.lang.Object)]");
- assertTrue(path.evaluateOn().iterator().hasNext());
- assertEquals(path.evaluateOn().iterator().next(), class_HashSet.getMethodBySignature("contains(java.lang.Object)"));
+ assertNotNull(path.evaluateOnShadowModel());
+ assertEquals(path.evaluateOnShadowModel(), class_HashSet.getMethodBySignature("contains(java.lang.Object)"));
// test constructor
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#constructor[signature=()]");
- assertTrue(path.evaluateOn().iterator().hasNext());
- assertEquals(path.evaluateOn().iterator().next(), ((CtClass) class_HashSet).getConstructorBySignature("()"));
+ assertNotNull(path.evaluateOnShadowModel());
+ assertEquals(path.evaluateOnShadowModel(), ((CtClass) class_HashSet).getConstructorBySignature("()"));
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#constructor[signature=(int)]");
- assertTrue(path.evaluateOn().iterator().hasNext());
- assertEquals(path.evaluateOn().iterator().next(), ((CtClass) class_HashSet).getConstructorBySignature("(int)"));
+ assertNotNull(path.evaluateOnShadowModel());
+ assertEquals(path.evaluateOnShadowModel(), ((CtClass) class_HashSet).getConstructorBySignature("(int)"));
// test field
path = new CtPathStringBuilder().fromString("#subPackage[name=java]#subPackage[name=util]#containedType[name=HashSet]#field[name=map]");
- assertTrue(path.evaluateOn().iterator().hasNext());
- assertEquals(path.evaluateOn().iterator().next(), class_HashSet.getField("map"));
+ assertNotNull(path.evaluateOnShadowModel());
+ assertEquals(path.evaluateOnShadowModel(), class_HashSet.getField("map"));
}
}
\ No newline at end of file
From 6ddbcb2677164c231925f18f03929b6f44b28342 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Mon, 31 Oct 2022 09:00:30 +0800
Subject: [PATCH 11/12] refactor: adjust code style
---
.../reflect/path/CtPathStringBuilder.java | 4 +--
.../spoon/reflect/path/impl/CtPathImpl.java | 25 +++++++++++++------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/main/java/spoon/reflect/path/CtPathStringBuilder.java b/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
index 2013757bf01..7f1de58fff3 100644
--- a/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
+++ b/src/main/java/spoon/reflect/path/CtPathStringBuilder.java
@@ -13,8 +13,8 @@
import spoon.reflect.path.impl.CtNamedPathElement;
import spoon.reflect.path.impl.CtPathElement;
import spoon.reflect.path.impl.CtPathImpl;
-import spoon.reflect.path.impl.CtTypedNameElement;
import spoon.reflect.path.impl.CtRolePathElement;
+import spoon.reflect.path.impl.CtTypedNameElement;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -146,7 +146,7 @@ private String parseArgumentValue(Tokenizer tokenizer, String argName, CtPathEle
} else if ("]".equals(token) || ";".equals(token)) {
//finished reading of argument value
//[fix bug]:AbstractPathElement.getArguments([constructor with no parameters])
- pathElement.addArgument(argName, argValue.toString().replace("())","()"));
+ pathElement.addArgument(argName, argValue.toString().replace("())", "()"));
return token;
}
argValue.append(token);
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index 8aabb12009c..0dc7030f4d6 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -14,7 +14,11 @@
import spoon.reflect.path.CtPath;
import spoon.reflect.path.CtRole;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
/**
* Default implementation for a CtPath
@@ -44,20 +48,25 @@ public CtElement evaluateOnShadowModel() {
if (element instanceof CtRolePathElement) { // search by CtRolePathElement
Collection values = ((CtRolePathElement) element).getArguments().values();
String val = null;
- if (values.iterator().hasNext()) val = values.iterator().next();
+ if (values.iterator().hasNext()) {
+ val = values.iterator().next();
+ }
if (val != null) {
if (CtRole.SUB_PACKAGE.equals(((CtRolePathElement) element).getRole())
- || CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole()))
+ || CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole())) {
cls_name_list.add(val);
-
+ }
Class cls = getJdkClass(String.join(".", cls_name_list));
if (cls != null) {
- if (ctType == null) ctType = new TypeFactory().get(cls);
- else {
- if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole()))
+ if (ctType == null) {
+ ctType = new TypeFactory().get(cls);
+ } else {
+ if (CtRole.METHOD.equals(((CtRolePathElement) element).getRole())) {
return ctType.getMethodBySignature(val);
- if (CtRole.CONSTRUCTOR.equals(((CtRolePathElement) element).getRole()))
+ }
+ if (CtRole.CONSTRUCTOR.equals(((CtRolePathElement) element).getRole())) {
return ((CtClass) ctType).getConstructorBySignature(val);
+ }
if (CtRole.FIELD.equals(((CtRolePathElement) element).getRole())) {
return ctType.getField(val);
}
From 02adcd811a997644dd8321a67dc3378018527226 Mon Sep 17 00:00:00 2001
From: kaml8 <62456016+kaml8@users.noreply.github.com>
Date: Mon, 31 Oct 2022 09:08:12 +0800
Subject: [PATCH 12/12] refactor: adjust codeStyle
---
src/main/java/spoon/reflect/path/impl/CtPathImpl.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
index 0dc7030f4d6..ab78cd72469 100644
--- a/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
+++ b/src/main/java/spoon/reflect/path/impl/CtPathImpl.java
@@ -42,7 +42,7 @@ public List evaluateOn(CtElement... startNode) {
@Override
public CtElement evaluateOnShadowModel() {
- List cls_name_list = new LinkedList<>();
+ List classRoleNameList = new LinkedList<>();
CtType ctType = null;
for (CtPathElement element : elements) {
if (element instanceof CtRolePathElement) { // search by CtRolePathElement
@@ -54,9 +54,9 @@ public CtElement evaluateOnShadowModel() {
if (val != null) {
if (CtRole.SUB_PACKAGE.equals(((CtRolePathElement) element).getRole())
|| CtRole.CONTAINED_TYPE.equals(((CtRolePathElement) element).getRole())) {
- cls_name_list.add(val);
+ classRoleNameList.add(val);
}
- Class cls = getJdkClass(String.join(".", cls_name_list));
+ Class cls = getJdkClass(String.join(".", classRoleNameList));
if (cls != null) {
if (ctType == null) {
ctType = new TypeFactory().get(cls);