From a418936c50f43c7db2aff507f6d585ea87afeefd Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 26 Oct 2020 20:10:47 +0100 Subject: [PATCH 1/4] Added try/catch block to guarantee best-effort parsing and not fail the whole analysis for one malformed file --- .../spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java index 92f6c200e47..30f72057f8e 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java @@ -459,7 +459,11 @@ private void forEachCompilationUnit(List unitList, S if (unit.isModuleInfo() || !unit.isEmpty()) { final String unitPath = new String(unit.getFileName()); if (canProcessCompilationUnit(unitPath)) { - consumer.accept(unit); + try { + consumer.accept(unit); + } catch (Exception e) { + getEnvironment().report(null, Level.ERROR, "An error occurred while processing a unit in " + String.valueOf(unit.getFileName()) + ", some units may be missing in the model: " + e.getMessage()); + } } getEnvironment().getSpoonProgress().step(process, unitPath, ++i, unitList.size()); } From d68236b8257e3026842c12c18b98609dfcc8c84c Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 28 Oct 2020 09:11:10 +0100 Subject: [PATCH 2/4] Added overridable method for traversing unit AST --- .../compiler/jdt/JDTBasedSpoonCompiler.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java index 30f72057f8e..d012f176f10 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java @@ -11,8 +11,12 @@ import org.apache.logging.log4j.Level; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; +import org.eclipse.jdt.internal.core.CompilationUnit; import spoon.OutputType; import spoon.SpoonException; import spoon.compiler.Environment; @@ -432,7 +436,7 @@ protected void buildModel(CompilationUnitDeclaration[] units, Factory aFactory) forEachCompilationUnit(unitList, SpoonProgress.Process.MODEL, unit -> { // we need first to go through the whole model before getting the right reference for imports - unit.traverse(builder, unit.scope); + traverseUnitDeclaration(builder, unit); }); //we need first imports before we can place comments. Mainly comments on imports need that forEachCompilationUnit(unitList, SpoonProgress.Process.IMPORT, unit -> { @@ -459,18 +463,25 @@ private void forEachCompilationUnit(List unitList, S if (unit.isModuleInfo() || !unit.isEmpty()) { final String unitPath = new String(unit.getFileName()); if (canProcessCompilationUnit(unitPath)) { - try { - consumer.accept(unit); - } catch (Exception e) { - getEnvironment().report(null, Level.ERROR, "An error occurred while processing a unit in " + String.valueOf(unit.getFileName()) + ", some units may be missing in the model: " + e.getMessage()); - } + consumer.accept(unit); } - getEnvironment().getSpoonProgress().step(process, unitPath, ++i, unitList.size()); + getEnvironment().getSpoonProgress().step(process, unitPath, ++i, unitList.size()); } } - getEnvironment().getSpoonProgress().end(process); + getEnvironment().getSpoonProgress().end(process); } + /** + * Invokes the traversal of the given compilation unit declaration using the given builder as visitor. + * This method must invoke {@link CompilationUnitDeclaration#traverse(ASTVisitor, CompilationUnitScope)})} )} + * @param builder the builder to use to traverse the unit. + * @param unitDeclaration the unit declaration. + */ + protected void traverseUnitDeclaration(JDTTreeBuilder builder, CompilationUnitDeclaration unitDeclaration){ + unitDeclaration.traverse(builder, unitDeclaration.scope); + } + + private boolean canProcessCompilationUnit(String unitPath) { for (final CompilationUnitFilter cuf : compilationUnitFilters) { if (cuf.exclude(unitPath)) { From f0c478d461d63aee94e776fdcaa39281c67da33f Mon Sep 17 00:00:00 2001 From: Darius Date: Fri, 30 Oct 2020 19:59:28 +0100 Subject: [PATCH 3/4] Updated javadoc --- .../spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java index d012f176f10..8fe917a3183 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java @@ -472,8 +472,8 @@ private void forEachCompilationUnit(List unitList, S } /** - * Invokes the traversal of the given compilation unit declaration using the given builder as visitor. - * This method must invoke {@link CompilationUnitDeclaration#traverse(ASTVisitor, CompilationUnitScope)})} )} + * Invokes the traversal of the given compilation unit declaration using the given builder as a visitor. + * Overriders of this method must invoke {@link CompilationUnitDeclaration#traverse(ASTVisitor, CompilationUnitScope)})} )} * @param builder the builder to use to traverse the unit. * @param unitDeclaration the unit declaration. */ From a51fc57eda461a38ea82f48861fc225e7c36f3d3 Mon Sep 17 00:00:00 2001 From: Darius Date: Sun, 1 Nov 2020 09:49:37 +0100 Subject: [PATCH 4/4] Added overridable method to instantiate model builder --- src/main/java/spoon/Launcher.java | 13 ++++++++++++- .../support/compiler/jdt/JDTBasedSpoonCompiler.java | 7 +++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/spoon/Launcher.java b/src/main/java/spoon/Launcher.java index 4f2996eed8d..b099a0a9da2 100644 --- a/src/main/java/spoon/Launcher.java +++ b/src/main/java/spoon/Launcher.java @@ -596,7 +596,7 @@ protected JSAPResult parseArgs() { * the factory this compiler works on */ public SpoonModelBuilder createCompiler(Factory factory) { - SpoonModelBuilder comp = new JDTBasedSpoonCompiler(factory); + SpoonModelBuilder comp = getCompilerInstance(factory); Environment env = getEnvironment(); // building comp.setBinaryOutputDirectory(jsapActualArgs.getFile("destination")); @@ -614,6 +614,17 @@ public SpoonModelBuilder createCompiler(Factory factory) { return comp; } + /** + * Instantiates the compiler. This method is invoked by {@link #createCompiler(Factory)} to retrieve + * an empty compiler instance. Clients can override this method to use their custom compiler implementation. + * @param factory the factory to pass on to the compiler. + * @return a new compiler. + * @see #createCompiler(Factory) + */ + protected SpoonModelBuilder getCompilerInstance(Factory factory) { + return new JDTBasedSpoonCompiler(factory); + } + public SpoonModelBuilder createCompiler(Factory factory, List inputSources) { SpoonModelBuilder c = createCompiler(factory); c.addInputSources(inputSources); diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java index 8fe917a3183..e92bb0afe17 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java @@ -14,9 +14,7 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; -import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; -import org.eclipse.jdt.internal.core.CompilationUnit; import spoon.OutputType; import spoon.SpoonException; import spoon.compiler.Environment; @@ -473,11 +471,12 @@ private void forEachCompilationUnit(List unitList, S /** * Invokes the traversal of the given compilation unit declaration using the given builder as a visitor. - * Overriders of this method must invoke {@link CompilationUnitDeclaration#traverse(ASTVisitor, CompilationUnitScope)})} )} + * Overriders of this method must either invoke {@link CompilationUnitDeclaration#traverse(ASTVisitor, CompilationUnitScope)})} )} + * or this method before returning. * @param builder the builder to use to traverse the unit. * @param unitDeclaration the unit declaration. */ - protected void traverseUnitDeclaration(JDTTreeBuilder builder, CompilationUnitDeclaration unitDeclaration){ + protected void traverseUnitDeclaration(JDTTreeBuilder builder, CompilationUnitDeclaration unitDeclaration) { unitDeclaration.traverse(builder, unitDeclaration.scope); }