Fix for issue #800. Adds getOverridableMethods() to JClassType. See the unit tests as well for the cases that are included/excluded. Also added some dictionary entries to allow JClassType to pass the spellchecker.

Review by: scottb

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@603 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
index 1e11306..13e9ff5 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -18,16 +18,17 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 
 import java.io.UnsupportedEncodingException;
-
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 /**
  * Type representing a Java class or interface type.
@@ -71,6 +72,8 @@
 
   private final int bodyStart;
 
+  private JMethod[] cachedOverridableMethods;
+
   private final List constructors = new ArrayList();
 
   private final CompilationUnitProvider cup;
@@ -305,6 +308,37 @@
     }
   }
 
+  /**
+   * Iterates over the most-derived declaration of each unique overridable
+   * method available in the type hierarchy of the specified type, including
+   * those found in superclasses and superinterfaces. A method is overridable if
+   * it is not <code>final</code> and its accessibility is <code>public</code>,
+   * <code>protected</code>, or package protected.
+   * 
+   * Deferred binding generators often need to generate method implementations;
+   * this method offers a convenient way to find candidate methods to implement.
+   * 
+   * Note that the behavior does not match
+   * {@link Class#getMethod(String, Class[])}, which does not return the most
+   * derived method in some cases.
+   * 
+   * @return an array of {@link JMethod} objects representing overridable
+   *         methods
+   */
+  public JMethod[] getOverridableMethods() {
+    if (cachedOverridableMethods == null) {
+      Map methodsBySignature = new TreeMap();
+      getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(methodsBySignature);
+      if (isClass() != null) {
+        getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
+      }
+      int size = methodsBySignature.size();
+      Collection leafMethods = methodsBySignature.values();
+      cachedOverridableMethods = (JMethod[]) leafMethods.toArray(new JMethod[size]);
+    }
+    return cachedOverridableMethods;
+  }
+
   public JPackage getPackage() {
     return declaringPackage;
   }
@@ -527,6 +561,88 @@
     notifySuperTypesOf(me);
   }
 
