Author: b...@google.com Date: Mon Jul 13 16:05:32 2009 New Revision: 5727 Added: trunk/dev/core/test/com/google/gwt/dev/cfg/ trunk/dev/core/test/com/google/gwt/dev/cfg/ModuleDefTest.java Modified: trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
Log: Ensure that a <define-linker> after an <add-linker> will correctly replace the previously-defined implementation. Patch by: bobv Review by: scottb Modified: trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java ============================================================================== --- trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java (original) +++ trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java Mon Jul 13 16:05:32 2009 @@ -72,9 +72,9 @@ return true; } - private final Set<Class<? extends Linker>> activeLinkers = new LinkedHashSet<Class<? extends Linker>>(); + private final Set<String> activeLinkers = new LinkedHashSet<String>(); - private Class<? extends Linker> activePrimaryLinker; + private String activePrimaryLinker; private final List<String> entryPointTypeNames = new ArrayList<String>(); @@ -134,9 +134,9 @@ LinkerOrder order = clazz.getAnnotation(LinkerOrder.class); if (order.value() == Order.PRIMARY) { - activePrimaryLinker = clazz; + activePrimaryLinker = name; } else { - activeLinkers.add(clazz); + activeLinkers.add(name); } } @@ -196,7 +196,36 @@ entryPointTypeNames.clear(); } - public void defineLinker(String name, Class<? extends Linker> linker) { + /** + * Associate a Linker class with a symbolic name. If the name had been + * previously assigned, this method will redefine the name. If the redefined + * linker had been previously added to the set of active linkers, the old + * active linker will be replaced with the new linker. + */ + public void defineLinker(TreeLogger logger, String name, + Class<? extends Linker> linker) throws UnableToCompleteException { + Class<? extends Linker> old = getLinker(name); + if (old != null) { + // Redefining an existing name + if (activePrimaryLinker.equals(name)) { + // Make sure the new one is also a primary linker + if (!linker.getAnnotation(LinkerOrder.class).value().equals( + Order.PRIMARY)) { + logger.log(TreeLogger.ERROR, "Redefining primary linker " + name + + " with non-primary implementation " + linker.getName()); + throw new UnableToCompleteException(); + } + + } else if (activeLinkers.contains(name)) { + // Make sure it's a not a primary linker + if (linker.getAnnotation(LinkerOrder.class).value().equals( + Order.PRIMARY)) { + logger.log(TreeLogger.ERROR, "Redefining non-primary linker " + name + + " with primary implementation " + linker.getName()); + throw new UnableToCompleteException(); + } + } + } linkerTypesByName.put(name, linker); } @@ -225,11 +254,17 @@ } public Set<Class<? extends Linker>> getActiveLinkers() { - return activeLinkers; + Set<Class<? extends Linker>> toReturn = new LinkedHashSet<Class<? extends Linker>>(); + for (String linker : activeLinkers) { + assert linkerTypesByName.containsKey(linker) : linker; + toReturn.add(linkerTypesByName.get(linker)); + } + return toReturn; } public Class<? extends Linker> getActivePrimaryLinker() { - return activePrimaryLinker; + assert linkerTypesByName.containsKey(activePrimaryLinker) : activePrimaryLinker; + return linkerTypesByName.get(activePrimaryLinker); } public String[] getAllPublicFiles() { Modified: trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java ============================================================================== --- trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java (original) +++ trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java Mon Jul 13 16:05:32 2009 @@ -250,7 +250,7 @@ + LinkerOrder.class.getName() + " annotation", null); throw new UnableToCompleteException(); } - moduleDef.defineLinker(name.name, linker); + moduleDef.defineLinker(logger, name.name, linker); return null; } Added: trunk/dev/core/test/com/google/gwt/dev/cfg/ModuleDefTest.java ============================================================================== --- (empty file) +++ trunk/dev/core/test/com/google/gwt/dev/cfg/ModuleDefTest.java Mon Jul 13 16:05:32 2009 @@ -0,0 +1,155 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.cfg; + +import com.google.gwt.core.ext.Linker; +import com.google.gwt.core.ext.LinkerContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.linker.ArtifactSet; +import com.google.gwt.core.ext.linker.LinkerOrder; +import com.google.gwt.core.ext.linker.LinkerOrder.Order; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Runs tests directly on ModuleDef. + */ +public class ModuleDefTest extends TestCase { + + static class FakeLinker extends Linker { + @Override + public String getDescription() { + return null; + } + + @Override + public ArtifactSet link(TreeLogger logger, LinkerContext context, + ArtifactSet artifacts) throws UnableToCompleteException { + return null; + } + + @Override + public ArtifactSet relink(TreeLogger logger, LinkerContext context, + ArtifactSet newArtifacts) throws UnableToCompleteException { + return null; + } + } + + @LinkerOrder(Order.POST) + static class FakeLinkerPost extends FakeLinker { + } + + @LinkerOrder(Order.POST) + static class FakeLinkerPost2 extends FakeLinker { + } + + @LinkerOrder(Order.PRE) + static class FakeLinkerPre extends FakeLinker { + } + + @LinkerOrder(Order.PRE) + static class FakeLinkerPre2 extends FakeLinker { + } + + @LinkerOrder(Order.PRIMARY) + static class FakeLinkerPrimary extends FakeLinker { + } + + @LinkerOrder(Order.PRIMARY) + static class FakeLinkerPrimary2 extends FakeLinker { + } + + public void testLinkerOrder() throws UnableToCompleteException { + ModuleDef def = new ModuleDef("fake"); + + def.defineLinker(TreeLogger.NULL, "pre", FakeLinkerPre.class); + def.defineLinker(TreeLogger.NULL, "pre2", FakeLinkerPre2.class); + def.defineLinker(TreeLogger.NULL, "post", FakeLinkerPost.class); + def.defineLinker(TreeLogger.NULL, "post2", FakeLinkerPost2.class); + def.defineLinker(TreeLogger.NULL, "primary", FakeLinkerPrimary.class); + + def.addLinker("pre2"); + def.addLinker("pre"); + def.addLinker("post"); + def.addLinker("post2"); + def.addLinker("primary"); + + Class<?>[] expectedClasses = { + FakeLinkerPre2.class, FakeLinkerPre.class, FakeLinkerPost.class, + FakeLinkerPost2.class}; + assertEquals(FakeLinkerPrimary.class, def.getActivePrimaryLinker()); + // Test iteration order + assertEquals(Arrays.asList(expectedClasses), + new ArrayList<Class<? extends Linker>>(def.getActiveLinkers())); + } + + public void testLinkerRedefinition() throws UnableToCompleteException { + ModuleDef def = new ModuleDef("fake"); + + def.defineLinker(TreeLogger.NULL, "pre", FakeLinkerPre.class); + def.defineLinker(TreeLogger.NULL, "post", FakeLinkerPost.class); + def.defineLinker(TreeLogger.NULL, "primary", FakeLinkerPrimary.class); + def.addLinker("pre"); + def.addLinker("post"); + def.addLinker("primary"); + + def.defineLinker(TreeLogger.NULL, "pre", FakeLinkerPre2.class); + def.defineLinker(TreeLogger.NULL, "post", FakeLinkerPost2.class); + def.defineLinker(TreeLogger.NULL, "primary", FakeLinkerPrimary2.class); + // Intentional duplication + def.addLinker("post"); + + Class<?>[] expectedClasses = {FakeLinkerPre2.class, FakeLinkerPost2.class}; + assertEquals(FakeLinkerPrimary2.class, def.getActivePrimaryLinker()); + // Test iteration order + assertEquals(Arrays.asList(expectedClasses), + new ArrayList<Class<? extends Linker>>(def.getActiveLinkers())); + } + + public void testLinkerRedefinitionErrors() throws UnableToCompleteException { + ModuleDef def = new ModuleDef("fake"); + + def.defineLinker(TreeLogger.NULL, "pre", FakeLinkerPre.class); + def.defineLinker(TreeLogger.NULL, "post", FakeLinkerPost.class); + def.defineLinker(TreeLogger.NULL, "primary", FakeLinkerPrimary.class); + def.addLinker("pre"); + def.addLinker("post"); + def.addLinker("primary"); + + try { + def.defineLinker(TreeLogger.NULL, "pre", FakeLinkerPrimary.class); + fail(); + } catch (UnableToCompleteException e) { + // OK + } + try { + def.defineLinker(TreeLogger.NULL, "post", FakeLinkerPrimary.class); + fail(); + } catch (UnableToCompleteException e) { + // OK + } + try { + def.defineLinker(TreeLogger.NULL, "primary", FakeLinkerPre.class); + fail(); + } catch (UnableToCompleteException e) { + // OK + } + } +} --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---