@Override public String getContainerQualifiedName() { if (container instanceof ResolvedReferenceTypeDeclaration) { return ((ResolvedReferenceTypeDeclaration) container).getQualifiedName(); } else { return ((ResolvedMethodLikeDeclaration) container).getQualifiedSignature(); } }
public ResolvedFieldDeclaration getField(String name) { for (Field field : clazz.getDeclaredFields()) { if (field.getName().equals(name)) { return new ReflectionFieldDeclaration(field, typeSolver); } } for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { if (ancestor.getTypeDeclaration().hasField(name)) { ReflectionFieldDeclaration reflectionFieldDeclaration = (ReflectionFieldDeclaration) ancestor.getTypeDeclaration().getField(name); return reflectionFieldDeclaration.replaceType(ancestor.getFieldType(name).get()); } } throw new UnsolvedSymbolException(name, "Field in " + this); }
public List<ResolvedFieldDeclaration> getAllFields() { ArrayList<ResolvedFieldDeclaration> fields = new ArrayList<>(); for (Field field : clazz.getDeclaredFields()) { fields.add(new ReflectionFieldDeclaration(field, typeSolver)); } for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { fields.addAll(ancestor.getTypeDeclaration().getAllFields()); } return fields; }
public boolean hasField(String name) { for (Field field : clazz.getDeclaredFields()) { if (field.getName().equals(name)) { return true; } } for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { if (ancestor.getTypeDeclaration().hasField(name)) { return true; } } return false; }
@Override public List<ResolvedReferenceType> getInterfaces() { return superTypeDeclaration .asReferenceType().getAncestors() .stream() .filter(type -> type.getTypeDeclaration().isInterface()) .collect(Collectors.toList()); }
public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { List<ResolvedMethodDeclaration> candidateMethods = typeDeclaration.getDeclaredMethods().stream() .filter(m -> m.getName().equals(name)) .filter(m -> !staticOnly || (staticOnly && m.isStatic())) .collect(Collectors.toList()); if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) { for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors()) { if (candidateMethods.isEmpty() && typeDeclaration.isInterface()) { SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver); if (res.isSolved()) {
/** * Java Parser can't differentiate between packages, internal types, and fields. * All three are lumped together into FieldAccessExpr. We need to differentiate them. */ private ResolvedType solveDotExpressionType(ResolvedReferenceTypeDeclaration parentType, FieldAccessExpr node) { // Fields and internal type declarations cannot have the same name. // Thus, these checks will always be mutually exclusive. if (parentType.isEnum() && parentType.asEnum().hasEnumConstant(node.getName().getId())) { return parentType.asEnum().getEnumConstant(node.getName().getId()).getType(); } else if (parentType.hasField(node.getName().getId())) { return parentType.getField(node.getName().getId()).getType(); } else if (parentType.hasInternalType(node.getName().getId())) { return new ReferenceTypeImpl(parentType.getInternalType(node.getName().getId()), typeSolver); } else { throw new UnsolvedSymbolException(node.getName().getId()); } }
/** * Java Parser can't differentiate between packages, internal types, and fields. * All three are lumped together into FieldAccessExpr. We need to differentiate them. */ private ResolvedType solveDotExpressionType(ResolvedReferenceTypeDeclaration parentType, FieldAccessExpr node) { // Fields and internal type declarations cannot have the same name. // Thus, these checks will always be mutually exclusive. if (parentType.hasField(node.getName().getId())) { return parentType.getField(node.getName().getId()).getType(); } else if (parentType.hasInternalType(node.getName().getId())) { return new ReferenceTypeImpl(parentType.getInternalType(node.getName().getId()), typeSolver); } else { throw new UnsolvedSymbolException(node.getName().getId()); } }
public static ResolvedReferenceType undeterminedParameters(ResolvedReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) { return new ReferenceTypeImpl(typeDeclaration, typeDeclaration.getTypeParameters().stream().map( ResolvedTypeVariable::new ).collect(Collectors.toList()), typeSolver); }
@Override public boolean hasInternalType(String name) { /* The name of the ReferenceTypeDeclaration could be composed on the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part. In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works. */ return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name)); } }
public List<ResolvedReferenceType> getDirectAncestors() { // We need to go through the inheritance line and propagate the type parametes List<ResolvedReferenceType> ancestors = typeDeclaration.getAncestors(); ancestors = ancestors.stream() .map(a -> typeParametersMap().replaceAll(a).asReferenceType()) .collect(Collectors.toList()); // Avoid repetitions of Object ancestors.removeIf(a -> a.getQualifiedName().equals(Object.class.getCanonicalName())); boolean isClassWithSuperClassOrObject = this.getTypeDeclaration().isClass() && (this.getTypeDeclaration().asClass().getSuperClass() == null || !this.getTypeDeclaration().asClass().getSuperClass().getQualifiedName().equals(Object.class.getCanonicalName())); if (!isClassWithSuperClassOrObject) { ResolvedReferenceTypeDeclaration objectType = typeSolver.solveType(Object.class.getCanonicalName()); ResolvedReferenceType objectRef = create(objectType); ancestors.add(objectRef); } return ancestors; }
if (scopeType instanceof ResolvedReferenceTypeDeclaration) { ResolvedReferenceTypeDeclaration scopeRefType = scopeType.asReferenceType(); if (scopeRefType.getAllMethods().stream().anyMatch(m -> m.getName().equals(rightName))) { return NameCategory.EXPRESSION_NAME; if (scopeRefType.getAllFields().stream().anyMatch(f -> f.isStatic() && f.getName().equals(rightName))) { return NameCategory.EXPRESSION_NAME; if (scopeRefType.hasInternalType(rightName)) { return NameCategory.TYPE_NAME;
@Override public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) { if (typeSolver == null) throw new IllegalArgumentException(); // among constants for (EnumConstantDeclaration constant : wrappedNode.getEntries()) { if (constant.getName().getId().equals(name)) { return SymbolReference.solved(new JavaParserEnumConstantDeclaration(constant, typeSolver)); } } if (this.getDeclaration().hasField(name)) { return SymbolReference.solved(this.getDeclaration().getField(name)); } // then to parent return getParent().solveSymbol(name); }
@Override public ResolvedTypeParametrizable getContainer() { Node parentNode = getParentNode(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 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(); }
/** * This method gets all direct and indirect Ancestors of a given class if * possible. (If ancestor is not a external dependency for example) * * @param currentClass * @return ancestors */ public static List<ResolvedReferenceType> getAllAncestors(ResolvedReferenceTypeDeclaration currentClass) { // Init ancestor list List<ResolvedReferenceType> ancestors = new ArrayList<>(); // Check class if (!(Object.class.getCanonicalName().equals(currentClass.getQualifiedName()))) { // Get all direct ancestors that can be resolved for (ResolvedReferenceType ancestor : currentClass.getAncestors(true)) { // Add them to list ancestors.add(ancestor); // Get indirect ancestors recursively for (ResolvedReferenceType inheritedAncestor : getAllAncestors(ancestor.getTypeDeclaration())) { if (!ancestors.contains(inheritedAncestor)) { ancestors.add(inheritedAncestor); } } } } return ancestors; }
public SymbolReference<ResolvedValueDeclaration> solveField(String name) { Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope())); for (ResolvedReferenceTypeDeclaration rrtd : rrtds) { if (rrtd.isEnum()) { Optional<ResolvedEnumConstantDeclaration> enumConstant = rrtd.asEnum().getEnumConstants().stream().filter(c -> c.getName().equals(name)).findFirst(); if (enumConstant.isPresent()) { return SymbolReference.solved(enumConstant.get()); } } try { return SymbolReference.solved(rrtd.getField(wrappedNode.getName().getId())); } catch (Throwable t) { } } return SymbolReference.unsolved(ResolvedFieldDeclaration.class); } }
@Override public List<ResolvedReferenceType> getAncestors() { return ImmutableList. <ResolvedReferenceType>builder() .add(getSuperClass()) .addAll(superTypeDeclaration.asReferenceType().getAncestors()) .build(); }
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; }
@Test public void findAllInheritedFieldsAndGenerics() throws ParseException { CompilationUnit cu = parseSample("AClassWithFieldsAndGenerics"); ClassOrInterfaceDeclaration classC = Navigator.demandClass(cu, "C"); ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(classC); assertEquals(3, typeDeclaration.getAllFields().size()); assertEquals(ImmutableSet.of("a", "b", "c"), typeDeclaration.getAllFields().stream().map(ResolvedDeclaration::getName).collect(Collectors.toSet())); assertEquals("java.util.List<java.lang.String>", typeDeclaration.getField("b").getType().describe()); } }