+  private String computeInternalSignature(JMethod method) {
+    StringBuffer sb = new StringBuffer();
+    sb.setLength(0);
+    sb.append(method.getName());
+    JParameter[] params = method.getParameters();
+    for (int j = 0; j < params.length; j++) {
+      JParameter param = params[j];
+      sb.append("/");
+      sb.append(param.getType().getQualifiedSourceName());
+    }
+    return sb.toString();
+  }
+
+  private void getOverridableMethodsOnSuperclassesAndThisClass(
+      Map methodsBySignature) {
+    assert (isClass() != null);
+
+    // Recurse first so that more derived methods will clobber less derived
+    // methods.
+    JClassType superClass = getSuperclass();
+    if (superClass != null) {
+      superClass.getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
+    }
+
+    JMethod[] declaredMethods = getMethods();
+    for (int i = 0; i < declaredMethods.length; i++) {
+      JMethod method = declaredMethods[i];
+
+      // Ensure that this method is overridable.
+      if (method.isFinal() || method.isPrivate()) {
+        // We cannot override this method, so skip it.
+        continue;
+      }
+
+      // We can override this method, so record it.
+      String sig = computeInternalSignature(method);
+      methodsBySignature.put(sig, method);
+    }
+  }
+
+  /**
+   * Gets the methods declared in interfaces that this type extends. If this
+   * type is a class, its own methods are not added. If this type is an
+   * interface, its own methods are added. Used internally by
+   * {@link #getOverridableMethods()}.
+   * 
+   * @param methodsBySignature
+   */
+  private void getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(
+      Map methodsBySignature) {
+    // Recurse first so that more derived methods will clobber less derived
+    // methods.
+    JClassType[] superIntfs = getImplementedInterfaces();
+    for (int i = 0; i < superIntfs.length; i++) {
+      JClassType superIntf = superIntfs[i];
+      superIntf.getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(methodsBySignature);
+    }
+
+    if (isInterface() == null) {
+      // This is not an interface, so we're done after having visited its
+      // implemented interfaces.
+      return;
+    }
+
+    JMethod[] declaredMethods = getMethods();
+    for (int i = 0; i < declaredMethods.length; i++) {
+      JMethod method = declaredMethods[i];
+
+      String sig = computeInternalSignature(method);
+      JMethod existing = (JMethod) methodsBySignature.get(sig);
+      if (existing != null) {
+        JClassType existingType = existing.getEnclosingType();
+        JClassType thisType = method.getEnclosingType();
+        if (thisType.isAssignableFrom(existingType)) {
+          // The existing method is in a more-derived type, so don't replace it.
+          continue;
+        }
+      }
+      methodsBySignature.put(sig, method);
+    }
+  }
+
   private String makeCompoundName(JClassType type) {
     if (type.enclosingType == null) {
       return type.name;
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/JClassTypeTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/JClassTypeTest.java
new file mode 100644
index 0000000..07c29a9
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/JClassTypeTest.java
@@ -0,0 +1,354 @@
+/*

+ * Copyright 2007 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.core.ext.typeinfo;

+

+import com.google.gwt.core.ext.TreeLogger;

+import com.google.gwt.core.ext.UnableToCompleteException;

+import com.google.gwt.dev.jdt.StaticCompilationUnitProvider;

+import com.google.gwt.dev.jdt.TypeOracleBuilder;

+import com.google.gwt.dev.jdt.URLCompilationUnitProvider;

+

+import junit.framework.TestCase;

+

+import java.io.File;

+import java.net.MalformedURLException;

+import java.net.URI;

+import java.net.URISyntaxException;

+import java.net.URL;

+

+/**

+ * Tests related to JClassType. See individual test methods to details.

+ */

+public class JClassTypeTest extends TestCase {

+

+  public void testGetOverridableMethods() throws UnableToCompleteException,

+      TypeOracleException {

+    TreeLogger logger = TreeLogger.NULL;

+    TypeOracle typeOracle = buildOracleFromTestPackage(logger);

+

+    String[] noParams = new String[0];

+    String[] intObjectParams = new String[] {"int", "java.lang.Object"};

+

+    // Verify IA.

+    {

+      JClassType type = typeOracle.getType("com.google.gwt.core.ext.typeinfo.test.IA");

+      JMethod[] leafMethods = type.getOverridableMethods();

+      assertEquals(3, leafMethods.length);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IA", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IA", "ia", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IA", "foo", noParams);

+    }

+

+    // Verify IB.

+    {

+      JClassType type = typeOracle.getType("com.google.gwt.core.ext.typeinfo.test.IB");

+      JMethod[] leafMethods = type.getOverridableMethods();

+      assertEquals(5, leafMethods.length);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IB", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IB", "ia", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.IB", "ib", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.IB", "ib", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.IB", "foo", noParams);

+    }

+

+    // Verify IC.

+    {

+      JClassType type = typeOracle.getType("com.google.gwt.core.ext.typeinfo.test.IC");

+      JMethod[] leafMethods = type.getOverridableMethods();

+      assertEquals(7, leafMethods.length);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ia", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ib", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ib", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ic", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "ic", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "foo", noParams);

+    }

+

+    // Both overloads of ia are only declared in IA, so all searches should find

+    // them there.

+    {

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CA", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CB", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ia", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CA", "ia", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CB", "ia", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IA",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ia", intObjectParams);

+    }

+

+    // Both overloads of ib are declared in both IB and IC, so

+    // - searching for ib in CB will return IB

+    // - searching for ib in CC will return IC

+    {

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.CB", "ib", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ib", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.CB", "ib", intObjectParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ib", intObjectParams);

+    }

+

+    // Both overloads of ic are declared only in IC, but ic() is also declared

+    // in CB, so

+    // - searching for ic() in CB will return CB

+    // - searching for ic() in CC will return CB

+    // - searching for ic(int, Object) in CC will return IC

+    {

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.CB",

+          "com.google.gwt.core.ext.typeinfo.test.CB", "ic", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.CB",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ic", noParams);

+

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IC",

+          "com.google.gwt.core.ext.typeinfo.test.CC", "ic", intObjectParams);

+    }

+

