Adding an option to change the debug id property and prefix. Some users prefer to use a random attribute instead of the element ID, or they do not want the "gwt-debug-" prefix. I added two static methods, DebugInfo#setDebugIdAttribute() and DebugInfo#setDebugIdPrefix(), to make it easy to configure these settings.

An alternative approach was to create a new implementation of DebugIdImplEnabled, which would not use a prefix. The problem is that switching to that implementation requires the user to add a gwt.xml rule, and its less flexible because you cannot set an arbitrary prefix.  Users who are comfortable with deferred binding can always override DebugIdImpl (as many already do) to control how debug IDs are applied.

Issue: 4179

Review at http://gwt-code-reviews.appspot.com/1618804

Review by: unnurg@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10806 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/debug/Debug.gwt.xml b/user/src/com/google/gwt/debug/Debug.gwt.xml
index 9d77e6d..d731b06 100644
--- a/user/src/com/google/gwt/debug/Debug.gwt.xml
+++ b/user/src/com/google/gwt/debug/Debug.gwt.xml
@@ -14,23 +14,8 @@
 
 <!-- Adds debug ID support for UIObjects.                                   -->
 <module>
-  <inherits name="com.google.gwt.core.Core" />
+  <inherits name="com.google.gwt.debug.DebugBase" />
   
-  <!-- Enable or disable the UIObject.ensureDebugID method -->
-  <define-property name="gwt.enableDebugId" values="true, false"/>
-  
-  <!-- Default to enabled -->
+  <!-- Enable debug IDs -->
   <set-property name="gwt.enableDebugId" value="true"/> 
-
-  <!-- Replace the DebugIdImpl -->
-  <replace-with class="com.google.gwt.user.client.ui.UIObject.DebugIdImplEnabled">
-    <when-type-is class="com.google.gwt.user.client.ui.UIObject.DebugIdImpl"/>
-    <when-property-is name="gwt.enableDebugId" value="true"/>
-  </replace-with>
-
-  <!-- Replace the DebugInfoImpl -->
-  <replace-with class="com.google.gwt.debug.client.DebugInfo.DebugInfoImplEnabled">
-    <when-type-is class="com.google.gwt.debug.client.DebugInfo.DebugInfoImpl"/>
-    <when-property-is name="gwt.enableDebugId" value="true"/>
-  </replace-with>
 </module>
diff --git a/user/src/com/google/gwt/debug/DebugBase.gwt.xml b/user/src/com/google/gwt/debug/DebugBase.gwt.xml
new file mode 100644
index 0000000..e9f8e80
--- /dev/null
+++ b/user/src/com/google/gwt/debug/DebugBase.gwt.xml
@@ -0,0 +1,34 @@
+<!--                                                                        -->
+<!-- Copyright 2011 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   -->
+<!-- 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. License for the specific language governing permissions and   -->
+<!-- limitations under the License.                                         -->
+
+<!-- Base module for Debug code.                                            -->
+<module>
+  <inherits name="com.google.gwt.core.Core" />
+  
+  <!-- Enable or disable the UIObject.ensureDebugID method -->
+  <define-property name="gwt.enableDebugId" values="true, false"/>
+  <set-property name="gwt.enableDebugId" value="false"/> 
+
+  <!-- Replace the DebugIdImpl -->
+  <replace-with class="com.google.gwt.user.client.ui.UIObject.DebugIdImplEnabled">
+    <when-type-is class="com.google.gwt.user.client.ui.UIObject.DebugIdImpl"/>
+    <when-property-is name="gwt.enableDebugId" value="true"/>
+  </replace-with>
+
+  <!-- Replace the DebugInfoImpl -->
+  <replace-with class="com.google.gwt.debug.client.DebugInfo.DebugInfoImplEnabled">
+    <when-type-is class="com.google.gwt.debug.client.DebugInfo.DebugInfoImpl"/>
+    <when-property-is name="gwt.enableDebugId" value="true"/>
+  </replace-with>
+</module>
diff --git a/user/src/com/google/gwt/debug/client/DebugInfo.java b/user/src/com/google/gwt/debug/client/DebugInfo.java
index 94474b6..e8d19d8 100644
--- a/user/src/com/google/gwt/debug/client/DebugInfo.java
+++ b/user/src/com/google/gwt/debug/client/DebugInfo.java
@@ -18,7 +18,8 @@
 import com.google.gwt.core.client.GWT;
 
 /**
- * Provides low-level functionality to support the creation of testing and diagnostic frameworks.
+ * Provides low-level functionality to support the creation of testing and
+ * diagnostic frameworks.
  * 
  * @see com.google.gwt.user.client.ui.UIObject#ensureDebugId(String)
  */
