From daaeb29559312a9675002711b11e445c6d8950dd Mon Sep 17 00:00:00 2001 From: Danny van Bruggen Date: Thu, 31 May 2018 19:12:47 +0200 Subject: [PATCH] Lots of documentation --- .../utils/ParserCollectionStrategyTest.java | 2 +- .../javaparser/utils/CollectionContext.java | 4 +- .../javaparser/utils/CollectionStrategy.java | 3 +- .../utils/ParserCollectionStrategy.java | 7 ++- .../github/javaparser/utils/ProjectRoot.java | 29 +++++++++---- .../symbolsolver/JavaSymbolSolver.java | 30 +++++++------ .../resolution/typesolvers/AarTypeSolver.java | 3 ++ .../typesolvers/CombinedTypeSolver.java | 3 ++ .../resolution/typesolvers/JarTypeSolver.java | 23 ++++------ .../typesolvers/JavaParserTypeSolver.java | 2 +- .../typesolvers/ReflectionTypeSolver.java | 9 ++++ .../utils/SymbolSolverCollectionStrategy.java | 2 +- .../SymbolSolverCollectionStrategyTest.java | 43 ++++++++++--------- 13 files changed, 97 insertions(+), 63 deletions(-) diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java index f078c5e5e5..41d49f967b 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java @@ -12,7 +12,7 @@ public class ParserCollectionStrategyTest { private final Path root = CodeGenerationUtils.mavenModuleRoot(ParserCollectionStrategyTest.class).resolve("").getParent(); - private final ProjectRoot projectRoot = new CollectionContext(new ParserCollectionStrategy()).collect(root); + private final ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); @Test public void getSourceRoots() { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionContext.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionContext.java index 751f51931b..0c661406b3 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionContext.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionContext.java @@ -4,10 +4,12 @@ /** * Set the strategy to be applied for collecting files for the ProjectRoot. + * @deprecated use {@link CollectionStrategy} directly */ +@Deprecated public class CollectionContext { - private CollectionStrategy strategy; + private final CollectionStrategy strategy; public CollectionContext(CollectionStrategy strategy) { this.strategy = strategy; diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java index f02f21977c..1cc930f5f9 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java @@ -11,7 +11,8 @@ import java.util.Optional; /** - * Defines a strategy to collect files for the ProjectRoot. + * A strategy for discovering the structure of a project. + * Implementations could read a pom.xml, a Gradle build file, a makefile... */ public interface CollectionStrategy { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java b/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java index 86e5ac9c9e..01231e233b 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java @@ -9,7 +9,12 @@ import static java.nio.file.FileVisitResult.*; /** - * Strategy which collects all SourceRoots and returns them in a ProjectRoot object. + * A brute force {@link CollectionStrategy} for discovering a project structure. + * It will search through the given project root path for Java files, + * look at their package declarations, and figure out the root directories for those files. + * No project definition files like pom.xml or build.gradle are used. + * This strategy is crude, but can work for many cases. + * Note that any build artifacts will also be detected: jar files in target directories and so on. */ public class ParserCollectionStrategy implements CollectionStrategy { diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java b/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java index 3c1c969168..6a2d2ff4f8 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java +++ b/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java @@ -10,21 +10,24 @@ import java.util.concurrent.ConcurrentHashMap; /** - * Find and to compile all files in a project folder, which results in a collection of SourceRoots. - * To populate the ProjectRoot, set the CollectionStrategy in the CollectionContext to collect the required files. + * The structure of a Java project directory. + * It was originally created specifically to quickly configure the symbol solver. + * You can use it as a general container for project information. + *

A project has a root directory, and it has zero or more directories that contain source code. + *

To create a ProjectRoot use a CollectionStrategy, or instantiate ProjectRoot yourself. */ public class ProjectRoot { - private final Path projectRoot; + private final Path root; private final Map cache = new ConcurrentHashMap<>(); - private ParserConfiguration parserConfiguration = new ParserConfiguration(); + private final ParserConfiguration parserConfiguration; - public ProjectRoot(Path projectRoot) { - this.projectRoot = projectRoot; + public ProjectRoot(Path root) { + this(root, new ParserConfiguration()); } - public ProjectRoot(Path projectRoot, ParserConfiguration parserConfiguration) { - this.projectRoot = projectRoot; + public ProjectRoot(Path root, ParserConfiguration parserConfiguration) { + this.root = root; this.parserConfiguration = parserConfiguration; } @@ -40,7 +43,15 @@ public void addSourceRoot(Path path) { cache.put(path, new SourceRoot(path).setParserConfiguration(parserConfiguration)); } + /** + * @deprecated use getRoot() + */ + @Deprecated public Path getProjectRoot() { - return projectRoot; + return root; + } + + public Path getRoot() { + return root; } } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java index 38425559f3..675f16440e 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java @@ -17,11 +17,13 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; /** - * This implementation of the SymbolResolver wraps the functionalities of the library to make them easily usable + * This implementation of the SymbolResolver wraps the functionality of the library to make them easily usable * from JavaParser nodes. - * + *

* An instance of this class should be created once and then injected in all the CompilationUnit for which we - * want to enable symbol resolution. To do so the method inject can be used. + * want to enable symbol resolution. To do so the method inject can be used, or you can use + * {@link com.github.javaparser.ParserConfiguration#setSymbolResolver(SymbolResolver)} and the parser will do the + * injection for you. * * @author Federico Tomassetti */ @@ -44,7 +46,7 @@ public void inject(CompilationUnit destination) { @Override public T resolveDeclaration(Node node, Class resultClass) { if (node instanceof MethodDeclaration) { - return resultClass.cast(new JavaParserMethodDeclaration((MethodDeclaration)node, typeSolver)); + return resultClass.cast(new JavaParserMethodDeclaration((MethodDeclaration) node, typeSolver)); } if (node instanceof ClassOrInterfaceDeclaration) { ResolvedReferenceTypeDeclaration resolved = JavaParserFactory.toTypeDeclaration(node, typeSolver); @@ -60,16 +62,16 @@ public T resolveDeclaration(Node node, Class resultClass) { } if (node instanceof EnumConstantDeclaration) { ResolvedEnumDeclaration enumDeclaration = node.findParent(EnumDeclaration.class).get().resolve().asEnum(); - ResolvedEnumConstantDeclaration resolved = enumDeclaration.getEnumConstants().stream().filter(c -> ((JavaParserEnumConstantDeclaration)c).getWrappedNode() == node).findFirst().get(); + ResolvedEnumConstantDeclaration resolved = enumDeclaration.getEnumConstants().stream().filter(c -> ((JavaParserEnumConstantDeclaration) c).getWrappedNode() == node).findFirst().get(); if (resultClass.isInstance(resolved)) { return resultClass.cast(resolved); } } if (node instanceof ConstructorDeclaration) { - ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)node; - ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)node.getParentNode().get(); + ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) node; + ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) node.getParentNode().get(); ResolvedClassDeclaration resolvedClass = resolveDeclaration(classOrInterfaceDeclaration, ResolvedClassDeclaration.class).asClass(); - ResolvedConstructorDeclaration resolved = resolvedClass.getConstructors().stream().filter(c -> ((JavaParserConstructorDeclaration)c).getWrappedNode() == constructorDeclaration).findFirst().get(); + ResolvedConstructorDeclaration resolved = resolvedClass.getConstructors().stream().filter(c -> ((JavaParserConstructorDeclaration) c).getWrappedNode() == constructorDeclaration).findFirst().get(); if (resultClass.isInstance(resolved)) { return resultClass.cast(resolved); } @@ -82,13 +84,13 @@ public T resolveDeclaration(Node node, Class resultClass) { } if (node instanceof AnnotationMemberDeclaration) { ResolvedAnnotationDeclaration annotationDeclaration = node.findParent(AnnotationDeclaration.class).get().resolve(); - ResolvedAnnotationMemberDeclaration resolved = annotationDeclaration.getAnnotationMembers().stream().filter(c -> ((JavaParserAnnotationMemberDeclaration)c).getWrappedNode() == node).findFirst().get(); + ResolvedAnnotationMemberDeclaration resolved = annotationDeclaration.getAnnotationMembers().stream().filter(c -> ((JavaParserAnnotationMemberDeclaration) c).getWrappedNode() == node).findFirst().get(); if (resultClass.isInstance(resolved)) { return resultClass.cast(resolved); } } if (node instanceof FieldDeclaration) { - FieldDeclaration fieldDeclaration = (FieldDeclaration)node; + FieldDeclaration fieldDeclaration = (FieldDeclaration) node; if (fieldDeclaration.getVariables().size() != 1) { throw new RuntimeException("Cannot resolve a Field Declaration including multiple variable declarators. Resolve the single variable declarators"); } @@ -98,13 +100,13 @@ public T resolveDeclaration(Node node, Class resultClass) { } } if (node instanceof VariableDeclarator) { - ResolvedFieldDeclaration resolved = new JavaParserFieldDeclaration((VariableDeclarator)node, typeSolver); + ResolvedFieldDeclaration resolved = new JavaParserFieldDeclaration((VariableDeclarator) node, typeSolver); if (resultClass.isInstance(resolved)) { return resultClass.cast(resolved); } } if (node instanceof MethodCallExpr) { - SymbolReference result = JavaParserFacade.get(typeSolver).solve((MethodCallExpr)node); + SymbolReference result = JavaParserFacade.get(typeSolver).solve((MethodCallExpr) node); if (result.isSolved()) { if (resultClass.isInstance(result.getCorrespondingDeclaration())) { return resultClass.cast(result.getCorrespondingDeclaration()); @@ -165,7 +167,7 @@ public T resolveDeclaration(Node node, Class resultClass) { } if (node instanceof Parameter) { if (ResolvedParameterDeclaration.class.equals(resultClass)) { - Parameter parameter = (Parameter)node; + Parameter parameter = (Parameter) node; CallableDeclaration callableDeclaration = node.findParent(CallableDeclaration.class).get(); ResolvedMethodLikeDeclaration resolvedMethodLikeDeclaration; if (callableDeclaration.isConstructorDeclaration()) { @@ -173,7 +175,7 @@ public T resolveDeclaration(Node node, Class resultClass) { } else { resolvedMethodLikeDeclaration = callableDeclaration.asMethodDeclaration().resolve(); } - for (int i=0;i e = jarFile.entries(); while (e.hasMoreElements()) { entry = e.nextElement(); if (entry != null && !entry.isDirectory() && entry.getName().endsWith(".class")) { String name = entryPathToClassName(entry.getName()); - classpathElements.put(name, new ClasspathElement(jarFile, entry, name)); + classpathElements.put(name, new ClasspathElement(jarFile, entry)); } } } @@ -159,12 +156,10 @@ public ResolvedReferenceTypeDeclaration solveType(String name) throws UnsolvedSy private class ClasspathElement { private JarFile jarFile; private JarEntry entry; - private String path; - ClasspathElement(JarFile jarFile, JarEntry entry, String path) { + ClasspathElement(JarFile jarFile, JarEntry entry) { this.jarFile = jarFile; this.entry = entry; - this.path = path; } CtClass toCtClass() throws IOException { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java index cbf755053f..98799c5f37 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java @@ -43,7 +43,7 @@ import static com.github.javaparser.Providers.provider; /** - * Defines a directory containig source code that should be used for solving symbols. + * Defines a directory containing source code that should be used for solving symbols. * The directory must correspond to the root package of the files within. * * @author Federico Tomassetti diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java index 8e05473541..96ced8a426 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java @@ -24,12 +24,21 @@ import java.util.Optional; /** + * Uses reflection to resolve types. + * All classes on the classpath used to run your application will be found. + * No source code is available for the resolved types. + * * @author Federico Tomassetti */ public class ReflectionTypeSolver implements TypeSolver { private TypeSolver parent; + /** + * @param jreOnly if true, will only resolve types from the java or javax packages. + * This is an easy way to say "I need a JRE to solve classes, and the one that is currently running is fine." + * If false, will resolve any kind of type. + */ public ReflectionTypeSolver(boolean jreOnly) { this.jreOnly = jreOnly; } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java index 7373cb8052..848ca24aa1 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java @@ -18,7 +18,7 @@ import static java.nio.file.FileVisitResult.SKIP_SUBTREE; /** - * Strategy which collects all SourceRoots and initialises the TypeSolver and returns the SourceRoots configured + * {@link CollectionStrategy} which collects all SourceRoots and initialises the TypeSolver and returns the SourceRoots configured * with the TypeSolver in a ProjectRoot object. */ public class SymbolSolverCollectionStrategy implements CollectionStrategy { diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java index d1387ae1b7..9cc777efeb 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java @@ -1,42 +1,45 @@ package com.github.javaparser.symbolsolver.utils; +import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.utils.*; +import com.github.javaparser.utils.CodeGenerationUtils; +import com.github.javaparser.utils.Log; +import com.github.javaparser.utils.ProjectRoot; +import com.github.javaparser.utils.SourceRoot; import org.junit.Test; import java.io.IOException; import java.nio.file.Path; -import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertTrue; public class SymbolSolverCollectionStrategyTest { - private final Path root = CodeGenerationUtils.mavenModuleRoot(SymbolSolverCollectionStrategyTest.class).resolve("").getParent(); - private final ProjectRoot projectRoot = new CollectionContext(new SymbolSolverCollectionStrategy()).collect(root); + private final Path root = CodeGenerationUtils.mavenModuleRoot(JavaParser.class); + private final ProjectRoot projectRoot = new SymbolSolverCollectionStrategy().collect(root); @Test public void resolveExpressions() throws IOException { - Log.setAdapter(new Log.StandardOutStandardErrorAdapter()); - Optional sourceRoot = projectRoot.getSourceRoot(root.resolve("javaparser-core/src/main/java")); - assertTrue(sourceRoot.isPresent()); - int unresolved = 0; - for (ParseResult parseResult : sourceRoot.get().tryToParse()) { - CompilationUnit compilationUnit = parseResult.getResult().get(); - for (MethodDeclaration expr : compilationUnit.findAll(MethodDeclaration.class)) { - try { - expr.resolve().getQualifiedSignature(); - } catch (UnsupportedOperationException e) { - // not supported operation, just skip - } catch (Exception e) { - unresolved++; - Log.error(e, "Unable to resolve %s from %s", expr, compilationUnit.getStorage().get().getPath()); + SourceRoot sourceRoot = projectRoot.getSourceRoot(root.resolve("src/main/java")).get(); + AtomicInteger unresolved = new AtomicInteger(); + for (ParseResult parseResult : sourceRoot.tryToParse()) { + parseResult.ifSuccessful(compilationUnit -> { + for (MethodDeclaration expr : compilationUnit.findAll(MethodDeclaration.class)) { + try { + expr.resolve().getQualifiedSignature(); + } catch (UnsupportedOperationException e) { + // not supported operation, just skip + } catch (Exception e) { + unresolved.getAndIncrement(); + Log.error(e, "Unable to resolve %s from %s", expr, compilationUnit.getStorage().get().getPath()); + } } - } + }); } // not too many MethodDeclarations should be unresolved - assertTrue(unresolved < 10); + assertTrue(unresolved.get() < 10); } }