aboutsummaryrefslogtreecommitdiffstats
path: root/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
diff options
context:
space:
mode:
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java')
-rw-r--r--javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java291
1 files changed, 291 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
new file mode 100644
index 000000000..e6a4aa0d5
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
@@ -0,0 +1,291 @@
+/*
+ * 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.contexts;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class CompilationUnitContext extends AbstractJavaParserContext<CompilationUnit> {
+
+ ///
+ /// Static methods
+ ///
+
+ private static boolean isQualifiedName(String name) {
+ return name.contains(".");
+ }
+
+ ///
+ /// Constructors
+ ///
+
+ public CompilationUnitContext(CompilationUnit wrappedNode, TypeSolver typeSolver) {
+ super(wrappedNode, typeSolver);
+ }
+
+ ///
+ /// Public methods
+ ///
+
+ @Override
+ public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+
+ // solve absolute references
+ String itName = name;
+ while (itName.contains(".")) {
+ String typeName = getType(itName);
+ String memberName = getMember(itName);
+ SymbolReference<ResolvedTypeDeclaration> type = this.solveType(typeName, typeSolver);
+ if (type.isSolved()) {
+ return new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName);
+ } else {
+ itName = typeName;
+ }
+ }
+
+ // Look among statically imported values
+ if (wrappedNode.getImports() != null) {
+ for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+ if(importDecl.isStatic()){
+ if(importDecl.isAsterisk()) {
+ String qName = importDecl.getNameAsString();
+ ResolvedTypeDeclaration importedType = typeSolver.solveType(qName);
+ SymbolReference<? extends ResolvedValueDeclaration> ref = new SymbolSolver(typeSolver).solveSymbolInType(importedType, name);
+ if (ref.isSolved()) {
+ return ref;
+ }
+ } else{
+ String whole = importDecl.getNameAsString();
+
+ // split in field/method name and type name
+ String memberName = getMember(whole);
+ String typeName = getType(whole);
+
+ if (memberName.equals(name)) {
+ ResolvedTypeDeclaration importedType = typeSolver.solveType(typeName);
+ return new SymbolSolver(typeSolver).solveSymbolInType(importedType, memberName);
+ }
+ }
+ }
+ }
+ }
+
+ return SymbolReference.unsolved(ResolvedValueDeclaration.class);
+ }
+
+ @Override
+ public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+ if (wrappedNode.getTypes() != null) {
+ for (TypeDeclaration<?> type : wrappedNode.getTypes()) {
+ if (type.getName().getId().equals(name)) {
+ if (type instanceof ClassOrInterfaceDeclaration) {
+ return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type));
+ } else if (type instanceof AnnotationDeclaration) {
+ return SymbolReference.solved(new JavaParserAnnotationDeclaration((AnnotationDeclaration) type, typeSolver));
+ } else if (type instanceof EnumDeclaration) {
+ return SymbolReference.solved(new JavaParserEnumDeclaration((EnumDeclaration) type, typeSolver));
+ } else {
+ throw new UnsupportedOperationException(type.getClass().getCanonicalName());
+ }
+ }
+ }
+ }
+
+ if (wrappedNode.getImports() != null) {
+ int dotPos = name.indexOf('.');
+ String prefix = null;
+ if (dotPos > -1) {
+ prefix = name.substring(0, dotPos);
+ }
+ // look into type imports
+ for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+ if (!importDecl.isAsterisk()) {
+ String qName = importDecl.getNameAsString();
+ boolean defaultPackage = !importDecl.getName().getQualifier().isPresent();
+ boolean found = !defaultPackage && importDecl.getName().getIdentifier().equals(name);
+ if (!found) {
+ if (prefix != null) {
+ found = qName.endsWith("." + prefix);
+ if (found) {
+ qName = qName + name.substring(dotPos);
+ }
+ }
+ }
+ if (found) {
+ SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+ if (ref.isSolved()) {
+ return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+ }
+ }
+ }
+ }
+ // look into type imports on demand
+ for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+ if (importDecl.isAsterisk()) {
+ String qName = importDecl.getNameAsString() + "." + name;
+ SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+ if (ref.isSolved()) {
+ return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+ }
+ }
+ }
+ }
+
+ // Look in current package
+ if (this.wrappedNode.getPackageDeclaration().isPresent()) {
+ String qName = this.wrappedNode.getPackageDeclaration().get().getName().toString() + "." + name;
+ SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+ if (ref.isSolved()) {
+ return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+ }
+ } else {
+ // look for classes in the default package
+ String qName = name;
+ SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+ if (ref.isSolved()) {
+ return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+ }
+ }
+
+ // Look in the java.lang package
+ SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType("java.lang." + name);
+ if (ref.isSolved()) {
+ return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+ }
+
+ // DO NOT look for absolute name if this name is not qualified: you cannot import classes from the default package
+ if (isQualifiedName(name)) {
+ return SymbolReference.adapt(typeSolver.tryToSolveType(name), ResolvedTypeDeclaration.class);
+ } else {
+ return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+ }
+ }
+
+ private String qName(ClassOrInterfaceType type) {
+ if (type.getScope().isPresent()) {
+ return qName(type.getScope().get()) + "." + type.getName().getId();
+ } else {
+ return type.getName().getId();
+ }
+ }
+
+ private String qName(Name name) {
+ if (name.getQualifier().isPresent()) {
+ return qName(name.getQualifier().get()) + "." + name.getId();
+ } else {
+ return name.getId();
+ }
+ }
+
+ private String toSimpleName(String qName) {
+ String[] parts = qName.split("\\.");
+ return parts[parts.length - 1];
+ }
+
+ private String packageName(String qName) {
+ int lastDot = qName.lastIndexOf('.');
+ if (lastDot == -1) {
+ throw new UnsupportedOperationException();
+ } else {
+ return qName.substring(0, lastDot);
+ }
+ }
+
+ @Override
+ public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+ for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+ if(importDecl.isStatic()){
+ if(importDecl.isAsterisk()){
+ String importString = importDecl.getNameAsString();
+
+ if (this.wrappedNode.getPackageDeclaration().isPresent()
+ && this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier().equals(packageName(importString))
+ && this.wrappedNode.getTypes().stream().anyMatch(it -> it.getName().getIdentifier().equals(toSimpleName(importString)))) {
+ // We are using a static import on a type defined in this file. It means the value was not found at
+ // a lower level so this will fail
+ return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
+ }
+
+ ResolvedTypeDeclaration ref = typeSolver.solveType(importString);
+ SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+
+ if (method.isSolved()) {
+ return method;
+ }
+ } else{
+ String qName = importDecl.getNameAsString();
+
+ if (qName.equals(name) || qName.endsWith("." + name)) {
+ String typeName = getType(qName);
+ ResolvedTypeDeclaration ref = typeSolver.solveType(typeName);
+ SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+ if (method.isSolved()) {
+ return method;
+ }
+ }
+ }
+ }
+ }
+ return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
+ }
+
+ ///
+ /// Private methods
+ ///
+
+ private String getType(String qName) {
+ int index = qName.lastIndexOf('.');
+ if (index == -1) {
+ throw new UnsupportedOperationException();
+ }
+ String typeName = qName.substring(0, index);
+ return typeName;
+ }
+
+ private String getMember(String qName) {
+ int index = qName.lastIndexOf('.');
+ if (index == -1) {
+ throw new UnsupportedOperationException();
+ }
+ String memberName = qName.substring(index + 1);
+ return memberName;
+ }
+}