+    // Both IA and IB define foo(), and searching for foo() on IC should return

+    // IB.foo(). This matters because IC also extends IA, so a naive algorithm

+    // for getLeafMethods() might prefer IA.foo() to IB.foo().

+    {

+      assertMethodOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.IB",

+          "com.google.gwt.core.ext.typeinfo.test.IC", "foo", noParams);

+    }

+

+    // Check that we aren't including methods that aren't actually overridable

+    // because they are final and/or private.

+    {

+      assertMethodNotOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.CA",

+          "com.google.gwt.core.ext.typeinfo.test.CA", "caNotOverridableFinal",

+          noParams);

+

+      assertMethodNotOverridable(typeOracle,

+          "com.google.gwt.core.ext.typeinfo.test.CA",

+          "com.google.gwt.core.ext.typeinfo.test.CA",

+          "caNotOverridablePrivate", noParams);

+    }

+  }

+

+  private void addCompilationUnitsInPath(TypeOracleBuilder builder,

+      File sourcePathEntry, String pkgName) throws UnableToCompleteException,

+      MalformedURLException {

+    File pkgPath = new File(sourcePathEntry, pkgName.replace('.', '/'));

+    File[] files = pkgPath.listFiles();

+    if (files == null) {

+      // No files found.

+      return;

+    }

+    

+    for (int i = 0; i < files.length; i++) {

+      File file = files[i];

+      if (file.isFile()) {

+        // If it's a source file, slurp it in.

+        if (file.getName().endsWith(".java")) {

+          URL location = file.toURL();

+          CompilationUnitProvider cup = new URLCompilationUnitProvider(

+              location, pkgName);

+          builder.addCompilationUnit(cup);

+        }

+      } else {

+        // Recurse into subpackages.

+        addCompilationUnitsInPath(builder, sourcePathEntry, pkgName

+            + file.getName());

+      }

+    }

+  }

+

+  private void assertMethodNotOverridable(TypeOracle typeOracle,

+      String expectedTypeName, String searchTypeName, String methodName,

+      String[] paramTypeNames) throws TypeOracleException {

+    assertOverridableMethodInclusion(false, typeOracle, expectedTypeName,

+        searchTypeName, methodName, paramTypeNames);

+  }

+

+  private void assertMethodOverridable(TypeOracle typeOracle,

+      String expectedTypeName, String searchTypeName, String methodName,

+      String[] paramTypeNames) throws TypeOracleException {

+    assertOverridableMethodInclusion(true, typeOracle, expectedTypeName,

+        searchTypeName, methodName, paramTypeNames);

+  }

+

+  private void assertOverridableMethodInclusion(boolean shouldBeFound,

+      TypeOracle oracle, String expectedTypeName, String searchTypeName,

+      String methodName, String[] paramTypeNames) throws TypeOracleException {

+

+    boolean wasFound = false;

+

+    JClassType expectedType = oracle.getType(expectedTypeName);

+    JClassType searchType = oracle.getType(searchTypeName);

+    JType[] paramTypes = new JType[paramTypeNames.length];

+    for (int i = 0; i < paramTypeNames.length; i++) {

+      String paramTypeName = paramTypeNames[i];

+      paramTypes[i] = oracle.parse(paramTypeName);

+    }

+

+    JMethod[] leafMethods = searchType.getOverridableMethods();

+    for (int i = 0; i < leafMethods.length; i++) {

+      JMethod method = leafMethods[i];

+      if (method.getName().equals(methodName)) {

+        if (method.hasParamTypes(paramTypes)) {

+          String typeName = method.getEnclosingType().getQualifiedSourceName();

+          assertEquals(expectedTypeName, typeName);

+          wasFound = true;

+          break;

+        }

+      }

+    }

+

+    if (shouldBeFound) {

+      if (wasFound) {

+        // Good. We wanted to find it and we did.

+      } else {

+        fail("Did not find expected method '" + methodName + "' on type '"

+            + expectedTypeName + "'");

+      }

+    } else {

+      // We want to *not* find it.

+      if (wasFound) {

+        fail("Did not expect to find method '" + methodName + "' on type '"

+            + expectedTypeName + "'");

+      } else {

+        // Good. We didn't want to find it and didn't.

+      }

+    }

+  }