@@ -27,9 +28,34 @@
    * Implementation class for {@link DebugInfo}.
    */
   private static class DebugInfoImpl {
+    private String debugIdPrefix = DEFAULT_DEBUG_ID_PREFIX;
+    private String debugIdAttribute = "id";
+    private boolean debugIdAsProperty = true;
+
+    public String getDebugIdAttribute() {
+      return debugIdAttribute;
+    }
+
+    public String getDebugIdPrefix() {
+      return debugIdPrefix;
+    }
+
+    public boolean isDebugIdAsProperty() {
+      return debugIdAsProperty;
+    }
+
     public boolean isDebugIdEnabled() {
       return false;
     }
+
+    public void setDebugIdAttribute(String attribute, boolean asProperty) {
+      this.debugIdAttribute = attribute;
+      this.debugIdAsProperty = asProperty;
+    }
+
+    public void setDebugIdPrefix(String prefix) {
+      this.debugIdPrefix = prefix;
+    }
   }
 
   /**
@@ -43,9 +69,34 @@
     }
   }
 
+  public static final String DEFAULT_DEBUG_ID_PREFIX = "gwt-debug-";
   private static DebugInfoImpl impl = GWT.create(DebugInfoImpl.class);
 
   /**
+   * Returns the element attribute or property where the debug ID is set.
+   * Defaults to the element id property. Use {@link #isDebugIdAsProperty()} to
+   * determine if the value is a property or attribute.
+   */
+  public static String getDebugIdAttribute() {
+    return impl.getDebugIdAttribute();
+  }
+
+  /**
+   * Returns the prefix string used for debug ids. Defaults to "gwt-debug-".
+   */
+  public static String getDebugIdPrefix() {
+    return impl.getDebugIdPrefix();
+  }
+
+  /**
+   * Returns true if the debug ID should be set as a property instead of an
+   * attribute.
+   */
+  public static boolean isDebugIdAsProperty() {
+    return impl.isDebugIdAsProperty();
+  }
+
+  /**
    * Returns true if debug IDs are enabled such that calls to
    * {@link com.google.gwt.user.client.ui.UIObject#ensureDebugId(String)} will
    * set DOM IDs on the {@link com.google.gwt.user.client.ui.UIObject} and its
@@ -57,4 +108,22 @@
   public static boolean isDebugIdEnabled() {
     return impl.isDebugIdEnabled();
   }
+
+  /**
+   * Sets the element attribute to assign the debug ID.
+   * 
+   * @param attribute an element property
+   * @param asProperty true to set the debug ID as a property instead of an
+   *          attribute
+   */
+  public static void setDebugIdAttribute(String attribute, boolean asProperty) {
+    impl.setDebugIdAttribute(attribute, asProperty);
+  }
+
+  /**
+   * Sets the prefix string used for debug IDs.
+   */
+  public static void setDebugIdPrefix(String prefix) {
+    impl.setDebugIdPrefix(prefix);
+  }
 }
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index 9b4f391..5f9b89c 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -21,6 +21,7 @@
    <inherits name="com.google.gwt.animation.Animation"/>
    <inherits name="com.google.gwt.canvas.Canvas"/>
    <inherits name="com.google.gwt.core.Core"/>
