diff options
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations')
17 files changed, 2868 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java new file mode 100644 index 000000000..aff7c7c85 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; + +import java.util.Collections; +import java.util.List; + +/** + * This represents the default constructor added by the compiler for objects not declaring one. + * It takes no parameters. See JLS 8.8.9 for details. + * + * @author Federico Tomassetti + */ +class DefaultConstructorDeclaration implements ResolvedConstructorDeclaration { + + private ResolvedClassDeclaration classDeclaration; + + DefaultConstructorDeclaration(ResolvedClassDeclaration classDeclaration) { + this.classDeclaration = classDeclaration; + } + + @Override + public ResolvedClassDeclaration declaringType() { + return classDeclaration; + } + + @Override + public int getNumberOfParams() { + return 0; + } + + @Override + public ResolvedParameterDeclaration getParam(int i) { + throw new UnsupportedOperationException("The default constructor has not parameters"); + } + + @Override + public String getName() { + return classDeclaration.getName(); + } + + @Override + public AccessSpecifier accessSpecifier() { + return AccessSpecifier.PUBLIC; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Collections.emptyList(); + } + + @Override + public int getNumberOfSpecifiedExceptions() { + return 0; + } + + @Override + public ResolvedType getSpecifiedException(int index) { + throw new UnsupportedOperationException("The default constructor does not throw exceptions"); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java new file mode 100644 index 000000000..d34e16412 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.*; + +import java.util.EnumSet; +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +class Helper { + + public static AccessSpecifier toAccessLevel(EnumSet<Modifier> modifiers) { + if (modifiers.contains(Modifier.PRIVATE)) { + return AccessSpecifier.PRIVATE; + } else if (modifiers.contains(Modifier.PROTECTED)) { + return AccessSpecifier.PROTECTED; + } else if (modifiers.contains(Modifier.PUBLIC)) { + return AccessSpecifier.PUBLIC; + } else { + return AccessSpecifier.DEFAULT; + } + } + + static String containerName(Node container) { + String packageName = getPackageName(container); + String className = getClassName("", container); + return packageName + + ((!packageName.isEmpty() && !className.isEmpty()) ? "." : "") + + className; + } + + static String getPackageName(Node container) { + if (container instanceof CompilationUnit) { + Optional<PackageDeclaration> p = ((CompilationUnit) container).getPackageDeclaration(); + if (p.isPresent()) { + return p.get().getName().toString(); + } + } else if (container != null) { + return getPackageName(container.getParentNode().orElse(null)); + } + return ""; + } + + static String getClassName(String base, Node container) { + if (container instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) { + String b = getClassName(base, container.getParentNode().orElse(null)); + String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId(); + if (b.isEmpty()) { + return cn; + } else { + return b + "." + cn; + } + } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) { + String b = getClassName(base, container.getParentNode().orElse(null)); + String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId(); + if (b.isEmpty()) { + return cn; + } else { + return b + "." + cn; + } + } else if (container != null) { + return getClassName(base, container.getParentNode().orElse(null)); + } + return base; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java new file mode 100644 index 000000000..1f6c6f33f --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java @@ -0,0 +1,103 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.body.AnnotationDeclaration; +import com.github.javaparser.ast.body.AnnotationMemberDeclaration; +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.logic.AbstractTypeDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserAnnotationDeclaration extends AbstractTypeDeclaration implements ResolvedAnnotationDeclaration { + + private com.github.javaparser.ast.body.AnnotationDeclaration wrappedNode; + private TypeSolver typeSolver; + + public JavaParserAnnotationDeclaration(AnnotationDeclaration wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + throw new UnsupportedOperationException(); + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasDirectlyAnnotation(String qualifiedName) { + throw new UnsupportedOperationException(); + } + + @Override + public String getPackageName() { + return Helper.getPackageName(wrappedNode); + } + + @Override + public String getClassName() { + return Helper.getClassName("", wrappedNode); + } + + @Override + public String getQualifiedName() { + String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null)); + if (containerName.isEmpty()) { + return wrappedNode.getName().getId(); + } else { + return containerName + "." + wrappedNode.getName(); + } + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName()); + } + + @Override + public List<ResolvedAnnotationMemberDeclaration> getAnnotationMembers() { + return wrappedNode.getMembers().stream() + .filter(m -> m instanceof AnnotationMemberDeclaration) + .map(m -> new JavaParserAnnotationMemberDeclaration((AnnotationMemberDeclaration)m, typeSolver)) + .collect(Collectors.toList()); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationMemberDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationMemberDeclaration.java new file mode 100644 index 000000000..2a603daf8 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationMemberDeclaration.java @@ -0,0 +1,40 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.body.AnnotationMemberDeclaration; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +/** + * @author Federico Tomassetti + */ +public class JavaParserAnnotationMemberDeclaration implements ResolvedAnnotationMemberDeclaration { + + private com.github.javaparser.ast.body.AnnotationMemberDeclaration wrappedNode; + private TypeSolver typeSolver; + + public AnnotationMemberDeclaration getWrappedNode() { + return wrappedNode; + } + + public JavaParserAnnotationMemberDeclaration(AnnotationMemberDeclaration wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public Expression getDefaultValue() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedType getType() { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + return wrappedNode.getNameAsString(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java new file mode 100644 index 000000000..3d2cb8f69 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java @@ -0,0 +1,205 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.expr.ObjectCreationExpr; +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.logic.AbstractClassDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * An anonymous class declaration representation. + */ +public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaration { + + private final TypeSolver typeSolver; + private final ObjectCreationExpr wrappedNode; + private final ResolvedTypeDeclaration superTypeDeclaration; + private final String name = "Anonymous-" + UUID.randomUUID(); + + public JavaParserAnonymousClassDeclaration(ObjectCreationExpr wrappedNode, + TypeSolver typeSolver) { + this.typeSolver = typeSolver; + this.wrappedNode = wrappedNode; + superTypeDeclaration = + JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver) + .solveType(wrappedNode.getType().getName().getId(), typeSolver) + .getCorrespondingDeclaration(); + } + + public ResolvedTypeDeclaration getSuperTypeDeclaration() { + return superTypeDeclaration; + } + + public <T extends Node> List<T> findMembersOfKind(final Class<T> memberClass) { + if (wrappedNode.getAnonymousClassBody().isPresent()) { + return wrappedNode + .getAnonymousClassBody() + .get() + .stream() + .filter(node -> memberClass.isAssignableFrom(node.getClass())) + .map(memberClass::cast) + .collect(Collectors.toList()); + } else { + return Collections.emptyList(); + } + } + + public Context getContext() { + return JavaParserFactory.getContext(wrappedNode, typeSolver); + } + + @Override + protected ResolvedReferenceType object() { + return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver); + } + + @Override + public ResolvedReferenceType getSuperClass() { + return new ReferenceTypeImpl(superTypeDeclaration.asReferenceType(), typeSolver); + } + + @Override + public List<ResolvedReferenceType> getInterfaces() { + return + superTypeDeclaration + .asReferenceType().getAncestors() + .stream() + .filter(type -> type.getTypeDeclaration().isInterface()) + .collect(Collectors.toList()); + } + + @Override + public List<ResolvedConstructorDeclaration> getConstructors() { + return + findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class) + .stream() + .map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver)) + .collect(Collectors.toList()); + } + + @Override + public AccessSpecifier accessSpecifier() { + return AccessSpecifier.PRIVATE; + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + return + ImmutableList. + <ResolvedReferenceType>builder() + .add(getSuperClass()) + .addAll(superTypeDeclaration.asReferenceType().getAncestors()) + .build(); + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + + List<JavaParserFieldDeclaration> myFields = + findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class) + .stream() + .flatMap(field -> + field.getVariables().stream() + .map(variable -> new JavaParserFieldDeclaration(variable, + typeSolver))) + .collect(Collectors.toList()); + + List<ResolvedFieldDeclaration> superClassFields = + getSuperClass().getTypeDeclaration().getAllFields(); + + List<ResolvedFieldDeclaration> interfaceFields = + getInterfaces().stream() + .flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()) + .collect(Collectors.toList()); + + return + ImmutableList + .<ResolvedFieldDeclaration>builder() + .addAll(myFields) + .addAll(superClassFields) + .addAll(interfaceFields) + .build(); + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + return + findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class) + .stream() + .map(method -> new JavaParserMethodDeclaration(method, typeSolver)) + .collect(Collectors.toSet()); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + return false; + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return false; + } + + @Override + public boolean hasDirectlyAnnotation(String qualifiedName) { + return false; + } + + @Override + public String getPackageName() { + return Helper.getPackageName(wrappedNode); + } + + @Override + public String getClassName() { + return Helper.getClassName("", wrappedNode); + } + + @Override + public String getQualifiedName() { + String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null)); + if (containerName.isEmpty()) { + return getName(); + } else { + return containerName + "." + getName(); + } + } + + @Override + public Set<ResolvedReferenceTypeDeclaration> internalTypes() { + return + findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class) + .stream() + .map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember)) + .collect(Collectors.toSet()); + } + + @Override + public String getName() { + return name; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Lists.newArrayList(); + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName()); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java new file mode 100644 index 000000000..bb9f91cc6 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java @@ -0,0 +1,397 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.type.ClassOrInterfaceType; +import com.github.javaparser.resolution.UnsolvedSymbolException; +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.logic.AbstractClassDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.LazyType; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; +import com.google.common.collect.ImmutableList; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public class JavaParserClassDeclaration extends AbstractClassDeclaration { + + /// + /// Fields + /// + + private TypeSolver typeSolver; + private com.github.javaparser.ast.body.ClassOrInterfaceDeclaration wrappedNode; + private JavaParserTypeAdapter<ClassOrInterfaceDeclaration> javaParserTypeAdapter; + + /// + /// Constructors + /// + + public JavaParserClassDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration wrappedNode, + TypeSolver typeSolver) { + if (wrappedNode.isInterface()) { + throw new IllegalArgumentException("Interface given"); + } + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + this.javaParserTypeAdapter = new JavaParserTypeAdapter<>(wrappedNode, typeSolver); + } + + /// + /// Public methods: from Object + /// + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JavaParserClassDeclaration that = (JavaParserClassDeclaration) o; + + if (!wrappedNode.equals(that.wrappedNode)) return false; + + return true; + } + + @Override + public int hashCode() { + return wrappedNode.hashCode(); + } + + @Override + public String toString() { + return "JavaParserClassDeclaration{" + + "wrappedNode=" + wrappedNode + + '}'; + } + + /// + /// Public methods: fields + /// + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables(); + + getAncestors().forEach(ancestor -> ancestor.getTypeDeclaration().getAllFields().forEach(f -> { + fields.add(new ResolvedFieldDeclaration() { + + @Override + public AccessSpecifier accessSpecifier() { + return f.accessSpecifier(); + } + + @Override + public String getName() { + return f.getName(); + } + + @Override + public ResolvedType getType() { + return ancestor.useThisTypeParametersOnTheGivenType(f.getType()); + } + + @Override + public boolean isStatic() { + return f.isStatic(); + } + + @Override + public ResolvedTypeDeclaration declaringType() { + return f.declaringType(); + } + }); + })); + + return fields; + } + + /// + /// Public methods + /// + + public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes) { + Context ctx = getContext(); + return ctx.solveMethod(name, parameterTypes, false, typeSolver); + } + + @Deprecated + public Context getContext() { + return JavaParserFactory.getContext(wrappedNode, typeSolver); + } + + public ResolvedType getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public ResolvedReferenceType getSuperClass() { + if (wrappedNode.getExtendedTypes().isEmpty()) { + return object(); + } else { + return toReferenceType(wrappedNode.getExtendedTypes().get(0)); + } + } + + @Override + public List<ResolvedReferenceType> getInterfaces() { + List<ResolvedReferenceType> interfaces = new ArrayList<>(); + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) { + interfaces.add(toReferenceType(t)); + } + } + return interfaces; + } + + @Override + public List<ResolvedConstructorDeclaration> getConstructors() { + List<ResolvedConstructorDeclaration> declared = new LinkedList<>(); + for (BodyDeclaration<?> member : wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.ConstructorDeclaration) { + com.github.javaparser.ast.body.ConstructorDeclaration constructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) member; + declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver)); + } + } + if (declared.isEmpty()) { + // If there are no constructors insert the default constructor + return ImmutableList.of(new DefaultConstructorDeclaration(this)); + } else { + return declared; + } + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) { + if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) { + return true; + } + } + return false; + } + + @Override + public boolean isInterface() { + return wrappedNode.isInterface(); + } + + @Override + public String getPackageName() { + return javaParserTypeAdapter.getPackageName(); + } + + @Override + public String getClassName() { + return javaParserTypeAdapter.getClassName(); + } + + @Override + public String getQualifiedName() { + return javaParserTypeAdapter.getQualifiedName(); + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return javaParserTypeAdapter.isAssignableBy(other); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + return javaParserTypeAdapter.isAssignableBy(type); + } + + @Override + public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + // TODO consider generic types + if (this.getQualifiedName().equals(other.getQualifiedName())) { + return true; + } + ResolvedClassDeclaration superclass = (ResolvedClassDeclaration) getSuperClass().getTypeDeclaration(); + if (superclass != null) { + // We want to avoid infinite recursion in case of Object having Object as ancestor + if (Object.class.getCanonicalName().equals(superclass.getQualifiedName())) { + return true; + } + if (superclass.canBeAssignedTo(other)) { + return true; + } + } + + if (this.wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType type : wrappedNode.getImplementedTypes()) { + ResolvedReferenceTypeDeclaration ancestor = (ResolvedReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type); + if (ancestor.canBeAssignedTo(other)) { + return true; + } + } + } + + return false; + } + + @Override + public boolean isTypeParameter() { + return false; + } + + @Deprecated + public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getName().getId().equals(name)) { + return SymbolReference.solved(this); + } + SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver); + if (ref.isSolved()) { + return ref; + } + + String prefix = wrappedNode.getName() + "."; + if (name.startsWith(prefix) && name.length() > prefix.length()) { + return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver); + } + + return getContext().getParent().solveType(name, typeSolver); + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + List<ResolvedReferenceType> ancestors = new ArrayList<>(); + + // We want to avoid infinite recursion in case of Object having Object as ancestor + if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) { + ResolvedReferenceType superclass = getSuperClass(); + if (superclass != null) { + ancestors.add(superclass); + } + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) { + ResolvedReferenceType ancestor = toReferenceType(implemented); + ancestors.add(ancestor); + } + } + } + + return ancestors; + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + Set<ResolvedMethodDeclaration> methods = new HashSet<>(); + for (BodyDeclaration<?> member : wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) { + methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)); + } + } + return methods; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return this.wrappedNode.getTypeParameters().stream().map( + (tp) -> new JavaParserTypeParameter(tp, typeSolver) + ).collect(Collectors.toList()); + } + + /** + * Returns the JavaParser node associated with this JavaParserClassDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.ClassOrInterfaceDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(wrappedNode.getModifiers()); + } + + /// + /// Protected methods + /// + + @Override + protected ResolvedReferenceType object() { + return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver); + } + + @Override + public Set<ResolvedReferenceTypeDeclaration> internalTypes() { + Set<ResolvedReferenceTypeDeclaration> res = new HashSet<>(); + for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) { + res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member)); + } + } + return res; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + return javaParserTypeAdapter.containerType(); + } + + /// + /// Private methods + /// + + private ResolvedReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) { + String className = classOrInterfaceType.getName().getId(); + if (classOrInterfaceType.getScope().isPresent()) { + // look for the qualified name (for example class of type Rectangle2D.Double) + className = classOrInterfaceType.getScope().get().toString() + "." + className; + } + SymbolReference<ResolvedTypeDeclaration> ref = solveType(className, typeSolver); + if (!ref.isSolved()) { + Optional<ClassOrInterfaceType> localScope = classOrInterfaceType.getScope(); + if (localScope.isPresent()) { + String localName = localScope.get().getName().getId() + "." + classOrInterfaceType.getName().getId(); + ref = solveType(localName, typeSolver); + } + } + if (!ref.isSolved()) { + throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId()); + } + if (!classOrInterfaceType.getTypeArguments().isPresent()) { + return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver); + } + List<ResolvedType> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get() + .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) + .collect(Collectors.toList()); + return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java new file mode 100644 index 000000000..e9500fed2 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java @@ -0,0 +1,103 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public class JavaParserConstructorDeclaration implements ResolvedConstructorDeclaration { + + private ResolvedClassDeclaration classDeclaration; + private com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode; + private TypeSolver typeSolver; + + JavaParserConstructorDeclaration(ResolvedClassDeclaration classDeclaration, com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode, + TypeSolver typeSolver) { + this.classDeclaration = classDeclaration; + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public ResolvedClassDeclaration declaringType() { + return classDeclaration; + } + + @Override + public int getNumberOfParams() { + return this.wrappedNode.getParameters().size(); + } + + @Override + public ResolvedParameterDeclaration getParam(int i) { + if (i < 0 || i >= getNumberOfParams()) { + throw new IllegalArgumentException(String.format("No param with index %d. Number of params: %d", i, getNumberOfParams())); + } + return new JavaParserParameterDeclaration(wrappedNode.getParameters().get(i), typeSolver); + } + + @Override + public String getName() { + return this.classDeclaration.getName(); + } + + /** + * Returns the JavaParser node associated with this JavaParserConstructorDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.ConstructorDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(wrappedNode.getModifiers()); + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()); + } + + @Override + public int getNumberOfSpecifiedExceptions() { + return wrappedNode.getThrownExceptions().size(); + } + + @Override + public ResolvedType getSpecifiedException(int index) { + if (index < 0 || index >= getNumberOfSpecifiedExceptions()) { + throw new IllegalArgumentException(String.format("No exception with index %d. Number of exceptions: %d", + index, getNumberOfSpecifiedExceptions())); + } + return JavaParserFacade.get(typeSolver) + .convert(wrappedNode.getThrownExceptions().get(index), wrappedNode); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java new file mode 100644 index 000000000..6f909582d --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java @@ -0,0 +1,59 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.body.EnumDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedEnumConstantDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserEnumConstantDeclaration implements ResolvedEnumConstantDeclaration { + + private TypeSolver typeSolver; + private com.github.javaparser.ast.body.EnumConstantDeclaration wrappedNode; + + public JavaParserEnumConstantDeclaration(com.github.javaparser.ast.body.EnumConstantDeclaration wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public ResolvedType getType() { + return new ReferenceTypeImpl(new JavaParserEnumDeclaration((EnumDeclaration) requireParentNode(wrappedNode), typeSolver), typeSolver); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + /** + * Returns the JavaParser node associated with this JavaParserEnumConstantDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.EnumConstantDeclaration getWrappedNode() { + return wrappedNode; + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java new file mode 100644 index 000000000..818c0604c --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java @@ -0,0 +1,350 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.BodyDeclaration; +import com.github.javaparser.ast.body.EnumConstantDeclaration; +import com.github.javaparser.ast.type.ClassOrInterfaceType; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.ResolvedArrayType; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap; +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.logic.AbstractTypeDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; + +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implements ResolvedEnumDeclaration { + + private TypeSolver typeSolver; + private com.github.javaparser.ast.body.EnumDeclaration wrappedNode; + private JavaParserTypeAdapter<com.github.javaparser.ast.body.EnumDeclaration> javaParserTypeAdapter; + + public JavaParserEnumDeclaration(com.github.javaparser.ast.body.EnumDeclaration wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + this.javaParserTypeAdapter = new JavaParserTypeAdapter<>(wrappedNode, typeSolver); + } + + @Override + public String toString() { + return "JavaParserEnumDeclaration{" + + "wrappedNode=" + wrappedNode + + '}'; + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + Set<ResolvedMethodDeclaration> methods = new HashSet<>(); + for (BodyDeclaration<?> member : wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) { + methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)); + } + } + return methods; + } + + public Context getContext() { + return JavaParserFactory.getContext(wrappedNode, typeSolver); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public boolean isField() { + return false; + } + + @Override + public boolean isParameter() { + return false; + } + + @Override + public boolean isType() { + return true; + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + String otherName = other.getQualifiedName(); + // Enums cannot be extended + if (otherName.equals(this.getQualifiedName())) { + return true; + } + if (otherName.equals(Enum.class.getCanonicalName())) { + return true; + } + // Enum implements Comparable and Serializable + if (otherName.equals(Comparable.class.getCanonicalName())) { + return true; + } + if (otherName.equals(Serializable.class.getCanonicalName())) { + return true; + } + if (otherName.equals(Object.class.getCanonicalName())) { + return true; + } + return false; + } + + @Override + public boolean isClass() { + return false; + } + + @Override + public boolean isInterface() { + return false; + } + + @Override + public String getPackageName() { + return javaParserTypeAdapter.getPackageName(); + } + + @Override + public String getClassName() { + return javaParserTypeAdapter.getClassName(); + } + + @Override + public String getQualifiedName() { + return javaParserTypeAdapter.getQualifiedName(); + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return javaParserTypeAdapter.isAssignableBy(other); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + return javaParserTypeAdapter.isAssignableBy(type); + } + + @Override + public boolean isTypeParameter() { + return false; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JavaParserEnumDeclaration that = (JavaParserEnumDeclaration) o; + + if (!wrappedNode.equals(that.wrappedNode)) return false; + + return true; + } + + @Override + public int hashCode() { + return wrappedNode.hashCode(); + } + + @Deprecated + public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes, + TypeSolver typeSolver, Context invokationContext, List<ResolvedType> typeParameterValues) { + if (name.equals("values") && parameterTypes.isEmpty()) { + return Optional.of(new ValuesMethod(this, typeSolver).getUsage(null)); + } + // TODO add methods inherited from Enum + return getContext().solveMethodAsUsage(name, parameterTypes, typeSolver); + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables(); + + if (this.wrappedNode.getEntries() != null) { + for (EnumConstantDeclaration member : this.wrappedNode.getEntries()) { + fields.add(new JavaParserFieldDeclaration(member, typeSolver)); + } + } + + return fields; + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + List<ResolvedReferenceType> ancestors = new ArrayList<>(); + ResolvedReferenceType enumClass = ReflectionFactory.typeUsageFor(Enum.class, typeSolver).asReferenceType(); + ResolvedTypeParameterDeclaration eTypeParameter = enumClass.getTypeDeclaration().getTypeParameters().get(0); + enumClass = enumClass.deriveTypeParameters(new ResolvedTypeParametersMap.Builder().setValue(eTypeParameter, new ReferenceTypeImpl(this, typeSolver)).build()); + ancestors.add(enumClass); + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType implementedType : wrappedNode.getImplementedTypes()) { + SymbolReference<ResolvedTypeDeclaration> implementedDeclRef = new SymbolSolver(typeSolver).solveTypeInType(this, implementedType.getName().getId()); + if (!implementedDeclRef.isSolved()) { + throw new UnsolvedSymbolException(implementedType.getName().getId()); + } + ancestors.add(new ReferenceTypeImpl((ResolvedReferenceTypeDeclaration) implementedDeclRef.getCorrespondingDeclaration(), typeSolver)); + } + } + return ancestors; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Collections.emptyList(); + } + + /** + * Returns the JavaParser node associated with this JavaParserEnumDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.EnumDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public List<ResolvedEnumConstantDeclaration> getEnumConstants() { + return wrappedNode.getEntries().stream() + .map(entry -> new JavaParserEnumConstantDeclaration(entry, typeSolver)) + .collect(Collectors.toList()); + } + + // Needed by ContextHelper + public static class ValuesMethod implements ResolvedMethodDeclaration { + + private JavaParserEnumDeclaration enumDeclaration; + private TypeSolver typeSolver; + + public ValuesMethod(JavaParserEnumDeclaration enumDeclaration, TypeSolver typeSolver) { + this.enumDeclaration = enumDeclaration; + this.typeSolver = typeSolver; + } + + @Override + public ResolvedReferenceTypeDeclaration declaringType() { + return enumDeclaration; + } + + @Override + public ResolvedType getReturnType() { + return new ResolvedArrayType(new ReferenceTypeImpl(enumDeclaration, typeSolver)); + } + + @Override + public int getNumberOfParams() { + return 0; + } + + @Override + public ResolvedParameterDeclaration getParam(int i) { + throw new UnsupportedOperationException(); + } + + public MethodUsage getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes) { + return new MethodUsage(this); + } + + @Override + public boolean isAbstract() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isDefaultMethod() { + return false; + } + + @Override + public boolean isStatic() { + return false; + } + + @Override + public String getName() { + return "values"; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Collections.emptyList(); + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(enumDeclaration.getWrappedNode().getModifiers()); + } + + @Override + public int getNumberOfSpecifiedExceptions() { + return 0; + } + + @Override + public ResolvedType getSpecifiedException(int index) { + throw new UnsupportedOperationException("The values method of an enum does not throw any exception"); + } + } + + @Override + public AccessSpecifier accessSpecifier() { + throw new UnsupportedOperationException(); + } + + @Override + public Set<ResolvedReferenceTypeDeclaration> internalTypes() { + Set<ResolvedReferenceTypeDeclaration> res = new HashSet<>(); + for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) { + res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member)); + } + } + return res; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + return javaParserTypeAdapter.containerType(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java new file mode 100644 index 000000000..1c9e00511 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java @@ -0,0 +1,121 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Modifier; +import com.github.javaparser.ast.body.EnumConstantDeclaration; +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparser.Navigator; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; + +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserFieldDeclaration implements ResolvedFieldDeclaration { + + private VariableDeclarator variableDeclarator; + private com.github.javaparser.ast.body.FieldDeclaration wrappedNode; + private EnumConstantDeclaration enumConstantDeclaration; + private TypeSolver typeSolver; + + public JavaParserFieldDeclaration(VariableDeclarator variableDeclarator, TypeSolver typeSolver) { + if (typeSolver == null) { + throw new IllegalArgumentException("typeSolver should not be null"); + } + this.variableDeclarator = variableDeclarator; + this.typeSolver = typeSolver; + if (!(requireParentNode(variableDeclarator) instanceof com.github.javaparser.ast.body.FieldDeclaration)) { + throw new IllegalStateException(requireParentNode(variableDeclarator).getClass().getCanonicalName()); + } + this.wrappedNode = (com.github.javaparser.ast.body.FieldDeclaration) requireParentNode(variableDeclarator); + } + + public JavaParserFieldDeclaration(EnumConstantDeclaration enumConstantDeclaration, TypeSolver typeSolver) { + if (typeSolver == null) { + throw new IllegalArgumentException("typeSolver should not be null"); + } + this.enumConstantDeclaration = enumConstantDeclaration; + this.typeSolver = typeSolver; + } + + @Override + public ResolvedType getType() { + if (enumConstantDeclaration != null) { + com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = (com.github.javaparser.ast.body.EnumDeclaration) requireParentNode(enumConstantDeclaration); + return new ReferenceTypeImpl(new JavaParserEnumDeclaration(enumDeclaration, typeSolver), typeSolver); + } + return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode); + } + + @Override + public String getName() { + if (enumConstantDeclaration != null) { + return enumConstantDeclaration.getName().getId(); + } else { + return variableDeclarator.getName().getId(); + } + } + + @Override + public boolean isStatic() { + return wrappedNode.getModifiers().contains(Modifier.STATIC); + } + + @Override + public boolean isField() { + return true; + } + + /** + * Returns the JavaParser node associated with this JavaParserFieldDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.FieldDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public String toString() { + return "JPField{" + getName() + "}"; + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(wrappedNode.getModifiers()); + } + + @Override + public ResolvedTypeDeclaration declaringType() { + Optional<com.github.javaparser.ast.body.TypeDeclaration> typeDeclaration = wrappedNode.findParent(com.github.javaparser.ast.body.TypeDeclaration.class); + if (typeDeclaration.isPresent()) { + return JavaParserFacade.get(typeSolver).getTypeDeclaration(typeDeclaration.get()); + } + throw new IllegalStateException(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java new file mode 100644 index 000000000..34955a0c0 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java @@ -0,0 +1,335 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.BodyDeclaration; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.type.ClassOrInterfaceType; +import com.github.javaparser.resolution.UnsolvedSymbolException; +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.logic.AbstractTypeDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.LazyType; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements ResolvedInterfaceDeclaration { + + private TypeSolver typeSolver; + private ClassOrInterfaceDeclaration wrappedNode; + private JavaParserTypeAdapter<ClassOrInterfaceDeclaration> javaParserTypeAdapter; + + public JavaParserInterfaceDeclaration(ClassOrInterfaceDeclaration wrappedNode, TypeSolver typeSolver) { + if (!wrappedNode.isInterface()) { + throw new IllegalArgumentException(); + } + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + this.javaParserTypeAdapter = new JavaParserTypeAdapter<>(wrappedNode, typeSolver); + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + Set<ResolvedMethodDeclaration> methods = new HashSet<>(); + for (BodyDeclaration<?> member : wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) { + methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)); + } + } + return methods; + } + + public Context getContext() { + return JavaParserFactory.getContext(wrappedNode, typeSolver); + } + + public ResolvedType getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JavaParserInterfaceDeclaration that = (JavaParserInterfaceDeclaration) o; + + if (!wrappedNode.equals(that.wrappedNode)) return false; + + return true; + } + + @Override + public int hashCode() { + return wrappedNode.hashCode(); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public ResolvedInterfaceDeclaration asInterface() { + return this; + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) { + if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) { + return true; + } + } + return false; + } + + @Override + public boolean isInterface() { + return true; + } + + @Override + public List<ResolvedReferenceType> getInterfacesExtended() { + List<ResolvedReferenceType> interfaces = new ArrayList<>(); + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) { + interfaces.add(new ReferenceTypeImpl(solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface(), typeSolver)); + } + } + return interfaces; + } + + @Override + public String getPackageName() { + return javaParserTypeAdapter.getPackageName(); + } + + @Override + public String getClassName() { + return javaParserTypeAdapter.getClassName(); + } + + @Override + public String getQualifiedName() { + return javaParserTypeAdapter.getQualifiedName(); + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return javaParserTypeAdapter.isAssignableBy(other); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + return javaParserTypeAdapter.isAssignableBy(type); + } + + @Override + public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + // TODO consider generic types + if (this.getQualifiedName().equals(other.getQualifiedName())) { + return true; + } + if (this.wrappedNode.getExtendedTypes() != null) { + for (ClassOrInterfaceType type : wrappedNode.getExtendedTypes()) { + ResolvedReferenceTypeDeclaration ancestor = (ResolvedReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type); + if (ancestor.canBeAssignedTo(other)) { + return true; + } + } + } + + if (this.wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType type : wrappedNode.getImplementedTypes()) { + ResolvedReferenceTypeDeclaration ancestor = (ResolvedReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type); + if (ancestor.canBeAssignedTo(other)) { + return true; + } + } + } + + return false; + } + + @Override + public boolean isTypeParameter() { + return false; + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables(); + + getAncestors().forEach(ancestor -> ancestor.getTypeDeclaration().getAllFields().forEach(f -> { + fields.add(new ResolvedFieldDeclaration() { + + @Override + public AccessSpecifier accessSpecifier() { + return f.accessSpecifier(); + } + + @Override + public String getName() { + return f.getName(); + } + + @Override + public ResolvedType getType() { + return ancestor.useThisTypeParametersOnTheGivenType(f.getType()); + } + + @Override + public boolean isStatic() { + return f.isStatic(); + } + + @Override + public ResolvedTypeDeclaration declaringType() { + return f.declaringType(); + } + }); + })); + + return fields; + } + + + @Override + public String toString() { + return "JavaParserInterfaceDeclaration{" + + "wrappedNode=" + wrappedNode + + '}'; + } + + @Deprecated + public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getName().getId().equals(name)) { + return SymbolReference.solved(this); + } + SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver); + if (ref.isSolved()) { + return ref; + } + + String prefix = wrappedNode.getName() + "."; + if (name.startsWith(prefix) && name.length() > prefix.length()) { + return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver); + } + + return getContext().getParent().solveType(name, typeSolver); + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + List<ResolvedReferenceType> ancestors = new ArrayList<>(); + if (wrappedNode.getExtendedTypes() != null) { + for (ClassOrInterfaceType extended : wrappedNode.getExtendedTypes()) { + ancestors.add(toReferenceType(extended)); + } + } + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) { + ancestors.add(toReferenceType(implemented)); + } + } + return ancestors; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + if (this.wrappedNode.getTypeParameters() == null) { + return Collections.emptyList(); + } else { + return this.wrappedNode.getTypeParameters().stream().map( + (tp) -> new JavaParserTypeParameter(tp, typeSolver) + ).collect(Collectors.toList()); + } + } + + /** + * Returns the JavaParser node associated with this JavaParserInterfaceDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public ClassOrInterfaceDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(wrappedNode.getModifiers()); + } + + @Override + public Set<ResolvedReferenceTypeDeclaration> internalTypes() { + Set<ResolvedReferenceTypeDeclaration> res = new HashSet<>(); + for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) { + res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member)); + } + } + return res; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + return javaParserTypeAdapter.containerType(); + } + + /// + /// Private methods + /// + + private ResolvedReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) { + SymbolReference<? extends ResolvedTypeDeclaration> ref = null; + if (classOrInterfaceType.toString().indexOf('.') > -1) { + ref = typeSolver.tryToSolveType(classOrInterfaceType.toString()); + } + if (ref == null || !ref.isSolved()) { + ref = solveType(classOrInterfaceType.toString(), typeSolver); + } + if (!ref.isSolved()) { + ref = solveType(classOrInterfaceType.getName().getId(), typeSolver); + } + if (!ref.isSolved()) { + throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId()); + } + if (!classOrInterfaceType.getTypeArguments().isPresent()) { + return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver); + } + List<ResolvedType> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get() + .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) + .collect(Collectors.toList()); + return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java new file mode 100644 index 000000000..4f3cb3569 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java @@ -0,0 +1,167 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.expr.ObjectCreationExpr; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.List; +import java.util.stream.Collectors; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserMethodDeclaration implements ResolvedMethodDeclaration { + + private com.github.javaparser.ast.body.MethodDeclaration wrappedNode; + private TypeSolver typeSolver; + + public JavaParserMethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public String toString() { + return "JavaParserMethodDeclaration{" + + "wrappedNode=" + wrappedNode + + ", typeSolver=" + typeSolver + + '}'; + } + + @Override + public ResolvedReferenceTypeDeclaration declaringType() { + if (requireParentNode(wrappedNode) instanceof ObjectCreationExpr) { + ObjectCreationExpr parentNode = (ObjectCreationExpr) requireParentNode(wrappedNode); + return new JavaParserAnonymousClassDeclaration(parentNode, typeSolver); + } + return JavaParserFactory.toTypeDeclaration(requireParentNode(wrappedNode), typeSolver); + } + + @Override + public ResolvedType getReturnType() { + return JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), getContext()); + } + + @Override + public int getNumberOfParams() { + return wrappedNode.getParameters().size(); + } + + @Override + public ResolvedParameterDeclaration getParam(int i) { + if (i < 0 || i >= getNumberOfParams()) { + throw new IllegalArgumentException(String.format("No param with index %d. Number of params: %d", i, getNumberOfParams())); + } + return new JavaParserParameterDeclaration(wrappedNode.getParameters().get(i), typeSolver); + } + + public MethodUsage getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes) { + return new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes); + } + + private Context getContext() { + return JavaParserFactory.getContext(wrappedNode, typeSolver); + } + + @Override + public boolean isAbstract() { + return !wrappedNode.getBody().isPresent(); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public boolean isField() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isParameter() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isType() { + throw new UnsupportedOperationException(); + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()); + } + + @Override + public boolean isDefaultMethod() { + return wrappedNode.isDefault(); + } + + @Override + public boolean isStatic() { + return wrappedNode.isStatic(); + } + + /** + * Returns the JavaParser node associated with this JavaParserMethodDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.body.MethodDeclaration getWrappedNode() { + return wrappedNode; + } + + @Override + public AccessSpecifier accessSpecifier() { + return Helper.toAccessLevel(wrappedNode.getModifiers()); + } + + @Override + public int getNumberOfSpecifiedExceptions() { + return wrappedNode.getThrownExceptions().size(); + } + + @Override + public ResolvedType getSpecifiedException(int index) { + if (index < 0 || index >= getNumberOfSpecifiedExceptions()) { + throw new IllegalArgumentException(String.format("No exception with index %d. Number of exceptions: %d", + index, getNumberOfSpecifiedExceptions())); + } + return JavaParserFacade.get(typeSolver).convert(wrappedNode.getThrownExceptions() + .get(index), wrappedNode); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java new file mode 100644 index 000000000..cba7d32b1 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java @@ -0,0 +1,100 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.body.Parameter; +import com.github.javaparser.ast.type.UnknownType; +import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedArrayType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.javaparsermodel.contexts.LambdaExprContext; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; + +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public class JavaParserParameterDeclaration implements ResolvedParameterDeclaration { + + private Parameter wrappedNode; + private TypeSolver typeSolver; + + public JavaParserParameterDeclaration(Parameter wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public boolean isField() { + return false; + } + + @Override + public boolean isParameter() { + return true; + } + + @Override + public boolean isVariadic() { + return wrappedNode.isVarArgs(); + } + + @Override + public boolean isType() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedType getType() { + if (wrappedNode.getType() instanceof UnknownType && JavaParserFactory.getContext(wrappedNode, typeSolver) instanceof LambdaExprContext) { + Optional<Value> value = JavaParserFactory.getContext(wrappedNode, typeSolver).solveSymbolAsValue(wrappedNode.getNameAsString(), typeSolver); + if (value.isPresent()) { + return value.get().getType(); + } + } + ResolvedType res = JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), wrappedNode); + if (isVariadic()) { + res = new ResolvedArrayType(res); + } + return res; + } + + @Override + public ResolvedParameterDeclaration asParameter() { + return this; + } + + /** + * Returns the JavaParser node associated with this JavaParserParameterDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public Parameter getWrappedNode() { + return wrappedNode; + } + + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java new file mode 100644 index 000000000..f1f1ffb69 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java @@ -0,0 +1,171 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.body.Parameter; +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.ast.expr.LambdaExpr; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.VariableDeclarationExpr; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedArrayType; +import com.github.javaparser.resolution.types.ResolvedPrimitiveType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration { + + private String name; + private Node wrappedNode; + private boolean field; + private boolean parameter; + private boolean variable; + private TypeSolver typeSolver; + + private JavaParserSymbolDeclaration(Node wrappedNode, String name, TypeSolver typeSolver, boolean field, boolean parameter, boolean variable) { + this.name = name; + this.wrappedNode = wrappedNode; + this.field = field; + this.variable = variable; + this.parameter = parameter; + this.typeSolver = typeSolver; + } + + public static JavaParserFieldDeclaration field(VariableDeclarator wrappedNode, TypeSolver typeSolver) { + return new JavaParserFieldDeclaration(wrappedNode, typeSolver); + } + + public static JavaParserParameterDeclaration parameter(Parameter parameter, TypeSolver typeSolver) { + return new JavaParserParameterDeclaration(parameter, typeSolver); + } + + public static JavaParserSymbolDeclaration localVar(VariableDeclarator variableDeclarator, TypeSolver typeSolver) { + return new JavaParserSymbolDeclaration(variableDeclarator, variableDeclarator.getName().getId(), typeSolver, false, false, true); + } + + public static int getParamPos(Parameter parameter) { + int pos = 0; + for (Node node : requireParentNode(parameter).getChildNodes()) { + if (node == parameter) { + return pos; + } else if (node instanceof Parameter) { + pos++; + } + } + return pos; + } + + public static int getParamPos(Node node) { + if (requireParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr call = (MethodCallExpr) requireParentNode(node); + for (int i = 0; i < call.getArguments().size(); i++) { + if (call.getArguments().get(i) == node) return i; + } + throw new IllegalStateException(); + } + throw new IllegalArgumentException(); + } + + @Override + public String toString() { + return "JavaParserSymbolDeclaration{" + + "name='" + name + '\'' + + ", wrappedNode=" + wrappedNode + + '}'; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isField() { + return field; + } + + @Override + public boolean isParameter() { + return parameter; + } + + @Override + public boolean isType() { + return false; + } + + @Override + public ResolvedType getType() { + if (wrappedNode instanceof Parameter) { + Parameter parameter = (Parameter) wrappedNode; + if (requireParentNode(wrappedNode) instanceof LambdaExpr) { + int pos = getParamPos(parameter); + ResolvedType lambdaType = JavaParserFacade.get(typeSolver).getType(requireParentNode(wrappedNode)); + + // TODO understand from the context to which method this corresponds + //MethodDeclaration methodDeclaration = JavaParserFacade.get(typeSolver).getMethodCalled + //MethodDeclaration methodCalled = JavaParserFacade.get(typeSolver).solve() + throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName()); + } else { + final ResolvedType rawType; + if (parameter.getType() instanceof com.github.javaparser.ast.type.PrimitiveType) { + rawType = ResolvedPrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) parameter.getType()).getType().name()); + } else { + rawType = JavaParserFacade.get(typeSolver).convertToUsage(parameter.getType(), wrappedNode); + } + if (parameter.isVarArgs()) { + return new ResolvedArrayType(rawType); + } + return rawType; + } + } else if (wrappedNode instanceof VariableDeclarator) { + VariableDeclarator variableDeclarator = (VariableDeclarator) wrappedNode; + if (requireParentNode(wrappedNode) instanceof VariableDeclarationExpr) { + return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver)); + } else if (requireParentNode(wrappedNode) instanceof FieldDeclaration) { + return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver)); + } + } + throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName()); + } + + @Override + public ResolvedTypeDeclaration asType() { + throw new UnsupportedOperationException(this.getClass().getCanonicalName() + ": wrapping " + this.getWrappedNode().getClass().getCanonicalName()); + } + + /** + * Returns the JavaParser node associated with this JavaParserSymbolDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public Node getWrappedNode() { + return wrappedNode; + } + + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java new file mode 100644 index 000000000..198083f7a --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java @@ -0,0 +1,140 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.BodyDeclaration; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.EnumDeclaration; +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.ast.nodeTypes.NodeWithMembers; +import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName; +import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserTypeAdapter<T extends Node & NodeWithSimpleName<T> & NodeWithMembers<T>> { + + private T wrappedNode; + private TypeSolver typeSolver; + + public JavaParserTypeAdapter(T wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + public String getPackageName() { + return Helper.getPackageName(wrappedNode); + } + + public String getClassName() { + return Helper.getClassName("", wrappedNode); + } + + public String getQualifiedName() { + String containerName = Helper.containerName(getParentNode(wrappedNode)); + if (containerName.isEmpty()) { + return wrappedNode.getName().getId(); + } else { + return containerName + "." + wrappedNode.getName().getId(); + } + } + + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + List<ResolvedReferenceType> ancestorsOfOther = other.getAllAncestors(); + ancestorsOfOther.add(new ReferenceTypeImpl(other, typeSolver)); + for (ResolvedReferenceType ancestorOfOther : ancestorsOfOther) { + if (ancestorOfOther.getQualifiedName().equals(this.getQualifiedName())) { + return true; + } + } + return false; + } + + public boolean isAssignableBy(ResolvedType type) { + if (type.isNull()) { + return true; + } + if (type.isReferenceType()) { + ResolvedReferenceTypeDeclaration other = typeSolver.solveType(type.describe()); + return isAssignableBy(other); + } else { + throw new UnsupportedOperationException(); + } + } + + public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) { + if(wrappedNode instanceof NodeWithTypeParameters<?>) { + NodeList<TypeParameter> typeParameters = ((NodeWithTypeParameters<?>) wrappedNode).getTypeParameters(); + for (com.github.javaparser.ast.type.TypeParameter typeParameter : typeParameters) { + if (typeParameter.getName().getId().equals(name)) { + return SymbolReference.solved(new JavaParserTypeVariableDeclaration(typeParameter, typeSolver)); + } + } + } + + // 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; + String prefix = internalType.getName() + "."; + if (internalType.getName().getId().equals(name)) { + if (internalType instanceof ClassOrInterfaceDeclaration) { + return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver)); + } else if (internalType instanceof EnumDeclaration) { + return SymbolReference.solved(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver)); + } else { + throw new UnsupportedOperationException(); + } + } else if (name.startsWith(prefix) && name.length() > prefix.length()) { + if (internalType instanceof ClassOrInterfaceDeclaration) { + return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length()), typeSolver); + } else if (internalType instanceof EnumDeclaration) { + return new SymbolSolver(typeSolver).solveTypeInType(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver), name.substring(prefix.length())); + } else { + throw new UnsupportedOperationException(); + } + } + } + } + return SymbolReference.unsolved(ResolvedTypeDeclaration.class); + } + + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + return wrappedNode + .getParentNode() + .map(node -> JavaParserFactory.toTypeDeclaration(node, typeSolver)); + } + + public List<ResolvedFieldDeclaration> getFieldsForDeclaredVariables() { + List<ResolvedFieldDeclaration> fields = new ArrayList<>(); + if (wrappedNode.getMembers() != null) { + for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.FieldDeclaration) { + com.github.javaparser.ast.body.FieldDeclaration field = (com.github.javaparser.ast.body.FieldDeclaration) member; + for (VariableDeclarator vd : field.getVariables()) { + fields.add(new JavaParserFieldDeclaration(vd, typeSolver)); + } + } + } + } + return fields; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java new file mode 100644 index 000000000..0d1f42e68 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java @@ -0,0 +1,223 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.type.ClassOrInterfaceType; +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.logic.AbstractTypeDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserTypeParameter extends AbstractTypeDeclaration implements ResolvedTypeParameterDeclaration { + + private com.github.javaparser.ast.type.TypeParameter wrappedNode; + private TypeSolver typeSolver; + + public JavaParserTypeParameter(com.github.javaparser.ast.type.TypeParameter wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + return Collections.emptySet(); + } + + public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes) { + return getContext().solveMethod(name, parameterTypes, false, typeSolver); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof JavaParserTypeParameter)) return false; + + JavaParserTypeParameter that = (JavaParserTypeParameter) o; + + if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = wrappedNode != null ? wrappedNode.hashCode() : 0; + result = 31 * result + (typeSolver != null ? typeSolver.hashCode() : 0); + return result; + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return isAssignableBy(new ReferenceTypeImpl(other, typeSolver)); + } + + @Override + public String getContainerQualifiedName() { + ResolvedTypeParametrizable container = getContainer(); + if (container instanceof ResolvedReferenceTypeDeclaration) { + return ((ResolvedReferenceTypeDeclaration) container).getQualifiedName(); + } else if (container instanceof JavaParserConstructorDeclaration) { + return ((JavaParserConstructorDeclaration) container).getQualifiedSignature(); + } else { + return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); + } + } + + @Override + public String getContainerId() { + ResolvedTypeParametrizable container = getContainer(); + if (container instanceof ResolvedReferenceTypeDeclaration) { + return ((ResolvedReferenceTypeDeclaration) container).getId(); + } else if (container instanceof JavaParserConstructorDeclaration) { + return ((JavaParserConstructorDeclaration) container).getQualifiedSignature(); + } else { + return ((JavaParserMethodDeclaration) container).getQualifiedSignature(); + } + } + + @Override + public ResolvedTypeParametrizable getContainer() { + Node parentNode = requireParentNode(wrappedNode); + if (parentNode instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) { + com.github.javaparser.ast.body.ClassOrInterfaceDeclaration jpTypeDeclaration = (com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) parentNode; + return JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration); + } else if (parentNode instanceof com.github.javaparser.ast.body.ConstructorDeclaration){ + com.github.javaparser.ast.body.ConstructorDeclaration jpConstructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) parentNode; + Optional<ClassOrInterfaceDeclaration> jpTypeDeclaration = jpConstructorDeclaration.getAncestorOfType(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class); + if (jpTypeDeclaration.isPresent()) { + ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration.get()); + if (typeDeclaration.isClass()) { + return new JavaParserConstructorDeclaration(typeDeclaration.asClass(), jpConstructorDeclaration, typeSolver); + } + } + } else { + com.github.javaparser.ast.body.MethodDeclaration jpMethodDeclaration = (com.github.javaparser.ast.body.MethodDeclaration) parentNode; + return new JavaParserMethodDeclaration(jpMethodDeclaration, typeSolver); + } + throw new UnsupportedOperationException(); + } + + @Override + public String getQualifiedName() { + return String.format("%s.%s", getContainerQualifiedName(), getName()); + } + + @Override + public List<Bound> getBounds() { + return wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)).collect(Collectors.toList()); + } + + private Bound toBound(ClassOrInterfaceType classOrInterfaceType, TypeSolver typeSolver) { + ResolvedType type = JavaParserFacade.get(typeSolver).convertToUsage(classOrInterfaceType, classOrInterfaceType); + return Bound.extendsBound(type); + } + + public Context getContext() { + throw new UnsupportedOperationException(); + } + + public ResolvedType getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedFieldDeclaration getField(String name) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasField(String name) { + return false; + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + return new ArrayList<>(); + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isTypeParameter() { + return true; + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + throw new UnsupportedOperationException(); + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Collections.emptyList(); + } + + /** + * Returns the JavaParser node associated with this JavaParserTypeParameter. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public com.github.javaparser.ast.type.TypeParameter getWrappedNode() { + return wrappedNode; + } + + @Override + public String toString() { + return "JPTypeParameter(" + wrappedNode.getName() + ", bounds=" + wrappedNode.getTypeBound() + ")"; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + ResolvedTypeParametrizable container = getContainer(); + if (container instanceof ResolvedReferenceTypeDeclaration) { + return Optional.of((ResolvedReferenceTypeDeclaration) container); + } + return Optional.empty(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java new file mode 100644 index 000000000..a602ebf19 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java @@ -0,0 +1,187 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +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.logic.AbstractTypeDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * @author Federico Tomassetti + */ +public class JavaParserTypeVariableDeclaration extends AbstractTypeDeclaration { + + private TypeParameter wrappedNode; + private TypeSolver typeSolver; + + public JavaParserTypeVariableDeclaration(TypeParameter wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + @Override + public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) { + return isAssignableBy(new ReferenceTypeImpl(other, typeSolver)); + } + + @Override + public String getPackageName() { + return Helper.getPackageName(wrappedNode); + } + + @Override + public String getClassName() { + return Helper.getClassName("", wrappedNode); + } + + @Override + public String getQualifiedName() { + return getName(); + } + + public Context getContext() { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return "JavaParserTypeVariableDeclaration{" + + wrappedNode.getName() + + '}'; + } + + public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes) { + throw new UnsupportedOperationException(); + } + + public ResolvedType getUsage(Node node) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAssignableBy(ResolvedType type) { + if (type.isTypeVariable()) { + throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type.describe()); + } else { + throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type); + } + } + + @Override + public boolean isTypeParameter() { + return true; + } + + @Override + public ResolvedFieldDeclaration getField(String name) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasField(String name) { + return false; + } + + @Override + public List<ResolvedFieldDeclaration> getAllFields() { + return new ArrayList<>(); + } + + @Override + public List<ResolvedReferenceType> getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + return Collections.emptySet(); + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public boolean isField() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isParameter() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isType() { + return true; + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isClass() { + return false; + } + + @Override + public boolean isInterface() { + return false; + } + + @Override + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + return Collections.emptyList(); + } + + public ResolvedTypeParameterDeclaration asTypeParameter() { + return new JavaParserTypeParameter(this.wrappedNode, typeSolver); + } + + /** + * Returns the JavaParser node associated with this JavaParserTypeVariableDeclaration. + * + * @return A visitable JavaParser node wrapped by this object. + */ + public TypeParameter getWrappedNode() { + return wrappedNode; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + return asTypeParameter().containerType(); + } +} |