diff --git a/src/main/java/spoon/reflect/CtModel.java b/src/main/java/spoon/reflect/CtModel.java index 756f0a3f86a..1376c0805ed 100644 --- a/src/main/java/spoon/reflect/CtModel.java +++ b/src/main/java/spoon/reflect/CtModel.java @@ -1,3 +1,19 @@ +/** + * Copyright (C) 2006-2015 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.reflect; import java.util.Collection; @@ -21,6 +37,6 @@ public interface CtModel { Collection getAllPackages(); /** process this model with the given processor */ - void processWith(Processor abstractProcessor); + void processWith(Processor processor); } diff --git a/src/main/java/spoon/reflect/CtModelImpl.java b/src/main/java/spoon/reflect/CtModelImpl.java index 6c50c228dd0..2da062b8308 100644 --- a/src/main/java/spoon/reflect/CtModelImpl.java +++ b/src/main/java/spoon/reflect/CtModelImpl.java @@ -1,3 +1,19 @@ +/** + * Copyright (C) 2006-2015 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.reflect; import java.util.Collection; @@ -78,12 +94,12 @@ public Collection> getAllTypes() { @Override public Collection getAllPackages() { - return Collections.unmodifiableCollection(rootPackage.getElements(new TypeFilter<>(CtPackage.class))); + return Collections.unmodifiableCollection(rootPackage.getElements(new TypeFilter(CtPackage.class))); } @Override - public void processWith(Processor abstractProcessor) { + public void processWith(Processor processor) { // processing (consume all the processors) ProcessingManager processing = new QueueProcessingManager(rootPackage.getFactory()); processing.process(getRootPackage()); diff --git a/src/main/java/spoon/reflect/declaration/CtPackage.java b/src/main/java/spoon/reflect/declaration/CtPackage.java index 48949c15f52..e6334e575c4 100644 --- a/src/main/java/spoon/reflect/declaration/CtPackage.java +++ b/src/main/java/spoon/reflect/declaration/CtPackage.java @@ -37,7 +37,7 @@ public interface CtPackage extends CtNamedElement { String TOP_LEVEL_PACKAGE_NAME = "unnamed package"; /** - * Gets the declaring package of the current one. + * Gets the declaring package of the current one. Returns null if the package is not yet in another one. */ CtPackage getDeclaringPackage(); diff --git a/src/main/java/spoon/support/reflect/declaration/CtNamedElementImpl.java b/src/main/java/spoon/support/reflect/declaration/CtNamedElementImpl.java index ebbffca7ca2..74cd49c94dc 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtNamedElementImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtNamedElementImpl.java @@ -25,7 +25,7 @@ public abstract class CtNamedElementImpl extends CtElementImpl implements CtName private static final long serialVersionUID = 1L; - String simpleName; + String simpleName = ""; @Override public CtReference getReference() { diff --git a/src/main/java/spoon/support/reflect/declaration/CtPackageImpl.java b/src/main/java/spoon/support/reflect/declaration/CtPackageImpl.java index eb93638a914..6373c87e81d 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtPackageImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtPackageImpl.java @@ -16,15 +16,16 @@ */ package spoon.support.reflect.declaration; +import java.util.Set; +import java.util.TreeSet; + import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.ParentNotInitializedException; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.visitor.CtVisitor; -import java.util.Set; -import java.util.TreeSet; - /** * The implementation for {@link spoon.reflect.declaration.CtPackage}. * @@ -33,7 +34,7 @@ public class CtPackageImpl extends CtNamedElementImpl implements CtPackage { private static final long serialVersionUID = 1L; - private Set packs = new TreeSet(); + protected Set packs = new TreeSet(); private Set> types = new TreeSet>(); @@ -48,11 +49,42 @@ public void accept(CtVisitor v) { @Override public T addPackage(CtPackage pack) { + // they are the same + if (this.getQualifiedName().equals(pack.getQualifiedName())) { + addAllTypes(pack, this); + addAllPackages(pack, this); + return (T) this; + } + + // it already exists + for (CtPackage p1 : packs) { + if (p1.getQualifiedName().equals(pack.getQualifiedName())) { + addAllTypes(pack, p1); + addAllPackages(pack, p1); + return (T) this; + } + } + + this.packs.add(pack); pack.setParent(this); - packs.add(pack); + return (T) this; } + /** add all types of "from" in "to" */ + private void addAllTypes(CtPackage from, CtPackage to) { + for (CtType t : from.getTypes()) { + to.addType(t); + } + } + + /** add all packages of "from" in "to" */ + private void addAllPackages(CtPackage from, CtPackage to) { + for (CtPackage p : from.getPackages()) { + to.addPackage(p); + } + } + @Override public boolean removePackage(CtPackage pack) { return packs.remove(pack); @@ -60,7 +92,11 @@ public boolean removePackage(CtPackage pack) { @Override public CtPackage getDeclaringPackage() { - return getParent(CtPackage.class); + try { + return getParent(CtPackage.class); + } catch (ParentNotInitializedException e) { + return null; + } } @Override diff --git a/src/test/java/spoon/test/factory/FactoryTest.java b/src/test/java/spoon/test/factory/FactoryTest.java index 0bce360c4a2..47e47ce4683 100644 --- a/src/test/java/spoon/test/factory/FactoryTest.java +++ b/src/test/java/spoon/test/factory/FactoryTest.java @@ -105,4 +105,39 @@ public void testCtModel() throws Exception { // [, spoon, spoon.test, spoon.test.factory, spoon.test.factory.testclasses] assertEquals(5, model.getAllPackages().size()); } + + @Test + public void testIncrementalModel() throws Exception { + + // Feed some inputResources to a spoon compiler + SpoonAPI spoon = new Launcher(); + spoon.addInputResource("src/test/java/spoon/test/factory/testclasses"); + + // Build model + spoon.buildModel(); + + // Do something with that model.. + CtModel model = spoon.getModel(); + model.processWith(new AbstractProcessor() { + @Override + public void process(CtMethod element) { + element.setDefaultMethod(false); + } + }); + + // Feed some new inputResources + SpoonAPI spoon2 = new Launcher(); + spoon2.addInputResource("src/test/java/spoon/test/factory/testclasses2"); + + // Build models of newly added classes/packages + spoon2.buildModel(); + + // attach them to the existing model. + model.getRootPackage().addPackage(spoon2.getModel().getRootPackage()); + + // checking the results + assertEquals(6, model.getAllPackages().size()); + assertEquals(3, model.getAllTypes().size()); + } + } diff --git a/src/test/java/spoon/test/factory/testclasses2/Baz.java b/src/test/java/spoon/test/factory/testclasses2/Baz.java new file mode 100644 index 00000000000..00f4d3a2312 --- /dev/null +++ b/src/test/java/spoon/test/factory/testclasses2/Baz.java @@ -0,0 +1,4 @@ +package spoon.test.factory.testclasses2; + +public class Baz { +} diff --git a/src/test/java/spoon/test/parent/ParentContractTest.java b/src/test/java/spoon/test/parent/ParentContractTest.java index 13f1968581e..feca3575f9d 100644 --- a/src/test/java/spoon/test/parent/ParentContractTest.java +++ b/src/test/java/spoon/test/parent/ParentContractTest.java @@ -5,6 +5,8 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.Mockito; + +import spoon.SpoonException; import spoon.reflect.code.CtCatchVariable; import spoon.reflect.code.CtConstructorCall; import spoon.reflect.code.CtInvocation; @@ -20,6 +22,7 @@ import spoon.reflect.reference.CtReference; import spoon.reflect.visitor.CtVisitable; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -130,7 +133,13 @@ public void testContract() throws Throwable { // we check that setParent has been called verify(mockedArgument).setParent((CtElement) receiver); } catch (AssertionError e) { - Assert.fail("call setParent contract failed for "+setter.toString()+" "+e.toString()); + Assert.fail("call setParent contract failed for "+setter.toString()+" "+e.toString()); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + throw e.getCause(); + } else { + throw new SpoonException(e.getCause()); + } } } }