+   <inherits name="com.google.gwt.debug.DebugBase"/>
    <inherits name='com.google.gwt.dom.builder.DomBuilder'/>
    <inherits name="com.google.gwt.editor.Editor" />
    <inherits name="com.google.gwt.event.Event"/>
diff --git a/user/src/com/google/gwt/user/client/ui/UIObject.java b/user/src/com/google/gwt/user/client/ui/UIObject.java
index a9bc6ab..0aa817c 100644
--- a/user/src/com/google/gwt/user/client/ui/UIObject.java
+++ b/user/src/com/google/gwt/user/client/ui/UIObject.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.debug.client.DebugInfo;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.user.client.DOM;
 
@@ -171,12 +172,18 @@
     public void ensureDebugId(Element elem, String baseID, String id) {
       assert baseID != null;
       baseID = (baseID.length() > 0) ? baseID + "-" : "";
-      DOM.setElementProperty(elem.<com.google.gwt.user.client.Element> cast(),
-          "id", DEBUG_ID_PREFIX + baseID + id);
+      String prefix = DebugInfo.getDebugIdPrefix();
+      String debugId = ((prefix == null) ? "" : prefix) + baseID + id;
+      String attribute = DebugInfo.getDebugIdAttribute();
+      if (DebugInfo.isDebugIdAsProperty()) {
+        elem.setPropertyString(attribute, debugId);
+      } else {
+        elem.setAttribute(attribute, debugId);
+      }
     }
   }
 
-  public static final String DEBUG_ID_PREFIX = "gwt-debug-";
+  public static final String DEBUG_ID_PREFIX = DebugInfo.DEFAULT_DEBUG_ID_PREFIX;
 
   static final String MISSING_ELEMENT_ERROR = "This UIObject's element is not set; "
       + "you may be missing a call to either Composite.initWidget() or "
diff --git a/user/test/com/google/gwt/user/client/ui/UIObjectTest.java b/user/test/com/google/gwt/user/client/ui/UIObjectTest.java
index 7a2da7c..19a4b65 100644
--- a/user/test/com/google/gwt/user/client/ui/UIObjectTest.java
+++ b/user/test/com/google/gwt/user/client/ui/UIObjectTest.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.debug.client.DebugInfo;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.SpanElement;
 import com.google.gwt.junit.client.GWTTestCase;
@@ -181,6 +182,36 @@
     assertDebugId("test3-subElem", o.subElement);
   }
 
+  public void testDebugIdAsAttribute() {
+    String oldAttribute = DebugInfo.getDebugIdAttribute();
+    boolean asProperty = DebugInfo.isDebugIdAsProperty();
+    DebugInfo.setDebugIdAttribute("debugid", false);
+
+    MyObject o = new MyObject();
+    Element oElem = o.getElement();
+    o.ensureDebugId("test");
+    assertEquals(DebugInfo.DEFAULT_DEBUG_ID_PREFIX + "test", oElem.getAttribute("debugid"));
+    assertEquals(DebugInfo.DEFAULT_DEBUG_ID_PREFIX + "test-subElem", o.subElement
+        .getAttribute("debugid"));
+
+    // Reset the old attribute.
+    DebugInfo.setDebugIdAttribute(oldAttribute, asProperty);
+  }
+
+  public void testDebugIdWithoutPrefix() {
+    String oldPrefix = DebugInfo.getDebugIdPrefix();
+    DebugInfo.setDebugIdPrefix("");
+
+    MyObject o = new MyObject();
+    Element oElem = o.getElement();
+    o.ensureDebugId("test");
+    assertEquals("test", oElem.getPropertyString("id"));
+    assertEquals("test-subElem", o.subElement.getPropertyString("id"));
+
+    // Reset the prefix.
+    DebugInfo.setDebugIdPrefix(oldPrefix);
+  }
+
   public void testNormal() {
     // Test the basic set/get case.
     MyObject o = new MyObject();