diff options
author | Ryan Beckett <beckett.ryan@gmail.com> | 2017-10-07 00:22:00 -0400 |
---|---|---|
committer | Ryan Beckett <beckett.ryan@gmail.com> | 2017-10-07 00:22:00 -0400 |
commit | 18fc54740d8373ac384ba2811dc308296dcca429 (patch) | |
tree | 0a3d3f44a29cbf02a57a94417f3c5f337030fa03 /javaparser-core/src/main | |
parent | 5807302b24c943577962b65e75fd647c23fe1cc9 (diff) | |
parent | d4e119c24f16decfba0d67898530418139a0db11 (diff) | |
download | javaparser-18fc54740d8373ac384ba2811dc308296dcca429.tar.gz |
Merge branch '#1072_visitor_set' of https://github.com/ryan-beckett/javaparser into #1072_visitor_set
Diffstat (limited to 'javaparser-core/src/main')
49 files changed, 3740 insertions, 15 deletions
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java index 5f45e75b0..0694d5cd7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Node.java @@ -41,6 +41,7 @@ import com.github.javaparser.metamodel.NodeMetaModel; import com.github.javaparser.metamodel.PropertyMetaModel; import com.github.javaparser.printer.PrettyPrinter; import com.github.javaparser.printer.PrettyPrinterConfiguration; +import com.github.javaparser.resolution.SymbolResolver; import javax.annotation.Generated; import java.util.*; @@ -663,4 +664,17 @@ public abstract class Node implements Cloneable, HasParentNode<Node>, Visitable, } return Optional.empty(); } + + protected SymbolResolver getSymbolResolver() { + return findCompilationUnit().map(cu -> { + SymbolResolver symbolResolver = cu.getData(SYMBOL_RESOLVER_KEY); + if (symbolResolver == null) { + throw new IllegalStateException("Symbol resolution not configured"); + } + return symbolResolver; + }).orElseThrow(() -> new IllegalStateException("The node is not inserted in a CompilationUnit")); + } + + // We need to expose it because we will need to use it to inject the SymbolSolver + public static final DataKey<SymbolResolver> SYMBOL_RESOLVER_KEY = new DataKey<SymbolResolver>() { }; } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java index f0bbaaa8d..ccda1673d 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java @@ -48,6 +48,9 @@ import com.github.javaparser.metamodel.MethodDeclarationMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.Resolvable; +import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; + import java.util.function.Consumer; /** @@ -59,7 +62,7 @@ import java.util.function.Consumer; * * @author Julio Vilmar Gesser */ -public final class MethodDeclaration extends CallableDeclaration<MethodDeclaration> implements NodeWithType<MethodDeclaration, Type>, NodeWithOptionalBlockStmt<MethodDeclaration>, NodeWithJavadoc<MethodDeclaration>, NodeWithDeclaration, NodeWithSimpleName<MethodDeclaration>, NodeWithParameters<MethodDeclaration>, NodeWithThrownExceptions<MethodDeclaration>, NodeWithTypeParameters<MethodDeclaration>, NodeWithAccessModifiers<MethodDeclaration>, NodeWithAbstractModifier<MethodDeclaration>, NodeWithStaticModifier<MethodDeclaration>, NodeWithFinalModifier<MethodDeclaration>, NodeWithStrictfpModifier<MethodDeclaration> { +public final class MethodDeclaration extends CallableDeclaration<MethodDeclaration> implements NodeWithType<MethodDeclaration, Type>, NodeWithOptionalBlockStmt<MethodDeclaration>, NodeWithJavadoc<MethodDeclaration>, NodeWithDeclaration, NodeWithSimpleName<MethodDeclaration>, NodeWithParameters<MethodDeclaration>, NodeWithThrownExceptions<MethodDeclaration>, NodeWithTypeParameters<MethodDeclaration>, NodeWithAccessModifiers<MethodDeclaration>, NodeWithAbstractModifier<MethodDeclaration>, NodeWithStaticModifier<MethodDeclaration>, NodeWithFinalModifier<MethodDeclaration>, NodeWithStrictfpModifier<MethodDeclaration>, Resolvable<ResolvedMethodDeclaration> { private Type type; @@ -323,4 +326,9 @@ public final class MethodDeclaration extends CallableDeclaration<MethodDeclarati public void ifMethodDeclaration(Consumer<MethodDeclaration> action) { action.accept(this); } + + @Override + public ResolvedMethodDeclaration resolve() { + return getSymbolResolver().resolve(this, ResolvedMethodDeclaration.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java index e51c8adbf..6d5f0c3ff 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java @@ -18,13 +18,13 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
-
package com.github.javaparser.ast.nodeTypes;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.type.VoidType;
@@ -46,6 +46,10 @@ import static java.util.stream.Collectors.toList; * method.
*/
public interface NodeWithMembers<N extends Node> {
+ /**
+ * @return all members inside the braces of this node,
+ * like fields, methods, nested types, etc.
+ */
NodeList<BodyDeclaration<?>> getMembers();
void tryAddImportToParentCompilationUnit(Class<?> clazz);
@@ -82,7 +86,7 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Add a field to this
+ * Add a field to this.
*
* @param type the type of the field
* @param name the name of the field
@@ -94,7 +98,7 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Add a field to this
+ * Add a field to this.
*
* @param type the type of the field
* @param name the name of the field
@@ -112,7 +116,22 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Add a private field to this
+ * Add a field to this.
+ *
+ * @param type the type of the field
+ * @param name the name of the field
+ * @param initializer the initializer of the field
+ * @param modifiers the modifiers like {@link Modifier#PUBLIC}
+ * @return the {@link FieldDeclaration} created
+ */
+ default FieldDeclaration addFieldWithInitializer(Type type, String name, Expression initializer, Modifier... modifiers) {
+ FieldDeclaration declaration = addField(type, name, modifiers);
+ declaration.getVariables().iterator().next().setInitializer(initializer);
+ return declaration;
+ }
+
+ /**
+ * Add a private field to this.
*
* @param typeClass the type of the field
* @param name the name of the field
@@ -124,7 +143,7 @@ public interface NodeWithMembers<N extends Node> { /**
* Add a private field to this and automatically add the import of the type if
- * needed
+ * needed.
*
* @param type the type of the field
* @param name the name of the field
@@ -135,7 +154,7 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Add a public field to this
+ * Add a public field to this.
*
* @param typeClass the type of the field
* @param name the name of the field
@@ -147,7 +166,7 @@ public interface NodeWithMembers<N extends Node> { /**
* Add a public field to this and automatically add the import of the type if
- * needed
+ * needed.
*
* @param type the type of the field
* @param name the name of the field
@@ -158,7 +177,7 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Add a protected field to this
+ * Add a protected field to this.
*
* @param typeClass the type of the field
* @param name the name of the field
@@ -170,7 +189,7 @@ public interface NodeWithMembers<N extends Node> { /**
* Add a protected field to this and automatically add the import of the type
- * if needed
+ * if needed.
*
* @param type the type of the field
* @param name the name of the field
@@ -181,7 +200,7 @@ public interface NodeWithMembers<N extends Node> { }
/**
- * Adds a methods with void return by default to this
+ * Adds a methods with void return by default to this.
*
* @param methodName the method name
* @param modifiers the modifiers like {@link Modifier#PUBLIC}
@@ -197,6 +216,9 @@ public interface NodeWithMembers<N extends Node> { return methodDeclaration;
}
+ /**
+ * Add an initializer block ({@link InitializerDeclaration}) to this.
+ */
default BlockStmt addInitializer() {
BlockStmt block = new BlockStmt();
InitializerDeclaration initializerDeclaration = new InitializerDeclaration(false, block);
@@ -204,6 +226,9 @@ public interface NodeWithMembers<N extends Node> { return block;
}
+ /**
+ * Add a static initializer block ({@link InitializerDeclaration}) to this.
+ */
default BlockStmt addStaticInitializer() {
BlockStmt block = new BlockStmt();
InitializerDeclaration initializerDeclaration = new InitializerDeclaration(true, block);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java index d9ba8bf4a..91cf98369 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ArrayType.java @@ -32,6 +32,7 @@ import com.github.javaparser.ast.visitor.GenericVisitor; import com.github.javaparser.ast.visitor.VoidVisitor; import com.github.javaparser.metamodel.ArrayTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; +import com.github.javaparser.resolution.types.ResolvedArrayType; import com.github.javaparser.utils.Pair; import javax.annotation.Generated; import java.util.ArrayList; @@ -47,6 +48,11 @@ import java.util.function.Consumer; */ public final class ArrayType extends ReferenceType implements NodeWithAnnotations<ArrayType> { + @Override + public ResolvedArrayType resolve() { + return getSymbolResolver().resolve(this, ResolvedArrayType.class); + } + /** * The origin of a pair of array brackets []. */ diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java index 6758234d5..5a7328de4 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java @@ -41,6 +41,8 @@ import static com.github.javaparser.utils.Utils.assertNotNull; import static java.util.stream.Collectors.joining; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedReferenceType; + import java.util.function.Consumer; /** @@ -280,4 +282,10 @@ public final class ClassOrInterfaceType extends ReferenceType implements NodeWit public void ifClassOrInterfaceType(Consumer<ClassOrInterfaceType> action) { action.accept(this); } + + @Override + public ResolvedReferenceType resolve() { + return getSymbolResolver().resolve(this, ResolvedReferenceType.class); + } + } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java index 8a719be4c..8799e7470 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java @@ -38,6 +38,9 @@ import static com.github.javaparser.utils.Utils.assertNotNull; import static java.util.stream.Collectors.joining; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedIntersectionType; +import com.github.javaparser.resolution.types.ResolvedReferenceType; + import java.util.function.Consumer; /** @@ -165,4 +168,9 @@ public final class IntersectionType extends Type implements NodeWithAnnotations< public void ifIntersectionType(Consumer<IntersectionType> action) { action.accept(this); } + + @Override + public ResolvedIntersectionType resolve() { + return getSymbolResolver().resolve(this, ResolvedIntersectionType.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java index c98817533..c88ad7b1d 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java @@ -38,6 +38,9 @@ import com.github.javaparser.metamodel.PrimitiveTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedPrimitiveType; +import com.github.javaparser.resolution.types.ResolvedReferenceType; + import java.util.function.Consumer; /** @@ -219,4 +222,9 @@ public final class PrimitiveType extends Type implements NodeWithAnnotations<Pri public void ifPrimitiveType(Consumer<PrimitiveType> action) { action.accept(this); } + + @Override + public ResolvedPrimitiveType resolve() { + return getSymbolResolver().resolve(this, ResolvedPrimitiveType.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java index f27b32c69..5b0d13b36 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java @@ -29,6 +29,8 @@ import com.github.javaparser.metamodel.ReferenceTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedReferenceType; + import java.util.function.Consumer; /** diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java index 2efe4887e..585bf029b 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/Type.java @@ -21,6 +21,7 @@ package com.github.javaparser.ast.type; import com.github.javaparser.ast.AllFieldsConstructor; +import com.github.javaparser.ast.DataKey; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.expr.AnnotationExpr; @@ -31,7 +32,13 @@ import com.github.javaparser.metamodel.TypeMetaModel; import static com.github.javaparser.utils.Utils.assertNotNull; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.Resolvable; +import com.github.javaparser.resolution.SymbolResolver; +import com.github.javaparser.resolution.types.ResolvedType; + import java.util.function.Consumer; +import java.util.function.Supplier; + import static com.github.javaparser.utils.CodeGenerationUtils.f; /** @@ -39,7 +46,7 @@ import static com.github.javaparser.utils.CodeGenerationUtils.f; * * @author Julio Vilmar Gesser */ -public abstract class Type extends Node { +public abstract class Type extends Node implements Resolvable<Object> { private NodeList<AnnotationExpr> annotations; @@ -288,4 +295,7 @@ public abstract class Type extends Node { @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") public void ifWildcardType(Consumer<WildcardType> action) { } + + @Override + public abstract ResolvedType resolve(); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java index 11d01c50f..3d4f470b7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/TypeParameter.java @@ -30,8 +30,6 @@ import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName; import com.github.javaparser.ast.observer.ObservableProperty; import com.github.javaparser.ast.visitor.GenericVisitor; import com.github.javaparser.ast.visitor.VoidVisitor; -import java.util.Arrays; -import java.util.List; import static com.github.javaparser.utils.Utils.assertNotNull; import static java.util.stream.Collectors.joining; import com.github.javaparser.ast.Node; @@ -40,6 +38,9 @@ import com.github.javaparser.metamodel.TypeParameterMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedTypeVariable; + import java.util.function.Consumer; /** @@ -54,7 +55,8 @@ import java.util.function.Consumer; * @author Julio Vilmar Gesser * @see com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters */ -public final class TypeParameter extends ReferenceType implements NodeWithSimpleName<TypeParameter>, NodeWithAnnotations<TypeParameter> { +public final class TypeParameter extends ReferenceType + implements NodeWithSimpleName<TypeParameter>, NodeWithAnnotations<TypeParameter> { private SimpleName name; @@ -227,4 +229,9 @@ public final class TypeParameter extends ReferenceType implements NodeWithSimple public void ifTypeParameter(Consumer<TypeParameter> action) { action.accept(this); } + + @Override + public ResolvedTypeVariable resolve() { + return getSymbolResolver().resolve(this, ResolvedTypeVariable.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java index e6b48dd36..c60d2c443 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java @@ -38,6 +38,9 @@ import com.github.javaparser.metamodel.UnionTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedUnionType; + import java.util.function.Consumer; /** @@ -174,4 +177,9 @@ public final class UnionType extends Type implements NodeWithAnnotations<UnionTy public void ifUnionType(Consumer<UnionType> action) { action.accept(this); } + + @Override + public ResolvedUnionType resolve() { + return getSymbolResolver().resolve(this, ResolvedUnionType.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java index 2bd7849e7..733fff848 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java @@ -33,6 +33,10 @@ import com.github.javaparser.metamodel.UnknownTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedUnionType; + import java.util.function.Consumer; /** @@ -125,4 +129,9 @@ public final class UnknownType extends Type { public void ifUnknownType(Consumer<UnknownType> action) { action.accept(this); } + + @Override + public ResolvedType resolve() { + return getSymbolResolver().resolve(this, ResolvedReferenceType.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java index 91f21054b..74420da36 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java @@ -34,6 +34,9 @@ import com.github.javaparser.metamodel.VoidTypeMetaModel; import com.github.javaparser.metamodel.JavaParserMetaModel; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedUnionType; +import com.github.javaparser.resolution.types.ResolvedVoidType; + import java.util.function.Consumer; /** @@ -121,4 +124,9 @@ public final class VoidType extends Type implements NodeWithAnnotations<VoidType public void ifVoidType(Consumer<VoidType> action) { action.accept(this); } + + @Override + public ResolvedVoidType resolve() { + return getSymbolResolver().resolve(this, ResolvedVoidType.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java index f685ff8bf..fb23f7a36 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java @@ -36,6 +36,9 @@ import java.util.List; import java.util.Optional; import javax.annotation.Generated; import com.github.javaparser.TokenRange; +import com.github.javaparser.resolution.types.ResolvedUnionType; +import com.github.javaparser.resolution.types.ResolvedWildcard; + import java.util.function.Consumer; /** @@ -276,4 +279,9 @@ public final class WildcardType extends Type implements NodeWithAnnotations<Wild public void ifWildcardType(Consumer<WildcardType> action) { action.accept(this); } + + @Override + public ResolvedWildcard resolve() { + return getSymbolResolver().resolve(this, ResolvedWildcard.class); + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodAmbiguityException.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodAmbiguityException.java new file mode 100644 index 000000000..76632c5ab --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodAmbiguityException.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution; + +/** + * It is not possible to decide how to resolve a method invocation. + * + * @author Federico Tomassetti + */ +public class MethodAmbiguityException extends RuntimeException { + + /** + * Create an instance from a description of the reason why there is ambiguity in this particular case. + */ + public MethodAmbiguityException(String description) { + super(description); + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java new file mode 100644 index 000000000..ec3a06bbe --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution; + +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.ResolvedType; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametrized; + + +import java.util.*; + +/** + * This is basically a MethodDeclaration with some TypeParameters defined. + * The defined TypeParameters can comes from the Method itself or from the surrounding types. + * + * @author Federico Tomassetti + */ +public class MethodUsage implements ResolvedTypeParametrized { + private ResolvedMethodDeclaration declaration; + private List<ResolvedType> paramTypes = new ArrayList<>(); + private List<ResolvedType> exceptionTypes = new ArrayList<>(); + private ResolvedType returnType; + private ResolvedTypeParametersMap typeParametersMap; + + public MethodUsage(ResolvedMethodDeclaration declaration) { + this.typeParametersMap = ResolvedTypeParametersMap.empty(); + this.declaration = declaration; + for (int i = 0; i < declaration.getNumberOfParams(); i++) { + paramTypes.add(declaration.getParam(i).getType()); + } + for (int i = 0; i < declaration.getNumberOfSpecifiedExceptions(); i++) { + exceptionTypes.add(declaration.getSpecifiedException(i)); + } + returnType = declaration.getReturnType(); + } + + public MethodUsage(ResolvedMethodDeclaration declaration, + List<ResolvedType> paramTypes, ResolvedType returnType) { + this(declaration, paramTypes, returnType, declaration.getSpecifiedExceptions(), + ResolvedTypeParametersMap.empty()); + } + + public MethodUsage(ResolvedMethodDeclaration declaration, List<ResolvedType> paramTypes, ResolvedType returnType, + List<ResolvedType> exceptionTypes) { + this(declaration, paramTypes, returnType, exceptionTypes, ResolvedTypeParametersMap.empty()); + } + + private MethodUsage(ResolvedMethodDeclaration declaration, List<ResolvedType> paramTypes, ResolvedType returnType, + List<ResolvedType> exceptionTypes, ResolvedTypeParametersMap typeParametersMap) { + this.declaration = declaration; + this.paramTypes = paramTypes; + this.returnType = returnType; + this.exceptionTypes = exceptionTypes; + this.typeParametersMap = typeParametersMap; + } + + @Override + public String toString() { + return "MethodUsage{" + + "declaration=" + declaration + + ", paramTypes=" + paramTypes + + '}'; + } + + public ResolvedMethodDeclaration getDeclaration() { + return declaration; + } + + public String getName() { + return declaration.getName(); + } + + public ResolvedReferenceTypeDeclaration declaringType() { + return declaration.declaringType(); + } + + public ResolvedType returnType() { + return returnType; + } + + public List<ResolvedType> getParamTypes() { + return paramTypes; + } + + public MethodUsage replaceParamType(int i, ResolvedType replaced) { + if (i < 0 || i >= getNoParams()) { + throw new IllegalArgumentException(); + } + if (paramTypes.get(i) == replaced) { + return this; + } + List<ResolvedType> newParams = new LinkedList<>(paramTypes); + newParams.set(i, replaced); + return new MethodUsage(declaration, newParams, returnType, exceptionTypes, typeParametersMap); + } + + public MethodUsage replaceExceptionType(int i, ResolvedType replaced) { + if (i < 0 || i >= exceptionTypes.size()) { + throw new IllegalArgumentException(); + } + if (exceptionTypes.get(i) == replaced) { + return this; + } + List<ResolvedType> newTypes = new LinkedList<>(exceptionTypes); + newTypes.set(i, replaced); + return new MethodUsage(declaration, paramTypes, returnType, newTypes, typeParametersMap); + } + + public MethodUsage replaceReturnType(ResolvedType returnType) { + if (returnType == this.returnType) { + return this; + } else { + return new MethodUsage(declaration, paramTypes, returnType, exceptionTypes, typeParametersMap); + } + } + + /** + * Return the number of formal arguments accepted by this method. + */ + public int getNoParams() { + return paramTypes.size(); + } + + /** + * Return the type of the formal argument at the given position. + */ + public ResolvedType getParamType(int i) { + return paramTypes.get(i); + } + + public MethodUsage replaceTypeParameter(ResolvedTypeParameterDeclaration typeParameter, ResolvedType type) { + if (type == null) { + throw new IllegalArgumentException(); + } + + // TODO if the method declaration has a type param with that name ignore this call + MethodUsage res = new MethodUsage(declaration, paramTypes, returnType, exceptionTypes, + typeParametersMap.toBuilder().setValue(typeParameter, type).build()); + + Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes = new HashMap<>(); + for (int i = 0; i < paramTypes.size(); i++) { + ResolvedType originalParamType = paramTypes.get(i); + ResolvedType newParamType = originalParamType.replaceTypeVariables(typeParameter, type, inferredTypes); + res = res.replaceParamType(i, newParamType); + } + for (int i = 0; i < exceptionTypes.size(); i++) { + ResolvedType originalType = exceptionTypes.get(i); + ResolvedType newType = originalType.replaceTypeVariables(typeParameter, type, inferredTypes); + res = res.replaceExceptionType(i, newType); + } + ResolvedType oldReturnType = res.returnType; + ResolvedType newReturnType = oldReturnType.replaceTypeVariables(typeParameter, type, inferredTypes); + res = res.replaceReturnType(newReturnType); + return res; + } + + @Override + public ResolvedTypeParametersMap typeParametersMap() { + return typeParametersMap; + } + + public String getQualifiedSignature() { + // TODO use the type parameters + return this.getDeclaration().getQualifiedSignature(); + } + + public List<ResolvedType> exceptionTypes() { + return exceptionTypes; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/Resolvable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/Resolvable.java new file mode 100644 index 000000000..2b12a1bb8 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/Resolvable.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution; + +public interface Resolvable<T> { + T resolve(); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/SymbolResolver.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/SymbolResolver.java new file mode 100644 index 000000000..977fb0904 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/SymbolResolver.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution; + +import com.github.javaparser.ast.Node; + +public interface SymbolResolver { + <T> T resolve(Node node, Class<T> resultClass); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java new file mode 100644 index 000000000..b915096d0 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution; + +/** + * This exception is thrown when a symbol cannot be resolved. + * + * @author Federico Tomassetti + */ +public class UnsolvedSymbolException extends RuntimeException { + + private String context; + private String name; + + public UnsolvedSymbolException(String name, String context) { + 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 + '\''+ + '}'; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java new file mode 100644 index 000000000..5d7e5bb55 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.ast.AccessSpecifier; + +/** + * Anything which can have an AccessSpecifier. + * + * @author Federico Tomassetti + */ +public interface HasAccessSpecifier { + + /** + * The access specifier of this element. + */ + AccessSpecifier accessSpecifier(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java new file mode 100644 index 000000000..f52937c06 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * @author Federico Tomassetti + */ +public interface ResolvedAnnotationDeclaration extends ResolvedReferenceTypeDeclaration { +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java new file mode 100644 index 000000000..08a8d75a2 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.resolution.types.ResolvedReferenceType; + +import java.util.List; + +/** + * Declaration of a Class (not an interface or an enum). + * + * @author Federico Tomassetti + */ +public interface ResolvedClassDeclaration extends ResolvedReferenceTypeDeclaration, + ResolvedTypeParametrizable, HasAccessSpecifier { + + /** + * This method should always return true. + */ + @Override + default boolean isClass() { + return true; + } + + /** + * This is a ReferenceTypeUsage because it could contain type typeParametersValues. + * For example: class A extends B<Integer, String>. + * <p> + * Note that only the Object class should not have a superclass and therefore + * return null. + */ + ResolvedReferenceType getSuperClass(); + + /** + * Return all the interfaces implemented directly by this class. + * It does not include the interfaces implemented by superclasses or extended + * by the interfaces implemented. + */ + List<ResolvedReferenceType> getInterfaces(); + + /** + * Get all superclasses, with all the type typeParametersValues expressed as functions of the type + * typeParametersValues of this declaration. + */ + List<ResolvedReferenceType> getAllSuperClasses(); + + /** + * Return all the interfaces implemented by this class, either directly or indirectly, including the interfaces + * extended by interfaces it implements. + * <p> + * Get all interfaces, with all the type typeParametersValues expressed as functions of the type + * typeParametersValues of this declaration. + */ + List<ResolvedReferenceType> getAllInterfaces(); + + /// + /// Constructors + /// + + /** + * List of constructors available for the class. + * This list should also include the default constructor. + */ + List<ResolvedConstructorDeclaration> getConstructors(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java new file mode 100644 index 000000000..4bc6cb4e4 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * A declaration of a constructor. + * + * @author Federico Tomassetti + */ +public interface ResolvedConstructorDeclaration extends ResolvedMethodLikeDeclaration { + + @Override + ResolvedClassDeclaration declaringType(); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java new file mode 100644 index 000000000..86bee80aa --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * A generic declaration. + * + * @author Federico Tomassetti + */ +public interface ResolvedDeclaration { + + /** + * Anonymous classes do not have a name, for example. + */ + default boolean hasName() { + return true; + } + + /** + * Should return the name or throw a RuntimeException if the name is not available. + */ + String getName(); + + /** + * Does this declaration represents a class field? + */ + default boolean isField() { + return false; + } + + /** + * Does this declaration represents a method parameter? + */ + default boolean isParameter() { + return false; + } + + /** + * Does this declaration represents a type? + */ + default boolean isType() { + return false; + } + + /** + * Does this declaration represents a method? + */ + default boolean isMethod() { + return false; + } + + /** + * Return this as a FieldDeclaration or throw an UnsupportedOperationException + */ + default ResolvedFieldDeclaration asField() { + throw new UnsupportedOperationException(String.format("%s is not a FieldDeclaration", this)); + } + + /** + * Return this as a ParameterDeclaration or throw an UnsupportedOperationException + */ + default ResolvedParameterDeclaration asParameter() { + throw new UnsupportedOperationException(String.format("%s is not a ParameterDeclaration", this)); + } + + /** + * Return this as a TypeDeclaration or throw an UnsupportedOperationException + */ + default ResolvedTypeDeclaration asType() { + throw new UnsupportedOperationException(String.format("%s is not a TypeDeclaration", this)); + } + + /** + * Return this as a MethodDeclaration or throw an UnsupportedOperationException + */ + default ResolvedMethodDeclaration asMethod() { + throw new UnsupportedOperationException(String.format("%s is not a MethodDeclaration", this)); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java new file mode 100644 index 000000000..20fd38932 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * Declaration of an Enum. + * + * @author Federico Tomassetti + */ +public interface ResolvedEnumDeclaration extends ResolvedReferenceTypeDeclaration, + HasAccessSpecifier { + + @Override + default boolean isEnum() { + return true; + } + + @Override + default ResolvedEnumDeclaration asEnum() { + return this; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedFieldDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedFieldDeclaration.java new file mode 100644 index 000000000..194c892c5 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedFieldDeclaration.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * Declaration of a field. + * + * @author Federico Tomassetti + */ +public interface ResolvedFieldDeclaration extends ResolvedValueDeclaration, HasAccessSpecifier { + + /** + * Is the field static? + */ + boolean isStatic(); + + @Override + default boolean isField() { + return true; + } + + @Override + default ResolvedFieldDeclaration asField() { + return this; + } + + /** + * The type on which this field has been declared + */ + ResolvedTypeDeclaration declaringType(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java new file mode 100644 index 000000000..5ef53b2ce --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.resolution.types.ResolvedReferenceType; + +import java.util.ArrayList; +import java.util.List; + +/** + * An interface declaration. + * + * @author Federico Tomassetti + */ +public interface ResolvedInterfaceDeclaration extends ResolvedReferenceTypeDeclaration, + ResolvedTypeParametrizable, HasAccessSpecifier { + + @Override + default boolean isInterface() { + return true; + } + + /** + * Return the list of interfaces extended directly by this one. + */ + List<ResolvedReferenceType> getInterfacesExtended(); + + /** + * Return the list of interfaces extended directly or indirectly by this one. + */ + default List<ResolvedReferenceType> getAllInterfacesExtended() { + List<ResolvedReferenceType> interfaces = new ArrayList<>(); + for (ResolvedReferenceType interfaceDeclaration : getInterfacesExtended()) { + interfaces.add(interfaceDeclaration); + interfaces.addAll(interfaceDeclaration.getAllInterfacesAncestors()); + } + return interfaces; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java new file mode 100644 index 000000000..9f2f64ce3 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.resolution.types.ResolvedType; + +/** + * A declaration of a method (either in an interface, a class, an enum or an annotation). + * + * @author Federico Tomassetti + */ +public interface ResolvedMethodDeclaration extends ResolvedMethodLikeDeclaration { + + /** + * The type of the value returned by the current method. This method can also be invoked + * for methods returning void. + */ + ResolvedType getReturnType(); + + /** + * Is the method abstract? All interface methods not marked as default are abstract. + */ + boolean isAbstract(); + + /** + * Is this a default method? + */ + boolean isDefaultMethod(); + + /* + * Is this method static? + */ + boolean isStatic(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java new file mode 100644 index 000000000..90aa2e72d --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodLikeDeclaration.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.resolution.types.ResolvedType; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +/** + * This is a common interface for MethodDeclaration and ConstructorDeclaration. + * + * @author Federico Tomassetti + */ +public interface ResolvedMethodLikeDeclaration extends ResolvedDeclaration, + ResolvedTypeParametrizable, HasAccessSpecifier { + /** + * The package name of the declaring type. + */ + default String getPackageName() { + return declaringType().getPackageName(); + } + + /** + * The class(es) wrapping the declaring type. + */ + default String getClassName() { + return declaringType().getClassName(); + } + + /** + * The qualified name of the method composed by the qualfied name of the declaring type + * followed by a dot and the name of the method. + */ + default String getQualifiedName() { + return declaringType().getQualifiedName() + "." + this.getName(); + } + + /** + * The signature of the method. + */ + default String getSignature() { + StringBuffer sb = new StringBuffer(); + sb.append(getName()); + sb.append("("); + for (int i = 0; i < getNumberOfParams(); i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(getParam(i).describeType()); + } + sb.append(")"); + return sb.toString(); + } + + /** + * The qualified signature of the method. It is composed by the qualified name of the declaring type + * followed by the signature of the method. + */ + default String getQualifiedSignature() { + return declaringType().getId() + "." + this.getSignature(); + } + + /** + * The type in which the method is declared. + */ + ResolvedReferenceTypeDeclaration declaringType(); + + /** + * Number of params. + */ + int getNumberOfParams(); + + /** + * Get the ParameterDeclaration at the corresponding position or throw IllegalArgumentException. + */ + ResolvedParameterDeclaration getParam(int i); + + /** + * Utility method to get the last ParameterDeclaration. It throws UnsupportedOperationException if the method + * has no parameters. + * The last parameter can be variadic and sometimes it needs to be handled in a special way. + */ + default ResolvedParameterDeclaration getLastParam() { + if (getNumberOfParams() == 0) { + throw new UnsupportedOperationException("This method has no typeParametersValues, therefore it has no a last parameter"); + } + return getParam(getNumberOfParams() - 1); + } + + /** + * Has the method or construcor a variadic parameter? + * Note that when a method has a variadic parameter it should have an array type. + */ + default boolean hasVariadicParameter() { + if (getNumberOfParams() == 0) { + return false; + } else { + return getParam(getNumberOfParams() - 1).isVariadic(); + } + } + + @Override + default Optional<ResolvedTypeParameterDeclaration> findTypeParameter(String name) { + for (ResolvedTypeParameterDeclaration tp : this.getTypeParameters()) { + if (tp.getName().equals(name)) { + return Optional.of(tp); + } + } + return declaringType().findTypeParameter(name); + } + + /** + * Number of exceptions listed in the throws clause. + */ + int getNumberOfSpecifiedExceptions(); + + /** + * Type of the corresponding entry in the throws clause. + * + * @throws IllegalArgumentException if the index is negative or it is equal or greater than the value returned by + * getNumberOfSpecifiedExceptions + * @throws UnsupportedOperationException for those types of methods of constructor that do not declare exceptions + */ + ResolvedType getSpecifiedException(int index); + + default List<ResolvedType> getSpecifiedExceptions() { + if (getNumberOfSpecifiedExceptions() == 0) { + return Collections.emptyList(); + } else { + List<ResolvedType> exceptions = new LinkedList<>(); + for (int i=0;i<getNumberOfSpecifiedExceptions();i++) { + exceptions.add(getSpecifiedException(i)); + } + return exceptions; + } + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java new file mode 100644 index 000000000..668652271 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +/** + * Declaration of a parameter. + * + * @author Federico Tomassetti + */ +public interface ResolvedParameterDeclaration extends ResolvedValueDeclaration { + + @Override + default boolean isParameter() { + return true; + } + + @Override + default ResolvedParameterDeclaration asParameter() { + return this; + } + + /** + * Is this parameter declared as variadic? + */ + boolean isVariadic(); + + /** + * Describe the type of the parameter. In practice add three dots to the type name + * is the parameter is variadic. + */ + default String describeType() { + if (isVariadic()) { + return getType().asArrayType().getComponentType().describe() + "..."; + } else { + return getType().describe(); + } + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java new file mode 100644 index 000000000..b39521067 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public interface ResolvedReferenceTypeDeclaration extends ResolvedTypeDeclaration, + ResolvedTypeParametrizable { + + @Override + default ResolvedReferenceTypeDeclaration asReferenceType() { + return this; + } + + /// + /// Ancestors + /// + + /** + * The list of all the direct ancestors of the current declaration. + * Note that the ancestor can be parametrized types with values specified. For example: + * <p> + * class A implements Comparable<String> {} + * <p> + * In this case the ancestor is Comparable<String> + */ + List<ResolvedReferenceType> getAncestors(); + + /** + * The list of all the ancestors of the current declaration, direct and indirect. + * This list does not contains duplicates with the exacting same type parameters. + */ + default List<ResolvedReferenceType> getAllAncestors() { + List<ResolvedReferenceType> ancestors = new ArrayList<>(); + // We want to avoid infinite recursion in case of Object having Object as ancestor + if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) { + for (ResolvedReferenceType ancestor : getAncestors()) { + ancestors.add(ancestor); + for (ResolvedReferenceType inheritedAncestor : ancestor.getAllAncestors()) { + if (!ancestors.contains(inheritedAncestor)) { + ancestors.add(inheritedAncestor); + } + } + } + } + return ancestors; + } + + /// + /// Fields + /// + + /** + * Note that the type of the field should be expressed using the type variables of this particular type. + * Consider for example: + * <p> + * class Foo<E> { E field; } + * <p> + * class Bar extends Foo<String> { } + * <p> + * When calling getField("field") on Foo I should get a FieldDeclaration with type E, while calling it on + * Bar I should get a FieldDeclaration with type String. + */ + default ResolvedFieldDeclaration getField(String name) { + Optional<ResolvedFieldDeclaration> field = this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst(); + if (field.isPresent()) { + return field.get(); + } else { + throw new UnsolvedSymbolException("Field not found: " + name); + } + } + + /** + * Consider only field or inherited field which is not private. + */ + default ResolvedFieldDeclaration getVisibleField(String name) { + Optional<ResolvedFieldDeclaration> field = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst(); + if (field.isPresent()) { + return field.get(); + } else { + throw new IllegalArgumentException(); + } + } + + /** + * Has this type a field with the given name? + */ + default boolean hasField(String name) { + return this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent(); + } + + /** + * Either a declared field or inherited field which is not private. + */ + default boolean hasVisibleField(String name) { + return getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent(); + } + + /** + * Return a list of all fields, either declared in this declaration or inherited. + */ + List<ResolvedFieldDeclaration> getAllFields(); + + /** + * Return a list of all fields declared and the inherited ones which are not private. + */ + default List<ResolvedFieldDeclaration> getVisibleFields() { + return getAllFields().stream() + .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE) + .collect(Collectors.toList()); + } + + /** + * Return a list of all the non static fields, either declared or inherited. + */ + default List<ResolvedFieldDeclaration> getAllNonStaticFields() { + return getAllFields().stream().filter(it -> !it.isStatic()).collect(Collectors.toList()); + } + + /** + * Return a list of all the static fields, either declared or inherited. + */ + default List<ResolvedFieldDeclaration> getAllStaticFields() { + return getAllFields().stream().filter(it -> it.isStatic()).collect(Collectors.toList()); + } + + /** + * Return a list of all the fields declared in this type. + */ + default List<ResolvedFieldDeclaration> getDeclaredFields() { + return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName().equals(getQualifiedName())).collect(Collectors.toList()); + } + + /// + /// Methods + /// + + /** + * Return a list of all the methods declared in this type declaration. + */ + Set<ResolvedMethodDeclaration> getDeclaredMethods(); + + /** + * Return a list of all the methods declared of this type declaration, either declared or inherited. + * Note that it should not include overridden methods. + */ + Set<MethodUsage> getAllMethods(); + + /// + /// Assignability + /// + + /** + * Can we assign instances of the given type to variables having the type defined + * by this declaration? + */ + boolean isAssignableBy(ResolvedType type); + + /** + * Can we assign instances of the type defined by this declaration to variables having the type defined + * by the given type? + */ + default boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + return other.isAssignableBy(this); + } + + /** + * Can we assign instances of the given type to variables having the type defined + * by this declaration? + */ + boolean isAssignableBy(ResolvedReferenceTypeDeclaration other); + + /// + /// Annotations + /// + + /** + * Has the type at least one annotation declared having the specified qualified name? + */ + boolean hasDirectlyAnnotation(String qualifiedName); + + /** + * Has the type at least one annotation declared or inherited having the specified qualified name? + */ + default boolean hasAnnotation(String qualifiedName) { + if (hasDirectlyAnnotation(qualifiedName)) { + return true; + } + return getAllAncestors().stream().anyMatch(it -> it.asReferenceType().getTypeDeclaration().hasDirectlyAnnotation(qualifiedName)); + } + + /** + * This means that the type has a functional method. Conceptually, a functional interface has exactly one abstract method. + * Typically these classes has the FunctionInterface annotation but this is not mandatory. + */ + boolean isFunctionalInterface(); + + /// + /// Type parameters + /// + + @Override + default Optional<ResolvedTypeParameterDeclaration> findTypeParameter(String name) { + for (ResolvedTypeParameterDeclaration tp : this.getTypeParameters()) { + if (tp.getName().equals(name)) { + return Optional.of(tp); + } + } + if (this.containerType().isPresent()) { + return this.containerType().get().findTypeParameter(name); + } + return Optional.empty(); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java new file mode 100644 index 000000000..bb96f00e3 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.resolution.UnsolvedSymbolException; + +import java.util.Optional; +import java.util.Set; + +/** + * A declaration of a type. It could be a primitive type, an enum, a class, an interface + * or a type variable. + * It cannot be an annotation or an array. + * + * @author Federico Tomassetti + */ +public interface ResolvedTypeDeclaration extends ResolvedDeclaration { + + /// + /// Containment + /// + + /** + * Get the list of types defined inside the current type. + */ + default Set<ResolvedReferenceTypeDeclaration> internalTypes() { + throw new UnsupportedOperationException("InternalTypes not available for " + this.getClass().getCanonicalName()); + } + + /** + * Returns a type declaration for the internal type based on name. + * (Does not include internal types inside internal types). + */ + default ResolvedReferenceTypeDeclaration getInternalType(String name) { + Optional<ResolvedReferenceTypeDeclaration> type = + this.internalTypes().stream().filter(f -> f.getName().equals(name)).findFirst(); + return type.orElseThrow(() -> + new UnsolvedSymbolException("Internal type not found: " + name)); + } + + /** + * Does this type contain an internal type with the given name? + * (Does not include internal types inside internal types). + */ + default boolean hasInternalType(String name) { + return this.internalTypes().stream().anyMatch(f -> f.getName().equals(name)); + } + + /** + * Get the ReferenceTypeDeclaration enclosing this declaration. + * + * @return + */ + Optional<ResolvedReferenceTypeDeclaration> containerType(); + + /// + /// Misc + /// + + /** + * Is this the declaration of a class? + * Note that an Enum is not considered a Class in this case. + */ + default boolean isClass() { + return false; + } + + /** + * Is this the declaration of an interface? + */ + default boolean isInterface() { + return false; + } + + /** + * Is this the declaration of an enum? + */ + default boolean isEnum() { + return false; + } + + /** + * Is this the declaration of a type parameter? + */ + default boolean isTypeParameter() { + return false; + } + + @Override + default boolean isType() { + return true; + } + + @Override + default ResolvedTypeDeclaration asType() { + return this; + } + + /** + * Return this as a ClassDeclaration or throw UnsupportedOperationException. + */ + default ResolvedClassDeclaration asClass() { + throw new UnsupportedOperationException(String.format("%s is not a class", this)); + } + + /** + * Return this as a InterfaceDeclaration or throw UnsupportedOperationException. + */ + default ResolvedInterfaceDeclaration asInterface() { + throw new UnsupportedOperationException(String.format("%s is not an interface", this)); + } + + /** + * Return this as a EnumDeclaration or throw UnsupportedOperationException. + */ + default ResolvedEnumDeclaration asEnum() { + throw new UnsupportedOperationException(String.format("%s is not an enum", this)); + } + + /** + * Return this as a TypeParameterDeclaration or throw UnsupportedOperationException. + */ + default ResolvedTypeParameterDeclaration asTypeParameter() { + throw new UnsupportedOperationException(String.format("%s is not a type parameter", this)); + } + + default ResolvedReferenceTypeDeclaration asReferenceType() { + throw new UnsupportedOperationException(String.format("%s is not a reference type", this)); + } + + /** + * The package name of the type. + */ + String getPackageName(); + + /** + * The class(es) wrapping this type. + */ + String getClassName(); + + /** + * The fully qualified name of the type declared. + */ + String getQualifiedName(); + + /** + * The ID corresponds most of the type to the qualified name. It differs only for local + * classes which do not have a qualified name but have an ID. + */ + default String getId() { + String qname = getQualifiedName(); + if (qname == null) { + return String.format("<localClass>:%s", getName()); + } + return qname; + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java new file mode 100644 index 000000000..14326db1f --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + + +import com.github.javaparser.resolution.types.ResolvedType; + +import java.util.List; +import java.util.Optional; + +/** + * Declaration of a type parameter. + * For example: + * <p> + * class A<E extends String>{} + * </p> + * <p> + * In this case <b>E</b> would be a type parameter. + * + * @author Federico Tomassetti + */ +public interface ResolvedTypeParameterDeclaration extends ResolvedTypeDeclaration { + + /** + * Instantiate a TypeParameter defined on a Type with the given data. + */ + static ResolvedTypeParameterDeclaration onType(final String name, String classQName, List<Bound> bounds) { + return new ResolvedTypeParameterDeclaration() { + @Override + public String getName() { + return name; + } + + @Override + public boolean declaredOnType() { + return true; + } + + @Override + public boolean declaredOnMethod() { + return false; + } + + @Override + public boolean declaredOnConstructor() { + return false; + } + + @Override + public String getContainerQualifiedName() { + return classQName; + } + + @Override + public String getContainerId() { + return classQName; + } + + @Override + public ResolvedTypeParametrizable getContainer() { + return null; + } + + @Override + public List<Bound> getBounds() { + return bounds; + } + + @Override + public String toString() { + return "TypeParameter onType " + name; + } + + @Override + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + throw new UnsupportedOperationException(); + } + }; + } + + /** + * Name of the type parameter. + */ + String getName(); + + /** + * Is the type parameter been defined on a type? + */ + default boolean declaredOnType() { + return (getContainer() instanceof ResolvedReferenceTypeDeclaration); + } + + /** + * Is the type parameter been defined on a method? + */ + default boolean declaredOnMethod() { + return (getContainer() instanceof ResolvedMethodDeclaration); + } + + /** + * Is the type parameter been defined on a constructor? + */ + default boolean declaredOnConstructor() { + return (getContainer() instanceof ResolvedConstructorDeclaration); + } + + /** + * The package name of the type bound(s). + * This is unsupported because there is no package for a Type Parameter, only for its container. + */ + default String getPackageName() { + throw new UnsupportedOperationException(); + } + + /** + * The class(es) wrapping the type bound(s). + * This is unsupported because there is no class for a Type Parameter, only for its container. + */ + default String getClassName() { + throw new UnsupportedOperationException(); + } + + /** + * The qualified name of the Type Parameter. + * It is composed by the qualified name of the container followed by a dot and the name of the Type Parameter. + * The qualified name of a method is its qualified signature. + */ + default String getQualifiedName() { + return String.format("%s.%s", getContainerId(), getName()); + } + + /** + * The qualified name of the container. + */ + String getContainerQualifiedName(); + + /** + * The ID of the container. See TypeContainer.getId + */ + String getContainerId(); + + /** + * The TypeParametrizable of the container. Can be either a ReferenceTypeDeclaration or a MethodLikeDeclaration + */ + ResolvedTypeParametrizable getContainer(); + + /** + * The bounds specified for the type parameter. + * For example: + * "extends A" or "super B" + */ + List<Bound> getBounds(); + + /** + * Has the type parameter a lower bound? + */ + default boolean hasLowerBound() { + for (Bound b : getBounds()) { + if (b.isExtends()) { + return true; + } + } + return false; + } + + /** + * Has the type parameter an upper bound? + */ + default boolean hasUpperBound() { + for (Bound b : getBounds()) { + if (b.isSuper()) { + return true; + } + } + return false; + } + + /** + * Get the type used as lower bound. + * + * @throws IllegalStateException if there is no lower bound + */ + default ResolvedType getLowerBound() { + for (Bound b : getBounds()) { + if (b.isExtends()) { + return b.getType(); + } + } + throw new IllegalStateException(); + } + + /** + * Get the type used as upper bound. + * + * @throws IllegalStateException if there is no upper bound + */ + default ResolvedType getUpperBound() { + for (Bound b : getBounds()) { + if (b.isSuper()) { + return b.getType(); + } + } + throw new IllegalStateException(); + } + + /** + * A Bound on a Type Parameter. + */ + class Bound { + private boolean extendsBound; + private ResolvedType type; + + private Bound(boolean extendsBound, ResolvedType type) { + this.extendsBound = extendsBound; + this.type = type; + } + + /** + * Create an extends bound with the given type: + * <p> + * extends "given type" + * </p> + */ + public static Bound extendsBound(ResolvedType type) { + return new Bound(true, type); + } + + /** + * Create a super bound with the given type: + * <p> + * super "given type" + * </p> + */ + public static Bound superBound(ResolvedType type) { + return new Bound(false, type); + } + + /** + * Get the type used in the Bound. + */ + public ResolvedType getType() { + return type; + } + + /** + * Is this an extends bound? + */ + public boolean isExtends() { + return extendsBound; + } + + /** + * Is this a super bound? + */ + public boolean isSuper() { + return !isExtends(); + } + + @Override + public String toString() { + return "Bound{" + + "extendsBound=" + extendsBound + + ", type=" + type + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Bound bound = (Bound) o; + + if (extendsBound != bound.extendsBound) return false; + return type != null ? type.equals(bound.type) : bound.type == null; + } + + @Override + public int hashCode() { + int result = (extendsBound ? 1 : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParametrizable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParametrizable.java new file mode 100644 index 000000000..3d6b92e7a --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParametrizable.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import java.util.List; +import java.util.Optional; + +/** + * An entity which has type parameter. + * + * @author Federico Tomassetti + */ +public interface ResolvedTypeParametrizable { + + /** + * The list of type parameters defined on this element. + */ + List<ResolvedTypeParameterDeclaration> getTypeParameters(); + + /** + * Find the closest TypeParameterDeclaration with the given name. + * It first look on this element itself and then on the containers. + */ + Optional<ResolvedTypeParameterDeclaration> findTypeParameter(String name); + + default boolean isGeneric() { + return !getTypeParameters().isEmpty(); + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedValueDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedValueDeclaration.java new file mode 100644 index 000000000..ee6230ad8 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedValueDeclaration.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + + +import com.github.javaparser.resolution.types.ResolvedType; + +/** + * Declaration of a value. + * + * @author Federico Tomassetti + */ +public interface ResolvedValueDeclaration extends ResolvedDeclaration { + + /** + * Type of the declaration. + */ + ResolvedType getType(); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java new file mode 100644 index 000000000..bc422f75f --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + +import java.util.Map; + +/** + * Array Type. + * + * @author Federico Tomassetti + */ +public class ResolvedArrayType implements ResolvedType { + + private ResolvedType baseType; + + public ResolvedArrayType(ResolvedType baseType) { + this.baseType = baseType; + } + + /// + /// Object methods + /// + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ResolvedArrayType that = (ResolvedArrayType) o; + + if (!baseType.equals(that.baseType)) return false; + + return true; + } + + @Override + public int hashCode() { + return baseType.hashCode(); + } + + @Override + public String toString() { + return "ResolvedArrayType{" + baseType + "}"; + } + + /// + /// Type methods + /// + + @Override + public ResolvedArrayType asArrayType() { + return this; + } + + @Override + public boolean isArray() { + return true; + } + + @Override + public String describe() { + return baseType.describe() + "[]"; + } + + public ResolvedType getComponentType() { + return baseType; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + if (other.isArray()) { + if (baseType.isPrimitive() && other.asArrayType().getComponentType().isPrimitive()) { + return baseType.equals(other.asArrayType().getComponentType()); + } + return baseType.isAssignableBy(other.asArrayType().getComponentType()); + } else if (other.isNull()) { + return true; + } + return false; + } + + @Override + public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + ResolvedType baseTypeReplaced = baseType.replaceTypeVariables(tpToReplace, replaced, inferredTypes); + if (baseTypeReplaced == baseType) { + return this; + } else { + return new ResolvedArrayType(baseTypeReplaced); + } + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java new file mode 100644 index 000000000..e308feace --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedIntersectionType.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * An intersection type is defined in java as list of types separates by ampersands. + * + * @author Federico Tomassetti + */ +public class ResolvedIntersectionType implements ResolvedType { + private List<ResolvedType> elements; + + public ResolvedIntersectionType(Collection<ResolvedType> elements) { + if (elements.size() < 2) { + throw new IllegalArgumentException("An intersection type should have at least two elements. This has " + elements.size()); + } + this.elements = new LinkedList<>(elements); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ResolvedIntersectionType that = (ResolvedIntersectionType) o; + + return new HashSet<>(elements).equals(new HashSet<>(that.elements)); + } + + @Override + public int hashCode() { + return new HashSet<>(elements).hashCode(); + } + + @Override + public String describe() { + return String.join(" & ", elements.stream().map(ResolvedType::describe).collect(Collectors.toList())); + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + return elements.stream().allMatch(e -> e.isAssignableBy(other)); + } + + @Override + public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tp, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + List<ResolvedType> elementsReplaced = elements.stream() + .map(e -> e.replaceTypeVariables(tp, replaced, inferredTypes)) + .collect(Collectors.toList()); + if (elementsReplaced.equals(elements)) { + return this; + } else { + return new ResolvedIntersectionType(elementsReplaced); + } + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedLambdaConstraintType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedLambdaConstraintType.java new file mode 100644 index 000000000..e43d434d8 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedLambdaConstraintType.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +public class ResolvedLambdaConstraintType implements ResolvedType { + private ResolvedType bound; + + private ResolvedLambdaConstraintType(ResolvedType bound) { + this.bound = bound; + } + + @Override + public String describe() { + return "? super " + bound.describe(); + } + + public ResolvedType getBound() { + return bound; + } + + @Override + public boolean isConstraint() { + return true; + } + + @Override + public ResolvedLambdaConstraintType asConstraintType() { + return this; + } + + public static ResolvedLambdaConstraintType bound(ResolvedType bound){ + return new ResolvedLambdaConstraintType(bound); + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + return bound.isAssignableBy(other); + } + + @Override + public String toString() { + return "LambdaConstraintType{" + + "bound=" + bound + + '}'; + } +}
\ No newline at end of file diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java new file mode 100644 index 000000000..05b6102e9 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author Federico Tomassetti + */ +public class ResolvedPrimitiveType implements ResolvedType { + + /// + /// Constants + /// + + public static final ResolvedPrimitiveType BYTE = new ResolvedPrimitiveType("byte", + Byte.class.getCanonicalName(), Collections.emptyList()); + public static final ResolvedPrimitiveType SHORT = new ResolvedPrimitiveType("short", + Short.class.getCanonicalName(), Collections.singletonList(BYTE)); + public static final ResolvedPrimitiveType CHAR = new ResolvedPrimitiveType("char", + Character.class.getCanonicalName(), Collections.emptyList()); + public static final ResolvedPrimitiveType INT = new ResolvedPrimitiveType("int", + Integer.class.getCanonicalName(), Arrays.asList(BYTE, SHORT, CHAR)); + public static final ResolvedPrimitiveType LONG = new ResolvedPrimitiveType("long", + Long.class.getCanonicalName(), Arrays.asList(BYTE, SHORT, INT, CHAR)); + public static final ResolvedPrimitiveType BOOLEAN = new ResolvedPrimitiveType("boolean", + Boolean.class.getCanonicalName(), Collections.emptyList()); + public static final ResolvedPrimitiveType FLOAT = new ResolvedPrimitiveType("float", + Float.class.getCanonicalName(), Arrays.asList(LONG, INT, SHORT, BYTE, CHAR)); + public static final ResolvedPrimitiveType DOUBLE = new ResolvedPrimitiveType("double", + Double.class.getCanonicalName(), Arrays.asList(FLOAT, LONG, INT, SHORT, BYTE, CHAR)); + public static final List<ResolvedPrimitiveType> ALL = Arrays.asList( + INT, BOOLEAN, LONG, CHAR, FLOAT, DOUBLE, SHORT, BYTE); + + /// + /// Fields + /// + + private String name; + private String boxTypeQName; + private List<ResolvedPrimitiveType> promotionTypes; + + private ResolvedPrimitiveType(String name, String boxTypeQName, List<ResolvedPrimitiveType> promotionTypes) { + this.name = name; + this.boxTypeQName = boxTypeQName; + this.promotionTypes = promotionTypes; + } + + public static ResolvedType byName(String name) { + name = name.toLowerCase(); + for (ResolvedPrimitiveType ptu : ALL) { + if (ptu.describe().equals(name)) { + return ptu; + } + } + throw new IllegalArgumentException("Name " + name); + } + + @Override + public String toString() { + return "PrimitiveTypeUsage{" + + "name='" + name + '\'' + + '}'; + } + + public ResolvedPrimitiveType asPrimitive() { + return this; + } + + @Override + public boolean isArray() { + return false; + } + + @Override + public boolean isPrimitive() { + return true; + } + + @Override + public boolean isReferenceType() { + return false; + } + + @Override + public String describe() { + return name; + } + + @Override + public boolean isTypeVariable() { + return false; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + if (other.isPrimitive()) { + return this == other || promotionTypes.contains(other); + } else if (other.isReferenceType()) { + if (other.asReferenceType().getQualifiedName().equals(boxTypeQName)) { + return true; + } + for (ResolvedPrimitiveType promotion : promotionTypes) { + if (other.asReferenceType().getQualifiedName().equals(promotion.boxTypeQName)) { + return true; + } + } + return false; + } else if (other.isConstraint()){ + return this.isAssignableBy(other.asConstraintType().getBound()); + } else { + return false; + } + } + + public String getBoxTypeQName() { + return boxTypeQName; + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java new file mode 100644 index 000000000..4fecaf6ec --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParameterValueProvider; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametrized; +import com.github.javaparser.utils.Pair; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * A ReferenceType like a class, an interface or an enum. Note that this type can contain also the values + * specified for the type parameters. + * + * @author Federico Tomassetti + */ +public abstract class ResolvedReferenceType implements ResolvedType, + ResolvedTypeParametrized, ResolvedTypeParameterValueProvider { + + // + // Fields + // + + protected ResolvedReferenceTypeDeclaration typeDeclaration; + protected ResolvedTypeParametersMap typeParametersMap; + + // + // Constructors + // + + public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration) { + this(typeDeclaration, deriveParams(typeDeclaration)); + } + + public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration, List<ResolvedType> typeArguments) { + if (typeDeclaration.isTypeParameter()) { + throw new IllegalArgumentException("You should use only Classes, Interfaces and enums"); + } + if (typeArguments.size() > 0 && typeArguments.size() != typeDeclaration.getTypeParameters().size()) { + throw new IllegalArgumentException(String.format( + "expected either zero type arguments or has many as defined in the declaration (%d). Found %d", + typeDeclaration.getTypeParameters().size(), typeArguments.size())); + } + ResolvedTypeParametersMap.Builder typeParametersMapBuilder = new ResolvedTypeParametersMap.Builder(); + for (int i = 0; i < typeArguments.size(); i++) { + typeParametersMapBuilder.setValue(typeDeclaration.getTypeParameters().get(i), typeArguments.get(i)); + } + this.typeParametersMap = typeParametersMapBuilder.build(); + this.typeDeclaration = typeDeclaration; + } + + // + // Public Object methods + // + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ResolvedReferenceType that = (ResolvedReferenceType) o; + + if (!typeDeclaration.equals(that.typeDeclaration)) return false; + if (!typeParametersMap.equals(that.typeParametersMap)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = typeDeclaration.hashCode(); + result = 31 * result + typeParametersMap.hashCode(); + return result; + } + + @Override + public String toString() { + return "ReferenceType{" + getQualifiedName() + + ", typeParametersMap=" + typeParametersMap + + '}'; + } + + /// + /// Relation with other types + /// + + @Override + public final boolean isReferenceType() { + return true; + } + + /// + /// Downcasting + /// + + @Override + public ResolvedReferenceType asReferenceType() { + return this; + } + + /// + /// Naming + /// + + @Override + public String describe() { + StringBuilder sb = new StringBuilder(); + if (hasName()) { + sb.append(typeDeclaration.getQualifiedName()); + } else { + sb.append("<anonymous class>"); + } + if (!typeParametersMap().isEmpty()) { + sb.append("<"); + sb.append(String.join(", ", typeDeclaration.getTypeParameters().stream() + .map(tp -> typeParametersMap().getValue(tp).describe()) + .collect(Collectors.toList()))); + sb.append(">"); + } + return sb.toString(); + } + + /// + /// TypeParameters + /// + + /** + * Execute a transformation on all the type parameters of this element. + */ + public abstract ResolvedType transformTypeParameters(ResolvedTypeTransformer transformer); + + @Override + public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, + Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + if (replaced == null) { + throw new IllegalArgumentException(); + } + + ResolvedReferenceType result = this; + int i = 0; + for (ResolvedType tp : this.typeParametersValues()) { + ResolvedType transformedTp = tp.replaceTypeVariables(tpToReplace, replaced, inferredTypes); + // Identity comparison on purpose + if (tp.isTypeVariable() && tp.asTypeVariable().describe().equals(tpToReplace.getName())) { + inferredTypes.put(tp.asTypeParameter(), replaced); + } + // FIXME + if (true) { + List<ResolvedType> typeParametersCorrected = result.asReferenceType().typeParametersValues(); + typeParametersCorrected.set(i, transformedTp); + result = create(typeDeclaration, typeParametersCorrected); + } + i++; + } + + List<ResolvedType> values = result.typeParametersValues(); + // FIXME + if(values.contains(tpToReplace)){ + int index = values.indexOf(tpToReplace); + values.set(index, replaced); + return create(result.getTypeDeclaration(), values); + } + + return result; + } + + /// + /// Assignability + /// + + /** + * This method checks if ThisType t = new OtherType() would compile. + */ + @Override + public abstract boolean isAssignableBy(ResolvedType other); + + /// + /// Ancestors + /// + + /** + * Return all ancestors, that means all superclasses and interfaces. + * This list should always include Object (unless this is a reference to Object). + * The type typeParametersValues should be expressed in terms of this type typeParametersValues. + * <p> + * For example, given: + * <p> + * class Foo<A, B> {} + * class Bar<C> extends Foo<C, String> {} + * <p> + * a call to getAllAncestors on a reference to Bar having type parameter Boolean should include + * Foo<Boolean, String>. + */ + public abstract List<ResolvedReferenceType> getAllAncestors(); + + public final List<ResolvedReferenceType> getAllInterfacesAncestors() { + return getAllAncestors().stream() + .filter(it -> it.getTypeDeclaration().isInterface()) + .collect(Collectors.toList()); + } + + public final List<ResolvedReferenceType> getAllClassesAncestors() { + return getAllAncestors().stream() + .filter(it -> it.getTypeDeclaration().isClass()) + .collect(Collectors.toList()); + } + + /// + /// Type parameters + /// + + /** + * Get the type associated with the type parameter with the given name. + * It returns Optional.empty unless the type declaration declares a type parameter with the given name. + */ + public Optional<ResolvedType> getGenericParameterByName(String name) { + for (ResolvedTypeParameterDeclaration tp : typeDeclaration.getTypeParameters()) { + if (tp.getName().equals(name)) { + return Optional.of(this.typeParametersMap().getValue(tp)); + } + } + return Optional.empty(); + } + + /** + * Get the values for all type parameters declared on this type. + * The list can be empty for raw types. + */ + public List<ResolvedType> typeParametersValues() { + return this.typeParametersMap.isEmpty() ? Collections.emptyList() : typeDeclaration.getTypeParameters().stream().map(tp -> typeParametersMap.getValue(tp)).collect(Collectors.toList()); + } + + /** + * Get the values for all type parameters declared on this type. + * In case of raw types the values correspond to TypeVariables. + */ + public List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> getTypeParametersMap() { + List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParametersMap = new ArrayList<>(); + if (!isRawType()) { + for (int i = 0; i < typeDeclaration.getTypeParameters().size(); i++) { + typeParametersMap.add(new Pair<>(typeDeclaration.getTypeParameters().get(0), typeParametersValues().get(i))); + } + } + return typeParametersMap; + } + + @Override + public ResolvedTypeParametersMap typeParametersMap() { + return typeParametersMap; + } + + /// + /// Other methods introduced by ReferenceType + /// + + /** + * Corresponding TypeDeclaration + */ + public final ResolvedReferenceTypeDeclaration getTypeDeclaration() { + return typeDeclaration; + } + + /** + * The type of the field could be different from the one in the corresponding FieldDeclaration because + * type variables would be solved. + */ + public Optional<ResolvedType> getFieldType(String name) { + if (!typeDeclaration.hasField(name)) { + return Optional.empty(); + } + ResolvedType type = typeDeclaration.getField(name).getType(); + type = useThisTypeParametersOnTheGivenType(type); + return Optional.of(type); + } + + /** + * Has the TypeDeclaration a name? Anonymous classes do not have one. + */ + public boolean hasName() { + return typeDeclaration.hasName(); + } + + /** + * Qualified name of the declaration. + */ + public String getQualifiedName() { + return typeDeclaration.getQualifiedName(); + } + + /** + * Id of the declaration. It corresponds to the qualified name, unless for local classes. + */ + public String getId() { + return typeDeclaration.getId(); + } + + /** + * Methods declared on this type. + */ + public abstract Set<MethodUsage> getDeclaredMethods(); + + public boolean isRawType() { + if (!typeDeclaration.getTypeParameters().isEmpty()) { + if (typeParametersMap().isEmpty()) { + return true; + } + for (String name : typeParametersMap().getNames()) { + Optional<ResolvedType> value = typeParametersMap().getValueBySignature(name); + if (value.isPresent() && value.get().isTypeVariable() && value.get().asTypeVariable().qualifiedName().equals(name)) { + // nothing to do + } else { + return false; + } + } + return true; + } + return false; + } + + public Optional<ResolvedType> typeParamValue(ResolvedTypeParameterDeclaration typeParameterDeclaration) { + if (typeParameterDeclaration.declaredOnMethod()) { + throw new IllegalArgumentException(); + } + String typeId = this.getTypeDeclaration().getId(); + if (typeId.equals(typeParameterDeclaration.getContainerId())) { + return Optional.of(this.typeParametersMap().getValue(typeParameterDeclaration)); + } + for (ResolvedReferenceType ancestor : this.getAllAncestors()) { + if (ancestor.getId().equals(typeParameterDeclaration.getContainerId())) { + return Optional.of(ancestor.typeParametersMap().getValue(typeParameterDeclaration)); + } + } + return Optional.empty(); + } + + public abstract ResolvedType toRawType(); + + // + // Protected methods + // + + protected abstract ResolvedReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration, List<ResolvedType> typeParameters); + + protected ResolvedReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration, ResolvedTypeParametersMap typeParametersMap) { + return create(typeDeclaration, typeDeclaration.getTypeParameters().stream() + .map(typeParametersMap::getValue) + .collect(Collectors.toList())); + } + + protected abstract ResolvedReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration); + + protected boolean isCorrespondingBoxingType(String typeName) { + switch (typeName) { + case "boolean": + return getQualifiedName().equals(Boolean.class.getCanonicalName()); + case "char": + return getQualifiedName().equals(Character.class.getCanonicalName()); + case "byte": + return getQualifiedName().equals(Byte.class.getCanonicalName()); + case "short": + return getQualifiedName().equals(Short.class.getCanonicalName()); + case "int": + return getQualifiedName().equals(Integer.class.getCanonicalName()); + case "long": + return getQualifiedName().equals(Long.class.getCanonicalName()); + case "float": + return getQualifiedName().equals(Float.class.getCanonicalName()); + case "double": + return getQualifiedName().equals(Double.class.getCanonicalName()); + default: + throw new UnsupportedOperationException(typeName); + } + } + + protected boolean compareConsideringTypeParameters(ResolvedReferenceType other) { + if (other.equals(this)) { + return true; + } + if (this.getQualifiedName().equals(other.getQualifiedName())) { + if (this.isRawType() || other.isRawType()) { + return true; + } + if (this.typeParametersValues().size() != other.typeParametersValues().size()) { + throw new IllegalStateException(); + } + for (int i = 0; i < typeParametersValues().size(); i++) { + ResolvedType thisParam = typeParametersValues().get(i); + ResolvedType otherParam = other.typeParametersValues().get(i); + if (!thisParam.equals(otherParam)) { + if (thisParam instanceof ResolvedWildcard) { + ResolvedWildcard thisParamAsWildcard = (ResolvedWildcard) thisParam; + if (thisParamAsWildcard.isSuper() && otherParam.isAssignableBy(thisParamAsWildcard.getBoundedType())) { + // ok + } else if (thisParamAsWildcard.isExtends() && thisParamAsWildcard.getBoundedType().isAssignableBy(otherParam)) { + // ok + } else if (!thisParamAsWildcard.isBounded()) { + // ok + } else { + return false; + } + } else { + if (thisParam instanceof ResolvedTypeVariable && otherParam instanceof ResolvedTypeVariable) { + List<ResolvedType> thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList()); + List<ResolvedType> otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList()); + if (thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds)) { + return true; + } + } + return false; + } + } + } + return true; + } + return false; + } + + // + // Private methods + // + + private static List<ResolvedType> deriveParams(ResolvedReferenceTypeDeclaration typeDeclaration) { + return typeDeclaration.getTypeParameters().stream().map((tp) -> new ResolvedTypeVariable(tp)).collect(Collectors.toList()); + } + + public abstract ResolvedReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java new file mode 100644 index 000000000..4f6857f99 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedType.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A resolved type. It could be a primitive type or a reference type (enum, class, interface). In the later case it + * could take type typeParametersValues (other TypeUsages). It could also be a TypeVariable, like in: + * <p> + * class A<Bgt; { } + * <p> + * where B is a TypeVariable. It could also be Wildcard Type, possibly with constraints. + * + * @author Federico Tomassetti + */ +public interface ResolvedType { + + /// + /// Relation with other types + /// + + /** + * Does this type represent an array? + */ + default boolean isArray() { + return false; + } + + default int arrayLevel() { + if (isArray()) { + return 1 + this.asArrayType().getComponentType().arrayLevel(); + } else { + return 0; + } + } + + /** + * Is this a primitive type? + */ + default boolean isPrimitive() { + return false; + } + + /** + * Is this the null type? + */ + default boolean isNull() { + return false; + } + + /** + * Is this a non primitive value? + */ + default boolean isReference() { + return isReferenceType() || isArray() || isTypeVariable() || isNull() || isWildcard(); + } + + /** + * Is this a lambda constraint type? + */ + default boolean isConstraint() { return false; } + + /** + * Can this be seen as a ReferenceTypeUsage? + * In other words: is this a reference to a class, an interface or an enum? + */ + default boolean isReferenceType() { + return false; + } + + default boolean isVoid() { + return false; + } + + default boolean isTypeVariable() { + return false; + } + + default boolean isWildcard() { + return false; + } + + /// + /// Downcasting + /// + + default ResolvedArrayType asArrayType() { + throw new UnsupportedOperationException(String.format("%s is not an Array", this)); + } + + default ResolvedReferenceType asReferenceType() { + throw new UnsupportedOperationException(String.format("%s is not a Reference Type", this)); + } + + default ResolvedTypeParameterDeclaration asTypeParameter() { + throw new UnsupportedOperationException(String.format("%s is not a Type parameter", this)); + } + + default ResolvedTypeVariable asTypeVariable() { + throw new UnsupportedOperationException(String.format("%s is not a Type variable", this)); + } + + default ResolvedPrimitiveType asPrimitive() { + throw new UnsupportedOperationException(String.format("%s is not a Primitive type", this)); + } + + default ResolvedWildcard asWildcard() { + throw new UnsupportedOperationException(String.format("%s is not a Wildcard", this)); + } + + default ResolvedLambdaConstraintType asConstraintType() { + throw new UnsupportedOperationException(String.format("%s is not a constraint type", this)); + } + + /// + /// Naming + /// + + String describe(); + + /// + /// TypeParameters + /// + + /** + * Replace all variables referring to the given TypeParameter with the given value. + * By replacing these values I could also infer some type equivalence. + * Those would be collected in the given map. + */ + default ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tp, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + return this; + } + + /** + * This is like ({@link #replaceTypeVariables(ResolvedTypeParameterDeclaration, ResolvedType, Map)} but ignores the inferred values. + */ + default ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tp, ResolvedType replaced) { + return replaceTypeVariables(tp, replaced, new HashMap<>()); + } + + /** + * Does this type mention at all, directly or indirectly, the given type parameters? + */ + default boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) { + throw new UnsupportedOperationException(this.getClass().getCanonicalName()); + } + + /// + /// Assignability + /// + + /** + * This method checks if ThisType t = new OtherType() would compile. + */ + boolean isAssignableBy(ResolvedType other); + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java new file mode 100644 index 000000000..a5eaebe7e --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +/** + * @author Federico Tomassetti + */ +@FunctionalInterface +public interface ResolvedTypeTransformer { + ResolvedType transform(ResolvedType type); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java new file mode 100644 index 000000000..5e91057b9 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + +import java.util.List; +import java.util.Map; + +/** + * From JLS 4.4: A type variable is introduced by the declaration of a type parameter of a generic class, + * interface, method, or constructor (§8.1.2, §9.1.2, §8.4.4, §8.8.4). + * + * @author Federico Tomassetti + */ +public class ResolvedTypeVariable implements ResolvedType { + + private ResolvedTypeParameterDeclaration typeParameter; + + public ResolvedTypeVariable(ResolvedTypeParameterDeclaration typeParameter) { + this.typeParameter = typeParameter; + } + + @Override + public String toString() { + return "TypeVariable {" + typeParameter.getQualifiedName() + "}"; + } + + public String qualifiedName() { + return this.typeParameter.getQualifiedName(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ResolvedTypeVariable that = (ResolvedTypeVariable) o; + + if (!typeParameter.getName().equals(that.typeParameter.getName())) return false; + if (typeParameter.declaredOnType() != that.typeParameter.declaredOnType()) return false; + if (typeParameter.declaredOnMethod() != that.typeParameter.declaredOnMethod()) return false; + + return true; + } + + @Override + public int hashCode() { + return typeParameter.hashCode(); + } + + @Override + public boolean isArray() { + return false; + } + + @Override + public boolean isPrimitive() { + return false; + } + + @Override + public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToBeReplaced, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + if(tpToBeReplaced.getName().equals(this.typeParameter.getName())){ + inferredTypes.put(this.asTypeParameter(), replaced); + return replaced; + } else { + return this; + } + } + + @Override + public boolean isReferenceType() { + return false; + } + + @Override + public String describe() { + return typeParameter.getName(); + } + + @Override + public ResolvedTypeParameterDeclaration asTypeParameter() { + return typeParameter; + } + + @Override + public ResolvedTypeVariable asTypeVariable() { + return this; + } + + @Override + public boolean isTypeVariable() { + return true; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + if (other.isTypeVariable()) { + return describe().equals(other.describe()); + } else { + return true; + } + } + + @Override + public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) { + return typeParameters.contains(typeParameter); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java new file mode 100644 index 000000000..845fb8491 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A union type is defined in java as list of types separates by pipes. + * + * @author Federico Tomassetti + */ +public class ResolvedUnionType implements ResolvedType { + private List<ResolvedType> elements; + + public ResolvedUnionType(Collection<ResolvedType> elements) { + if (elements.size() < 2) { + throw new IllegalArgumentException("An union type should have at least two elements. This has " + elements.size()); + } + this.elements = new LinkedList<>(elements); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ResolvedUnionType that = (ResolvedUnionType) o; + + return new HashSet<>(elements).equals(new HashSet<>(that.elements)); + } + + @Override + public int hashCode() { + return new HashSet<>(elements).hashCode(); + } + + @Override + public String describe() { + return String.join(" | ", elements.stream().map(ResolvedType::describe).collect(Collectors.toList())); + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + return elements.stream().allMatch(e -> e.isAssignableBy(other)); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedVoidType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedVoidType.java new file mode 100644 index 000000000..b8f219453 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedVoidType.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +/** + * The special type void. + * + * @author Federico Tomassetti + */ +public class ResolvedVoidType implements ResolvedType { + public static final ResolvedType INSTANCE = new ResolvedVoidType(); + + private ResolvedVoidType() { + } + + @Override + public String describe() { + return "void"; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isVoid() { + return true; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java new file mode 100644 index 000000000..51fd099e4 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedWildcard.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; + +import java.util.List; +import java.util.Map; + +/** + * A wildcard can be: + * - unbounded (?) + * - have a lower bound (? super Number) + * - have an upper bound (? extends Number) + * It is not possible to have both a lower and an upper bound at the same time. + * + * @author Federico Tomassetti + */ +public class ResolvedWildcard implements ResolvedType { + + public static ResolvedWildcard UNBOUNDED = new ResolvedWildcard(null, null); + + private BoundType type; + private ResolvedType boundedType; + + private ResolvedWildcard(BoundType type, ResolvedType boundedType) { + if (type == null && boundedType != null) { + throw new IllegalArgumentException(); + } + if (type != null && boundedType == null) { + throw new IllegalArgumentException(); + } + this.type = type; + this.boundedType = boundedType; + } + + public static ResolvedWildcard superBound(ResolvedType type) { + return new ResolvedWildcard(BoundType.SUPER, type); + } + + public static ResolvedWildcard extendsBound(ResolvedType type) { + return new ResolvedWildcard(BoundType.EXTENDS, type); + } + + @Override + public String toString() { + return "WildcardUsage{" + + "type=" + type + + ", boundedType=" + boundedType + + '}'; + } + + public boolean isWildcard() { + return true; + } + + public ResolvedWildcard asWildcard() { + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ResolvedWildcard)) return false; + + ResolvedWildcard that = (ResolvedWildcard) o; + + if (boundedType != null ? !boundedType.equals(that.boundedType) : that.boundedType != null) return false; + if (type != that.type) return false; + + return true; + } + + @Override + public int hashCode() { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + (boundedType != null ? boundedType.hashCode() : 0); + return result; + } + + @Override + public String describe() { + if (type == null) { + return "?"; + } else if (type == BoundType.SUPER) { + return "? super " + boundedType.describe(); + } else if (type == BoundType.EXTENDS) { + return "? extends " + boundedType.describe(); + } else { + throw new UnsupportedOperationException(); + } + } + + public boolean isSuper() { + return type == BoundType.SUPER; + } + + public boolean isExtends() { + return type == BoundType.EXTENDS; + } + + public boolean isBounded() { + return isSuper() || isExtends(); + } + + public ResolvedType getBoundedType() { + if (boundedType == null) { + throw new IllegalStateException(); + } + return boundedType; + } + + @Override + public boolean isAssignableBy(ResolvedType other) { + if (boundedType == null) { + //return other.isReferenceType() && other.asReferenceType().getQualifiedName().equals(Object.class.getCanonicalName()); + return false; + } else if (type == BoundType.SUPER) { + return boundedType.isAssignableBy(other); + } else if (type == BoundType.EXTENDS) { + return false; + } else { + throw new RuntimeException(); + } + } + + @Override + public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) { + if (replaced == null) { + throw new IllegalArgumentException(); + } + if (boundedType == null) { + return this; + } + ResolvedType boundedTypeReplaced = boundedType.replaceTypeVariables(tpToReplace, replaced, inferredTypes); + if (boundedTypeReplaced == null) { + throw new RuntimeException(); + } + if (boundedTypeReplaced != boundedType) { + return new ResolvedWildcard(type, boundedTypeReplaced); + } else { + return this; + } + } + + @Override + public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) { + return boundedType != null && boundedType.mention(typeParameters); + } + + public boolean isUpperBounded() { + return isSuper(); + } + + public boolean isLowerBounded() { + return isExtends(); + } + + public enum BoundType { + SUPER, + EXTENDS + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java new file mode 100644 index 000000000..c310fb5f7 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types.parametrization; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedWildcard; + +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public interface ResolvedTypeParameterValueProvider { + + /** + * Calculate the value for the given type parameter. + * It could be inherited. + */ + Optional<ResolvedType> typeParamValue(ResolvedTypeParameterDeclaration typeParameterDeclaration); + + /** + * Replace the type typeParametersValues present in the given type with the ones for which this type + * has a value. + */ + default ResolvedType useThisTypeParametersOnTheGivenType(ResolvedType type) { + if (type.isTypeVariable()) { + ResolvedTypeParameterDeclaration typeParameter = type.asTypeParameter(); + if (typeParameter.declaredOnType()) { + Optional<ResolvedType> typeParam = typeParamValue(typeParameter); + if (typeParam.isPresent()) { + type = typeParam.get(); + } + } + } + + if (type.isWildcard() && type.asWildcard().isBounded()) { + if (type.asWildcard().isExtends()) { + return ResolvedWildcard.extendsBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); + } else { + return ResolvedWildcard.superBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); + } + } + + if (type.isReferenceType()) { + type = type.asReferenceType().transformTypeParameters(this::useThisTypeParametersOnTheGivenType); + } + + return type; + } + + Optional<ResolvedType> getGenericParameterByName(String name); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java new file mode 100644 index 000000000..b1cb16dae --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types.parametrization; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedTypeVariable; + +import java.util.*; + +/** + * A map of values associated to TypeParameters. + * + * @author Federico Tomassetti + */ +public class ResolvedTypeParametersMap { + + public static class Builder { + private Map<String, ResolvedType> nameToValue; + private Map<String, ResolvedTypeParameterDeclaration> nameToDeclaration; + + public Builder() { + nameToValue = new HashMap<>(); + nameToDeclaration = new HashMap<>(); + } + + private Builder(Map<String, ResolvedType> nameToValue, + Map<String, ResolvedTypeParameterDeclaration> nameToDeclaration) { + this.nameToValue = new HashMap<>(); + this.nameToValue.putAll(nameToValue); + this.nameToDeclaration = new HashMap<>(); + this.nameToDeclaration.putAll(nameToDeclaration); + } + + public ResolvedTypeParametersMap build() { + return new ResolvedTypeParametersMap(nameToValue, nameToDeclaration); + } + + public Builder setValue(ResolvedTypeParameterDeclaration typeParameter, + ResolvedType value) { + // TODO: we shouldn't just silently overwrite existing types! + String qualifiedName = typeParameter.getQualifiedName(); + nameToValue.put(qualifiedName, value); + nameToDeclaration.put(qualifiedName, typeParameter); + return this; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ResolvedTypeParametersMap)) return false; + + ResolvedTypeParametersMap that = (ResolvedTypeParametersMap) o; + + return nameToValue.equals(that.nameToValue) && nameToDeclaration.equals(that.nameToDeclaration); + + } + + @Override + public int hashCode() { + return nameToValue.hashCode(); + } + + @Override + public String toString() { + return "TypeParametersMap{" + + "nameToValue=" + nameToValue + + '}'; + } + + private Map<String, ResolvedType> nameToValue; + private Map<String, ResolvedTypeParameterDeclaration> nameToDeclaration; + + public static ResolvedTypeParametersMap empty() { + return new Builder().build(); + } + + private ResolvedTypeParametersMap(Map<String, ResolvedType> nameToValue, + Map<String, ResolvedTypeParameterDeclaration> nameToDeclaration) { + this.nameToValue = new HashMap<>(); + this.nameToValue.putAll(nameToValue); + this.nameToDeclaration = new HashMap<>(); + this.nameToDeclaration.putAll(nameToDeclaration); + } + + public ResolvedType getValue(ResolvedTypeParameterDeclaration typeParameter) { + String qualifiedName = typeParameter.getQualifiedName(); + if (nameToValue.containsKey(qualifiedName)) { + return nameToValue.get(qualifiedName); + } else { + return new ResolvedTypeVariable(typeParameter); + } + } + + public Optional<ResolvedType> getValueBySignature(String signature) { + if (nameToValue.containsKey(signature)) { + return Optional.of(nameToValue.get(signature)); + } else { + return Optional.empty(); + } + } + + public List<String> getNames(){ + return new ArrayList<>(nameToValue.keySet()); + } + + public List<ResolvedType> getTypes(){ + return new ArrayList<>(nameToValue.values()); + } + + public Builder toBuilder() { + return new Builder(nameToValue, nameToDeclaration); + } + + public boolean isEmpty() { + return nameToValue.isEmpty(); + } + + public ResolvedType replaceAll(ResolvedType type) { + Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes = new HashMap<>(); + for (ResolvedTypeParameterDeclaration typeParameterDeclaration : this.nameToDeclaration.values()) { + type = type.replaceTypeVariables(typeParameterDeclaration, getValue(typeParameterDeclaration), inferredTypes); + } + return type; + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametrized.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametrized.java new file mode 100644 index 000000000..91a792ab7 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametrized.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.types.parametrization; + +/** + * Something which can have values for TypeParameters. + * + * @author Federico Tomassetti + */ +public interface ResolvedTypeParametrized { + ResolvedTypeParametersMap typeParametersMap(); +} |