Bug 517614 - Revise default equals/hashCode for elements
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
index 328c36c..f9604d1 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
@@ -47,13 +47,13 @@
     @Override
     public boolean equals(Object obj)
     {
-        return hEquals(obj);
+        return hDefaultEquals(obj);
     }
 
     @Override
     public int hashCode()
     {
-        return hHashCode();
+        return hDefaultHashCode();
     }
 
     @Override
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplSupport.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplSupport.java
index b2b6fd5..9e3be04 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplSupport.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplSupport.java
@@ -57,10 +57,18 @@
      * A default implementation of {@link #hashCode()} cannot be provided in
      * an interface, but clients can implement <code>hashCode</code> by
      * delegating to this default method.
+     * <p>
+     * By default, the hash code for an element is a combination of its
+     * name and parent's hash code. This method is specialized in {@link
+     * ISourceFileImplSupport} to return hash code of the underlying
+     * <code>IFile</code> if the source file has an underlying file in the
+     * workspace. This method is not intended to be replaced by clients;
+     * if necessary, clients should override <code>hashCode</code> directly.
+     * </p>
      *
      * @return a hash code value
      */
-    default int hHashCode()
+    default int hDefaultHashCode()
     {
         final int prime = 31;
         int result = 1;
@@ -75,12 +83,22 @@
      * A default implementation of {@link #equals(Object)} cannot be provided in
      * an interface, but clients can implement <code>equals</code> by
      * delegating to this default method.
+     * <p>
+     * By default, two elements that implement this interface are equal
+     * if they are identical or if they {@link #hCanEqual(Object) can equal} to
+     * each other and have equal parents and names. This method is specialized
+     * in {@link ISourceConstructImplSupport} and {@link ISourceFileImplSupport}
+     * to also take into consideration the elements' occurrence count and
+     * underlying <code>IFile</code> respectively. This method is not intended
+     * to be replaced by clients; if necessary, clients should override
+     * <code>hashCode</code> directly.
+     * <p>
      *
      * @param obj the object with which to compare
      * @return <code>true</code> if this object is the same as the obj argument,
      *  <code>false</code> otherwise
      */
-    default boolean hEquals(Object obj)
+    default boolean hDefaultEquals(Object obj)
     {
         if (this == obj)
             return true;
@@ -91,8 +109,6 @@
         IElementImplSupport other = (IElementImplSupport)obj;
         if (!other.hCanEqual(this))
             return false;
-        if (!hModel().equals(other.hModel()))
-            return false;
         IElement parent = hParent();
         if (parent == null)
         {
@@ -119,13 +135,14 @@
      * <p>
      * This implementation compares run-time classes of the objects; as such,
      * it doesn't allow creating a subclass whose instances can equal superclass
-     * instances. Clients may override this method and implement a less
-     * discriminating technique using <code>instanceof</code> check,
-     * as described in http://www.artima.com/pins1ed/object-equality.html.
-     * For example, if a <code>ResolvedSourceType</code> can equal a
-     * <code>SourceType</code>, the <code>SourceType</code> should override
-     * <code>hCanEqual</code> and return <code>obj instanceof SourceType</code>.
+     * instances. Clients may provide their own implementation for this method
+     * and implement a less discriminating technique such as <code>instanceof</code>
+     * check.
      * </p>
+     * <p>
+     * For details, see <a href="http://www.artima.com/pins1ed/object-equality.html">
+     * http://www.artima.com/pins1ed/object-equality.html</a>.
+     * <p>
      *
      * @param obj not <code>null</code>
      * @return <code>true</code> if this element can equal the given object;
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplSupport.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplSupport.java
index 4606638..1e4675e 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplSupport.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplSupport.java
@@ -30,11 +30,11 @@
     extends ISourceElementImplSupport, ISourceConstructImplExtension
 {
     @Override
-    default boolean hEquals(Object obj)
+    default boolean hDefaultEquals(Object obj)
     {
         if (!(obj instanceof ISourceConstructImplSupport))
             return false;
-        return ISourceElementImplSupport.super.hEquals(obj)
+        return ISourceElementImplSupport.super.hDefaultEquals(obj)
             && hOccurrenceCount() == ((ISourceConstructImplSupport)obj).hOccurrenceCount();
     }
 
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceFileImplSupport.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceFileImplSupport.java
index a986869..73ca055 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceFileImplSupport.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceFileImplSupport.java
@@ -65,21 +65,21 @@
     extends ISourceElementImplSupport, ISourceFileImpl
 {
     @Override
-    default int hHashCode()
+    default int hDefaultHashCode()
     {
         IFile file = hFile();
         if (file != null)
             return file.hashCode();
-        return ISourceElementImplSupport.super.hHashCode();
+        return ISourceElementImplSupport.super.hDefaultHashCode();
     }
 
     @Override
-    default boolean hEquals(Object obj)
+    default boolean hDefaultEquals(Object obj)
     {
         if (!(obj instanceof ISourceFileImplSupport))
             return false;
         IFile file = hFile();
-        return ISourceElementImplSupport.super.hEquals(obj) && (file == null
+        return ISourceElementImplSupport.super.hDefaultEquals(obj) && (file == null
             || file.equals(((ISourceFileImplSupport)obj).hFile()));
     }