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
-~----------~----~----~----~------~----~------~--~---

Reply via email to