aboutsummaryrefslogtreecommitdiff
path: root/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java')
-rw-r--r--javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java133
1 files changed, 133 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
new file mode 100644
index 000000000..993f42d29
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
@@ -0,0 +1,133 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.reflectionmodel.*;
+import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeDeclarationAdapter {
+
+ private com.github.javaparser.ast.body.TypeDeclaration<?> wrappedNode;
+ private TypeSolver typeSolver;
+ private Context context;
+ private ResolvedReferenceTypeDeclaration typeDeclaration;
+
+ public JavaParserTypeDeclarationAdapter(com.github.javaparser.ast.body.TypeDeclaration<?> wrappedNode, TypeSolver typeSolver,
+ ResolvedReferenceTypeDeclaration typeDeclaration,
+ Context context) {
+ this.wrappedNode = wrappedNode;
+ this.typeSolver = typeSolver;
+ this.typeDeclaration = typeDeclaration;
+ this.context = context;
+ }
+
+ public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+ if (this.wrappedNode.getName().getId().equals(name)) {
+ return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(wrappedNode));
+ }
+
+ // Internal classes
+ for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
+ if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+ com.github.javaparser.ast.body.TypeDeclaration<?> internalType = (com.github.javaparser.ast.body.TypeDeclaration<?>) member;
+ if (internalType.getName().getId().equals(name)) {
+ return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType));
+ } else if (name.startsWith(String.format("%s.%s", wrappedNode.getName(), internalType.getName()))) {
+ return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1), typeSolver);
+ } else if (name.startsWith(String.format("%s.", internalType.getName()))) {
+ return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver);
+ }
+ }
+ }
+
+ if (wrappedNode instanceof NodeWithTypeParameters) {
+ NodeWithTypeParameters<?> nodeWithTypeParameters = (NodeWithTypeParameters<?>) wrappedNode;
+ for (TypeParameter astTpRaw : nodeWithTypeParameters.getTypeParameters()) {
+ TypeParameter astTp = astTpRaw;
+ if (astTp.getName().getId().equals(name)) {
+ return SymbolReference.solved(new JavaParserTypeParameter(astTp, typeSolver));
+ }
+ }
+ }
+
+ // Look into extended classes and implemented interfaces
+ for (ResolvedReferenceType ancestor : this.typeDeclaration.getAncestors()) {
+ try {
+ for (ResolvedTypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) {
+ if (internalTypeDeclaration.getName().equals(name)) {
+ return SymbolReference.solved(internalTypeDeclaration);
+ }
+ }
+ } catch (UnsupportedOperationException e) {
+ // just continue using the next ancestor
+ }
+ }
+
+ return context.getParent().solveType(name, typeSolver);
+ }
+
+ public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+ List<ResolvedMethodDeclaration> candidateMethods = typeDeclaration.getDeclaredMethods().stream()
+ .filter(m -> m.getName().equals(name))
+ .filter(m -> !staticOnly || (staticOnly && m.isStatic()))
+ .collect(Collectors.toList());
+ // We want to avoid infinite recursion in case of Object having Object as ancestor
+ if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) {
+ for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors()) {
+ // Avoid recursion on self
+ if (typeDeclaration != ancestor.getTypeDeclaration()) {
+ SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic
+ .solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver);
+ // consider methods from superclasses and only default methods from interfaces :
+ // not true, we should keep abstract as a valid candidate
+ // abstract are removed in MethodResolutionLogic.isApplicable is necessary
+ if (res.isSolved()) {
+ candidateMethods.add(res.getCorrespondingDeclaration());
+ }
+ }
+ }
+ }
+ // We want to avoid infinite recursion when a class is using its own method
+ // see issue #75
+ if (candidateMethods.isEmpty()) {
+ SymbolReference<ResolvedMethodDeclaration> parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+ if (parentSolution.isSolved()) {
+ candidateMethods.add(parentSolution.getCorrespondingDeclaration());
+ }
+ }
+
+ // if is interface and candidate method list is empty, we should check the Object Methods
+ if (candidateMethods.isEmpty() && typeDeclaration.isInterface()) {
+ SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver);
+ if (res.isSolved()) {
+ candidateMethods.add(res.getCorrespondingDeclaration());
+ }
+ }
+
+ return MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver);
+ }
+
+ public SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
+ if (typeDeclaration instanceof ResolvedClassDeclaration) {
+ return ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) typeDeclaration).getConstructors(), argumentsTypes, typeSolver);
+ }
+ return SymbolReference.unsolved(ResolvedConstructorDeclaration.class);
+ }
+}