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 Optional<Value> solveSymbolAsValue(String name) { Expression scope = wrappedNode.getScope(); if (wrappedNode.getName().toString().equals(name)) { ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); if (typeOfScope.isArray() && name.equals(ARRAY_LENGTH_FIELD_NAME)) { return Optional.of(new Value(ResolvedPrimitiveType.INT, ARRAY_LENGTH_FIELD_NAME)); } if (typeOfScope.isReferenceType()) { if (typeOfScope.asReferenceType().getTypeDeclaration().isEnum()) { ResolvedEnumDeclaration enumDeclaration = (ResolvedEnumDeclaration)typeOfScope.asReferenceType().getTypeDeclaration(); if (enumDeclaration.hasEnumConstant(name)) { return Optional.of(new Value(enumDeclaration.getEnumConstant(name).getType(), name)); } } Optional<ResolvedType> typeUsage = typeOfScope.asReferenceType().getFieldType(name); return typeUsage.map(resolvedType -> new Value(resolvedType, name)); } else { return Optional.empty(); } } else { return getParent().solveSymbolAsValue(name); } }
@Override public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) { SwitchStmt switchStmt = (SwitchStmt) getParentNode(wrappedNode); ResolvedType type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector()); if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) { if (type instanceof ReferenceTypeImpl) { ReferenceTypeImpl typeUsageOfTypeDeclaration = (ReferenceTypeImpl) type; if (typeUsageOfTypeDeclaration.getTypeDeclaration().hasField(name)) { return SymbolReference.solved(typeUsageOfTypeDeclaration.getTypeDeclaration().getField(name)); } } else { throw new UnsupportedOperationException(); } } // look for declaration in other switch statements for (SwitchEntryStmt seStmt : switchStmt.getEntries()) { if (!seStmt.equals(wrappedNode)) { for (Statement stmt : seStmt.getStatements()) { SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(stmt, typeSolver); SymbolReference<? extends ResolvedValueDeclaration> symbolReference = solveWith(symbolDeclarator, name); if (symbolReference.isSolved()) { return symbolReference; } } } } return getParent().solveSymbol(name, typeSolver); }
@Override public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) { SwitchStmt switchStmt = (SwitchStmt) getParentNode(wrappedNode); ResolvedType type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector()); if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) { if (type instanceof ReferenceTypeImpl) { ReferenceTypeImpl typeUsageOfTypeDeclaration = (ReferenceTypeImpl) type; if (typeUsageOfTypeDeclaration.getTypeDeclaration().hasField(name)) { return SymbolReference.solved(typeUsageOfTypeDeclaration.getTypeDeclaration().getField(name)); } } else { throw new UnsupportedOperationException(); } } // look for declaration in other switch statements for (SwitchEntryStmt seStmt : switchStmt.getEntries()) { if (!seStmt.equals(wrappedNode)) { for (Statement stmt : seStmt.getStatements()) { SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(stmt, typeSolver); SymbolReference<? extends ResolvedValueDeclaration> symbolReference = solveWith(symbolDeclarator, name); if (symbolReference.isSolved()) { return symbolReference; } } } } return getParent().solveSymbol(name, typeSolver); }
@Test public void resolvingReferenceToEnumDeclarationInSameFile() throws FileNotFoundException { String code = "package foo.bar;\nenum Foo {\n" + " FOO_A, FOO_B\n" + "}\n" + "\n" + "class UsingFoo {\n" + " Foo myFooField;\n" + "}"; CompilationUnit cu = JavaParser.parse(code); FieldDeclaration fieldDeclaration = Navigator.findNodeOfGivenClass(cu, FieldDeclaration.class); ResolvedType fieldType = javaParserFacade.getType(fieldDeclaration); assertEquals(true, fieldType.isReferenceType()); assertEquals(true, fieldType.asReferenceType().getTypeDeclaration().isEnum()); assertEquals("foo.bar.Foo", fieldType.asReferenceType().getQualifiedName()); } }
SwitchStmt switchStmt = (SwitchStmt) requireParentNode(wrappedNode); ResolvedType type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector()); if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) { if (type instanceof ReferenceTypeImpl) { ReferenceTypeImpl typeUsageOfTypeDeclaration = (ReferenceTypeImpl) type;
/** * 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()); } }