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