Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface to Exclude Compilation Units From CtModel. #1037

Merged
merged 9 commits into from
Dec 16, 2016
26 changes: 26 additions & 0 deletions src/main/java/spoon/SpoonModelBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.Filter;
import spoon.support.compiler.jdt.CompilationUnitFilter;
import spoon.support.compiler.jdt.FactoryCompilerConfig;
import spoon.support.compiler.jdt.FileCompilerConfig;
import spoon.support.compiler.jdt.JDTBatchCompiler;
Expand Down Expand Up @@ -303,4 +304,29 @@ interface InputType {
* Returns the working factory
*/
Factory getFactory();

/**
* Adds {@code filter}.
*
* @param filter
* The {@link CompilationUnitFilter} to add.
*/
void addCompilationUnitFilter(final CompilationUnitFilter filter);

/**
* Removes {@code filter}. Does nothing, if {@code filter} has not been
* added beforehand.
*
* @param filter
* The {@link CompilationUnitFilter} to remove.
*/
void removeCompilationUnitFilter(final CompilationUnitFilter filter);

/**
* Returns a copy of the internal list of {@link CompilationUnitFilter}s.
*
* @return
* A copy of the internal list of {@link CompilationUnitFilter}s.
*/
List<CompilationUnitFilter> getCompilationUnitFilter();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (C) 2006-2016 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program 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 CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.support.compiler.jdt;

/**
* This interface is used by instances of {@link spoon.SpoonModelBuilder} to
* exclude particular {@link spoon.reflect.cu.CompilationUnit}s while
* generating a {@link spoon.reflect.CtModel} with
* {@link spoon.SpoonModelBuilder#build(spoon.compiler.builder.JDTBuilder)}.
*
* This interface is useful for large sized software system where traversing
* all files takes several minutes. Unlike the approach of adding a subset of
* the files to examine, filtering unwanted files produces a more precise
* {@link spoon.reflect.CtModel} since all files will be compiled (but not
* transformed).
*/
public interface CompilationUnitFilter {

/**
* Tests if the file with path {@code path} should be excluded from the
* {@link spoon.reflect.CtModel} create by
* {@link spoon.SpoonModelBuilder#build(spoon.compiler.builder.JDTBuilder)}.
*
* @param path
* Path to the file that may or may not be excluded.
* @return {@code true} if and only if {@code path} should be excluded,
* {@code false} otherwise.
*/
boolean exclude(final String path);
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class JDTBasedSpoonCompiler implements SpoonCompiler {
protected File outputDirectory = new File(Launcher.OUTPUTDIR);
protected List<SpoonResource> forceBuildList = new ArrayList<>();
protected String encoding;
protected List<CompilationUnitFilter> compilationUnitFilters = new ArrayList<>();

/**
* Default constructor
Expand Down Expand Up @@ -413,7 +414,15 @@ protected CompilationUnitDeclaration[] buildUnits(JDTBuilder jdtBuilder, SpoonFo

protected void buildModel(CompilationUnitDeclaration[] units) {
JDTTreeBuilder builder = new JDTTreeBuilder(factory);
unitLoop:
for (CompilationUnitDeclaration unit : units) {
final String unitPath = new String(unit.getFileName());
for (final CompilationUnitFilter cuf : compilationUnitFilters) {
if (cuf.exclude(unitPath)) {
// do not traverse this unit
continue unitLoop;
}
}
unit.traverse(builder, unit.scope);
if (getFactory().getEnvironment().isCommentsEnabled()) {
new JDTCommentBuilder(unit, factory).build();
Expand Down Expand Up @@ -615,4 +624,19 @@ protected Environment getEnvironment() {
public boolean compileInputSources() {
return compile(InputType.FILES);
}

@Override
public void addCompilationUnitFilter(final CompilationUnitFilter filter) {
compilationUnitFilters.add(filter);
}

@Override
public void removeCompilationUnitFilter(CompilationUnitFilter filter) {
compilationUnitFilters.remove(filter);
}

@Override
public List<CompilationUnitFilter> getCompilationUnitFilter() {
return new ArrayList<>(compilationUnitFilters);
}
}
70 changes: 70 additions & 0 deletions src/test/java/spoon/test/filters/CUFilterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package spoon.test.filters;

import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.junit.Test;
import spoon.Launcher;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.code.CtReturn;
import spoon.support.compiler.jdt.CompilationUnitFilter;

import static org.junit.Assert.assertEquals;

public class CUFilterTest {

@Test
public void testWithoutFilters() {
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/resources/noclasspath/same-package");
launcher.buildModel();
final CtModel model = launcher.getModel();
assertEquals(2, model.getAllTypes().size());
assertEquals("spoon.test.same.B", model.getAllTypes().iterator().next()
.getMethod("createB").getType().getQualifiedName());
}

@Test
public void testSingleExcludeWithFilter() {
final Launcher launcher = new Launcher();
launcher.getEnvironment().setNoClasspath(true);
launcher.addInputResource("./src/test/resources/noclasspath/same-package");
launcher.getModelBuilder().addCompilationUnitFilter(
new CompilationUnitFilter() {
@Override
public boolean exclude(final String path) {
return path.endsWith("B.java");
}
});
launcher.buildModel();
final CtModel model = launcher.getModel();

assertEquals(1, model.getAllTypes().size());
// make sure `B` is not available in `model.getAllTypes`
assertEquals("A", model.getAllTypes().iterator().next().getSimpleName());
// make sure declaration of `B` is known in `model`
final CtReturn ctReturn = model.getAllTypes().iterator().next()
.getMethod("createB").getBody().getStatement(0);
final CtConstructorCall ctConstructorCall =
(CtConstructorCall)ctReturn.getReturnedExpression();
assertEquals("spoon.test.same.B", ctConstructorCall.getType().getQualifiedName());
}

@Test
public void testSingleExcludeWithoutFilter() {
final Launcher launcher = new Launcher();
launcher.getEnvironment().setNoClasspath(true);
launcher.addInputResource("./src/test/resources/noclasspath/same-package/A.java");
launcher.buildModel();
final CtModel model = launcher.getModel();

assertEquals(1, model.getAllTypes().size());
// make sure `B` is not available in `model.getAllTypes`
assertEquals("A", model.getAllTypes().iterator().next().getSimpleName());
// make sure declaration of `B` is unknown in `model`
final CtReturn ctReturn = model.getAllTypes().iterator().next()
.getMethod("createB").getBody().getStatement(0);
final CtConstructorCall ctConstructorCall =
(CtConstructorCall)ctReturn.getReturnedExpression();
assertEquals("B", ctConstructorCall.getType().getQualifiedName());
}
}
8 changes: 8 additions & 0 deletions src/test/resources/noclasspath/same-package/A.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package spoon.test.same;

public class A {

public B createB() {
return new B();
}
}
8 changes: 8 additions & 0 deletions src/test/resources/noclasspath/same-package/B.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package spoon.test.same;

public class B {

public String getName() {
return "This is B.";
}
}