From 09232ff6b0ea19e850482f3a87ac6ef1c063c759 Mon Sep 17 00:00:00 2001 From: Federico Tomassetti Date: Wed, 10 Jan 2018 13:52:19 +0100 Subject: rename JSS modules --- .../javaparsermodel/DefaultVisitorAdapter.java | 470 +++++++++++++++++ .../javaparsermodel/JavaParserFacade.java | 573 +++++++++++++++++++++ .../javaparsermodel/JavaParserFactory.java | 138 +++++ .../LambdaArgumentTypePlaceholder.java | 72 +++ .../javaparsermodel/TypeExtractor.java | 535 +++++++++++++++++++ .../javaparsermodel/UnsolvedSymbolException.java | 67 +++ .../contexts/AbstractJavaParserContext.java | 196 +++++++ .../AbstractMethodLikeDeclarationContext.java | 101 ++++ .../contexts/AnonymousClassDeclarationContext.java | 186 +++++++ .../contexts/CatchClauseContext.java | 54 ++ .../ClassOrInterfaceDeclarationContext.java | 109 ++++ .../contexts/CompilationUnitContext.java | 291 +++++++++++ .../contexts/ConstructorContext.java | 35 ++ .../javaparsermodel/contexts/ContextHelper.java | 74 +++ .../contexts/EnumDeclarationContext.java | 82 +++ .../contexts/FieldAccessContext.java | 108 ++++ .../contexts/ForStatementContext.java | 70 +++ .../contexts/ForechStatementContext.java | 61 +++ .../contexts/JavaParserTypeDeclarationAdapter.java | 133 +++++ .../contexts/LambdaExprContext.java | 194 +++++++ .../contexts/MethodCallExprContext.java | 433 ++++++++++++++++ .../javaparsermodel/contexts/MethodContext.java | 35 ++ .../javaparsermodel/contexts/StatementContext.java | 200 +++++++ .../contexts/SwitchEntryContext.java | 80 +++ .../contexts/TryWithResourceContext.java | 87 ++++ .../DefaultConstructorDeclaration.java | 82 +++ .../javaparsermodel/declarations/Helper.java | 85 +++ .../JavaParserAnnotationDeclaration.java | 103 ++++ .../JavaParserAnnotationMemberDeclaration.java | 40 ++ .../JavaParserAnonymousClassDeclaration.java | 205 ++++++++ .../declarations/JavaParserClassDeclaration.java | 392 ++++++++++++++ .../JavaParserConstructorDeclaration.java | 103 ++++ .../JavaParserEnumConstantDeclaration.java | 59 +++ .../declarations/JavaParserEnumDeclaration.java | 349 +++++++++++++ .../declarations/JavaParserFieldDeclaration.java | 123 +++++ .../JavaParserInterfaceDeclaration.java | 335 ++++++++++++ .../declarations/JavaParserMethodDeclaration.java | 168 ++++++ .../JavaParserParameterDeclaration.java | 100 ++++ .../declarations/JavaParserSymbolDeclaration.java | 177 +++++++ .../declarations/JavaParserTypeAdapter.java | 138 +++++ .../declarations/JavaParserTypeParameter.java | 224 ++++++++ .../JavaParserTypeVariableDeclaration.java | 187 +++++++ .../declarators/AbstractSymbolDeclarator.java | 35 ++ .../declarators/FieldSymbolDeclarator.java | 46 ++ .../declarators/NoSymbolDeclarator.java | 40 ++ .../declarators/ParameterSymbolDeclarator.java | 42 ++ .../declarators/VariableSymbolDeclarator.java | 52 ++ .../symbolsolver/javaparsermodel/package-info.java | 20 + 48 files changed, 7489 insertions(+) create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationMemberDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java create mode 100644 javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java new file mode 100644 index 000000000..dc9d86241 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java @@ -0,0 +1,470 @@ +package com.github.javaparser.symbolsolver.javaparsermodel; + +import com.github.javaparser.ast.*; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.comments.BlockComment; +import com.github.javaparser.ast.comments.JavadocComment; +import com.github.javaparser.ast.comments.LineComment; +import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.modules.*; +import com.github.javaparser.ast.stmt.*; +import com.github.javaparser.ast.type.*; +import com.github.javaparser.ast.visitor.GenericVisitor; +import com.github.javaparser.resolution.types.ResolvedType; + +public class DefaultVisitorAdapter implements GenericVisitor { + @Override + public ResolvedType visit(CompilationUnit node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(PackageDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(TypeParameter node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(LineComment node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(BlockComment node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ClassOrInterfaceDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(EnumDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(EnumConstantDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(AnnotationDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(AnnotationMemberDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(FieldDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(VariableDeclarator node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ConstructorDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(MethodDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(Parameter node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(InitializerDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(JavadocComment node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ClassOrInterfaceType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(PrimitiveType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ArrayType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ArrayCreationLevel node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(IntersectionType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(UnionType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(VoidType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(WildcardType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(UnknownType node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ArrayAccessExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ArrayCreationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ArrayInitializerExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(AssignExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(BinaryExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(CastExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ClassExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ConditionalExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(EnclosedExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(FieldAccessExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(InstanceOfExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(StringLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(IntegerLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(LongLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(CharLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(DoubleLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(BooleanLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(NullLiteralExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(MethodCallExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(NameExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ObjectCreationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ThisExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SuperExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(UnaryExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(VariableDeclarationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(MarkerAnnotationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SingleMemberAnnotationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(NormalAnnotationExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(MemberValuePair node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ExplicitConstructorInvocationStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(LocalClassDeclarationStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(AssertStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(BlockStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(LabeledStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(EmptyStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ExpressionStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SwitchStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SwitchEntryStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(BreakStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ReturnStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(IfStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(WhileStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ContinueStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(DoStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ForeachStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ForStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ThrowStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SynchronizedStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(TryStmt node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(CatchClause node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(LambdaExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(MethodReferenceExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(TypeExpr node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(NodeList node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(Name node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(SimpleName node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ImportDeclaration node, Boolean aBoolean) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleDeclaration node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleRequiresStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleExportsStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleProvidesStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleUsesStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ModuleOpensStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(UnparsableStmt node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(ReceiverParameter node, Boolean arg) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java new file mode 100644 index 000000000..39e0d29ea --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -0,0 +1,573 @@ +/* + * 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; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.body.EnumDeclaration; +import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; +import com.github.javaparser.ast.type.*; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.*; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.contexts.FieldAccessContext; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.*; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; + +import java.util.*; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * Class to be used by final users to solve symbols for JavaParser ASTs. + * + * @author Federico Tomassetti + */ +public class JavaParserFacade { + + private static Logger logger = Logger.getLogger(JavaParserFacade.class.getCanonicalName()); + + static { + logger.setLevel(Level.INFO); + ConsoleHandler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(Level.INFO); + logger.addHandler(consoleHandler); + } + + private static Map instances = new WeakHashMap<>(); + private TypeSolver typeSolver; + private SymbolSolver symbolSolver; + private Map cacheWithLambdasSolved = new IdentityHashMap<>(); + private Map cacheWithoutLambdasSolved = new IdentityHashMap<>(); + private TypeExtractor typeExtractor; + + private JavaParserFacade(TypeSolver typeSolver) { + this.typeSolver = typeSolver.getRoot(); + this.symbolSolver = new SymbolSolver(typeSolver); + this.typeExtractor = new TypeExtractor(typeSolver, this); + } + + public TypeSolver getTypeSolver() { + return typeSolver; + } + + public SymbolSolver getSymbolSolver() { + return symbolSolver; + } + + public static JavaParserFacade get(TypeSolver typeSolver) { + return instances.computeIfAbsent(typeSolver, JavaParserFacade::new); + } + + /** + * This method is used to clear internal caches for the sake of releasing memory. + */ + public static void clearInstances() { + instances.clear(); + } + + protected static ResolvedType solveGenericTypes(ResolvedType type, Context context, TypeSolver typeSolver) { + if (type.isTypeVariable()) { + Optional solved = context.solveGenericType(type.describe(), typeSolver); + if (solved.isPresent()) { + return solved.get(); + } else { + return type; + } + } else if (type.isWildcard()) { + if (type.asWildcard().isExtends() || type.asWildcard().isSuper()) { + ResolvedWildcard wildcardUsage = type.asWildcard(); + ResolvedType boundResolved = solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver); + if (wildcardUsage.isExtends()) { + return ResolvedWildcard.extendsBound(boundResolved); + } else { + return ResolvedWildcard.superBound(boundResolved); + } + } else { + return type; + } + } else { + ResolvedType result = type; + return result; + } + } + + public SymbolReference solve(NameExpr nameExpr) { + return symbolSolver.solveSymbol(nameExpr.getName().getId(), nameExpr); + } + + public SymbolReference solve(SimpleName nameExpr) { + return symbolSolver.solveSymbol(nameExpr.getId(), nameExpr); + } + + public SymbolReference solve(Expression expr) { + if (expr instanceof NameExpr) { + return solve((NameExpr) expr); + } else { + throw new IllegalArgumentException(expr.getClass().getCanonicalName()); + } + } + + public SymbolReference solve(MethodCallExpr methodCallExpr) { + return solve(methodCallExpr, true); + } + + public SymbolReference solve(ObjectCreationExpr objectCreationExpr) { + return solve(objectCreationExpr, true); + } + + public SymbolReference solve(ExplicitConstructorInvocationStmt explicitConstructorInvocationStmt) { + return solve(explicitConstructorInvocationStmt, true); + } + + public SymbolReference solve(ExplicitConstructorInvocationStmt explicitConstructorInvocationStmt, boolean solveLambdas) { + List argumentTypes = new LinkedList<>(); + List placeholders = new LinkedList<>(); + + solveArguments(explicitConstructorInvocationStmt, explicitConstructorInvocationStmt.getArguments(), solveLambdas, argumentTypes, placeholders); + + Optional optAncestor = explicitConstructorInvocationStmt.getAncestorOfType(ClassOrInterfaceDeclaration.class); + if (!optAncestor.isPresent()) { + return SymbolReference.unsolved(ResolvedConstructorDeclaration.class); + } + ClassOrInterfaceDeclaration classNode = optAncestor.get(); + ResolvedTypeDeclaration typeDecl = null; + if (!explicitConstructorInvocationStmt.isThis()) { + ResolvedType classDecl = JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode); + if (classDecl.isReferenceType()) { + typeDecl = classDecl.asReferenceType().getTypeDeclaration(); + } + } else { + SymbolReference sr = JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString(), typeSolver); + if (sr.isSolved()) { + typeDecl = sr.getCorrespondingDeclaration(); + } + } + if (typeDecl == null) { + return SymbolReference.unsolved(ResolvedConstructorDeclaration.class); + } + SymbolReference res = ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) typeDecl).getConstructors(), argumentTypes, typeSolver); + for (LambdaArgumentTypePlaceholder placeholder : placeholders) { + placeholder.setMethod(res); + } + return res; + } + + public SymbolReference solve(ThisExpr node){ + // If 'this' is prefixed by a class eg. MyClass.this + if (node.getClassExpr().isPresent()){ + // Get the class name + String className = node.getClassExpr().get().toString(); + // Attempt to resolve using a typeSolver + SymbolReference clazz = typeSolver.tryToSolveType(className); + if (clazz.isSolved()){ + return SymbolReference.solved(clazz.getCorrespondingDeclaration()); + } + // Attempt to resolve locally in Compilation unit + Optional cu = node.getAncestorOfType(CompilationUnit.class); + if (cu.isPresent()){ + Optional classByName = cu.get().getClassByName(className); + if (classByName.isPresent()){ + return SymbolReference.solved(getTypeDeclaration(classByName.get())); + } + } + } + return SymbolReference.solved(getTypeDeclaration(findContainingTypeDeclOrObjectCreationExpr(node))); + } + + /** + * Given a constructor call find out to which constructor declaration it corresponds. + */ + public SymbolReference solve(ObjectCreationExpr objectCreationExpr, boolean solveLambdas) { + List argumentTypes = new LinkedList<>(); + List placeholders = new LinkedList<>(); + + solveArguments(objectCreationExpr, objectCreationExpr.getArguments(), solveLambdas, argumentTypes, placeholders); + + ResolvedType classDecl = JavaParserFacade.get(typeSolver).convert(objectCreationExpr.getType(), objectCreationExpr); + if (!classDecl.isReferenceType()) { + return SymbolReference.unsolved(ResolvedConstructorDeclaration.class); + } + SymbolReference res = ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors(), argumentTypes, typeSolver); + for (LambdaArgumentTypePlaceholder placeholder : placeholders) { + placeholder.setMethod(res); + } + return res; + } + + private void solveArguments(Node node, NodeList args, boolean solveLambdas, List argumentTypes, + List placeholders) { + int i = 0; + for (Expression parameterValue : args) { + if (parameterValue instanceof LambdaExpr || parameterValue instanceof MethodReferenceExpr) { + LambdaArgumentTypePlaceholder placeholder = new LambdaArgumentTypePlaceholder(i); + argumentTypes.add(placeholder); + placeholders.add(placeholder); + } else { + try { + argumentTypes.add(JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas)); + } catch (UnsolvedSymbolException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(String.format("Unable to calculate the type of a parameter of a method call. Method call: %s, Parameter: %s", + node, parameterValue), e); + } + } + i++; + } + } + + /** + * Given a method call find out to which method declaration it corresponds. + */ + public SymbolReference solve(MethodCallExpr methodCallExpr, boolean solveLambdas) { + List argumentTypes = new LinkedList<>(); + List placeholders = new LinkedList<>(); + + solveArguments(methodCallExpr, methodCallExpr.getArguments(), solveLambdas, argumentTypes, placeholders); + + SymbolReference res = JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false, typeSolver); + for (LambdaArgumentTypePlaceholder placeholder : placeholders) { + placeholder.setMethod(res); + } + return res; + } + + public SymbolReference solve(AnnotationExpr annotationExpr) { + Context context = JavaParserFactory.getContext(annotationExpr, typeSolver); + SymbolReference typeDeclarationSymbolReference = context.solveType(annotationExpr.getNameAsString(), typeSolver); + ResolvedAnnotationDeclaration annotationDeclaration = (ResolvedAnnotationDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration(); + if (typeDeclarationSymbolReference.isSolved()) { + return SymbolReference.solved(annotationDeclaration); + } else { + return SymbolReference.unsolved(ResolvedAnnotationDeclaration.class); + } + } + + public SymbolReference solve(FieldAccessExpr fieldAccessExpr) { + return ((FieldAccessContext) JavaParserFactory.getContext(fieldAccessExpr, typeSolver)).solveField(fieldAccessExpr.getName().getId(), typeSolver); + } + + public ResolvedType getType(Node node) { + return getType(node, true); + } + + public ResolvedType getType(Node node, boolean solveLambdas) { + if (solveLambdas) { + if (!cacheWithLambdasSolved.containsKey(node)) { + ResolvedType res = getTypeConcrete(node, solveLambdas); + + cacheWithLambdasSolved.put(node, res); + + boolean secondPassNecessary = false; + if (node instanceof MethodCallExpr) { + MethodCallExpr methodCallExpr = (MethodCallExpr) node; + for (Node arg : methodCallExpr.getArguments()) { + if (!cacheWithLambdasSolved.containsKey(arg)) { + getType(arg, true); + secondPassNecessary = true; + } + } + } + if (secondPassNecessary) { + cacheWithLambdasSolved.remove(node); + cacheWithLambdasSolved.put(node, getType(node, true)); + } + logger.finer("getType on " + node + " -> " + res); + } + return cacheWithLambdasSolved.get(node); + } else { + Optional res = find(cacheWithLambdasSolved, node); + if (res.isPresent()) { + return res.get(); + } + res = find(cacheWithoutLambdasSolved, node); + if (!res.isPresent()) { + ResolvedType resType = getTypeConcrete(node, solveLambdas); + cacheWithoutLambdasSolved.put(node, resType); + logger.finer("getType on " + node + " (no solveLambdas) -> " + res); + return resType; + } + return res.get(); + } + } + + private Optional find(Map map, Node node) { + if (map.containsKey(node)) { + return Optional.of(map.get(node)); + } + if (node instanceof LambdaExpr) { + return find(map, (LambdaExpr) node); + } else { + return Optional.empty(); + } + } + + /** + * For some reasons LambdaExprs are duplicate and the equals method is not implemented correctly. + * + * @param map + * @return + */ + private Optional find(Map map, LambdaExpr lambdaExpr) { + for (Node key : map.keySet()) { + if (key instanceof LambdaExpr) { + LambdaExpr keyLambdaExpr = (LambdaExpr) key; + if (keyLambdaExpr.toString().equals(lambdaExpr.toString()) && getParentNode(keyLambdaExpr) == getParentNode(lambdaExpr)) { + return Optional.of(map.get(keyLambdaExpr)); + } + } + } + return Optional.empty(); + } + + protected MethodUsage toMethodUsage(MethodReferenceExpr methodReferenceExpr) { + if (!(methodReferenceExpr.getScope() instanceof TypeExpr)) { + throw new UnsupportedOperationException(); + } + TypeExpr typeExpr = (TypeExpr) methodReferenceExpr.getScope(); + if (!(typeExpr.getType() instanceof com.github.javaparser.ast.type.ClassOrInterfaceType)) { + throw new UnsupportedOperationException(typeExpr.getType().getClass().getCanonicalName()); + } + ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) typeExpr.getType(); + SymbolReference typeDeclarationSymbolReference = JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId(), typeSolver); + if (!typeDeclarationSymbolReference.isSolved()) { + throw new UnsupportedOperationException(); + } + List methodUsages = ((ResolvedReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())).collect(Collectors.toList()); + switch (methodUsages.size()) { + case 0: + throw new UnsupportedOperationException(); + case 1: + return methodUsages.get(0); + default: + throw new UnsupportedOperationException(); + } + } + + protected ResolvedType getBinaryTypeConcrete(Node left, Node right, boolean solveLambdas) { + ResolvedType leftType = getTypeConcrete(left, solveLambdas); + ResolvedType rightType = getTypeConcrete(right, solveLambdas); + if (rightType.isAssignableBy(leftType)) { + return rightType; + } + return leftType; + } + + + /** + * Should return more like a TypeApplication: a TypeDeclaration and possible typeParametersValues or array + * modifiers. + * + * @return + */ + private ResolvedType getTypeConcrete(Node node, boolean solveLambdas) { + if (node == null) throw new IllegalArgumentException(); + return node.accept(typeExtractor, solveLambdas); + } + + protected com.github.javaparser.ast.body.TypeDeclaration findContainingTypeDecl(Node node) { + if (node instanceof ClassOrInterfaceDeclaration) { + return (ClassOrInterfaceDeclaration) node; + } else if (node instanceof EnumDeclaration) { + return (EnumDeclaration) node; + } else if (getParentNode(node) == null) { + throw new IllegalArgumentException(); + } else { + return findContainingTypeDecl(getParentNode(node)); + } + } + + protected com.github.javaparser.ast.Node findContainingTypeDeclOrObjectCreationExpr(Node node) { + if (node instanceof ClassOrInterfaceDeclaration) { + return (ClassOrInterfaceDeclaration) node; + } else if (node instanceof EnumDeclaration) { + return (EnumDeclaration) node; + } else if (getParentNode(node) == null) { + throw new IllegalArgumentException(); + } else if (getParentNode(node) instanceof ObjectCreationExpr && !((ObjectCreationExpr)getParentNode(node)).getArguments().contains(node)) { + return getParentNode(node); + } else { + return findContainingTypeDeclOrObjectCreationExpr(getParentNode(node)); + } + } + + public ResolvedType convertToUsageVariableType(VariableDeclarator var) { + ResolvedType type = JavaParserFacade.get(typeSolver).convertToUsage(var.getType(), var); + return type; + } + + public ResolvedType convertToUsage(com.github.javaparser.ast.type.Type type, Node context) { + if (type instanceof UnknownType) { + throw new IllegalArgumentException("Unknown type"); + } + return convertToUsage(type, JavaParserFactory.getContext(context, typeSolver)); + } + + public ResolvedType convertToUsage(com.github.javaparser.ast.type.Type type) { + return convertToUsage(type, type); + } + + // This is an hack around an issue in JavaParser + private String qName(ClassOrInterfaceType classOrInterfaceType) { + String name = classOrInterfaceType.getName().getId(); + if (classOrInterfaceType.getScope().isPresent()) { + return qName(classOrInterfaceType.getScope().get()) + "." + name; + } else { + return name; + } + } + + protected ResolvedType convertToUsage(com.github.javaparser.ast.type.Type type, Context context) { + if (context == null) { + throw new NullPointerException("Context should not be null"); + } + if (type instanceof ClassOrInterfaceType) { + ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) type; + String name = qName(classOrInterfaceType); + SymbolReference ref = context.solveType(name, typeSolver); + if (!ref.isSolved()) { + throw new UnsolvedSymbolException(name); + } + ResolvedTypeDeclaration typeDeclaration = ref.getCorrespondingDeclaration(); + List typeParameters = Collections.emptyList(); + if (classOrInterfaceType.getTypeArguments().isPresent()) { + typeParameters = classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)).collect(Collectors.toList()); + } + if (typeDeclaration.isTypeParameter()) { + if (typeDeclaration instanceof ResolvedTypeParameterDeclaration) { + return new ResolvedTypeVariable((ResolvedTypeParameterDeclaration) typeDeclaration); + } else { + JavaParserTypeVariableDeclaration javaParserTypeVariableDeclaration = (JavaParserTypeVariableDeclaration) typeDeclaration; + return new ResolvedTypeVariable(javaParserTypeVariableDeclaration.asTypeParameter()); + } + } else { + return new ReferenceTypeImpl((ResolvedReferenceTypeDeclaration) typeDeclaration, typeParameters, typeSolver); + } + } else if (type instanceof com.github.javaparser.ast.type.PrimitiveType) { + return ResolvedPrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) type).getType().name()); + } else if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) type; + if (wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) { + return ResolvedWildcard.extendsBound(convertToUsage(wildcardType.getExtendedTypes().get(), context)); // removed (ReferenceTypeImpl) + } else if (!wildcardType.getExtendedTypes().isPresent() && wildcardType.getSuperTypes().isPresent()) { + return ResolvedWildcard.superBound(convertToUsage(wildcardType.getSuperTypes().get(), context)); // removed (ReferenceTypeImpl) + } else if (!wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) { + return ResolvedWildcard.UNBOUNDED; + } else { + throw new UnsupportedOperationException(wildcardType.toString()); + } + } else if (type instanceof com.github.javaparser.ast.type.VoidType) { + return ResolvedVoidType.INSTANCE; + } else if (type instanceof com.github.javaparser.ast.type.ArrayType) { + com.github.javaparser.ast.type.ArrayType jpArrayType = (com.github.javaparser.ast.type.ArrayType) type; + return new ResolvedArrayType(convertToUsage(jpArrayType.getComponentType(), context)); + } else if (type instanceof UnionType) { + UnionType unionType = (UnionType)type; + return new ResolvedUnionType(unionType.getElements().stream().map(el -> convertToUsage(el, context)).collect(Collectors.toList())); + } else { + throw new UnsupportedOperationException(type.getClass().getCanonicalName()); + } + } + + + public ResolvedType convert(Type type, Node node) { + return convert(type, JavaParserFactory.getContext(node, typeSolver)); + } + + public ResolvedType convert(com.github.javaparser.ast.type.Type type, Context context) { + return convertToUsage(type, context); + } + + public MethodUsage solveMethodAsUsage(MethodCallExpr call) { + List params = new ArrayList<>(); + if (call.getArguments() != null) { + for (Expression param : call.getArguments()) { + //getTypeConcrete(Node node, boolean solveLambdas) + try { + params.add(getType(param, false)); + } catch (Exception e) { + throw new RuntimeException(String.format("Error calculating the type of parameter %s of method call %s", param, call), e); + } + //params.add(getTypeConcrete(param, false)); + } + } + Context context = JavaParserFactory.getContext(call, typeSolver); + Optional methodUsage = context.solveMethodAsUsage(call.getName().getId(), params, typeSolver); + if (!methodUsage.isPresent()) { + throw new RuntimeException("Method '" + call.getName() + "' cannot be resolved in context " + + call + " (line: " + call.getRange().get().begin.line + ") " + context + ". Parameter types: " + params); + } + return methodUsage.get(); + } + + public ResolvedReferenceTypeDeclaration getTypeDeclaration(Node node) { + if (node instanceof TypeDeclaration) { + return getTypeDeclaration((TypeDeclaration)node); + } else if (node instanceof ObjectCreationExpr) { + return new JavaParserAnonymousClassDeclaration((ObjectCreationExpr)node, typeSolver); + } else { + throw new IllegalArgumentException(); + } + } + + public ResolvedReferenceTypeDeclaration getTypeDeclaration(ClassOrInterfaceDeclaration classOrInterfaceDeclaration) { + return JavaParserFactory.toTypeDeclaration(classOrInterfaceDeclaration, typeSolver); + } + + /** + * "this" inserted in the given point, which type would have? + */ + public ResolvedType getTypeOfThisIn(Node node) { + // TODO consider static methods + if (node instanceof ClassOrInterfaceDeclaration) { + return new ReferenceTypeImpl(getTypeDeclaration((ClassOrInterfaceDeclaration) node), typeSolver); + } else if (node instanceof EnumDeclaration) { + JavaParserEnumDeclaration enumDeclaration = new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver); + return new ReferenceTypeImpl(enumDeclaration, typeSolver); + } else if (node instanceof ObjectCreationExpr && ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) { + JavaParserAnonymousClassDeclaration anonymousDeclaration = new JavaParserAnonymousClassDeclaration((ObjectCreationExpr) node, typeSolver); + return new ReferenceTypeImpl(anonymousDeclaration, typeSolver); + } else { + return getTypeOfThisIn(getParentNode(node)); + } + } + + public ResolvedReferenceTypeDeclaration getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration typeDeclaration) { + return JavaParserFactory.toTypeDeclaration(typeDeclaration, typeSolver); + } + + public ResolvedType classToResolvedType(Class clazz) { + if (clazz.isPrimitive()) { + return ResolvedPrimitiveType.byName(clazz.getName()); + } + return new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java new file mode 100644 index 000000000..1004bc31e --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java @@ -0,0 +1,138 @@ +/* + * 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; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.stmt.*; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.contexts.*; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter; +import com.github.javaparser.symbolsolver.javaparsermodel.declarators.FieldSymbolDeclarator; +import com.github.javaparser.symbolsolver.javaparsermodel.declarators.NoSymbolDeclarator; +import com.github.javaparser.symbolsolver.javaparsermodel.declarators.ParameterSymbolDeclarator; +import com.github.javaparser.symbolsolver.javaparsermodel.declarators.VariableSymbolDeclarator; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class JavaParserFactory { + + public static Context getContext(Node node, TypeSolver typeSolver) { + if (node == null) { + throw new NullPointerException("Node should not be null"); + } else if (node instanceof CompilationUnit) { + return new CompilationUnitContext((CompilationUnit) node, typeSolver); + } else if (node instanceof ForeachStmt) { + return new ForechStatementContext((ForeachStmt) node, typeSolver); + } else if (node instanceof ForStmt) { + return new ForStatementContext((ForStmt) node, typeSolver); + } else if (node instanceof LambdaExpr) { + return new LambdaExprContext((LambdaExpr) node, typeSolver); + } else if (node instanceof MethodDeclaration) { + return new MethodContext((MethodDeclaration) node, typeSolver); + } else if (node instanceof ConstructorDeclaration) { + return new ConstructorContext((ConstructorDeclaration) node, typeSolver); + } else if (node instanceof ClassOrInterfaceDeclaration) { + return new ClassOrInterfaceDeclarationContext((ClassOrInterfaceDeclaration) node, typeSolver); + } else if (node instanceof MethodCallExpr) { + return new MethodCallExprContext((MethodCallExpr) node, typeSolver); + } else if (node instanceof EnumDeclaration) { + return new EnumDeclarationContext((EnumDeclaration) node, typeSolver); + } else if (node instanceof FieldAccessExpr) { + return new FieldAccessContext((FieldAccessExpr) node, typeSolver); + } else if (node instanceof SwitchEntryStmt) { + return new SwitchEntryContext((SwitchEntryStmt) node, typeSolver); + } else if (node instanceof TryStmt) { + return new TryWithResourceContext((TryStmt) node, typeSolver); + } else if (node instanceof Statement) { + return new StatementContext((Statement) node, typeSolver); + } else if (node instanceof CatchClause) { + return new CatchClauseContext((CatchClause) node, typeSolver); + } else if (node instanceof ObjectCreationExpr && + ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) { + return new AnonymousClassDeclarationContext((ObjectCreationExpr) node, typeSolver); + } else { + if (node instanceof NameExpr) { + // to resolve a name when in a fieldAccess context, we can get to the grand parent to prevent a infinite loop if the name is the same as the field (ie x.x) + if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof FieldAccessExpr && node.getParentNode().get().getParentNode().isPresent()) { + return getContext(node.getParentNode().get().getParentNode().get(), typeSolver); + } + } + final Node parentNode = getParentNode(node); + if (parentNode instanceof ObjectCreationExpr && node == ((ObjectCreationExpr) parentNode).getType()) { + return getContext(getParentNode(parentNode), typeSolver); + } + if (parentNode == null) { + throw new IllegalStateException("The AST node does not appear to be inserted in a propert AST, therefore we cannot resolve symbols correctly"); + } + return getContext(parentNode, typeSolver); + } + } + + public static SymbolDeclarator getSymbolDeclarator(Node node, TypeSolver typeSolver) { + if (node instanceof FieldDeclaration) { + return new FieldSymbolDeclarator((FieldDeclaration) node, typeSolver); + } else if (node instanceof Parameter) { + return new ParameterSymbolDeclarator((Parameter) node, typeSolver); + } else if (node instanceof ExpressionStmt) { + ExpressionStmt expressionStmt = (ExpressionStmt) node; + if (expressionStmt.getExpression() instanceof VariableDeclarationExpr) { + return new VariableSymbolDeclarator((VariableDeclarationExpr) (expressionStmt.getExpression()), typeSolver); + } else { + return new NoSymbolDeclarator(expressionStmt, typeSolver); + } + } else if (node instanceof IfStmt) { + return new NoSymbolDeclarator((IfStmt) node, typeSolver); + } else if (node instanceof ForeachStmt) { + ForeachStmt foreachStmt = (ForeachStmt) node; + return new VariableSymbolDeclarator((VariableDeclarationExpr) (foreachStmt.getVariable()), typeSolver); + } else { + return new NoSymbolDeclarator(node, typeSolver); + } + } + + public static ResolvedReferenceTypeDeclaration toTypeDeclaration(Node node, TypeSolver typeSolver) { + if (node instanceof ClassOrInterfaceDeclaration) { + if (((ClassOrInterfaceDeclaration) node).isInterface()) { + return new JavaParserInterfaceDeclaration((ClassOrInterfaceDeclaration) node, typeSolver); + } else { + return new JavaParserClassDeclaration((ClassOrInterfaceDeclaration) node, typeSolver); + } + } else if (node instanceof TypeParameter) { + return new JavaParserTypeParameter((TypeParameter) node, typeSolver); + } else if (node instanceof EnumDeclaration) { + return new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver); + } else if (node instanceof AnnotationDeclaration) { + return new JavaParserAnnotationDeclaration((AnnotationDeclaration) node, typeSolver); + } else { + throw new IllegalArgumentException(node.getClass().getCanonicalName()); + } + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java new file mode 100644 index 000000000..c0e35bf43 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java @@ -0,0 +1,72 @@ +/* + * 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; + +import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; + +/** + * Placeholder used to represent a lambda argument type while it is being + * calculated. + * + * @author Federico Tomassetti + */ +public class LambdaArgumentTypePlaceholder implements ResolvedType { + + private int pos; + private SymbolReference method; + + public LambdaArgumentTypePlaceholder(int pos) { + this.pos = pos; + } + + @Override + public boolean isArray() { + return false; + } + + @Override + public boolean isPrimitive() { + return false; + } + + @Override + public boolean isReferenceType() { + return false; + } + + @Override + public String describe() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isTypeVariable() { + return false; + } + + public void setMethod(SymbolReference method) { + this.method = method; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + throw new UnsupportedOperationException(); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java new file mode 100644 index 000000000..1e15571d7 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java @@ -0,0 +1,535 @@ +package com.github.javaparser.symbolsolver.javaparsermodel; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +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.*; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; +import com.github.javaparser.ast.stmt.ReturnStmt; +import com.github.javaparser.ast.stmt.Statement; +import com.github.javaparser.ast.type.UnknownType; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration; +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.types.ResolvedArrayType; +import com.github.javaparser.resolution.types.ResolvedPrimitiveType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedVoidType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic; +import com.github.javaparser.symbolsolver.logic.InferenceContext; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.model.typesystem.*; +import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; +import com.google.common.collect.ImmutableList; + +import java.util.List; +import java.util.Optional; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +public class TypeExtractor extends DefaultVisitorAdapter { + + private static Logger logger = Logger.getLogger(TypeExtractor.class.getCanonicalName()); + + static { + logger.setLevel(Level.INFO); + ConsoleHandler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(Level.INFO); + logger.addHandler(consoleHandler); + } + + private TypeSolver typeSolver; + private JavaParserFacade facade; + + public TypeExtractor(TypeSolver typeSolver, JavaParserFacade facade) { + this.typeSolver = typeSolver; + this.facade = facade; + } + + @Override + public ResolvedType visit(VariableDeclarator node, Boolean solveLambdas) { + if (getParentNode(node) instanceof FieldDeclaration) { + return facade.convertToUsageVariableType(node); + } else if (getParentNode(node) instanceof VariableDeclarationExpr) { + return facade.convertToUsageVariableType(node); + } else { + throw new UnsupportedOperationException(getParentNode(node).getClass().getCanonicalName()); + } + } + + @Override + public ResolvedType visit(Parameter node, Boolean solveLambdas) { + if (node.getType() instanceof UnknownType) { + throw new IllegalStateException("Parameter has unknown type: " + node); + } + return facade.convertToUsage(node.getType(), node); + } + + + @Override + public ResolvedType visit(ArrayAccessExpr node, Boolean solveLambdas) { + ResolvedType arrayUsageType = node.getName().accept(this, solveLambdas); + if (arrayUsageType.isArray()) { + return ((ResolvedArrayType) arrayUsageType).getComponentType(); + } + return arrayUsageType; + } + + @Override + public ResolvedType visit(ArrayCreationExpr node, Boolean solveLambdas) { + ResolvedType res = facade.convertToUsage(node.getElementType(), JavaParserFactory.getContext(node, typeSolver)); + for (int i = 0; i < node.getLevels().size(); i++) { + res = new ResolvedArrayType(res); + } + return res; + } + + @Override + public ResolvedType visit(ArrayInitializerExpr node, Boolean solveLambdas) { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + + @Override + public ResolvedType visit(AssignExpr node, Boolean solveLambdas) { + return node.getTarget().accept(this, solveLambdas); + } + + @Override + public ResolvedType visit(BinaryExpr node, Boolean solveLambdas) { + switch (node.getOperator()) { + case PLUS: + case MINUS: + case DIVIDE: + case MULTIPLY: + return facade.getBinaryTypeConcrete(node.getLeft(), node.getRight(), solveLambdas); + case LESS_EQUALS: + case LESS: + case GREATER: + case GREATER_EQUALS: + case EQUALS: + case NOT_EQUALS: + case OR: + case AND: + return ResolvedPrimitiveType.BOOLEAN; + case BINARY_AND: + case BINARY_OR: + case SIGNED_RIGHT_SHIFT: + case UNSIGNED_RIGHT_SHIFT: + case LEFT_SHIFT: + case REMAINDER: + case XOR: + return node.getLeft().accept(this, solveLambdas); + default: + throw new UnsupportedOperationException("Operator " + node.getOperator().name()); + } + } + + @Override + public ResolvedType visit(CastExpr node, Boolean solveLambdas) { + return facade.convertToUsage(node.getType(), JavaParserFactory.getContext(node, typeSolver)); + } + + @Override + public ResolvedType visit(ClassExpr node, Boolean solveLambdas) { + // This implementation does not regard the actual type argument of the ClassExpr. + com.github.javaparser.ast.type.Type astType = node.getType(); + ResolvedType jssType = facade.convertToUsage(astType, node.getType()); + return new ReferenceTypeImpl(new ReflectionClassDeclaration(Class.class, typeSolver), ImmutableList.of(jssType), typeSolver); + } + + @Override + public ResolvedType visit(ConditionalExpr node, Boolean solveLambdas) { + return node.getThenExpr().accept(this, solveLambdas); + } + + @Override + public ResolvedType visit(EnclosedExpr node, Boolean solveLambdas) { + return node.getInner().accept(this, solveLambdas); + } + + /** + * 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()); + } + } + + @Override + public ResolvedType visit(FieldAccessExpr node, Boolean solveLambdas) { + // We should understand if this is a static access + if (node.getScope() instanceof NameExpr || + node.getScope() instanceof FieldAccessExpr) { + Expression staticValue = node.getScope(); + SymbolReference typeAccessedStatically = JavaParserFactory.getContext(node, typeSolver).solveType(staticValue.toString(), typeSolver); + if (typeAccessedStatically.isSolved()) { + // TODO here maybe we have to substitute type typeParametersValues + return solveDotExpressionType( + typeAccessedStatically.getCorrespondingDeclaration().asReferenceType(), node); + } + } else if (node.getScope()instanceof ThisExpr){ + // If we are accessing through a 'this' expression, first resolve the type + // corresponding to 'this' + SymbolReference solve = facade.solve((ThisExpr) node.getScope()); + // If found get it's declaration and get the field in there + if (solve.isSolved()){ + ResolvedTypeDeclaration correspondingDeclaration = solve.getCorrespondingDeclaration(); + if (correspondingDeclaration instanceof ResolvedReferenceTypeDeclaration){ + return solveDotExpressionType(correspondingDeclaration.asReferenceType(), node); + } + } + + } else if (node.getScope().toString().indexOf('.') > 0) { + // try to find fully qualified name + SymbolReference sr = typeSolver.tryToSolveType(node.getScope().toString()); + if (sr.isSolved()) { + return solveDotExpressionType(sr.getCorrespondingDeclaration(), node); + } + } + Optional value = null; + try { + value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getField().getId(), node); + } catch (UnsolvedSymbolException use) { + // This node may have a package name as part of its fully qualified name. + // We should solve for the type declaration inside this package. + SymbolReference sref = typeSolver.tryToSolveType(node.toString()); + if (sref.isSolved()) { + return new ReferenceTypeImpl(sref.getCorrespondingDeclaration(), typeSolver); + } + } + if (value != null && value.isPresent()) { + return value.get().getType(); + } else { + throw new UnsolvedSymbolException(node.getField().getId()); + } + } + + @Override + public ResolvedType visit(InstanceOfExpr node, Boolean solveLambdas) { + return ResolvedPrimitiveType.BOOLEAN; + } + + @Override + public ResolvedType visit(StringLiteralExpr node, Boolean solveLambdas) { + return new ReferenceTypeImpl(new ReflectionTypeSolver().solveType(String.class.getCanonicalName()), typeSolver); + } + + @Override + public ResolvedType visit(IntegerLiteralExpr node, Boolean solveLambdas) { + return ResolvedPrimitiveType.INT; + } + + @Override + public ResolvedType visit(LongLiteralExpr node, Boolean solveLambdas) { + return ResolvedPrimitiveType.LONG; + } + + @Override + public ResolvedType visit(CharLiteralExpr node, Boolean solveLambdas) { + return ResolvedPrimitiveType.CHAR; + } + + @Override + public ResolvedType visit(DoubleLiteralExpr node, Boolean solveLambdas) { + if (node.getValue().toLowerCase().endsWith("f")) { + return ResolvedPrimitiveType.FLOAT; + } + return ResolvedPrimitiveType.DOUBLE; + } + + @Override + public ResolvedType visit(BooleanLiteralExpr node, Boolean solveLambdas) { + return ResolvedPrimitiveType.BOOLEAN; + } + + @Override + public ResolvedType visit(NullLiteralExpr node, Boolean solveLambdas) { + return NullType.INSTANCE; + } + + @Override + public ResolvedType visit(MethodCallExpr node, Boolean solveLambdas) { + logger.finest("getType on method call " + node); + // first solve the method + MethodUsage ref = facade.solveMethodAsUsage(node); + logger.finest("getType on method call " + node + " resolved to " + ref); + logger.finest("getType on method call " + node + " return type is " + ref.returnType()); + return ref.returnType(); + // the type is the return type of the method + } + + @Override + public ResolvedType visit(NameExpr node, Boolean solveLambdas) { + logger.finest("getType on name expr " + node); + Optional value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node); + if (!value.isPresent()) { + throw new UnsolvedSymbolException("Solving " + node, node.getName().getId()); + } else { + return value.get().getType(); + } + } + + @Override + public ResolvedType visit(ObjectCreationExpr node, Boolean solveLambdas) { + ResolvedType type = facade.convertToUsage(node.getType(), node); + return type; + } + + @Override + public ResolvedType visit(ThisExpr node, Boolean solveLambdas) { + // If 'this' is prefixed by a class eg. MyClass.this + if (node.getClassExpr().isPresent()){ + // Get the class name + String className = node.getClassExpr().get().toString(); + // Attempt to resolve using a typeSolver + SymbolReference clazz = typeSolver.tryToSolveType(className); + if (clazz.isSolved()){ + return new ReferenceTypeImpl(clazz.getCorrespondingDeclaration(),typeSolver); + } + // Attempt to resolve locally in Compilation unit + Optional cu = node.getAncestorOfType(CompilationUnit.class); + if (cu.isPresent()){ + Optional classByName = cu.get().getClassByName(className); + if (classByName.isPresent()){ + return new ReferenceTypeImpl(facade.getTypeDeclaration(classByName.get()), typeSolver); + } + } + + } + return new ReferenceTypeImpl(facade.getTypeDeclaration(facade.findContainingTypeDeclOrObjectCreationExpr(node)), typeSolver); + } + + @Override + public ResolvedType visit(SuperExpr node, Boolean solveLambdas) { + ResolvedTypeDeclaration typeOfNode = facade.getTypeDeclaration(facade.findContainingTypeDecl(node)); + if (typeOfNode instanceof ResolvedClassDeclaration) { + return ((ResolvedClassDeclaration) typeOfNode).getSuperClass(); + } else { + throw new UnsupportedOperationException(node.getClass().getCanonicalName()); + } + } + + @Override + public ResolvedType visit(UnaryExpr node, Boolean solveLambdas) { + switch (node.getOperator()) { + case MINUS: + case PLUS: + return node.getExpression().accept(this, solveLambdas); + case LOGICAL_COMPLEMENT: + return ResolvedPrimitiveType.BOOLEAN; + case POSTFIX_DECREMENT: + case PREFIX_DECREMENT: + case POSTFIX_INCREMENT: + case PREFIX_INCREMENT: + return node.getExpression().accept(this, solveLambdas); + default: + throw new UnsupportedOperationException(node.getOperator().name()); + } + } + + @Override + public ResolvedType visit(VariableDeclarationExpr node, Boolean solveLambdas) { + if (node.getVariables().size() != 1) { + throw new UnsupportedOperationException(); + } + return facade.convertToUsageVariableType(node.getVariables().get(0)); + } + + + @Override + public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) { + if (getParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node); + int pos = JavaParserSymbolDeclaration.getParamPos(node); + SymbolReference refMethod = facade.solve(callExpr); + if (!refMethod.isSolved()) { + throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId()); + } + logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName()); + if (solveLambdas) { + + // The type parameter referred here should be the java.util.stream.Stream.T + ResolvedType result = refMethod.getCorrespondingDeclaration().getParam(pos).getType(); + + if (callExpr.getScope().isPresent()) { + Expression scope = callExpr.getScope().get(); + + // If it is a static call we should not try to get the type of the scope + boolean staticCall = false; + if (scope instanceof NameExpr) { + NameExpr nameExpr = (NameExpr) scope; + try { + SymbolReference type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver); + if (type.isSolved()){ + staticCall = true; + } + } catch (Exception e) { + + } + } + + if (!staticCall) { + ResolvedType scopeType = facade.getType(scope); + if (scopeType.isReferenceType()) { + result = scopeType.asReferenceType().useThisTypeParametersOnTheGivenType(result); + } + } + } + + // We need to replace the type variables + Context ctx = JavaParserFactory.getContext(node, typeSolver); + result = facade.solveGenericTypes(result, ctx, typeSolver); + + //We should find out which is the functional method (e.g., apply) and replace the params of the + //solveLambdas with it, to derive so the values. We should also consider the value returned by the + //lambdas + Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result); + if (functionalMethod.isPresent()) { + LambdaExpr lambdaExpr = node; + + InferenceContext lambdaCtx = new InferenceContext(MyObjectProvider.INSTANCE); + InferenceContext funcInterfaceCtx = new InferenceContext(MyObjectProvider.INSTANCE); + + // At this point parameterType + // if Function + // we should replace Stream.T + ResolvedType functionalInterfaceType = ReferenceTypeImpl.undeterminedParameters(functionalMethod.get().getDeclaration().declaringType(), typeSolver); + + lambdaCtx.addPair(result, functionalInterfaceType); + + ResolvedType actualType; + + if (lambdaExpr.getBody() instanceof ExpressionStmt) { + actualType = facade.getType(((ExpressionStmt)lambdaExpr.getBody()).getExpression()); + } else if (lambdaExpr.getBody() instanceof BlockStmt) { + BlockStmt blockStmt = (BlockStmt) lambdaExpr.getBody(); + NodeList statements = blockStmt.getStatements(); + + // Get all the return statements in the lambda block + List returnStmts = blockStmt.getNodesByType(ReturnStmt.class); + + if (returnStmts.size() > 0){ + + actualType = returnStmts.stream() + .map(returnStmt -> { + Optional expression = returnStmt.getExpression(); + if (expression.isPresent()){ + return facade.getType(expression.get()); + } else{ + return ResolvedVoidType.INSTANCE; + } + }) + .filter(x -> x != null && !x.isVoid() && !x.isNull()) + .findFirst() + .orElse(ResolvedVoidType.INSTANCE); + + } else { + return ResolvedVoidType.INSTANCE; + } + + + } else { + throw new UnsupportedOperationException(); + } + + ResolvedType formalType = functionalMethod.get().returnType(); + + // Infer the functional interfaces' return vs actual type + funcInterfaceCtx.addPair(formalType, actualType); + // Substitute to obtain a new type + ResolvedType functionalTypeWithReturn = funcInterfaceCtx.resolve(funcInterfaceCtx.addSingle(functionalInterfaceType)); + + // if the functional method returns void anyway + // we don't need to bother inferring types + if (!(formalType instanceof ResolvedVoidType)){ + lambdaCtx.addPair(result, functionalTypeWithReturn); + result = lambdaCtx.resolve(lambdaCtx.addSingle(result)); + } + } + + return result; + } else { + return refMethod.getCorrespondingDeclaration().getParam(pos).getType(); + } + } else { + throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value"); + } + } + + @Override + public ResolvedType visit(MethodReferenceExpr node, Boolean solveLambdas) { + if (getParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node); + int pos = JavaParserSymbolDeclaration.getParamPos(node); + SymbolReference refMethod = facade.solve(callExpr, false); + if (!refMethod.isSolved()) { + throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId()); + } + logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName()); + //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos)); + if (solveLambdas) { + MethodUsage usage = facade.solveMethodAsUsage(callExpr); + ResolvedType result = usage.getParamType(pos); + // We need to replace the type variables + Context ctx = JavaParserFactory.getContext(node, typeSolver); + result = facade.solveGenericTypes(result, ctx, typeSolver); + + //We should find out which is the functional method (e.g., apply) and replace the params of the + //solveLambdas with it, to derive so the values. We should also consider the value returned by the + //lambdas + Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result); + if (functionalMethod.isPresent()) { + if (node instanceof MethodReferenceExpr) { + MethodReferenceExpr methodReferenceExpr = (MethodReferenceExpr) node; + + ResolvedType actualType = facade.toMethodUsage(methodReferenceExpr).returnType(); + ResolvedType formalType = functionalMethod.get().returnType(); + + InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE); + inferenceContext.addPair(formalType, actualType); + result = inferenceContext.resolve(inferenceContext.addSingle(result)); + } + } + + return result; + } else { + return refMethod.getCorrespondingDeclaration().getParam(pos).getType(); + } + } else { + throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value"); + } + } + + @Override + public ResolvedType visit(FieldDeclaration node, Boolean solveLambdas) { + if (node.getVariables().size() == 1) { + return node.getVariables().get(0).accept(this, solveLambdas); + } else { + throw new IllegalArgumentException("Cannot resolve the type of a field with multiple variable declarations. Pick one"); + } + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java new file mode 100644 index 000000000..21dcf7c9e --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java @@ -0,0 +1,67 @@ +/* + * 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; + +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +/** + * @author Federico Tomassetti + * + * @deprecated Use {@link com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException} instead + */ +// Use the one in model instead +@Deprecated +public class UnsolvedSymbolException extends RuntimeException { + + private String context; + private String name; + private TypeSolver typeSolver; + + public UnsolvedSymbolException(String name, TypeSolver typeSolver) { + super("Unsolved symbol : " + name + " using typesolver " + typeSolver); + this.typeSolver = typeSolver; + this.name = name; + } + + public UnsolvedSymbolException(Context context, String name) { + super("Unsolved symbol in " + context + " : " + name); + this.context = context.toString(); + this.name = name; + } + + public UnsolvedSymbolException(String context, String name) { + super("Unsolved symbol in " + context + " : " + name); + this.context = context; + this.name = name; + } + + public UnsolvedSymbolException(String name) { + super("Unsolved symbol : " + name); + this.context = "unknown"; + this.name = name; + } + + @Override + public String toString() { + return "UnsolvedSymbolException{" + + "context='" + context + '\'' + + ", name='" + name + '\'' + + ", typeSolver=" + typeSolver + + '}'; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java new file mode 100644 index 000000000..e2f348ce1 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java @@ -0,0 +1,196 @@ +/* + * 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.Node; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.FieldAccessExpr; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +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.javaparsermodel.JavaParserFacade; +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.resolution.Value; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public abstract class AbstractJavaParserContext implements Context { + + protected N wrappedNode; + protected TypeSolver typeSolver; + + /// + /// Static methods + /// + + public static final SymbolReference solveWith(SymbolDeclarator symbolDeclarator, String name) { + for (ResolvedValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) { + if (decl.getName().equals(name)) { + return SymbolReference.solved(decl); + } + } + return SymbolReference.unsolved(ResolvedValueDeclaration.class); + } + + /// + /// Constructors + /// + + public AbstractJavaParserContext(N wrappedNode, TypeSolver typeSolver) { + if (wrappedNode == null) { + throw new NullPointerException(); + } + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } + + /// + /// Public methods + /// + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AbstractJavaParserContext that = (AbstractJavaParserContext) o; + + if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false; + + return true; + } + + @Override + public int hashCode() { + return wrappedNode != null ? wrappedNode.hashCode() : 0; + } + + @Override + public Optional solveGenericType(String name, TypeSolver typeSolver) { + Context parent = getParent(); + if (parent == null) { + return Optional.empty(); + } else { + return parent.solveGenericType(name, typeSolver); + } + } + + @Override + public final Context getParent() { + if (getParentNode(wrappedNode) instanceof MethodCallExpr) { + MethodCallExpr parentCall = (MethodCallExpr) getParentNode(wrappedNode); + boolean found = false; + if (parentCall.getArguments() != null) { + for (Expression expression : parentCall.getArguments()) { + if (expression == wrappedNode) { + found = true; + } + } + } + if (found) { + Node notMethod = getParentNode(wrappedNode); + while (notMethod instanceof MethodCallExpr) { + notMethod = getParentNode(notMethod); + } + return JavaParserFactory.getContext(notMethod, typeSolver); + } + } + Node notMethod = getParentNode(wrappedNode); + while (notMethod instanceof MethodCallExpr || notMethod instanceof FieldAccessExpr) { + notMethod = getParentNode(notMethod); + } + if (notMethod == null) { + return null; + } + return JavaParserFactory.getContext(notMethod, typeSolver); + } + + /// + /// Protected methods + /// + + protected Optional solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) { + return symbolDeclarator.getSymbolDeclarations().stream() + .filter(d -> d.getName().equals(name)) + .map(d -> Value.from(d)) + .findFirst(); + } + + protected Collection findTypeDeclarations(Optional optScope, TypeSolver typeSolver) { + if (optScope.isPresent()) { + Expression scope = optScope.get(); + + // consider static methods + if (scope instanceof NameExpr) { + NameExpr scopeAsName = (NameExpr) scope; + SymbolReference symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver); + if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) { + return Arrays.asList(symbolReference.getCorrespondingDeclaration().asReferenceType()); + } + } + + ResolvedType typeOfScope = null; + try { + typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); + } catch (Exception e) { + throw new RuntimeException(String.format("Issue calculating the type of the scope of " + this), e); + } + if (typeOfScope.isWildcard()) { + if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) { + return Arrays.asList(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration()); + } else { + return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + } + } else if (typeOfScope.isArray()) { + // method call on array are Object methods + return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + } else if (typeOfScope.isTypeVariable()) { + Collection result = new ArrayList<>(); + for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { + result.add(bound.getType().asReferenceType().getTypeDeclaration()); + } + return result; + } else if (typeOfScope.isConstraint()){ + return Arrays.asList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration()); + } else { + return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + } + } else { + ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); + return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + } + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java new file mode 100644 index 000000000..4e7b760bd --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java @@ -0,0 +1,101 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.contexts; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.Parameter; +import com.github.javaparser.ast.nodeTypes.NodeWithParameters; +import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +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.resolution.types.ResolvedTypeVariable; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +import java.util.List; +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public abstract class AbstractMethodLikeDeclarationContext + & NodeWithTypeParameters> extends AbstractJavaParserContext { + + public AbstractMethodLikeDeclarationContext(T wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + public final SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + for (Parameter parameter : wrappedNode.getParameters()) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver); + SymbolReference symbolReference = AbstractJavaParserContext.solveWith(sb, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public final Optional solveGenericType(String name, TypeSolver typeSolver) { + for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) { + if (tp.getName().getId().equals(name)) { + return Optional.of(new ResolvedTypeVariable(new JavaParserTypeParameter(tp, typeSolver))); + } + } + return super.solveGenericType(name, typeSolver); + } + + @Override + public final Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + for (Parameter parameter : wrappedNode.getParameters()) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver); + Optional symbolReference = solveWithAsValue(sb, name, typeSolver); + if (symbolReference.isPresent()) { + // Perform parameter type substitution as needed + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbolAsValue(name, typeSolver); + } + + @Override + public final SymbolReference solveType(String name, TypeSolver typeSolver) { + if (wrappedNode.getTypeParameters() != null) { + for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) { + if (tp.getName().getId().equals(name)) { + return SymbolReference.solved(new JavaParserTypeParameter(tp, typeSolver)); + } + } + } + + // Local types + List localTypes = wrappedNode.getChildNodesByType( + com.github.javaparser.ast.body.TypeDeclaration.class); + for (com.github.javaparser.ast.body.TypeDeclaration localType : localTypes) { + if (localType.getName().getId().equals(name)) { + return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(localType)); + } else if (name.startsWith(String.format("%s.", localType.getName()))) { + return JavaParserFactory.getContext(localType, typeSolver).solveType( + name.substring(localType.getName().getId().length() + 1), typeSolver); + } + } + + return getParent().solveType(name, typeSolver); + } + + @Override + public final SymbolReference solveMethod( + String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java new file mode 100644 index 000000000..48133596a --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java @@ -0,0 +1,186 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.contexts; + +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.expr.ObjectCreationExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +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.declarations + .JavaParserAnonymousClassDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic; +import com.google.common.base.Preconditions; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * A symbol resolution context for an object creation node. + */ +public class AnonymousClassDeclarationContext extends AbstractJavaParserContext { + + private final JavaParserAnonymousClassDeclaration myDeclaration = + new JavaParserAnonymousClassDeclaration(wrappedNode, typeSolver); + + public AnonymousClassDeclarationContext(ObjectCreationExpr node, TypeSolver typeSolver) { + super(node, typeSolver); + Preconditions.checkArgument(node.getAnonymousClassBody().isPresent(), + "An anonymous class must have a body"); + } + + @Override + public SymbolReference solveMethod(String name, + List argumentsTypes, + boolean staticOnly, + TypeSolver typeSolver) { + List candidateMethods = + myDeclaration + .getDeclaredMethods() + .stream() + .filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic())) + .collect(Collectors.toList()); + + if (!Object.class.getCanonicalName().equals(myDeclaration.getQualifiedName())) { + for (ResolvedReferenceType ancestor : myDeclaration.getAncestors()) { + SymbolReference res = + MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), + name, + argumentsTypes, + staticOnly, + typeSolver); + // consider methods from superclasses and only default methods from interfaces : + // not true, we should keep abstract as a valid candidate + // abstract are removed in MethodResolutionLogic.isApplicable is necessary + if (res.isSolved()) { + candidateMethods.add(res.getCorrespondingDeclaration()); + } + } + } + + // We want to avoid infinite recursion when a class is using its own method + // see issue #75 + if (candidateMethods.isEmpty()) { + SymbolReference parentSolution = + getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver); + if (parentSolution.isSolved()) { + candidateMethods.add(parentSolution.getCorrespondingDeclaration()); + } + } + + // if is interface and candidate method list is empty, we should check the Object Methods + if (candidateMethods.isEmpty() && myDeclaration.getSuperTypeDeclaration().isInterface()) { + SymbolReference res = + MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, + typeSolver), + name, + argumentsTypes, + false, + typeSolver); + if (res.isSolved()) { + candidateMethods.add(res.getCorrespondingDeclaration()); + } + } + + return MethodResolutionLogic.findMostApplicable(candidateMethods, + name, + argumentsTypes, + typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + List typeDeclarations = + myDeclaration + .findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class); + + Optional> exactMatch = + typeDeclarations + .stream() + .filter(internalType -> internalType.getName().getId().equals(name)) + .findFirst() + .map(internalType -> + SymbolReference.solved( + JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType))); + + if(exactMatch.isPresent()){ + return exactMatch.get(); + } + + Optional> recursiveMatch = + typeDeclarations + .stream() + .filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))) + .findFirst() + .map(internalType -> + JavaParserFactory + .getContext(internalType, typeSolver) + .solveType(name.substring(internalType.getName().getId().length() + 1), + typeSolver)); + + if (recursiveMatch.isPresent()) { + return recursiveMatch.get(); + } + + Optional> typeArgumentsMatch = + wrappedNode + .getTypeArguments() + .map(nodes -> + ((NodeWithTypeArguments) nodes).getTypeArguments() + .orElse(new NodeList<>())) + .orElse(new NodeList<>()) + .stream() + .filter(type -> type.toString().equals(name)) + .findFirst() + .map(matchingType -> + SymbolReference.solved( + new JavaParserTypeParameter(new TypeParameter(matchingType.toString()), + typeSolver))); + + if (typeArgumentsMatch.isPresent()) { + return typeArgumentsMatch.get(); + } + + // Look into extended classes and implemented interfaces + for (ResolvedReferenceType ancestor : myDeclaration.getAncestors()) { + // look at names of extended classes and implemented interfaces (this may not be important because they are checked in CompilationUnitContext) + if (ancestor.getTypeDeclaration().getName().equals(name)) { + return SymbolReference.solved(ancestor.getTypeDeclaration()); + } + // look into internal types of extended classes and implemented interfaces + try { + for (ResolvedTypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) { + if (internalTypeDeclaration.getName().equals(name)) { + return SymbolReference.solved(internalTypeDeclaration); + } + } + } catch (UnsupportedOperationException e) { + // just continue using the next ancestor + } + } + + return getParent().solveType(name, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, + TypeSolver typeSolver) { + Preconditions.checkArgument(typeSolver != null); + + if (myDeclaration.hasVisibleField(name)) { + return SymbolReference.solved(myDeclaration.getVisibleField(name)); + } + + return getParent().solveSymbol(name, typeSolver); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java new file mode 100644 index 000000000..4683f272a --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java @@ -0,0 +1,54 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.contexts; + +import com.github.javaparser.ast.stmt.CatchClause; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +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.resolution.Value; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +import java.util.List; +import java.util.Optional; + +/** + * @author Fred Lefévère-Laoide + */ +public class CatchClauseContext extends AbstractJavaParserContext { + + public CatchClauseContext(CatchClause wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + public final SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver); + SymbolReference symbolReference = AbstractJavaParserContext.solveWith(sb, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public final Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver); + Optional symbolReference = solveWithAsValue(sb, name, typeSolver); + if (symbolReference.isPresent()) { + // Perform parameter type substitution as needed + return symbolReference; + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbolAsValue(name, typeSolver); + } + + @Override + public final SymbolReference solveMethod( + String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java new file mode 100644 index 000000000..01f4b050c --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java @@ -0,0 +1,109 @@ +/* + * 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.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedTypeVariable; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; + +import java.util.List; +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public class ClassOrInterfaceDeclarationContext extends AbstractJavaParserContext { + + private JavaParserTypeDeclarationAdapter javaParserTypeDeclarationAdapter; + + /// + /// Constructors + /// + + public ClassOrInterfaceDeclarationContext(ClassOrInterfaceDeclaration wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + this.javaParserTypeDeclarationAdapter = new JavaParserTypeDeclarationAdapter(wrappedNode, typeSolver, + getDeclaration(), this); + } + + /// + /// Public methods + /// + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + if (typeSolver == null) throw new IllegalArgumentException(); + + if (this.getDeclaration().hasVisibleField(name)) { + return SymbolReference.solved(this.getDeclaration().getVisibleField(name)); + } + + // then to parent + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + if (typeSolver == null) throw new IllegalArgumentException(); + + if (this.getDeclaration().hasVisibleField(name)) { + return Optional.of(Value.from(this.getDeclaration().getVisibleField(name))); + } + + // then to parent + return getParent().solveSymbolAsValue(name, typeSolver); + } + + @Override + public Optional solveGenericType(String name, TypeSolver typeSolver) { + for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) { + if (tp.getName().getId().equals(name)) { + return Optional.of(new ResolvedTypeVariable(new JavaParserTypeParameter(tp, typeSolver))); + } + } + return getParent().solveGenericType(name, typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + return javaParserTypeDeclarationAdapter.solveType(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver); + } + + public SymbolReference solveConstructor(List argumentsTypes, TypeSolver typeSolver) { + return javaParserTypeDeclarationAdapter.solveConstructor(argumentsTypes, typeSolver); + } + + /// + /// Private methods + /// + + private ResolvedReferenceTypeDeclaration getDeclaration() { + return JavaParserFacade.get(typeSolver).getTypeDeclaration(this.wrappedNode); + } +} 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 { + + /// + /// 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 solveSymbol(String name, TypeSolver typeSolver) { + + // solve absolute references + String itName = name; + while (itName.contains(".")) { + String typeName = getType(itName); + String memberName = getMember(itName); + SymbolReference 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 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 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 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 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 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 ref = typeSolver.tryToSolveType(qName); + if (ref.isSolved()) { + return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class); + } + } + + // Look in the java.lang package + SymbolReference 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 solveMethod(String name, List 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 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 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; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java new file mode 100644 index 000000000..bebaa7313 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java @@ -0,0 +1,35 @@ +/* + * 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.body.ConstructorDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +/** + * @author Federico Tomassetti + */ +public class ConstructorContext extends AbstractMethodLikeDeclarationContext { + + /// + /// Constructors + /// + + public ConstructorContext(ConstructorDeclaration wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java new file mode 100644 index 000000000..e0eda24b0 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java @@ -0,0 +1,74 @@ +/* + * 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.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration; +import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration; +import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration; +import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration; + +import java.util.List; +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public class ContextHelper { + + private ContextHelper() { + // prevent instantiation + } + + public static Optional solveMethodAsUsage(ResolvedTypeDeclaration typeDeclaration, String name, + List argumentsTypes, TypeSolver typeSolver, + Context invokationContext, List typeParameters) { + if (typeDeclaration instanceof JavassistClassDeclaration) { + return ((JavassistClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof JavassistInterfaceDeclaration) { + return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof JavassistEnumDeclaration) { + return ((JavassistEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof ReflectionClassDeclaration) { + return ((ReflectionClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof ReflectionInterfaceDeclaration) { + return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof ReflectionEnumDeclaration) { + return ((ReflectionEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters); + } else if (typeDeclaration instanceof JavaParserClassDeclaration) { + return ((JavaParserClassDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver); + } else if (typeDeclaration instanceof JavaParserInterfaceDeclaration) { + return ((JavaParserInterfaceDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver); + } else if (typeDeclaration instanceof JavaParserEnumDeclaration) { + return ((JavaParserEnumDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver); + } else if (typeDeclaration instanceof JavaParserAnonymousClassDeclaration) { + return ((JavaParserAnonymousClassDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver); + } + throw new UnsupportedOperationException(typeDeclaration.toString()); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java new file mode 100644 index 000000000..7f2365fe7 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.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.contexts; + +import com.github.javaparser.ast.body.EnumConstantDeclaration; +import com.github.javaparser.ast.body.EnumDeclaration; +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.declarations.JavaParserEnumConstantDeclaration; +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 java.util.List; + +/** + * @author Federico Tomassetti + */ +public class EnumDeclarationContext extends AbstractJavaParserContext { + + private JavaParserTypeDeclarationAdapter javaParserTypeDeclarationAdapter; + + public EnumDeclarationContext(EnumDeclaration wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + this.javaParserTypeDeclarationAdapter = new JavaParserTypeDeclarationAdapter(wrappedNode, typeSolver, + getDeclaration(), this); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + 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, typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + return javaParserTypeDeclarationAdapter.solveType(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver); + } + + /// + /// Private methods + /// + + private ResolvedReferenceTypeDeclaration getDeclaration() { + return new JavaParserEnumDeclaration(this.wrappedNode, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java new file mode 100644 index 000000000..860fe6bc4 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java @@ -0,0 +1,108 @@ +/* + * 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.expr.Expression; +import com.github.javaparser.ast.expr.FieldAccessExpr; +import com.github.javaparser.ast.expr.ThisExpr; +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.declarations.ResolvedFieldDeclaration; +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.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.resolution.SymbolSolver; + +import java.util.Collection; +import java.util.List; +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 FieldAccessContext extends AbstractJavaParserContext { + + private static final String ARRAY_LENGTH_FIELD_NAME = "length"; + + public FieldAccessContext(FieldAccessExpr wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + if (wrappedNode.getField().toString().equals(name)) { + if (wrappedNode.getScope() instanceof ThisExpr) { + ResolvedType typeOfThis = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); + return new SymbolSolver(typeSolver).solveSymbolInType(typeOfThis.asReferenceType().getTypeDeclaration(), name); + } + } + return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveSymbol(name, typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveType(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List parameterTypes, boolean staticOnly, TypeSolver typeSolver) { + return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveMethod(name, parameterTypes, false, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + Expression scope = wrappedNode.getScope(); + if (wrappedNode.getField().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()) { + Optional typeUsage = typeOfScope.asReferenceType().getFieldType(name); + if (typeUsage.isPresent()) { + return Optional.of(new Value(typeUsage.get(), name)); + } else { + return Optional.empty(); + } + } else { + return Optional.empty(); + } + } else { + return getParent().solveSymbolAsValue(name, typeSolver); + } + } + + public SymbolReference solveField(String name, TypeSolver typeSolver) { + Collection rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope()), typeSolver); + for (ResolvedReferenceTypeDeclaration rrtd : rrtds) { + try { + return SymbolReference.solved(rrtd.getField(wrappedNode.getName().getId())); + } catch (Throwable t) { + } + } + return SymbolReference.unsolved(ResolvedFieldDeclaration.class); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java new file mode 100644 index 000000000..77965bd08 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java @@ -0,0 +1,70 @@ +/* + * 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.body.VariableDeclarator; +import com.github.javaparser.ast.expr.AssignExpr; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.VariableDeclarationExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithStatements; +import com.github.javaparser.ast.stmt.ForStmt; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.List; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +public class ForStatementContext extends AbstractJavaParserContext { + + public ForStatementContext(ForStmt wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + for (Expression expression : wrappedNode.getInitialization()) { + if (expression instanceof VariableDeclarationExpr) { + VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr) expression; + for (VariableDeclarator variableDeclarator : variableDeclarationExpr.getVariables()) { + if (variableDeclarator.getName().getId().equals(name)) { + return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver)); + } + } + } else if (!(expression instanceof AssignExpr || expression instanceof MethodCallExpr)) { + throw new UnsupportedOperationException(expression.getClass().getCanonicalName()); + } + } + + if (getParentNode(wrappedNode) instanceof NodeWithStatements) { + return StatementContext.solveInBlock(name, typeSolver, wrappedNode); + } else { + return getParent().solveSymbol(name, typeSolver); + } + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, + boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java new file mode 100644 index 000000000..ed874899f --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java @@ -0,0 +1,61 @@ +/* + * 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.body.VariableDeclarator; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ForeachStmt; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.List; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +public class ForechStatementContext extends AbstractJavaParserContext { + + public ForechStatementContext(ForeachStmt wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + if (wrappedNode.getVariable().getVariables().size() != 1) { + throw new IllegalStateException(); + } + VariableDeclarator variableDeclarator = wrappedNode.getVariable().getVariables().get(0); + if (variableDeclarator.getName().getId().equals(name)) { + return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver)); + } else { + if (getParentNode(wrappedNode) instanceof BlockStmt) { + return StatementContext.solveInBlock(name, typeSolver, wrappedNode); + } else { + return getParent().solveSymbol(name, typeSolver); + } + } + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, + boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java new file mode 100644 index 000000000..993f42d29 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java @@ -0,0 +1,133 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.contexts; + +import com.github.javaparser.ast.body.BodyDeclaration; +import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.reflectionmodel.*; +import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic; +import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public class JavaParserTypeDeclarationAdapter { + + private com.github.javaparser.ast.body.TypeDeclaration wrappedNode; + private TypeSolver typeSolver; + private Context context; + private ResolvedReferenceTypeDeclaration typeDeclaration; + + public JavaParserTypeDeclarationAdapter(com.github.javaparser.ast.body.TypeDeclaration wrappedNode, TypeSolver typeSolver, + ResolvedReferenceTypeDeclaration typeDeclaration, + Context context) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + this.typeDeclaration = typeDeclaration; + this.context = context; + } + + public SymbolReference solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getName().getId().equals(name)) { + return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(wrappedNode)); + } + + // Internal classes + for (BodyDeclaration member : this.wrappedNode.getMembers()) { + if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) { + com.github.javaparser.ast.body.TypeDeclaration internalType = (com.github.javaparser.ast.body.TypeDeclaration) member; + if (internalType.getName().getId().equals(name)) { + return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType)); + } else if (name.startsWith(String.format("%s.%s", wrappedNode.getName(), internalType.getName()))) { + return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1), typeSolver); + } else if (name.startsWith(String.format("%s.", internalType.getName()))) { + return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver); + } + } + } + + if (wrappedNode instanceof NodeWithTypeParameters) { + NodeWithTypeParameters nodeWithTypeParameters = (NodeWithTypeParameters) wrappedNode; + for (TypeParameter astTpRaw : nodeWithTypeParameters.getTypeParameters()) { + TypeParameter astTp = astTpRaw; + if (astTp.getName().getId().equals(name)) { + return SymbolReference.solved(new JavaParserTypeParameter(astTp, typeSolver)); + } + } + } + + // Look into extended classes and implemented interfaces + for (ResolvedReferenceType ancestor : this.typeDeclaration.getAncestors()) { + try { + for (ResolvedTypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) { + if (internalTypeDeclaration.getName().equals(name)) { + return SymbolReference.solved(internalTypeDeclaration); + } + } + } catch (UnsupportedOperationException e) { + // just continue using the next ancestor + } + } + + return context.getParent().solveType(name, typeSolver); + } + + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + List candidateMethods = typeDeclaration.getDeclaredMethods().stream() + .filter(m -> m.getName().equals(name)) + .filter(m -> !staticOnly || (staticOnly && m.isStatic())) + .collect(Collectors.toList()); + // We want to avoid infinite recursion in case of Object having Object as ancestor + if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) { + for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors()) { + // Avoid recursion on self + if (typeDeclaration != ancestor.getTypeDeclaration()) { + SymbolReference res = MethodResolutionLogic + .solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver); + // consider methods from superclasses and only default methods from interfaces : + // not true, we should keep abstract as a valid candidate + // abstract are removed in MethodResolutionLogic.isApplicable is necessary + if (res.isSolved()) { + candidateMethods.add(res.getCorrespondingDeclaration()); + } + } + } + } + // We want to avoid infinite recursion when a class is using its own method + // see issue #75 + if (candidateMethods.isEmpty()) { + SymbolReference parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver); + if (parentSolution.isSolved()) { + candidateMethods.add(parentSolution.getCorrespondingDeclaration()); + } + } + + // if is interface and candidate method list is empty, we should check the Object Methods + if (candidateMethods.isEmpty() && typeDeclaration.isInterface()) { + SymbolReference res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver); + if (res.isSolved()) { + candidateMethods.add(res.getCorrespondingDeclaration()); + } + } + + return MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver); + } + + public SymbolReference solveConstructor(List argumentsTypes, TypeSolver typeSolver) { + if (typeDeclaration instanceof ResolvedClassDeclaration) { + return ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) typeDeclaration).getConstructors(), argumentsTypes, typeSolver); + } + return SymbolReference.unsolved(ResolvedConstructorDeclaration.class); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java new file mode 100644 index 000000000..fe2ec8ba9 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java @@ -0,0 +1,194 @@ +/* + * 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.body.Parameter; +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.LambdaExpr; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedLambdaConstraintType; +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.logic.FunctionalInterfaceLogic; +import com.github.javaparser.symbolsolver.logic.InferenceContext; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; +import javassist.compiler.ast.Pair; + +import java.util.*; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class LambdaExprContext extends AbstractJavaParserContext { + + public LambdaExprContext(LambdaExpr wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + for (Parameter parameter : wrappedNode.getParameters()) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver); + int index = 0; + for (ResolvedValueDeclaration decl : sb.getSymbolDeclarations()) { + if (decl.getName().equals(name)) { + if (getParentNode(wrappedNode) instanceof MethodCallExpr) { + MethodCallExpr methodCallExpr = (MethodCallExpr) getParentNode(wrappedNode); + MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(methodCallExpr); + int i = pos(methodCallExpr, wrappedNode); + ResolvedType lambdaType = methodUsage.getParamTypes().get(i); + + // Get the functional method in order for us to resolve it's type arguments properly + Optional functionalMethodOpt = FunctionalInterfaceLogic.getFunctionalMethod(lambdaType); + if (functionalMethodOpt.isPresent()){ + MethodUsage functionalMethod = functionalMethodOpt.get(); + InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE); + + // Resolve each type variable of the lambda, and use this later to infer the type of each + // implicit parameter + inferenceContext.addPair(lambdaType, new ReferenceTypeImpl(lambdaType.asReferenceType().getTypeDeclaration(), typeSolver)); + + // Find the position of this lambda argument + boolean found = false; + int lambdaParamIndex; + for (lambdaParamIndex = 0; lambdaParamIndex < wrappedNode.getParameters().size(); lambdaParamIndex++){ + if (wrappedNode.getParameter(lambdaParamIndex).getName().getIdentifier().equals(name)){ + found = true; + break; + } + } + if (!found) { return Optional.empty(); } + + // Now resolve the argument type using the inference context + ResolvedType argType = inferenceContext.resolve(inferenceContext.addSingle(functionalMethod.getParamType(lambdaParamIndex))); + + ResolvedLambdaConstraintType conType; + if (argType.isWildcard()){ + conType = ResolvedLambdaConstraintType.bound(argType.asWildcard().getBoundedType()); + } else { + conType = ResolvedLambdaConstraintType.bound(argType); + } + Value value = new Value(conType, name); + return Optional.of(value); + } else{ + return Optional.empty(); + } + } else if (getParentNode(wrappedNode) instanceof VariableDeclarator) { + VariableDeclarator variableDeclarator = (VariableDeclarator) getParentNode(wrappedNode); + ResolvedType t = JavaParserFacade.get(typeSolver).convertToUsageVariableType(variableDeclarator); + Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t); + if (functionalMethod.isPresent()) { + ResolvedType lambdaType = functionalMethod.get().getParamType(index); + + // Replace parameter from declarator + Map inferredTypes = new HashMap<>(); + if (lambdaType.isReferenceType()) { + for (com.github.javaparser.utils.Pair entry : lambdaType.asReferenceType().getTypeParametersMap()) { + if (entry.b.isTypeVariable() && entry.b.asTypeParameter().declaredOnType()) { + ResolvedType ot = t.asReferenceType().typeParametersMap().getValue(entry.a); + lambdaType = lambdaType.replaceTypeVariables(entry.a, ot, inferredTypes); + } + } + } else if (lambdaType.isTypeVariable() && lambdaType.asTypeParameter().declaredOnType()) { + lambdaType = t.asReferenceType().typeParametersMap().getValue(lambdaType.asTypeParameter()); + } + + Value value = new Value(lambdaType, name); + return Optional.of(value); + } else { + throw new UnsupportedOperationException(); + } + } else { + throw new UnsupportedOperationException(); + } + } + index++; + } + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbolAsValue(name, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + for (Parameter parameter : wrappedNode.getParameters()) { + SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver); + SymbolReference symbolReference = solveWith(sb, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + return getParent().solveType(name, typeSolver); + } + + @Override + public SymbolReference solveMethod( + String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } + + /// + /// Protected methods + /// + + protected final Optional solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) { + for (ResolvedValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) { + if (decl.getName().equals(name)) { + + throw new UnsupportedOperationException(); + } + } + return Optional.empty(); + } + + /// + /// Private methods + /// + + private int pos(MethodCallExpr callExpr, Expression param) { + int i = 0; + for (Expression p : callExpr.getArguments()) { + if (p == param) { + return i; + } + i++; + } + throw new IllegalArgumentException(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java new file mode 100644 index 000000000..ca9f07c42 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java @@ -0,0 +1,433 @@ +/* + * 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.expr.Expression; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.*; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.model.typesystem.*; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; +import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic; +import com.github.javaparser.utils.Pair; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class MethodCallExprContext extends AbstractJavaParserContext { + + /// + /// Constructors + /// + + public MethodCallExprContext(MethodCallExpr wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + /// + /// Public methods + /// + + @Override + public Optional solveGenericType(String name, TypeSolver typeSolver) { + if(wrappedNode.getScope().isPresent()){ + ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(wrappedNode.getScope().get()); + Optional res = typeOfScope.asReferenceType().getGenericParameterByName(name); + return res; + } else{ + return Optional.empty(); + } + } + + @Override + public String toString() { + return "MethodCallExprContext{wrapped=" + wrappedNode + "}"; + } + + @Override + public Optional solveMethodAsUsage(String name, List argumentsTypes, TypeSolver typeSolver) { + if (wrappedNode.getScope().isPresent()) { + Expression scope = wrappedNode.getScope().get(); + // Consider static method calls + if (scope instanceof NameExpr) { + String className = ((NameExpr) scope).getName().getId(); + SymbolReference ref = solveType(className, typeSolver); + if (ref.isSolved()) { + SymbolReference m = MethodResolutionLogic.solveMethodInType(ref.getCorrespondingDeclaration(), name, argumentsTypes, typeSolver); + if (m.isSolved()) { + MethodUsage methodUsage = new MethodUsage(m.getCorrespondingDeclaration()); + methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage); + methodUsage = resolveMethodTypeParameters(methodUsage, argumentsTypes); + return Optional.of(methodUsage); + } else { + throw new UnsolvedSymbolException(ref.getCorrespondingDeclaration().toString(), + "Method '" + name + "' with parameterTypes " + argumentsTypes); + } + } + } + + ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); + // we can replace the parameter types from the scope into the typeParametersValues + + Map inferredTypes = new HashMap<>(); + for (int i = 0; i < argumentsTypes.size(); i++) { + // by replacing types I can also find new equivalences + // for example if I replace T=U with String because I know that T=String I can derive that also U equal String + ResolvedType originalArgumentType = argumentsTypes.get(i); + ResolvedType updatedArgumentType = usingParameterTypesFromScope(typeOfScope, originalArgumentType, inferredTypes); + argumentsTypes.set(i, updatedArgumentType); + } + for (int i = 0; i < argumentsTypes.size(); i++) { + ResolvedType updatedArgumentType = applyInferredTypes(argumentsTypes.get(i), inferredTypes); + argumentsTypes.set(i, updatedArgumentType); + } + + return solveMethodAsUsage(typeOfScope, name, argumentsTypes, typeSolver, this); + } else { + Context parentContext = getParent(); + while (parentContext instanceof MethodCallExprContext) { + parentContext = parentContext.getParent(); + } + return parentContext.solveMethodAsUsage(name, argumentsTypes, typeSolver); + } + } + + private MethodUsage resolveMethodTypeParametersFromExplicitList(TypeSolver typeSolver, MethodUsage methodUsage) { + if (wrappedNode.getTypeArguments().isPresent()) { + final List typeArguments = new ArrayList<>(); + for (com.github.javaparser.ast.type.Type ty : wrappedNode.getTypeArguments().get()) { + typeArguments.add(JavaParserFacade.get(typeSolver).convertToUsage(ty)); + } + + List tyParamDecls = methodUsage.getDeclaration().getTypeParameters(); + if (tyParamDecls.size() == typeArguments.size()) { + for (int i = 0; i < tyParamDecls.size(); i++) { + methodUsage = methodUsage.replaceTypeParameter(tyParamDecls.get(i), typeArguments.get(i)); + } + } + } + + return methodUsage; + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + Context parentContext = getParent(); + return parentContext.solveSymbolAsValue(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + Collection rrtds = findTypeDeclarations(wrappedNode.getScope(), typeSolver); + for (ResolvedReferenceTypeDeclaration rrtd : rrtds) { + SymbolReference res = MethodResolutionLogic.solveMethodInType(rrtd, name, argumentsTypes, false, typeSolver); + if (res.isSolved()) { + return res; + } + } + return SymbolReference.unsolved(ResolvedMethodDeclaration.class); + } + + /// + /// Private methods + /// + + private Optional solveMethodAsUsage(ResolvedReferenceType refType, String name, + List argumentsTypes, TypeSolver typeSolver, + Context invokationContext) { + Optional ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, refType.typeParametersValues()); + if (ref.isPresent()) { + MethodUsage methodUsage = ref.get(); + + methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage); + + // At this stage I should derive from the context and the value some information on the type parameters + // for example, when calling: + // myStream.collect(Collectors.toList()) + // I should be able to figure out that considering the type of the stream (e.g., Stream) + // and considering that Stream has this method: + // + // R collect(Collector collector) + // + // and collector has this method: + // + // static Collector> toList() + // + // In this case collect.R has to be equal to List + // And toList.T has to be equal to ? super Stream.T + // Therefore R has to be equal to List. + // In our example Stream.T equal to String, so the R (and the result of the call to collect) is + // List + + Map derivedValues = new HashMap<>(); + for (int i = 0; i < methodUsage.getParamTypes().size(); i++) { + ResolvedParameterDeclaration parameter = methodUsage.getDeclaration().getParam(i); + ResolvedType parameterType = parameter.getType(); + if (parameter.isVariadic()) { + parameterType = parameterType.asArrayType().getComponentType(); + } + inferTypes(argumentsTypes.get(i), parameterType, derivedValues); + } + + for (Map.Entry entry : derivedValues.entrySet()){ + methodUsage = methodUsage.replaceTypeParameter(entry.getKey(), entry.getValue()); + } + + ResolvedType returnType = refType.useThisTypeParametersOnTheGivenType(methodUsage.returnType()); + if (returnType != methodUsage.returnType()) { + methodUsage = methodUsage.replaceReturnType(returnType); + } + for (int i = 0; i < methodUsage.getParamTypes().size(); i++) { + ResolvedType replaced = refType.useThisTypeParametersOnTheGivenType(methodUsage.getParamTypes().get(i)); + methodUsage = methodUsage.replaceParamType(i, replaced); + } + return Optional.of(methodUsage); + } else { + return ref; + } + } + + private void inferTypes(ResolvedType source, ResolvedType target, Map mappings) { + if (source.equals(target)) { + return; + } + if (source.isReferenceType() && target.isReferenceType()) { + ResolvedReferenceType sourceRefType = source.asReferenceType(); + ResolvedReferenceType targetRefType = target.asReferenceType(); + if (sourceRefType.getQualifiedName().equals(targetRefType.getQualifiedName())) { + if (!sourceRefType.isRawType() && !targetRefType.isRawType()) { + for (int i = 0; i < sourceRefType.typeParametersValues().size(); i++) { + inferTypes(sourceRefType.typeParametersValues().get(i), targetRefType.typeParametersValues().get(i), mappings); + } + } + } + return; + } + if (source.isReferenceType() && target.isWildcard()) { + if (target.asWildcard().isBounded()) { + inferTypes(source, target.asWildcard().getBoundedType(), mappings); + return; + } + return; + } + if (source.isWildcard() && target.isWildcard()) { + if (source.asWildcard().isBounded() && target.asWildcard().isBounded()){ + inferTypes(source.asWildcard().getBoundedType(), target.asWildcard().getBoundedType(), mappings); + } + return; + } + if (source.isReferenceType() && target.isTypeVariable()) { + mappings.put(target.asTypeParameter(), source); + return; + } + if (source.isWildcard() && target.isTypeVariable()) { + mappings.put(target.asTypeParameter(), source); + return; + } + if (source.isArray() && target.isWildcard()){ + if(target.asWildcard().isBounded()){ + inferTypes(source, target.asWildcard().getBoundedType(), mappings); + return; + } + return; + } + if (source.isArray() && target.isTypeVariable()) { + mappings.put(target.asTypeParameter(), source); + return; + } + + if (source.isWildcard() && target.isReferenceType()){ + if (source.asWildcard().isBounded()){ + inferTypes(source.asWildcard().getBoundedType(), target, mappings); + } + return; + } + if (source.isConstraint() && target.isReferenceType()){ + inferTypes(source.asConstraintType().getBound(), target, mappings); + return; + } + + if (source.isConstraint() && target.isTypeVariable()){ + inferTypes(source.asConstraintType().getBound(), target, mappings); + return; + } + if (source.isTypeVariable() && target.isTypeVariable()) { + mappings.put(target.asTypeParameter(), source); + return; + } + if (source.isPrimitive() || target.isPrimitive()) { + return; + } + if (source.isNull()) { + return; + } + throw new RuntimeException(source.describe() + " " + target.describe()); + } + + private MethodUsage resolveMethodTypeParameters(MethodUsage methodUsage, List actualParamTypes) { + Map matchedTypeParameters = new HashMap<>(); + + if (methodUsage.getDeclaration().hasVariadicParameter()) { + if (actualParamTypes.size() == methodUsage.getDeclaration().getNumberOfParams()) { + // the varargs parameter is an Array, so extract the inner type + ResolvedType expectedType = + methodUsage.getDeclaration().getLastParam().getType().asArrayType().getComponentType(); + // the varargs corresponding type can be either T or Array + ResolvedType actualType = + actualParamTypes.get(actualParamTypes.size() - 1).isArray() ? + actualParamTypes.get(actualParamTypes.size() - 1).asArrayType().getComponentType() : + actualParamTypes.get(actualParamTypes.size() - 1); + if (!expectedType.isAssignableBy(actualType)) { + for (ResolvedTypeParameterDeclaration tp : methodUsage.getDeclaration().getTypeParameters()) { + expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver); + } + } + if (!expectedType.isAssignableBy(actualType)) { + // ok, then it needs to be wrapped + throw new UnsupportedOperationException( + String.format("Unable to resolve the type typeParametersValues in a MethodUsage. Expected type: %s, Actual type: %s. Method Declaration: %s. MethodUsage: %s", + expectedType, + actualType, + methodUsage.getDeclaration(), + methodUsage)); + } + // match only the varargs type + matchTypeParameters(expectedType, actualType, matchedTypeParameters); + } else { + return methodUsage; + } + } + + int until = methodUsage.getDeclaration().hasVariadicParameter() ? + actualParamTypes.size() - 1 : + actualParamTypes.size(); + + for (int i = 0; i < until; i++) { + ResolvedType expectedType = methodUsage.getParamType(i); + ResolvedType actualType = actualParamTypes.get(i); + matchTypeParameters(expectedType, actualType, matchedTypeParameters); + } + for (ResolvedTypeParameterDeclaration tp : matchedTypeParameters.keySet()) { + methodUsage = methodUsage.replaceTypeParameter(tp, matchedTypeParameters.get(tp)); + } + return methodUsage; + } + + private void matchTypeParameters(ResolvedType expectedType, ResolvedType actualType, Map matchedTypeParameters) { + if (expectedType.isTypeVariable()) { + if (!actualType.isTypeVariable() && !actualType.isReferenceType()) { + throw new UnsupportedOperationException(actualType.getClass().getCanonicalName()); + } + matchedTypeParameters.put(expectedType.asTypeParameter(), actualType); + } else if (expectedType.isArray()) { + if (!actualType.isArray()) { + throw new UnsupportedOperationException(actualType.getClass().getCanonicalName()); + } + matchTypeParameters( + expectedType.asArrayType().getComponentType(), + actualType.asArrayType().getComponentType(), + matchedTypeParameters); + } else if (expectedType.isReferenceType()) { + // avoid cases where the actual type has no type parameters but the expected one has. Such as: "classX extends classY" + if (actualType.isReferenceType() && actualType.asReferenceType().typeParametersValues().size() > 0) { + int i = 0; + for (ResolvedType tp : expectedType.asReferenceType().typeParametersValues()) { + matchTypeParameters(tp, actualType.asReferenceType().typeParametersValues().get(i), matchedTypeParameters); + i++; + } + } + } else if (expectedType.isPrimitive()) { + // nothing to do + } else if (expectedType.isWildcard()) { + // nothing to do + } else { + throw new UnsupportedOperationException(expectedType.getClass().getCanonicalName()); + } + } + + private Optional solveMethodAsUsage(ResolvedTypeVariable tp, String name, List argumentsTypes, TypeSolver typeSolver, Context invokationContext) { + for (ResolvedTypeParameterDeclaration.Bound bound : tp.asTypeParameter().getBounds()) { + Optional methodUsage = solveMethodAsUsage(bound.getType(), name, argumentsTypes, typeSolver, invokationContext); + if (methodUsage.isPresent()) { + return methodUsage; + } + } + return Optional.empty(); + } + + private Optional solveMethodAsUsage(ResolvedType type, String name, List argumentsTypes, TypeSolver typeSolver, Context invokationContext) { + if (type instanceof ResolvedReferenceType) { + return solveMethodAsUsage((ResolvedReferenceType) type, name, argumentsTypes, typeSolver, invokationContext); + } else if (type instanceof ResolvedTypeVariable) { + return solveMethodAsUsage((ResolvedTypeVariable) type, name, argumentsTypes, typeSolver, invokationContext); + } else if (type instanceof ResolvedWildcard) { + ResolvedWildcard wildcardUsage = (ResolvedWildcard) type; + if (wildcardUsage.isSuper()) { + return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, typeSolver, invokationContext); + } else if (wildcardUsage.isExtends()) { + throw new UnsupportedOperationException("extends wildcard"); + } else { + throw new UnsupportedOperationException("unbounded wildcard"); + } + } else if (type instanceof ResolvedLambdaConstraintType){ + ResolvedLambdaConstraintType constraintType = (ResolvedLambdaConstraintType) type; + return solveMethodAsUsage(constraintType.getBound(), name, argumentsTypes, typeSolver, invokationContext); + } else if (type instanceof ResolvedArrayType) { + // An array inherits methods from Object not from it's component type + return solveMethodAsUsage(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver), name, argumentsTypes, typeSolver, invokationContext); + } else { + throw new UnsupportedOperationException("type usage: " + type.getClass().getCanonicalName()); + } + } + + private ResolvedType usingParameterTypesFromScope(ResolvedType scope, ResolvedType type, Map inferredTypes) { + if (type.isReferenceType()) { + for (Pair entry : type.asReferenceType().getTypeParametersMap()) { + if (entry.a.declaredOnType() && scope.asReferenceType().getGenericParameterByName(entry.a.getName()).isPresent()) { + type = type.replaceTypeVariables(entry.a, scope.asReferenceType().getGenericParameterByName(entry.a.getName()).get(), inferredTypes); + } + } + return type; + } else { + return type; + } + } + + private ResolvedType applyInferredTypes(ResolvedType type, Map inferredTypes) { + for (ResolvedTypeParameterDeclaration tp : inferredTypes.keySet()) { + type = type.replaceTypeVariables(tp, inferredTypes.get(tp), inferredTypes); + } + return type; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java new file mode 100644 index 000000000..9a7530b18 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java @@ -0,0 +1,35 @@ +/* + * 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.body.MethodDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +/** + * @author Federico Tomassetti + */ +public class MethodContext extends AbstractMethodLikeDeclarationContext { + + /// + /// Constructors + /// + + public MethodContext(MethodDeclaration wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java new file mode 100644 index 000000000..51dd2d6d0 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java @@ -0,0 +1,200 @@ +/* + * 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.expr.LambdaExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithStatements; +import com.github.javaparser.ast.stmt.IfStmt; +import com.github.javaparser.ast.stmt.Statement; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +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.core.resolution.Context; +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.resolution.Value; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +import java.util.List; +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class StatementContext extends AbstractJavaParserContext { + + public StatementContext(N wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + public static SymbolReference solveInBlock(String name, TypeSolver typeSolver, Statement stmt) { + if (!(getParentNode(stmt) instanceof NodeWithStatements)) { + throw new IllegalArgumentException(); + } + NodeWithStatements blockStmt = (NodeWithStatements) getParentNode(stmt); + int position = -1; + for (int i = 0; i < blockStmt.getStatements().size(); i++) { + if (blockStmt.getStatements().get(i).equals(stmt)) { + position = i; + } + } + if (position == -1) { + throw new RuntimeException(); + } + for (int i = position - 1; i >= 0; i--) { + SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(blockStmt.getStatements().get(i), typeSolver); + SymbolReference symbolReference = solveWith(symbolDeclarator, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbol(name, typeSolver); + } + + public static Optional solveInBlockAsValue(String name, TypeSolver typeSolver, Statement stmt) { + if (!(getParentNode(stmt) instanceof NodeWithStatements)) { + throw new IllegalArgumentException(); + } + NodeWithStatements blockStmt = (NodeWithStatements) getParentNode(stmt); + int position = -1; + for (int i = 0; i < blockStmt.getStatements().size(); i++) { + if (blockStmt.getStatements().get(i).equals(stmt)) { + position = i; + } + } + if (position == -1) { + throw new RuntimeException(); + } + for (int i = position - 1; i >= 0; i--) { + SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(blockStmt.getStatements().get(i), typeSolver); + SymbolReference symbolReference = solveWith(symbolDeclarator, name); + if (symbolReference.isSolved()) { + return Optional.of(Value.from(symbolReference.getCorrespondingDeclaration())); + } + } + + // if nothing is found we should ask the parent context + return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbolAsValue(name, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + + // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;) + SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver); + Optional symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver); + if (symbolReference.isPresent()) { + return symbolReference; + } + + // we should look in all the statements preceding, treating them as SymbolDeclarators + if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { + return getParent().solveSymbolAsValue(name, typeSolver); + } + if (getParentNode(wrappedNode) instanceof LambdaExpr) { + return getParent().solveSymbolAsValue(name, typeSolver); + } + if (getParentNode(wrappedNode) instanceof IfStmt) { + return getParent().solveSymbolAsValue(name, typeSolver); + } + if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) { + return getParent().solveSymbolAsValue(name, typeSolver); + } + NodeWithStatements nodeWithStmt = (NodeWithStatements) getParentNode(wrappedNode); + int position = -1; + for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) { + if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) { + position = i; + } + } + if (position == -1) { + throw new RuntimeException(); + } + for (int i = position - 1; i >= 0; i--) { + symbolDeclarator = JavaParserFactory.getSymbolDeclarator(nodeWithStmt.getStatements().get(i), typeSolver); + symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver); + if (symbolReference.isPresent()) { + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + Context parentContext = getParent(); + return parentContext.solveSymbolAsValue(name, typeSolver); + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + + // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;) + SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver); + SymbolReference symbolReference = solveWith(symbolDeclarator, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + + // we should look in all the statements preceding, treating them as SymbolDeclarators + if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { + return getParent().solveSymbol(name, typeSolver); + } + if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.ConstructorDeclaration) { + return getParent().solveSymbol(name, typeSolver); + } + if (getParentNode(wrappedNode) instanceof LambdaExpr) { + return getParent().solveSymbol(name, typeSolver); + } + if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) { + return getParent().solveSymbol(name, typeSolver); + } + NodeWithStatements nodeWithStmt = (NodeWithStatements) getParentNode(wrappedNode); + int position = -1; + for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) { + if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) { + position = i; + } + } + if (position == -1) { + throw new RuntimeException(); + } + for (int i = position - 1; i >= 0; i--) { + symbolDeclarator = JavaParserFactory.getSymbolDeclarator(nodeWithStmt.getStatements().get(i), typeSolver); + symbolReference = solveWith(symbolDeclarator, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + } + + // if nothing is found we should ask the parent context + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } + + @Override + public SymbolReference solveType(String name, TypeSolver typeSolver) { + return getParent().solveType(name, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java new file mode 100644 index 000000000..053cc2de1 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java @@ -0,0 +1,80 @@ +/* + * 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.stmt.Statement; +import com.github.javaparser.ast.stmt.SwitchEntryStmt; +import com.github.javaparser.ast.stmt.SwitchStmt; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +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.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.SymbolDeclarator; + +import java.util.List; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class SwitchEntryContext extends AbstractJavaParserContext { + + public SwitchEntryContext(SwitchEntryStmt wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public SymbolReference 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 symbolReference = solveWith(symbolDeclarator, name); + if (symbolReference.isSolved()) { + return symbolReference; + } + } + } + } + + return getParent().solveSymbol(name, typeSolver); + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java new file mode 100644 index 000000000..de6516436 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java @@ -0,0 +1,87 @@ +/* + * 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.body.VariableDeclarator; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.VariableDeclarationExpr; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.TryStmt; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.resolution.Value; + +import java.util.List; +import java.util.Optional; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +public class TryWithResourceContext extends AbstractJavaParserContext { + + public TryWithResourceContext(TryStmt wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { + for (Expression expr : wrappedNode.getResources()) { + if (expr instanceof VariableDeclarationExpr) { + for (VariableDeclarator v : ((VariableDeclarationExpr)expr).getVariables()) { + if (v.getName().getIdentifier().equals(name)) { + JavaParserSymbolDeclaration decl = JavaParserSymbolDeclaration.localVar(v, typeSolver); + return Optional.of(Value.from(decl)); + } + } + } + } + + if (getParentNode(wrappedNode) instanceof BlockStmt) { + return StatementContext.solveInBlockAsValue(name, typeSolver, wrappedNode); + } else { + return getParent().solveSymbolAsValue(name, typeSolver); + } + } + + @Override + public SymbolReference solveSymbol(String name, TypeSolver typeSolver) { + for (Expression expr : wrappedNode.getResources()) { + if (expr instanceof VariableDeclarationExpr) { + for (VariableDeclarator v : ((VariableDeclarationExpr)expr).getVariables()) { + if (v.getName().getIdentifier().equals(name)) { + return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(v, typeSolver)); + } + } + } + } + + if (getParentNode(wrappedNode) instanceof BlockStmt) { + return StatementContext.solveInBlock(name, typeSolver, wrappedNode); + } else { + return getParent().solveSymbol(name, typeSolver); + } + } + + @Override + public SymbolReference solveMethod(String name, List argumentsTypes, + boolean staticOnly, TypeSolver typeSolver) { + return getParent().solveMethod(name, argumentsTypes, false, typeSolver); + } +} 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 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..18bc92cd1 --- /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 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 p = ((CompilationUnit) container).getPackageDeclaration(); + if (p.isPresent()) { + return p.get().getName().toString(); + } + } else if (container != null) { + return getPackageName(getParentNode(container)); + } + return ""; + } + + static String getClassName(String base, Node container) { + if (container instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) { + String b = getClassName(base, getParentNode(container)); + 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, getParentNode(container)); + 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, getParentNode(container)); + } + 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..c9431f6b6 --- /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 getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public List getAllFields() { + throw new UnsupportedOperationException(); + } + + @Override + public Set 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(getParentNode(wrappedNode)); + if (containerName.isEmpty()) { + return wrappedNode.getName().getId(); + } else { + return containerName + "." + wrappedNode.getName(); + } + } + + @Override + public String getName() { + return wrappedNode.getName().getId(); + } + + @Override + public List getTypeParameters() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional containerType() { + throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName()); + } + + @Override + public List 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..7a6abeba0 --- /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 List findMembersOfKind(final Class memberClass) { + if (wrappedNode.getAnonymousClassBody().isPresent()) { + return wrappedNode + .getAnonymousClassBody() + .get() + .stream() + .filter(node -> memberClass.isAssignableFrom(node.getClass())) + .map(node -> (T) node) + .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 getInterfaces() { + return + superTypeDeclaration + .asReferenceType().getAncestors() + .stream() + .filter(type -> type.getTypeDeclaration().isInterface()) + .collect(Collectors.toList()); + } + + @Override + public List 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 getAncestors() { + return + ImmutableList. + builder() + .add(getSuperClass()) + .addAll(superTypeDeclaration.asReferenceType().getAncestors()) + .build(); + } + + @Override + public List getAllFields() { + + List 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 superClassFields = + getSuperClass().getTypeDeclaration().getAllFields(); + + List interfaceFields = + getInterfaces().stream() + .flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()) + .collect(Collectors.toList()); + + return + ImmutableList + .builder() + .addAll(myFields) + .addAll(superClassFields) + .addAll(interfaceFields) + .build(); + } + + @Override + public Set 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(getParentNode(wrappedNode)); + if (containerName.isEmpty()) { + return getName(); + } else { + return containerName + "." + getName(); + } + } + + @Override + public Set 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 getTypeParameters() { + return Lists.newArrayList(); + } + + @Override + public Optional 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..7a6e198da --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java @@ -0,0 +1,392 @@ +/* + * 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.declarations.*; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException; +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 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 getAllFields() { + List 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 solveMethod(String name, List 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 getInterfaces() { + List interfaces = new ArrayList<>(); + if (wrappedNode.getImplementedTypes() != null) { + for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) { + interfaces.add(toReferenceType(t)); + } + } + return interfaces; + } + + @Override + public List getConstructors() { + List 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 solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getName().getId().equals(name)) { + return SymbolReference.solved(this); + } + SymbolReference 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 getAncestors() { + List ancestors = new ArrayList<>(); + 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 getDeclaredMethods() { + Set 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 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 internalTypes() { + Set 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 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 ref = solveType(className, typeSolver); + if (!ref.isSolved()) { + Optional 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 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 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..3ceda1a4e --- /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.getParentNode; + +/** + * @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) getParentNode(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..464aa7b83 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java @@ -0,0 +1,349 @@ +/* + * 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.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.javaparsermodel.UnsolvedSymbolException; +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 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 getDeclaredMethods() { + Set 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) { + // Enums cannot be extended + if (other.getQualifiedName().equals(this.getQualifiedName())) { + return true; + } + if (other.getQualifiedName().equals(Enum.class.getCanonicalName())) { + return true; + } + // Enum implements Comparable and Serializable + if (other.getQualifiedName().equals(Comparable.class.getCanonicalName())) { + return true; + } + if (other.getQualifiedName().equals(Serializable.class.getCanonicalName())) { + return true; + } + if (other.getQualifiedName().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 solveMethodAsUsage(String name, List parameterTypes, + TypeSolver typeSolver, Context invokationContext, List 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 getAllFields() { + List 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 getAncestors() { + List 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 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 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 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 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 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 internalTypes() { + Set 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 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..fe55deeb4 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java @@ -0,0 +1,123 @@ +/* + * 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; + +/** + * @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 (!(getParentNode(variableDeclarator) instanceof com.github.javaparser.ast.body.FieldDeclaration)) { + throw new IllegalStateException(getParentNode(variableDeclarator).getClass().getCanonicalName()); + } + this.wrappedNode = (com.github.javaparser.ast.body.FieldDeclaration) getParentNode(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) getParentNode(enumConstantDeclaration); + return new ReferenceTypeImpl(new JavaParserEnumDeclaration(enumDeclaration, typeSolver), typeSolver); + } else { + ResolvedType retType = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode); + return retType; + } + } + + @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 typeDeclaration = Navigator.findAncestor(wrappedNode, com.github.javaparser.ast.body.TypeDeclaration.class); + if (typeDeclaration.isPresent()) { + return JavaParserFacade.get(typeSolver).getTypeDeclaration(typeDeclaration.get()); + } else { + 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..5d33bcdce --- /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.declarations.*; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; +import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException; +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 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 getDeclaredMethods() { + Set 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 getInterfacesExtended() { + List 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 getAllFields() { + List 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 solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getName().getId().equals(name)) { + return SymbolReference.solved(this); + } + SymbolReference 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 getAncestors() { + List 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 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 internalTypes() { + Set 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 containerType() { + return javaParserTypeAdapter.containerType(); + } + + /// + /// Private methods + /// + + private ResolvedReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) { + SymbolReference 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 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..b352e905a --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java @@ -0,0 +1,168 @@ +/* + * 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.getParentNode; + +/** + * @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 (getParentNode(wrappedNode) instanceof ObjectCreationExpr) { + ObjectCreationExpr parentNode = (ObjectCreationExpr) getParentNode(wrappedNode); + return new JavaParserAnonymousClassDeclaration(parentNode, typeSolver); + } else { + return JavaParserFactory.toTypeDeclaration(getParentNode(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 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 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 = 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..9b8578849 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java @@ -0,0 +1,177 @@ +/* + * 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.getParentNode; + +/** + * @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 : getParentNode(parameter).getChildNodes()) { + if (node == parameter) { + return pos; + } else if (node instanceof Parameter) { + pos++; + } + } + return pos; + } + + public static int getParamPos(Node node) { + if (getParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr call = (MethodCallExpr) getParentNode(node); + for (int i = 0; i < call.getArguments().size(); i++) { + if (call.getArguments().get(i) == node) return i; + } + throw new IllegalStateException(); + } else { + 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 (getParentNode(wrappedNode) instanceof LambdaExpr) { + int pos = getParamPos(parameter); + ResolvedType lambdaType = JavaParserFacade.get(typeSolver).getType(getParentNode(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 { + ResolvedType rawType = null; + 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); + } else { + return rawType; + } + } + } else if (wrappedNode instanceof VariableDeclarator) { + VariableDeclarator variableDeclarator = (VariableDeclarator) wrappedNode; + if (getParentNode(wrappedNode) instanceof VariableDeclarationExpr) { + ResolvedType type = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver)); + return type; + } else if (getParentNode(wrappedNode) instanceof FieldDeclaration) { + return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver)); + } else { + throw new UnsupportedOperationException(getParentNode(wrappedNode).getClass().getCanonicalName()); + } + } else { + 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..c65b2d817 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java @@ -0,0 +1,138 @@ +package com.github.javaparser.symbolsolver.javaparsermodel.declarations; + +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.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.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 & NodeWithMembers & NodeWithTypeParameters> { + + 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 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 solveType(String name, TypeSolver typeSolver) { + if (this.wrappedNode.getTypeParameters() != null) { + for (com.github.javaparser.ast.type.TypeParameter typeParameter : this.wrappedNode.getTypeParameters()) { + 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 containerType() { + Optional parent = wrappedNode.getParentNode(); + return parent.isPresent() ? + Optional.of(JavaParserFactory.toTypeDeclaration(parent.get(), typeSolver)) : + Optional.empty(); + } + + public List getFieldsForDeclaredVariables() { + ArrayList 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..79eaf350f --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java @@ -0,0 +1,224 @@ +/* + * 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.getParentNode; + +/** + * @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 getDeclaredMethods() { + return Collections.emptySet(); + } + + public SymbolReference solveMethod(String name, List 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 = 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 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 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); + Bound bound = Bound.extendsBound(type); + return bound; + } + + 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 getAllFields() { + return new ArrayList<>(); + } + + @Override + public List getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isTypeParameter() { + return true; + } + + @Override + public boolean hasDirectlyAnnotation(String canonicalName) { + throw new UnsupportedOperationException(); + } + + @Override + public List 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 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 solveMethod(String name, List 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 getAllFields() { + return new ArrayList<>(); + } + + @Override + public List getAncestors() { + throw new UnsupportedOperationException(); + } + + @Override + public Set 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 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 containerType() { + return asTypeParameter().containerType(); + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java new file mode 100644 index 000000000..14fdafcd0 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java @@ -0,0 +1,35 @@ +/* + * 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.declarators; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; + +/** + * @author Federico Tomassetti + */ +public abstract class AbstractSymbolDeclarator implements SymbolDeclarator { + + protected N wrappedNode; + protected TypeSolver typeSolver; + + public AbstractSymbolDeclarator(N wrappedNode, TypeSolver typeSolver) { + this.wrappedNode = wrappedNode; + this.typeSolver = typeSolver; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java new file mode 100644 index 000000000..dddf7a538 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java @@ -0,0 +1,46 @@ +/* + * 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.declarators; + +import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author Federico Tomassetti + */ +public class FieldSymbolDeclarator extends AbstractSymbolDeclarator { + + public FieldSymbolDeclarator(FieldDeclaration wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public List getSymbolDeclarations() { + List symbols = new LinkedList<>(); + for (VariableDeclarator v : wrappedNode.getVariables()) { + symbols.add(JavaParserSymbolDeclaration.field(v, typeSolver)); + } + return symbols; + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java new file mode 100644 index 000000000..e950b70ee --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java @@ -0,0 +1,40 @@ +/* + * 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.declarators; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.Collections; +import java.util.List; + +/** + * @author Federico Tomassetti + */ +public class NoSymbolDeclarator extends AbstractSymbolDeclarator { + + public NoSymbolDeclarator(N wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public List getSymbolDeclarations() { + return Collections.emptyList(); + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java new file mode 100644 index 000000000..45d8e160f --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java @@ -0,0 +1,42 @@ +/* + * 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.declarators; + +import com.github.javaparser.ast.body.Parameter; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author Federico Tomassetti + */ +public class ParameterSymbolDeclarator extends AbstractSymbolDeclarator { + + public ParameterSymbolDeclarator(Parameter wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + } + + @Override + public List getSymbolDeclarations() { + List symbols = new LinkedList<>(); + symbols.add(JavaParserSymbolDeclaration.parameter(wrappedNode, typeSolver)); + return symbols; + } +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java new file mode 100644 index 000000000..be6a66924 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java @@ -0,0 +1,52 @@ +/* + * 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.declarators; + +import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.expr.VariableDeclarationExpr; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; + +/** + * @author Federico Tomassetti + */ +public class VariableSymbolDeclarator extends AbstractSymbolDeclarator { + + public VariableSymbolDeclarator(VariableDeclarationExpr wrappedNode, TypeSolver typeSolver) { + super(wrappedNode, typeSolver); + if (getParentNode(wrappedNode) instanceof FieldDeclaration) { + throw new IllegalArgumentException(); + } + } + + @Override + public List getSymbolDeclarations() { + List symbols = wrappedNode.getVariables().stream().map( + v -> JavaParserSymbolDeclaration.localVar(v, typeSolver) + ).collect( + Collectors.toCollection(() -> new LinkedList<>())); + return symbols; + } + +} diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java new file mode 100644 index 000000000..9ddf1cf01 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Implementation of model based on JavaParser. + */ +package com.github.javaparser.symbolsolver.javaparsermodel; \ No newline at end of file -- cgit v1.2.3 From 9a228915f61892f6ba99fcf1e42e42e1e2622a00 Mon Sep 17 00:00:00 2001 From: Danny van Bruggen Date: Wed, 24 Jan 2018 23:52:36 +0100 Subject: Deal with no common type for variables being available. --- .../javaparsermodel/contexts/FieldAccessContext.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java index 860fe6bc4..65ccedf00 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java @@ -53,7 +53,7 @@ public class FieldAccessContext extends AbstractJavaParserContext solveSymbol(String name, TypeSolver typeSolver) { - if (wrappedNode.getField().toString().equals(name)) { + if (wrappedNode.getName().toString().equals(name)) { if (wrappedNode.getScope() instanceof ThisExpr) { ResolvedType typeOfThis = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); return new SymbolSolver(typeSolver).solveSymbolInType(typeOfThis.asReferenceType().getTypeDeclaration(), name); @@ -75,18 +75,14 @@ public class FieldAccessContext extends AbstractJavaParserContext solveSymbolAsValue(String name, TypeSolver typeSolver) { Expression scope = wrappedNode.getScope(); - if (wrappedNode.getField().toString().equals(name)) { + 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()) { Optional typeUsage = typeOfScope.asReferenceType().getFieldType(name); - if (typeUsage.isPresent()) { - return Optional.of(new Value(typeUsage.get(), name)); - } else { - return Optional.empty(); - } + return typeUsage.map(resolvedType -> new Value(resolvedType, name)); } else { return Optional.empty(); } -- cgit v1.2.3 From fc0a1b721f63bd05ff54cfbb68488b32a6023ae2 Mon Sep 17 00:00:00 2001 From: dhardtke Date: Fri, 2 Feb 2018 04:21:11 +0100 Subject: fix(symbol solver): Fix infinite recursion when solving java.lang.Object --- .../declarations/JavaParserClassDeclaration.java | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') 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 index 7a6e198da..9b1979aad 100644 --- 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 @@ -290,16 +290,21 @@ public class JavaParserClassDeclaration extends AbstractClassDeclaration { @Override public List getAncestors() { List ancestors = new ArrayList<>(); - 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); + + // 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; } -- cgit v1.2.3 From b54617e765d73b3ce0d187cf12ad8da382bce439 Mon Sep 17 00:00:00 2001 From: Danny van Bruggen Date: Sat, 3 Feb 2018 15:45:46 +0100 Subject: Cleaning up JSS code --- .../javaparsermodel/JavaParserFacade.java | 104 ++++++++----------- .../javaparsermodel/JavaParserFactory.java | 15 +-- .../javaparsermodel/TypeExtractor.java | 114 +++++++++------------ .../javaparsermodel/UnsolvedSymbolException.java | 6 +- .../contexts/AbstractJavaParserContext.java | 49 +++++---- .../AbstractMethodLikeDeclarationContext.java | 2 +- .../contexts/ForStatementContext.java | 4 +- .../contexts/ForechStatementContext.java | 4 +- .../contexts/LambdaExprContext.java | 11 +- .../javaparsermodel/contexts/StatementContext.java | 34 +++--- .../contexts/SwitchEntryContext.java | 4 +- .../contexts/TryWithResourceContext.java | 5 +- .../javaparsermodel/declarations/Helper.java | 8 +- .../JavaParserAnnotationDeclaration.java | 2 +- .../JavaParserAnonymousClassDeclaration.java | 4 +- .../declarations/JavaParserClassDeclaration.java | 2 +- .../JavaParserEnumConstantDeclaration.java | 4 +- .../declarations/JavaParserEnumDeclaration.java | 17 +-- .../declarations/JavaParserFieldDeclaration.java | 18 ++-- .../JavaParserInterfaceDeclaration.java | 2 +- .../declarations/JavaParserMethodDeclaration.java | 9 +- .../declarations/JavaParserSymbolDeclaration.java | 32 +++--- .../declarations/JavaParserTypeAdapter.java | 18 ++-- .../declarations/JavaParserTypeParameter.java | 7 +- .../declarators/VariableSymbolDeclarator.java | 16 +-- 25 files changed, 224 insertions(+), 267 deletions(-) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java index 39e0d29ea..4a4783dd4 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -25,6 +25,7 @@ import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; import com.github.javaparser.ast.type.*; import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.*; import com.github.javaparser.resolution.types.*; import com.github.javaparser.symbolsolver.core.resolution.Context; @@ -43,7 +44,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * Class to be used by final users to solve symbols for JavaParser ASTs. @@ -95,13 +96,9 @@ public class JavaParserFacade { protected static ResolvedType solveGenericTypes(ResolvedType type, Context context, TypeSolver typeSolver) { if (type.isTypeVariable()) { - Optional solved = context.solveGenericType(type.describe(), typeSolver); - if (solved.isPresent()) { - return solved.get(); - } else { - return type; - } - } else if (type.isWildcard()) { + return context.solveGenericType(type.describe(), typeSolver).orElse(type); + } + if (type.isWildcard()) { if (type.asWildcard().isExtends() || type.asWildcard().isSuper()) { ResolvedWildcard wildcardUsage = type.asWildcard(); ResolvedType boundResolved = solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver); @@ -110,13 +107,9 @@ public class JavaParserFacade { } else { return ResolvedWildcard.superBound(boundResolved); } - } else { - return type; } - } else { - ResolvedType result = type; - return result; } + return type; } public SymbolReference solve(NameExpr nameExpr) { @@ -128,11 +121,7 @@ public class JavaParserFacade { } public SymbolReference solve(Expression expr) { - if (expr instanceof NameExpr) { - return solve((NameExpr) expr); - } else { - throw new IllegalArgumentException(expr.getClass().getCanonicalName()); - } + return expr.toNameExpr().map(this::solve).orElseThrow(() -> new IllegalArgumentException(expr.getClass().getCanonicalName())); } public SymbolReference solve(MethodCallExpr methodCallExpr) { @@ -180,21 +169,21 @@ public class JavaParserFacade { return res; } - public SymbolReference solve(ThisExpr node){ + public SymbolReference solve(ThisExpr node) { // If 'this' is prefixed by a class eg. MyClass.this - if (node.getClassExpr().isPresent()){ + if (node.getClassExpr().isPresent()) { // Get the class name String className = node.getClassExpr().get().toString(); // Attempt to resolve using a typeSolver SymbolReference clazz = typeSolver.tryToSolveType(className); - if (clazz.isSolved()){ + if (clazz.isSolved()) { return SymbolReference.solved(clazz.getCorrespondingDeclaration()); } // Attempt to resolve locally in Compilation unit Optional cu = node.getAncestorOfType(CompilationUnit.class); - if (cu.isPresent()){ + if (cu.isPresent()) { Optional classByName = cu.get().getClassByName(className); - if (classByName.isPresent()){ + if (classByName.isPresent()) { return SymbolReference.solved(getTypeDeclaration(classByName.get())); } } @@ -233,7 +222,7 @@ public class JavaParserFacade { } else { try { argumentTypes.add(JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas)); - } catch (UnsolvedSymbolException e) { + } catch (com.github.javaparser.resolution.UnsolvedSymbolException e) { throw e; } catch (Exception e) { throw new RuntimeException(String.format("Unable to calculate the type of a parameter of a method call. Method call: %s, Parameter: %s", @@ -332,15 +321,12 @@ public class JavaParserFacade { /** * For some reasons LambdaExprs are duplicate and the equals method is not implemented correctly. - * - * @param map - * @return */ private Optional find(Map map, LambdaExpr lambdaExpr) { for (Node key : map.keySet()) { if (key instanceof LambdaExpr) { LambdaExpr keyLambdaExpr = (LambdaExpr) key; - if (keyLambdaExpr.toString().equals(lambdaExpr.toString()) && getParentNode(keyLambdaExpr) == getParentNode(lambdaExpr)) { + if (keyLambdaExpr.toString().equals(lambdaExpr.toString()) && requireParentNode(keyLambdaExpr) == requireParentNode(lambdaExpr)) { return Optional.of(map.get(keyLambdaExpr)); } } @@ -385,8 +371,6 @@ public class JavaParserFacade { /** * Should return more like a TypeApplication: a TypeDeclaration and possible typeParametersValues or array * modifiers. - * - * @return */ private ResolvedType getTypeConcrete(Node node, boolean solveLambdas) { if (node == null) throw new IllegalArgumentException(); @@ -396,37 +380,35 @@ public class JavaParserFacade { protected com.github.javaparser.ast.body.TypeDeclaration findContainingTypeDecl(Node node) { if (node instanceof ClassOrInterfaceDeclaration) { return (ClassOrInterfaceDeclaration) node; - } else if (node instanceof EnumDeclaration) { + } + if (node instanceof EnumDeclaration) { return (EnumDeclaration) node; - } else if (getParentNode(node) == null) { - throw new IllegalArgumentException(); - } else { - return findContainingTypeDecl(getParentNode(node)); } + return findContainingTypeDecl(requireParentNode(node)); + } - protected com.github.javaparser.ast.Node findContainingTypeDeclOrObjectCreationExpr(Node node) { + protected Node findContainingTypeDeclOrObjectCreationExpr(Node node) { if (node instanceof ClassOrInterfaceDeclaration) { - return (ClassOrInterfaceDeclaration) node; - } else if (node instanceof EnumDeclaration) { - return (EnumDeclaration) node; - } else if (getParentNode(node) == null) { - throw new IllegalArgumentException(); - } else if (getParentNode(node) instanceof ObjectCreationExpr && !((ObjectCreationExpr)getParentNode(node)).getArguments().contains(node)) { - return getParentNode(node); - } else { - return findContainingTypeDeclOrObjectCreationExpr(getParentNode(node)); + return node; } + if (node instanceof EnumDeclaration) { + return node; + } + Node parent = requireParentNode(node); + if (parent instanceof ObjectCreationExpr && !((ObjectCreationExpr) parent).getArguments().contains(node)) { + return parent; + } + return findContainingTypeDeclOrObjectCreationExpr(parent); } public ResolvedType convertToUsageVariableType(VariableDeclarator var) { - ResolvedType type = JavaParserFacade.get(typeSolver).convertToUsage(var.getType(), var); - return type; + return get(typeSolver).convertToUsage(var.getType(), var); } public ResolvedType convertToUsage(com.github.javaparser.ast.type.Type type, Node context) { - if (type instanceof UnknownType) { - throw new IllegalArgumentException("Unknown type"); + if (type.isUnknownType()) { + throw new IllegalArgumentException("Inferred lambda parameter type"); } return convertToUsage(type, JavaParserFactory.getContext(context, typeSolver)); } @@ -440,9 +422,8 @@ public class JavaParserFacade { String name = classOrInterfaceType.getName().getId(); if (classOrInterfaceType.getScope().isPresent()) { return qName(classOrInterfaceType.getScope().get()) + "." + name; - } else { - return name; } + return name; } protected ResolvedType convertToUsage(com.github.javaparser.ast.type.Type type, Context context) { @@ -475,11 +456,11 @@ public class JavaParserFacade { return ResolvedPrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) type).getType().name()); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; - if (wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) { - return ResolvedWildcard.extendsBound(convertToUsage(wildcardType.getExtendedTypes().get(), context)); // removed (ReferenceTypeImpl) - } else if (!wildcardType.getExtendedTypes().isPresent() && wildcardType.getSuperTypes().isPresent()) { - return ResolvedWildcard.superBound(convertToUsage(wildcardType.getSuperTypes().get(), context)); // removed (ReferenceTypeImpl) - } else if (!wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) { + if (wildcardType.getExtendedType().isPresent() && !wildcardType.getSuperType().isPresent()) { + return ResolvedWildcard.extendsBound(convertToUsage(wildcardType.getExtendedType().get(), context)); // removed (ReferenceTypeImpl) + } else if (!wildcardType.getExtendedType().isPresent() && wildcardType.getSuperType().isPresent()) { + return ResolvedWildcard.superBound(convertToUsage(wildcardType.getSuperType().get(), context)); // removed (ReferenceTypeImpl) + } else if (!wildcardType.getExtendedType().isPresent() && !wildcardType.getSuperType().isPresent()) { return ResolvedWildcard.UNBOUNDED; } else { throw new UnsupportedOperationException(wildcardType.toString()); @@ -490,7 +471,7 @@ public class JavaParserFacade { com.github.javaparser.ast.type.ArrayType jpArrayType = (com.github.javaparser.ast.type.ArrayType) type; return new ResolvedArrayType(convertToUsage(jpArrayType.getComponentType(), context)); } else if (type instanceof UnionType) { - UnionType unionType = (UnionType)type; + UnionType unionType = (UnionType) type; return new ResolvedUnionType(unionType.getElements().stream().map(el -> convertToUsage(el, context)).collect(Collectors.toList())); } else { throw new UnsupportedOperationException(type.getClass().getCanonicalName()); @@ -523,16 +504,16 @@ public class JavaParserFacade { Optional methodUsage = context.solveMethodAsUsage(call.getName().getId(), params, typeSolver); if (!methodUsage.isPresent()) { throw new RuntimeException("Method '" + call.getName() + "' cannot be resolved in context " - + call + " (line: " + call.getRange().get().begin.line + ") " + context + ". Parameter types: " + params); + + call + " (line: " + call.getRange().map(r -> "" + r.begin.line).orElse("??") + ") " + context + ". Parameter types: " + params); } return methodUsage.get(); } public ResolvedReferenceTypeDeclaration getTypeDeclaration(Node node) { if (node instanceof TypeDeclaration) { - return getTypeDeclaration((TypeDeclaration)node); + return getTypeDeclaration((TypeDeclaration) node); } else if (node instanceof ObjectCreationExpr) { - return new JavaParserAnonymousClassDeclaration((ObjectCreationExpr)node, typeSolver); + return new JavaParserAnonymousClassDeclaration((ObjectCreationExpr) node, typeSolver); } else { throw new IllegalArgumentException(); } @@ -555,9 +536,8 @@ public class JavaParserFacade { } else if (node instanceof ObjectCreationExpr && ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) { JavaParserAnonymousClassDeclaration anonymousDeclaration = new JavaParserAnonymousClassDeclaration((ObjectCreationExpr) node, typeSolver); return new ReferenceTypeImpl(anonymousDeclaration, typeSolver); - } else { - return getTypeOfThisIn(getParentNode(node)); } + return getTypeOfThisIn(requireParentNode(node)); } public ResolvedReferenceTypeDeclaration getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration typeDeclaration) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java index 1004bc31e..8bd3496fd 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java @@ -38,6 +38,7 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -72,7 +73,7 @@ public class JavaParserFactory { } else if (node instanceof TryStmt) { return new TryWithResourceContext((TryStmt) node, typeSolver); } else if (node instanceof Statement) { - return new StatementContext((Statement) node, typeSolver); + return new StatementContext<>((Statement) node, typeSolver); } else if (node instanceof CatchClause) { return new CatchClauseContext((CatchClause) node, typeSolver); } else if (node instanceof ObjectCreationExpr && @@ -85,9 +86,9 @@ public class JavaParserFactory { return getContext(node.getParentNode().get().getParentNode().get(), typeSolver); } } - final Node parentNode = getParentNode(node); + final Node parentNode = requireParentNode(node); if (parentNode instanceof ObjectCreationExpr && node == ((ObjectCreationExpr) parentNode).getType()) { - return getContext(getParentNode(parentNode), typeSolver); + return getContext(requireParentNode(parentNode), typeSolver); } if (parentNode == null) { throw new IllegalStateException("The AST node does not appear to be inserted in a propert AST, therefore we cannot resolve symbols correctly"); @@ -106,15 +107,15 @@ public class JavaParserFactory { if (expressionStmt.getExpression() instanceof VariableDeclarationExpr) { return new VariableSymbolDeclarator((VariableDeclarationExpr) (expressionStmt.getExpression()), typeSolver); } else { - return new NoSymbolDeclarator(expressionStmt, typeSolver); + return new NoSymbolDeclarator<>(expressionStmt, typeSolver); } } else if (node instanceof IfStmt) { - return new NoSymbolDeclarator((IfStmt) node, typeSolver); + return new NoSymbolDeclarator<>((IfStmt) node, typeSolver); } else if (node instanceof ForeachStmt) { ForeachStmt foreachStmt = (ForeachStmt) node; - return new VariableSymbolDeclarator((VariableDeclarationExpr) (foreachStmt.getVariable()), typeSolver); + return new VariableSymbolDeclarator(foreachStmt.getVariable(), typeSolver); } else { - return new NoSymbolDeclarator(node, typeSolver); + return new NoSymbolDeclarator<>(node, typeSolver); } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java index 1e15571d7..44c8d2715 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java @@ -1,7 +1,6 @@ package com.github.javaparser.symbolsolver.javaparsermodel; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.Parameter; @@ -10,9 +9,9 @@ import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.ReturnStmt; -import com.github.javaparser.ast.stmt.Statement; import com.github.javaparser.ast.type.UnknownType; import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; @@ -41,7 +40,8 @@ import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; +import static com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes; public class TypeExtractor extends DefaultVisitorAdapter { @@ -64,13 +64,12 @@ public class TypeExtractor extends DefaultVisitorAdapter { @Override public ResolvedType visit(VariableDeclarator node, Boolean solveLambdas) { - if (getParentNode(node) instanceof FieldDeclaration) { + if (requireParentNode(node) instanceof FieldDeclaration) { return facade.convertToUsageVariableType(node); - } else if (getParentNode(node) instanceof VariableDeclarationExpr) { + } else if (requireParentNode(node) instanceof VariableDeclarationExpr) { return facade.convertToUsageVariableType(node); - } else { - throw new UnsupportedOperationException(getParentNode(node).getClass().getCanonicalName()); } + throw new UnsupportedOperationException(requireParentNode(node).getClass().getCanonicalName()); } @Override @@ -191,14 +190,14 @@ public class TypeExtractor extends DefaultVisitorAdapter { return solveDotExpressionType( typeAccessedStatically.getCorrespondingDeclaration().asReferenceType(), node); } - } else if (node.getScope()instanceof ThisExpr){ + } else if (node.getScope() instanceof ThisExpr) { // If we are accessing through a 'this' expression, first resolve the type // corresponding to 'this' SymbolReference solve = facade.solve((ThisExpr) node.getScope()); // If found get it's declaration and get the field in there - if (solve.isSolved()){ + if (solve.isSolved()) { ResolvedTypeDeclaration correspondingDeclaration = solve.getCorrespondingDeclaration(); - if (correspondingDeclaration instanceof ResolvedReferenceTypeDeclaration){ + if (correspondingDeclaration instanceof ResolvedReferenceTypeDeclaration) { return solveDotExpressionType(correspondingDeclaration.asReferenceType(), node); } } @@ -210,10 +209,10 @@ public class TypeExtractor extends DefaultVisitorAdapter { return solveDotExpressionType(sr.getCorrespondingDeclaration(), node); } } - Optional value = null; + Optional value = Optional.empty(); try { - value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getField().getId(), node); - } catch (UnsolvedSymbolException use) { + value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node); + } catch (com.github.javaparser.resolution.UnsolvedSymbolException use) { // This node may have a package name as part of its fully qualified name. // We should solve for the type declaration inside this package. SymbolReference sref = typeSolver.tryToSolveType(node.toString()); @@ -221,11 +220,10 @@ public class TypeExtractor extends DefaultVisitorAdapter { return new ReferenceTypeImpl(sref.getCorrespondingDeclaration(), typeSolver); } } - if (value != null && value.isPresent()) { + if (value.isPresent()) { return value.get().getType(); - } else { - throw new UnsolvedSymbolException(node.getField().getId()); } + throw new com.github.javaparser.resolution.UnsolvedSymbolException(node.getName().getId()); } @Override @@ -287,7 +285,7 @@ public class TypeExtractor extends DefaultVisitorAdapter { logger.finest("getType on name expr " + node); Optional value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node); if (!value.isPresent()) { - throw new UnsolvedSymbolException("Solving " + node, node.getName().getId()); + throw new com.github.javaparser.resolution.UnsolvedSymbolException("Solving " + node, node.getName().getId()); } else { return value.get().getType(); } @@ -295,26 +293,25 @@ public class TypeExtractor extends DefaultVisitorAdapter { @Override public ResolvedType visit(ObjectCreationExpr node, Boolean solveLambdas) { - ResolvedType type = facade.convertToUsage(node.getType(), node); - return type; + return facade.convertToUsage(node.getType(), node); } @Override public ResolvedType visit(ThisExpr node, Boolean solveLambdas) { // If 'this' is prefixed by a class eg. MyClass.this - if (node.getClassExpr().isPresent()){ + if (node.getClassExpr().isPresent()) { // Get the class name String className = node.getClassExpr().get().toString(); // Attempt to resolve using a typeSolver SymbolReference clazz = typeSolver.tryToSolveType(className); - if (clazz.isSolved()){ - return new ReferenceTypeImpl(clazz.getCorrespondingDeclaration(),typeSolver); + if (clazz.isSolved()) { + return new ReferenceTypeImpl(clazz.getCorrespondingDeclaration(), typeSolver); } // Attempt to resolve locally in Compilation unit Optional cu = node.getAncestorOfType(CompilationUnit.class); - if (cu.isPresent()){ + if (cu.isPresent()) { Optional classByName = cu.get().getClassByName(className); - if (classByName.isPresent()){ + if (classByName.isPresent()) { return new ReferenceTypeImpl(facade.getTypeDeclaration(classByName.get()), typeSolver); } } @@ -362,12 +359,12 @@ public class TypeExtractor extends DefaultVisitorAdapter { @Override public ResolvedType visit(LambdaExpr node, Boolean solveLambdas) { - if (getParentNode(node) instanceof MethodCallExpr) { - MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node); + if (requireParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr callExpr = (MethodCallExpr) requireParentNode(node); int pos = JavaParserSymbolDeclaration.getParamPos(node); SymbolReference refMethod = facade.solve(callExpr); if (!refMethod.isSolved()) { - throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId()); + throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId()); } logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName()); if (solveLambdas) { @@ -384,7 +381,7 @@ public class TypeExtractor extends DefaultVisitorAdapter { NameExpr nameExpr = (NameExpr) scope; try { SymbolReference type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver); - if (type.isSolved()){ + if (type.isSolved()) { staticCall = true; } } catch (Exception e) { @@ -402,7 +399,7 @@ public class TypeExtractor extends DefaultVisitorAdapter { // We need to replace the type variables Context ctx = JavaParserFactory.getContext(node, typeSolver); - result = facade.solveGenericTypes(result, ctx, typeSolver); + result = solveGenericTypes(result, ctx, typeSolver); //We should find out which is the functional method (e.g., apply) and replace the params of the //solveLambdas with it, to derive so the values. We should also consider the value returned by the @@ -424,28 +421,19 @@ public class TypeExtractor extends DefaultVisitorAdapter { ResolvedType actualType; if (lambdaExpr.getBody() instanceof ExpressionStmt) { - actualType = facade.getType(((ExpressionStmt)lambdaExpr.getBody()).getExpression()); + actualType = facade.getType(((ExpressionStmt) lambdaExpr.getBody()).getExpression()); } else if (lambdaExpr.getBody() instanceof BlockStmt) { BlockStmt blockStmt = (BlockStmt) lambdaExpr.getBody(); - NodeList statements = blockStmt.getStatements(); // Get all the return statements in the lambda block - List returnStmts = blockStmt.getNodesByType(ReturnStmt.class); - - if (returnStmts.size() > 0){ + List returnStmts = blockStmt.findAll(ReturnStmt.class); + if (returnStmts.size() > 0) { actualType = returnStmts.stream() - .map(returnStmt -> { - Optional expression = returnStmt.getExpression(); - if (expression.isPresent()){ - return facade.getType(expression.get()); - } else{ - return ResolvedVoidType.INSTANCE; - } - }) - .filter(x -> x != null && !x.isVoid() && !x.isNull()) - .findFirst() - .orElse(ResolvedVoidType.INSTANCE); + .map(returnStmt -> returnStmt.getExpression().map(e -> facade.getType(e)).orElse(ResolvedVoidType.INSTANCE)) + .filter(x -> x != null && !x.isVoid() && !x.isNull()) + .findFirst() + .orElse(ResolvedVoidType.INSTANCE); } else { return ResolvedVoidType.INSTANCE; @@ -465,7 +453,7 @@ public class TypeExtractor extends DefaultVisitorAdapter { // if the functional method returns void anyway // we don't need to bother inferring types - if (!(formalType instanceof ResolvedVoidType)){ + if (!(formalType instanceof ResolvedVoidType)) { lambdaCtx.addPair(result, functionalTypeWithReturn); result = lambdaCtx.resolve(lambdaCtx.addSingle(result)); } @@ -482,12 +470,12 @@ public class TypeExtractor extends DefaultVisitorAdapter { @Override public ResolvedType visit(MethodReferenceExpr node, Boolean solveLambdas) { - if (getParentNode(node) instanceof MethodCallExpr) { - MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node); + if (requireParentNode(node) instanceof MethodCallExpr) { + MethodCallExpr callExpr = (MethodCallExpr) requireParentNode(node); int pos = JavaParserSymbolDeclaration.getParamPos(node); SymbolReference refMethod = facade.solve(callExpr, false); if (!refMethod.isSolved()) { - throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId()); + throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId()); } logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName()); //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos)); @@ -496,40 +484,34 @@ public class TypeExtractor extends DefaultVisitorAdapter { ResolvedType result = usage.getParamType(pos); // We need to replace the type variables Context ctx = JavaParserFactory.getContext(node, typeSolver); - result = facade.solveGenericTypes(result, ctx, typeSolver); + result = solveGenericTypes(result, ctx, typeSolver); //We should find out which is the functional method (e.g., apply) and replace the params of the //solveLambdas with it, to derive so the values. We should also consider the value returned by the //lambdas - Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result); - if (functionalMethod.isPresent()) { - if (node instanceof MethodReferenceExpr) { - MethodReferenceExpr methodReferenceExpr = (MethodReferenceExpr) node; + if (FunctionalInterfaceLogic.getFunctionalMethod(result).isPresent()) { + MethodReferenceExpr methodReferenceExpr = node; - ResolvedType actualType = facade.toMethodUsage(methodReferenceExpr).returnType(); - ResolvedType formalType = functionalMethod.get().returnType(); + ResolvedType actualType = facade.toMethodUsage(methodReferenceExpr).returnType(); + ResolvedType formalType = FunctionalInterfaceLogic.getFunctionalMethod(result).get().returnType(); - InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE); - inferenceContext.addPair(formalType, actualType); - result = inferenceContext.resolve(inferenceContext.addSingle(result)); - } + InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE); + inferenceContext.addPair(formalType, actualType); + result = inferenceContext.resolve(inferenceContext.addSingle(result)); } return result; - } else { - return refMethod.getCorrespondingDeclaration().getParam(pos).getType(); } - } else { - throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value"); + return refMethod.getCorrespondingDeclaration().getParam(pos).getType(); } + throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value"); } @Override public ResolvedType visit(FieldDeclaration node, Boolean solveLambdas) { if (node.getVariables().size() == 1) { return node.getVariables().get(0).accept(this, solveLambdas); - } else { - throw new IllegalArgumentException("Cannot resolve the type of a field with multiple variable declarations. Pick one"); } + throw new IllegalArgumentException("Cannot resolve the type of a field with multiple variable declarations. Pick one"); } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java index 21dcf7c9e..f7ab7d11e 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java @@ -22,7 +22,7 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; /** * @author Federico Tomassetti * - * @deprecated Use {@link com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException} instead + * @deprecated Use {@link com.github.javaparser.resolution.UnsolvedSymbolException} instead */ // Use the one in model instead @Deprecated @@ -32,24 +32,28 @@ public class UnsolvedSymbolException extends RuntimeException { private String name; private TypeSolver typeSolver; + @Deprecated public UnsolvedSymbolException(String name, TypeSolver typeSolver) { super("Unsolved symbol : " + name + " using typesolver " + typeSolver); this.typeSolver = typeSolver; this.name = name; } + @Deprecated public UnsolvedSymbolException(Context context, String name) { super("Unsolved symbol in " + context + " : " + name); this.context = context.toString(); this.name = name; } + @Deprecated public UnsolvedSymbolException(String context, String name) { super("Unsolved symbol in " + context + " : " + name); this.context = context; this.name = name; } + @Deprecated public UnsolvedSymbolException(String name) { super("Unsolved symbol : " + name); this.context = "unknown"; diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java index e2f348ce1..cc008a527 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java @@ -35,13 +35,11 @@ import com.github.javaparser.symbolsolver.model.resolution.Value; import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Optional; +import java.util.*; import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; +import static java.util.Collections.*; /** * @author Federico Tomassetti @@ -55,7 +53,7 @@ public abstract class AbstractJavaParserContext implements Conte /// Static methods /// - public static final SymbolReference solveWith(SymbolDeclarator symbolDeclarator, String name) { + public static SymbolReference solveWith(SymbolDeclarator symbolDeclarator, String name) { for (ResolvedValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) { if (decl.getName().equals(name)) { return SymbolReference.solved(decl); @@ -109,8 +107,9 @@ public abstract class AbstractJavaParserContext implements Conte @Override public final Context getParent() { - if (getParentNode(wrappedNode) instanceof MethodCallExpr) { - MethodCallExpr parentCall = (MethodCallExpr) getParentNode(wrappedNode); + Node parent = wrappedNode.getParentNode().orElse(null); + if (parent instanceof MethodCallExpr) { + MethodCallExpr parentCall = (MethodCallExpr) parent; boolean found = false; if (parentCall.getArguments() != null) { for (Expression expression : parentCall.getArguments()) { @@ -120,16 +119,16 @@ public abstract class AbstractJavaParserContext implements Conte } } if (found) { - Node notMethod = getParentNode(wrappedNode); + Node notMethod = parent; while (notMethod instanceof MethodCallExpr) { - notMethod = getParentNode(notMethod); + notMethod = requireParentNode(notMethod); } return JavaParserFactory.getContext(notMethod, typeSolver); } } - Node notMethod = getParentNode(wrappedNode); + Node notMethod = parent; while (notMethod instanceof MethodCallExpr || notMethod instanceof FieldAccessExpr) { - notMethod = getParentNode(notMethod); + notMethod = notMethod.getParentNode().orElse(null); } if (notMethod == null) { return null; @@ -144,7 +143,7 @@ public abstract class AbstractJavaParserContext implements Conte protected Optional solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) { return symbolDeclarator.getSymbolDeclarations().stream() .filter(d -> d.getName().equals(name)) - .map(d -> Value.from(d)) + .map(Value::from) .findFirst(); } @@ -157,40 +156,38 @@ public abstract class AbstractJavaParserContext implements Conte NameExpr scopeAsName = (NameExpr) scope; SymbolReference symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver); if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) { - return Arrays.asList(symbolReference.getCorrespondingDeclaration().asReferenceType()); + return singletonList(symbolReference.getCorrespondingDeclaration().asReferenceType()); } } - ResolvedType typeOfScope = null; + ResolvedType typeOfScope; try { typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); } catch (Exception e) { - throw new RuntimeException(String.format("Issue calculating the type of the scope of " + this), e); + throw new RuntimeException("Issue calculating the type of the scope of " + this, e); } if (typeOfScope.isWildcard()) { if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) { - return Arrays.asList(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration()); + return singletonList(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration()); } else { - return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + return singletonList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); } } else if (typeOfScope.isArray()) { // method call on array are Object methods - return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + return singletonList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); } else if (typeOfScope.isTypeVariable()) { Collection result = new ArrayList<>(); for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { result.add(bound.getType().asReferenceType().getTypeDeclaration()); } return result; - } else if (typeOfScope.isConstraint()){ - return Arrays.asList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration()); - } else { - return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + } else if (typeOfScope.isConstraint()) { + return singletonList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration()); } - } else { - ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); - return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + return singletonList(typeOfScope.asReferenceType().getTypeDeclaration()); } + ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); + return singletonList(typeOfScope.asReferenceType().getTypeDeclaration()); } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java index 4e7b760bd..d611d71a5 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java @@ -79,7 +79,7 @@ public abstract class AbstractMethodLikeDeclarationContext } // Local types - List localTypes = wrappedNode.getChildNodesByType( + List localTypes = wrappedNode.findAll( com.github.javaparser.ast.body.TypeDeclaration.class); for (com.github.javaparser.ast.body.TypeDeclaration localType : localTypes) { if (localType.getName().getId().equals(name)) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java index 77965bd08..cf3fe3b0c 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java @@ -32,7 +32,7 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import java.util.List; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; public class ForStatementContext extends AbstractJavaParserContext { @@ -55,7 +55,7 @@ public class ForStatementContext extends AbstractJavaParserContext { } } - if (getParentNode(wrappedNode) instanceof NodeWithStatements) { + if (requireParentNode(wrappedNode) instanceof NodeWithStatements) { return StatementContext.solveInBlock(name, typeSolver, wrappedNode); } else { return getParent().solveSymbol(name, typeSolver); diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java index ed874899f..ba412023d 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java @@ -28,7 +28,7 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import java.util.List; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; public class ForechStatementContext extends AbstractJavaParserContext { @@ -45,7 +45,7 @@ public class ForechStatementContext extends AbstractJavaParserContext { int index = 0; for (ResolvedValueDeclaration decl : sb.getSymbolDeclarations()) { if (decl.getName().equals(name)) { - if (getParentNode(wrappedNode) instanceof MethodCallExpr) { - MethodCallExpr methodCallExpr = (MethodCallExpr) getParentNode(wrappedNode); + if (requireParentNode(wrappedNode) instanceof MethodCallExpr) { + MethodCallExpr methodCallExpr = (MethodCallExpr) requireParentNode(wrappedNode); MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(methodCallExpr); int i = pos(methodCallExpr, wrappedNode); ResolvedType lambdaType = methodUsage.getParamTypes().get(i); @@ -101,8 +100,8 @@ public class LambdaExprContext extends AbstractJavaParserContext { } else{ return Optional.empty(); } - } else if (getParentNode(wrappedNode) instanceof VariableDeclarator) { - VariableDeclarator variableDeclarator = (VariableDeclarator) getParentNode(wrappedNode); + } else if (requireParentNode(wrappedNode) instanceof VariableDeclarator) { + VariableDeclarator variableDeclarator = (VariableDeclarator) requireParentNode(wrappedNode); ResolvedType t = JavaParserFacade.get(typeSolver).convertToUsageVariableType(variableDeclarator); Optional functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t); if (functionalMethod.isPresent()) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java index 51dd2d6d0..8acab7a8a 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java @@ -34,7 +34,7 @@ import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; import java.util.List; 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 @@ -46,10 +46,10 @@ public class StatementContext extends AbstractJavaParserCon } public static SymbolReference solveInBlock(String name, TypeSolver typeSolver, Statement stmt) { - if (!(getParentNode(stmt) instanceof NodeWithStatements)) { + if (!(requireParentNode(stmt) instanceof NodeWithStatements)) { throw new IllegalArgumentException(); } - NodeWithStatements blockStmt = (NodeWithStatements) getParentNode(stmt); + NodeWithStatements blockStmt = (NodeWithStatements) requireParentNode(stmt); int position = -1; for (int i = 0; i < blockStmt.getStatements().size(); i++) { if (blockStmt.getStatements().get(i).equals(stmt)) { @@ -68,14 +68,14 @@ public class StatementContext extends AbstractJavaParserCon } // if nothing is found we should ask the parent context - return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbol(name, typeSolver); + return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbol(name, typeSolver); } public static Optional solveInBlockAsValue(String name, TypeSolver typeSolver, Statement stmt) { - if (!(getParentNode(stmt) instanceof NodeWithStatements)) { + if (!(requireParentNode(stmt) instanceof NodeWithStatements)) { throw new IllegalArgumentException(); } - NodeWithStatements blockStmt = (NodeWithStatements) getParentNode(stmt); + NodeWithStatements blockStmt = (NodeWithStatements) requireParentNode(stmt); int position = -1; for (int i = 0; i < blockStmt.getStatements().size(); i++) { if (blockStmt.getStatements().get(i).equals(stmt)) { @@ -94,7 +94,7 @@ public class StatementContext extends AbstractJavaParserCon } // if nothing is found we should ask the parent context - return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbolAsValue(name, typeSolver); + return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbolAsValue(name, typeSolver); } @Override @@ -108,19 +108,19 @@ public class StatementContext extends AbstractJavaParserCon } // we should look in all the statements preceding, treating them as SymbolDeclarators - if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { + if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { return getParent().solveSymbolAsValue(name, typeSolver); } - if (getParentNode(wrappedNode) instanceof LambdaExpr) { + if (requireParentNode(wrappedNode) instanceof LambdaExpr) { return getParent().solveSymbolAsValue(name, typeSolver); } - if (getParentNode(wrappedNode) instanceof IfStmt) { + if (requireParentNode(wrappedNode) instanceof IfStmt) { return getParent().solveSymbolAsValue(name, typeSolver); } - if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) { + if (!(requireParentNode(wrappedNode) instanceof NodeWithStatements)) { return getParent().solveSymbolAsValue(name, typeSolver); } - NodeWithStatements nodeWithStmt = (NodeWithStatements) getParentNode(wrappedNode); + NodeWithStatements nodeWithStmt = (NodeWithStatements) requireParentNode(wrappedNode); int position = -1; for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) { if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) { @@ -154,19 +154,19 @@ public class StatementContext extends AbstractJavaParserCon } // we should look in all the statements preceding, treating them as SymbolDeclarators - if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { + if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) { return getParent().solveSymbol(name, typeSolver); } - if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.ConstructorDeclaration) { + if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.ConstructorDeclaration) { return getParent().solveSymbol(name, typeSolver); } - if (getParentNode(wrappedNode) instanceof LambdaExpr) { + if (requireParentNode(wrappedNode) instanceof LambdaExpr) { return getParent().solveSymbol(name, typeSolver); } - if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) { + if (!(requireParentNode(wrappedNode) instanceof NodeWithStatements)) { return getParent().solveSymbol(name, typeSolver); } - NodeWithStatements nodeWithStmt = (NodeWithStatements) getParentNode(wrappedNode); + NodeWithStatements nodeWithStmt = (NodeWithStatements) requireParentNode(wrappedNode); int position = -1; for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) { if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java index 053cc2de1..15967295b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java @@ -31,7 +31,7 @@ import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; import java.util.List; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -44,7 +44,7 @@ public class SwitchEntryContext extends AbstractJavaParserContext solveSymbol(String name, TypeSolver typeSolver) { - SwitchStmt switchStmt = (SwitchStmt) getParentNode(wrappedNode); + SwitchStmt switchStmt = (SwitchStmt) requireParentNode(wrappedNode); ResolvedType type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector()); if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) { if (type instanceof ReferenceTypeImpl) { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java index de6516436..80932e563 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Optional; import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; public class TryWithResourceContext extends AbstractJavaParserContext { @@ -53,7 +54,7 @@ public class TryWithResourceContext extends AbstractJavaParserContext { } } - if (getParentNode(wrappedNode) instanceof BlockStmt) { + if (requireParentNode(wrappedNode) instanceof BlockStmt) { return StatementContext.solveInBlockAsValue(name, typeSolver, wrappedNode); } else { return getParent().solveSymbolAsValue(name, typeSolver); @@ -72,7 +73,7 @@ public class TryWithResourceContext extends AbstractJavaParserContext { } } - if (getParentNode(wrappedNode) instanceof BlockStmt) { + if (requireParentNode(wrappedNode) instanceof BlockStmt) { return StatementContext.solveInBlock(name, typeSolver, wrappedNode); } else { return getParent().solveSymbol(name, typeSolver); 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 index 18bc92cd1..d34e16412 100644 --- 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 @@ -55,14 +55,14 @@ class Helper { return p.get().getName().toString(); } } else if (container != null) { - return getPackageName(getParentNode(container)); + 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, getParentNode(container)); + String b = getClassName(base, container.getParentNode().orElse(null)); String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId(); if (b.isEmpty()) { return cn; @@ -70,7 +70,7 @@ class Helper { return b + "." + cn; } } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) { - String b = getClassName(base, getParentNode(container)); + String b = getClassName(base, container.getParentNode().orElse(null)); String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId(); if (b.isEmpty()) { return cn; @@ -78,7 +78,7 @@ class Helper { return b + "." + cn; } } else if (container != null) { - return getClassName(base, getParentNode(container)); + 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 index c9431f6b6..1f6c6f33f 100644 --- 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 @@ -70,7 +70,7 @@ public class JavaParserAnnotationDeclaration extends AbstractTypeDeclaration imp @Override public String getQualifiedName() { - String containerName = Helper.containerName(getParentNode(wrappedNode)); + String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null)); if (containerName.isEmpty()) { return wrappedNode.getName().getId(); } else { 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 index 7a6abeba0..3d2cb8f69 100644 --- 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 @@ -51,7 +51,7 @@ public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaratio .get() .stream() .filter(node -> memberClass.isAssignableFrom(node.getClass())) - .map(node -> (T) node) + .map(memberClass::cast) .collect(Collectors.toList()); } else { return Collections.emptyList(); @@ -171,7 +171,7 @@ public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaratio @Override public String getQualifiedName() { - String containerName = Helper.containerName(getParentNode(wrappedNode)); + String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null)); if (containerName.isEmpty()) { return getName(); } else { 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 index 9b1979aad..bb9f91cc6 100644 --- 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 @@ -21,13 +21,13 @@ 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.javaparsermodel.UnsolvedSymbolException; import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 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 index 3ceda1a4e..6f909582d 100644 --- 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 @@ -22,7 +22,7 @@ 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.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -39,7 +39,7 @@ public class JavaParserEnumConstantDeclaration implements ResolvedEnumConstantDe @Override public ResolvedType getType() { - return new ReferenceTypeImpl(new JavaParserEnumDeclaration((EnumDeclaration) getParentNode(wrappedNode), typeSolver), typeSolver); + return new ReferenceTypeImpl(new JavaParserEnumDeclaration((EnumDeclaration) requireParentNode(wrappedNode), typeSolver), typeSolver); } @Override 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 index 464aa7b83..818c0604c 100644 --- 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 @@ -22,6 +22,7 @@ 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; @@ -30,7 +31,6 @@ import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParame import com.github.javaparser.symbolsolver.core.resolution.Context; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; -import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException; import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; @@ -49,12 +49,12 @@ public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implement private TypeSolver typeSolver; private com.github.javaparser.ast.body.EnumDeclaration wrappedNode; - private JavaParserTypeAdapter javaParserTypeAdapter; + private JavaParserTypeAdapter javaParserTypeAdapter; public JavaParserEnumDeclaration(com.github.javaparser.ast.body.EnumDeclaration wrappedNode, TypeSolver typeSolver) { this.wrappedNode = wrappedNode; this.typeSolver = typeSolver; - this.javaParserTypeAdapter = new JavaParserTypeAdapter(wrappedNode, typeSolver); + this.javaParserTypeAdapter = new JavaParserTypeAdapter<>(wrappedNode, typeSolver); } @Override @@ -106,21 +106,22 @@ public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implement @Override public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + String otherName = other.getQualifiedName(); // Enums cannot be extended - if (other.getQualifiedName().equals(this.getQualifiedName())) { + if (otherName.equals(this.getQualifiedName())) { return true; } - if (other.getQualifiedName().equals(Enum.class.getCanonicalName())) { + if (otherName.equals(Enum.class.getCanonicalName())) { return true; } // Enum implements Comparable and Serializable - if (other.getQualifiedName().equals(Comparable.class.getCanonicalName())) { + if (otherName.equals(Comparable.class.getCanonicalName())) { return true; } - if (other.getQualifiedName().equals(Serializable.class.getCanonicalName())) { + if (otherName.equals(Serializable.class.getCanonicalName())) { return true; } - if (other.getQualifiedName().equals(Object.class.getCanonicalName())) { + if (otherName.equals(Object.class.getCanonicalName())) { return true; } return false; 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 index fe55deeb4..1c9e00511 100644 --- 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 @@ -31,6 +31,7 @@ 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 @@ -48,10 +49,10 @@ public class JavaParserFieldDeclaration implements ResolvedFieldDeclaration { } this.variableDeclarator = variableDeclarator; this.typeSolver = typeSolver; - if (!(getParentNode(variableDeclarator) instanceof com.github.javaparser.ast.body.FieldDeclaration)) { - throw new IllegalStateException(getParentNode(variableDeclarator).getClass().getCanonicalName()); + 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) getParentNode(variableDeclarator); + this.wrappedNode = (com.github.javaparser.ast.body.FieldDeclaration) requireParentNode(variableDeclarator); } public JavaParserFieldDeclaration(EnumConstantDeclaration enumConstantDeclaration, TypeSolver typeSolver) { @@ -65,12 +66,10 @@ public class JavaParserFieldDeclaration implements ResolvedFieldDeclaration { @Override public ResolvedType getType() { if (enumConstantDeclaration != null) { - com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = (com.github.javaparser.ast.body.EnumDeclaration) getParentNode(enumConstantDeclaration); + com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = (com.github.javaparser.ast.body.EnumDeclaration) requireParentNode(enumConstantDeclaration); return new ReferenceTypeImpl(new JavaParserEnumDeclaration(enumDeclaration, typeSolver), typeSolver); - } else { - ResolvedType retType = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode); - return retType; } + return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode); } @Override @@ -113,11 +112,10 @@ public class JavaParserFieldDeclaration implements ResolvedFieldDeclaration { @Override public ResolvedTypeDeclaration declaringType() { - Optional typeDeclaration = Navigator.findAncestor(wrappedNode, com.github.javaparser.ast.body.TypeDeclaration.class); + Optional typeDeclaration = wrappedNode.findParent(com.github.javaparser.ast.body.TypeDeclaration.class); if (typeDeclaration.isPresent()) { return JavaParserFacade.get(typeSolver).getTypeDeclaration(typeDeclaration.get()); - } else { - throw new IllegalStateException(); } + 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 index 5d33bcdce..34955a0c0 100644 --- 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 @@ -22,13 +22,13 @@ 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.javaparsermodel.UnsolvedSymbolException; import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.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 index b352e905a..4f3cb3569 100644 --- 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 @@ -34,7 +34,7 @@ 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.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -59,12 +59,11 @@ public class JavaParserMethodDeclaration implements ResolvedMethodDeclaration { @Override public ResolvedReferenceTypeDeclaration declaringType() { - if (getParentNode(wrappedNode) instanceof ObjectCreationExpr) { - ObjectCreationExpr parentNode = (ObjectCreationExpr) getParentNode(wrappedNode); + if (requireParentNode(wrappedNode) instanceof ObjectCreationExpr) { + ObjectCreationExpr parentNode = (ObjectCreationExpr) requireParentNode(wrappedNode); return new JavaParserAnonymousClassDeclaration(parentNode, typeSolver); - } else { - return JavaParserFactory.toTypeDeclaration(getParentNode(wrappedNode), typeSolver); } + return JavaParserFactory.toTypeDeclaration(requireParentNode(wrappedNode), typeSolver); } @Override 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 index 9b8578849..f1f1ffb69 100644 --- 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 @@ -32,7 +32,7 @@ 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.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -69,7 +69,7 @@ public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration { public static int getParamPos(Parameter parameter) { int pos = 0; - for (Node node : getParentNode(parameter).getChildNodes()) { + for (Node node : requireParentNode(parameter).getChildNodes()) { if (node == parameter) { return pos; } else if (node instanceof Parameter) { @@ -80,15 +80,14 @@ public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration { } public static int getParamPos(Node node) { - if (getParentNode(node) instanceof MethodCallExpr) { - MethodCallExpr call = (MethodCallExpr) getParentNode(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(); - } else { - throw new IllegalArgumentException(); } + throw new IllegalArgumentException(); } @Override @@ -123,16 +122,16 @@ public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration { public ResolvedType getType() { if (wrappedNode instanceof Parameter) { Parameter parameter = (Parameter) wrappedNode; - if (getParentNode(wrappedNode) instanceof LambdaExpr) { + if (requireParentNode(wrappedNode) instanceof LambdaExpr) { int pos = getParamPos(parameter); - ResolvedType lambdaType = JavaParserFacade.get(typeSolver).getType(getParentNode(wrappedNode)); + 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 { - ResolvedType rawType = null; + 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 { @@ -140,23 +139,18 @@ public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration { } if (parameter.isVarArgs()) { return new ResolvedArrayType(rawType); - } else { - return rawType; } + return rawType; } } else if (wrappedNode instanceof VariableDeclarator) { VariableDeclarator variableDeclarator = (VariableDeclarator) wrappedNode; - if (getParentNode(wrappedNode) instanceof VariableDeclarationExpr) { - ResolvedType type = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver)); - return type; - } else if (getParentNode(wrappedNode) instanceof FieldDeclaration) { + 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)); - } else { - throw new UnsupportedOperationException(getParentNode(wrappedNode).getClass().getCanonicalName()); } - } else { - throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName()); } + throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName()); } @Override 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 index c65b2d817..198083f7a 100644 --- 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 @@ -1,6 +1,7 @@ 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; @@ -8,6 +9,7 @@ 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; @@ -28,7 +30,7 @@ import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentN /** * @author Federico Tomassetti */ -public class JavaParserTypeAdapter & NodeWithMembers & NodeWithTypeParameters> { +public class JavaParserTypeAdapter & NodeWithMembers> { private T wrappedNode; private TypeSolver typeSolver; @@ -79,8 +81,9 @@ public class JavaParserTypeAdapter & Node } public SymbolReference solveType(String name, TypeSolver typeSolver) { - if (this.wrappedNode.getTypeParameters() != null) { - for (com.github.javaparser.ast.type.TypeParameter typeParameter : this.wrappedNode.getTypeParameters()) { + if(wrappedNode instanceof NodeWithTypeParameters) { + NodeList 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)); } @@ -115,14 +118,13 @@ public class JavaParserTypeAdapter & Node } public Optional containerType() { - Optional parent = wrappedNode.getParentNode(); - return parent.isPresent() ? - Optional.of(JavaParserFactory.toTypeDeclaration(parent.get(), typeSolver)) : - Optional.empty(); + return wrappedNode + .getParentNode() + .map(node -> JavaParserFactory.toTypeDeclaration(node, typeSolver)); } public List getFieldsForDeclaredVariables() { - ArrayList fields = new ArrayList<>(); + List fields = new ArrayList<>(); if (wrappedNode.getMembers() != null) { for (BodyDeclaration member : this.wrappedNode.getMembers()) { if (member instanceof com.github.javaparser.ast.body.FieldDeclaration) { 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 index 79eaf350f..0d1f42e68 100644 --- 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 @@ -36,7 +36,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; +import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; /** * @author Federico Tomassetti @@ -115,7 +115,7 @@ public class JavaParserTypeParameter extends AbstractTypeDeclaration implements @Override public ResolvedTypeParametrizable getContainer() { - Node parentNode = getParentNode(wrappedNode); + 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); @@ -147,8 +147,7 @@ public class JavaParserTypeParameter extends AbstractTypeDeclaration implements private Bound toBound(ClassOrInterfaceType classOrInterfaceType, TypeSolver typeSolver) { ResolvedType type = JavaParserFacade.get(typeSolver).convertToUsage(classOrInterfaceType, classOrInterfaceType); - Bound bound = Bound.extendsBound(type); - return bound; + return Bound.extendsBound(type); } public Context getContext() { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java index be6a66924..88865de0d 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java @@ -35,18 +35,18 @@ public class VariableSymbolDeclarator extends AbstractSymbolDeclarator { + if (p instanceof FieldDeclaration) { + throw new IllegalArgumentException(); + } + }); } @Override public List getSymbolDeclarations() { - List symbols = wrappedNode.getVariables().stream().map( - v -> JavaParserSymbolDeclaration.localVar(v, typeSolver) - ).collect( - Collectors.toCollection(() -> new LinkedList<>())); - return symbols; + return wrappedNode.getVariables().stream() + .map(v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)) + .collect(Collectors.toCollection(LinkedList::new)); } } -- cgit v1.2.3 From be10f7278344dacb0bcc43553579b5add828f9b7 Mon Sep 17 00:00:00 2001 From: Danny van Bruggen Date: Mon, 5 Feb 2018 21:21:02 +0100 Subject: Basic var support --- .../symbolsolver/javaparsermodel/DefaultVisitorAdapter.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java index dc9d86241..499ef3bd0 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java @@ -467,4 +467,9 @@ public class DefaultVisitorAdapter implements GenericVisitor Date: Wed, 14 Feb 2018 18:42:21 +0100 Subject: Make a simple "var" inferrer. --- .../javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java index 4a4783dd4..efe4e9b56 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -473,6 +473,9 @@ public class JavaParserFacade { } else if (type instanceof UnionType) { UnionType unionType = (UnionType) type; return new ResolvedUnionType(unionType.getElements().stream().map(el -> convertToUsage(el, context)).collect(Collectors.toList())); + } else if (type instanceof VarType) { + final VariableDeclarator variableDeclarator = (VariableDeclarator)type.getParentNode().get(); + return variableDeclarator.getInitializer().get().calculateResolvedType(); } else { throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } -- cgit v1.2.3 From 427dd53b9ebedcb0bdb687007eb0faf2de734df4 Mon Sep 17 00:00:00 2001 From: Danny van Bruggen Date: Wed, 14 Feb 2018 19:49:56 +0100 Subject: Better error handling for "var" inferrer. --- .../symbolsolver/javaparsermodel/JavaParserFacade.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel') diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java index efe4e9b56..f73dd986c 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -474,8 +474,14 @@ public class JavaParserFacade { UnionType unionType = (UnionType) type; return new ResolvedUnionType(unionType.getElements().stream().map(el -> convertToUsage(el, context)).collect(Collectors.toList())); } else if (type instanceof VarType) { - final VariableDeclarator variableDeclarator = (VariableDeclarator)type.getParentNode().get(); - return variableDeclarator.getInitializer().get().calculateResolvedType(); + Node parent = type.getParentNode().get(); + if (!(parent instanceof VariableDeclarator)) { + throw new IllegalStateException("Trying to resolve a `var` which is not in a variable declaration."); + } + final VariableDeclarator variableDeclarator = (VariableDeclarator) parent; + return variableDeclarator.getInitializer() + .map(Expression::calculateResolvedType) + .orElseThrow(() -> new IllegalStateException("Cannot resolve `var` which has no initializer.")); } else { throw new UnsupportedOperationException(type.getClass().getCanonicalName()); } -- cgit v1.2.3