+

+  /**

+   * Looks in the package containing this class and uses it as an anchor for

+   * including all the classes under the "test" subpackage.

+   * 

+   * TODO: This is not generalized yet, but it could be made reusable and put

+   * into TypeOracleBuilder.

+   * 

+   * @return

+   * @throws URISyntaxException

+   * @throws UnableToCompleteException

+   * @throws MalformedURLException

+   */

+  private TypeOracle buildOracleFromTestPackage(TreeLogger logger)

+      throws UnableToCompleteException {

+    Throwable caught;

+    try {

+      // Find the source path using this class as an anchor.

+      String className = getClass().getName();

+      String resName = className.replace('.', '/') + ".java";

+      URL location = getClass().getClassLoader().getResource(resName);

+      assertNotNull("Ensure that source is in classpath for: " + resName,

+          location);

+      String absPath = new File(new URI(location.toString())).getAbsolutePath();

+      int sourcePathEntryLen = absPath.length() - resName.length();

+      File sourcePathEntry = new File(absPath.substring(0, sourcePathEntryLen));

+

+      // Determine the starting package name.

+      int lastDot = className.lastIndexOf('.');

+      String pkgName = (lastDot < 0 ? "test" : className.substring(0, lastDot)

+          + ".test");

+

+      // Create the builder to be filled in.

+      TypeOracleBuilder builder = new TypeOracleBuilder();

+

+      // Add java.lang.Object.

+      builder.addCompilationUnit(new StaticCompilationUnitProvider("java.lang",

+          "Object", "package java.lang; public class Object { }".toCharArray()));

+

+      // Recursively walk the directories.

+      addCompilationUnitsInPath(builder, sourcePathEntry, pkgName);

+      return builder.build(logger);

+    } catch (URISyntaxException e) {

+      caught = e;

+    } catch (MalformedURLException e) {

+      caught = e;

+    }

+    logger.log(TreeLogger.ERROR, "Failed to build type oracle", caught);

+    throw new UnableToCompleteException();

+  }

+}

diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CA.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CA.java
new file mode 100644
index 0000000..605285a
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CA.java
@@ -0,0 +1,11 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public abstract class CA implements IA {
+  
+  public final void caNotOverridableFinal() {
+  }
+  
+  private final void caNotOverridablePrivate() {
+  }
+  
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CB.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CB.java
new file mode 100644
index 0000000..c9145c4
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CB.java
@@ -0,0 +1,7 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public abstract class CB extends CA implements IB {
+  
+  public abstract void ic();
+  
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CC.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CC.java
new file mode 100644
index 0000000..62ca353
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/CC.java
@@ -0,0 +1,5 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public abstract class CC extends CB implements IC {
+
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IA.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IA.java
new file mode 100644
index 0000000..cfc4a56
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IA.java
@@ -0,0 +1,10 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public interface IA {
+
+  void foo(); 
+  
+  void ia();
+
+  void ia(int x, Object y);
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IB.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IB.java
new file mode 100644
index 0000000..fad1da6
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IB.java
@@ -0,0 +1,10 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public interface IB extends IA {
+
+  void foo();
+
+  void ib();
+
+  void ib(int x, Object y);
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IC.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IC.java
new file mode 100644
index 0000000..c9b543b
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/IC.java
@@ -0,0 +1,13 @@
+package com.google.gwt.core.ext.typeinfo.test;
+
+public interface IC extends IB, IA {
+
+  void ib();
+
+  void ib(int x, Object y);
+
+  void ic();
+
+  void ic(int x, Object y);
+
+}
diff --git a/eclipse/settings/english.dictionary b/eclipse/settings/english.dictionary
index 2ba576b..f75a384 100644
--- a/eclipse/settings/english.dictionary
+++ b/eclipse/settings/english.dictionary
@@ -47230,3 +47230,12 @@
 recognize

 minimalist
 cacheable
+initializing
+superclasses
+superinterfaces
+overridable
+subpackage
+generalized
+classpath
+subpackages
+slurp