### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core.tests.compiler
Index: src/org/eclipse/jdt/core/tests/compiler/regression/UtilTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/UtilTest.java,v
retrieving revision 1.33
diff -u -r1.33 UtilTest.java
--- src/org/eclipse/jdt/core/tests/compiler/regression/UtilTest.java 18 Apr 2006 16:27:43 -0000 1.33
+++ src/org/eclipse/jdt/core/tests/compiler/regression/UtilTest.java 17 Aug 2007 17:03:21 -0000
@@ -13,6 +13,7 @@
import java.io.File;
//import org.apache.tools.ant.types.selectors.SelectorUtils;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.compiler.CharOperation;
//import junit.framework.AssertionFailedError;
@@ -36,7 +37,14 @@
* If result is invalid then store warning in buffer and display it.
*/
void assertCamelCase(String pattern, String name, boolean match) {
- boolean camelCase = CharOperation.camelCaseMatch(pattern==null?null:pattern.toCharArray(), name==null?null:name.toCharArray());
+
+}
+/**
+ * Assert that a pattern and a name matches or not.
+ * If result is invalid then store warning in buffer and display it.
+ */
+void assertCamelCase(String pattern, String name, boolean exactEnd, boolean match) {
+ boolean camelCase = CharOperation.camelCaseMatch(pattern==null?null:pattern.toCharArray(), name==null?null:name.toCharArray(), exactEnd);
if (match != camelCase) {
StringBuffer line = new StringBuffer("'");
line.append(name);
@@ -608,6 +616,128 @@
// Verify that there were no unexpected results
assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
}
+
+// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=109695
+public void test70() throws CoreException {
+ assertCamelCase("IDE3", "IDocumentExtension", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDE3", "IDocumentExtension2", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDE3", "IDocumentExtension3", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IDE3", "IDocumentExtension135", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IDE3", "IDocumentExtension315", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension2", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension4", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension3", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension5", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension54321", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IDPE3", "IDocumentProviderExtension12345", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IPL3", "IPerspectiveListener", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IPL3", "IPerspectiveListener2", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IPL3", "IPerspectiveListener3", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IPS2", "IPropertySource", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IPS2", "IPropertySource2", true /*exact end match*/, true /* should match */);
+ assertCamelCase("IWWPD2", "IWorkbenchWindowPulldownDelegate", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("IWWPD2", "IWorkbenchWindowPulldownDelegate2", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF16DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF16DSS", "UTF1DocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF16DSS", "UTF6DocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF16DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF1DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF1DSS", "UTF1DocScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF1DSS", "UTF6DocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF1DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF6DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF6DSS", "UTF1DocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTF6DSS", "UTF6DocScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTF6DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("UTFDSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTFDSS", "UTF1DocScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTFDSS", "UTF6DocScannerSupport", true /*exact end match*/, true /* should match */);
+ assertCamelCase("UTFDSS", "UTFDocScannerSupport", true /*exact end match*/, true /* should match */);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
+public void test71() {
+ assertCamelCase("HM", "HashMap", true /*exact end match*/, true /*should match*/);
+ assertCamelCase("HM", "HtmlMapper", true /*exact end match*/, true /*should match*/);
+ assertCamelCase("HM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaM", "HashMap", true /*exact end match*/, true /* should match */);
+ assertCamelCase("HaM", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashM", "HashMap", true /*exact end match*/, true /* should match */);
+ assertCamelCase("HashM", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+public void test71b() { // previous test cases but with 3.3 behavior
+ assertCamelCase("HM", "HashMap", true /*should match*/);
+ assertCamelCase("HM", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HM", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HaM", "HashMap", true /* should match */);
+ assertCamelCase("HaM", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HaM", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HashM", "HashMap", true /* should match */);
+ assertCamelCase("HashM", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HashM", "HashMapEntry", true /*should match*/);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
+public void test72() {
+ assertCamelCase("HMa", "HashMap", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaMa", "HashMap", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashMa", "HashMap", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+public void test72b() { // previous test cases but with 3.3 behavior
+ assertCamelCase("HMa", "HashMap", true /*should match*/);
+ assertCamelCase("HMa", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HMa", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HaMa", "HashMap", true /* should match */);
+ assertCamelCase("HaMa", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HaMa", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HashMa", "HashMap", true /* should match */);
+ assertCamelCase("HashMa", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HashMa", "HashMapEntry", true /*should match*/);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
+public void test73() {
+ assertCamelCase("HMap", "HashMap", true /*exact end match*/, true /*should match*/);
+ assertCamelCase("HMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaMap", "HashMap", true /*exact end match*/, true /* should match */);
+ assertCamelCase("HaMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HaMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashMap", "HashMap", true /*exact end match*/, true /* should match */);
+ assertCamelCase("HashMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
+ assertCamelCase("HashMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
+public void test73b() { // previous test cases but with 3.3 behavior
+ assertCamelCase("HMap", "HashMap", true /*should match*/);
+ assertCamelCase("HMap", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HMap", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HaMap", "HashMap", true /* should match */);
+ assertCamelCase("HaMap", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HaMap", "HashMapEntry", true /*should match*/);
+ assertCamelCase("HashMap", "HashMap", true /* should match */);
+ assertCamelCase("HashMap", "HtmlMapper", true /*should match*/);
+ assertCamelCase("HashMap", "HashMapEntry", true /*should match*/);
+ // Verify that there were no unexpected results
+ assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
+}
public static Class testClass() {
return UtilTest.class;
}
#P org.eclipse.jdt.core
Index: search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java,v
retrieving revision 1.23
diff -u -r1.23 JavaSearchPattern.java
--- search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java 7 Sep 2006 12:59:26 -0000 1.23
+++ search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java 17 Aug 2007 17:03:25 -0000
@@ -75,7 +75,7 @@
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=81377
int rule = getMatchRule();
this.isCaseSensitive = (rule & R_CASE_SENSITIVE) != 0;
- this.isCamelCase = (rule & R_CAMELCASE_MATCH) != 0;
+ this.isCamelCase = (rule & (R_CAMELCASE_MATCH | R_CAMELCASE_STRICT_MATCH)) != 0;
this.matchCompatibility = rule & MATCH_COMPATIBILITY_MASK;
this.matchMode = rule & MATCH_MODE_MASK;
}
Index: search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java,v
retrieving revision 1.38
diff -u -r1.38 PackageReferenceLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java 27 Apr 2007 15:51:38 -0000 1.38
+++ search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java 17 Aug 2007 17:03:25 -0000
@@ -96,11 +96,12 @@
if (this.pattern.pkgName == null) return ACCURATE_MATCH;
char[] packageName = null;
- if (this.isCamelCase) {
+ if (this.isCamelCase || this.isStrictCamelCase) {
packageName = CharOperation.concatWith(tokens, '.');
- if (CharOperation.camelCaseMatch(this.pattern.pkgName, packageName)) {
+ if (CharOperation.camelCaseMatch(this.pattern.pkgName, packageName, this.isStrictCamelCase)) {
return POSSIBLE_MATCH;
}
+ if (this.isStrictCamelCase) return IMPOSSIBLE_MATCH;
}
switch (this.matchMode) {
case SearchPattern.R_EXACT_MATCH:
Index: search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java,v
retrieving revision 1.66
diff -u -r1.66 PatternLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 4 Jul 2007 13:59:58 -0000 1.66
+++ search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 17 Aug 2007 17:03:26 -0000
@@ -24,6 +24,7 @@
protected int matchMode;
protected boolean isCaseSensitive;
protected boolean isCamelCase;
+protected boolean isStrictCamelCase;
protected boolean isEquivalentMatch;
protected boolean isErasureMatch;
protected boolean mustResolve;
@@ -118,7 +119,8 @@
public PatternLocator(SearchPattern pattern) {
int matchRule = pattern.getMatchRule();
this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
- this.isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
+ this.isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
+ this.isCamelCase = this.isStrictCamelCase || (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
this.isErasureMatch = (matchRule & SearchPattern.R_ERASURE_MATCH) != 0;
this.isEquivalentMatch = (matchRule & SearchPattern.R_EQUIVALENT_MATCH) != 0;
this.matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
@@ -282,18 +284,21 @@
boolean matchFirstChar = !this.isCaseSensitive || pattern[0] == name[0];
boolean sameLength = pattern.length == name.length;
boolean canBePrefix = name.length >= pattern.length;
- if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name)) {
- return POSSIBLE_MATCH;
+ if (this.isCamelCase || this.isStrictCamelCase) {
+ if (matchFirstChar && CharOperation.camelCaseMatch(pattern, name, this.isStrictCamelCase)) {
+ return POSSIBLE_MATCH;
+ }
+ if (this.isStrictCamelCase) return IMPOSSIBLE_MATCH;
}
switch (this.matchMode) {
case SearchPattern.R_EXACT_MATCH:
- if (!this.isCamelCase) {
+// if (!this.isCamelCase) {
if (sameLength && matchFirstChar && CharOperation.equals(pattern, name, this.isCaseSensitive)) {
return POSSIBLE_MATCH | EXACT_FLAVOR;
}
break;
- }
- // fall through next case to match as prefix if camel case failed
+// }
+// // fall through next case to match as prefix if camel case failed
case SearchPattern.R_PREFIX_MATCH:
if (canBePrefix && matchFirstChar && CharOperation.prefixEquals(pattern, name, this.isCaseSensitive)) {
return POSSIBLE_MATCH;
@@ -716,9 +721,9 @@
return ACCURATE_MATCH;
}
}
- if (this.isCamelCase) {
+ if (this.isCamelCase || this.isStrictCamelCase) {
if (!this.isCaseSensitive || (qualifiedPattern.length>0 && sourceName.length>0 && qualifiedPattern[0] == sourceName[0])) {
- if (CharOperation.camelCaseMatch(qualifiedPattern, sourceName)) {
+ if (CharOperation.camelCaseMatch(qualifiedPattern, sourceName, this.isStrictCamelCase)) {
return ACCURATE_MATCH;
}
}
Index: search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java,v
retrieving revision 1.56
diff -u -r1.56 TypeReferenceLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java 27 Apr 2007 15:51:38 -0000 1.56
+++ search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java 17 Aug 2007 17:03:26 -0000
@@ -112,8 +112,11 @@
return IMPOSSIBLE_MATCH;
}
boolean matchFirstChar = !this.isCaseSensitive || (qualifiedPattern[0] == qualifiedTypeName[0]);
- if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName)) {
- return POSSIBLE_MATCH;
+ if (this.isCamelCase || this.isStrictCamelCase) {
+ if (matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName, this.isStrictCamelCase)) {
+ return POSSIBLE_MATCH;
+ }
+ if (this.isStrictCamelCase) return IMPOSSIBLE_MATCH;
}
switch (this.matchMode) {
case SearchPattern.R_EXACT_MATCH:
Index: buildnotes_jdt-core.html
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/buildnotes_jdt-core.html,v
retrieving revision 1.6030
diff -u -r1.6030 buildnotes_jdt-core.html
--- buildnotes_jdt-core.html 16 Aug 2007 13:13:13 -0000 1.6030
+++ buildnotes_jdt-core.html 17 Aug 2007 17:03:23 -0000
@@ -50,10 +50,211 @@
New fix for bug 186781 required the index version to be incremented.
Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).
+Add strict mode for Camel Case matching (see bug 124624).
+Currently Camel Case rules are permissive as it accept prefix match for the last part.
+For instance, 'HM'
pattern will match 'HashMap'
but also 'HashMapEntry'
.
+Or 'HaMap'
pattern will match 'HashMap'
but also 'HatMapper'
.
+Some users now needs a more strict mode for Camel Case rule which forces a exact match for the last part of the pattern.
+To implement this functionality, following API methods/constants have been added in JDT/Core:
+- On org.eclipse.jdt.core.search.SearchPattern
+ /**
+ * Match rule: The search pattern contains a Camel Case expression with
+ * a strict number of parts and preventing automatic prefix matching for the last part
+ * (if it consists of multiple letters).
+ *
+ * Examples:
+ * .
'HM'
type string pattern will match
+ * 'HashMap'
and 'HtmlMapper'
types,
+ * but not 'HashMapEntry'
+ * . 'HMap'
type string pattern will match
+ * 'HashMap'
type but not 'HtmlMapper'
.
+ *
+ * @see CharOperation#camelCaseMatch(char[], char[], boolean) for a detailed explanation
+ * of Camel Case matching.
+ *
+ * Can be combined to {@link #R_PREFIX_MATCH} match rule. For example,
+ * when prefix match rule is combined with Camel Case match rule,
+ * "nPE"
pattern will match nPException
.
+ *
+ * Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
+ * will not be used simultaneously as they are mutually exclusive.
+ * Used match rule depends on whether string pattern contains specific pattern
+ * characters (e.g. '*' or '?') or not. If it does, then only Pattern match rule
+ * will be used, otherwise only Camel Case match will be used.
+ * For example, with "NPE"
string pattern, search will only use
+ * Camel Case match rule, but with N*P*E*
string pattern, it will
+ * use only Pattern match rule.
+ *
+ * @since 3.4
+ */
+ public static final int R_CAMELCASE_STRICT_MATCH = 0x0100;
+
+- On org.eclipse.jdt.core.compiler.CharOperation:
+
+/**
+ * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
+ * must have exactly the same number of parts and if last part must be identical if it contains lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but still not 'HashMapEntry'.
+ * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ * Examples:
+ *
+ * 1. pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ *...
+ * 6. pattern = { 'I', 'P', 'L', '3' }
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * result => true
+ * 7. pattern = { 'H', M' }
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * result => (exactMode == false)
+ * 8. pattern = { 'H', M', 'a', 'p' }
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * result => (exactMode == false)
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ * . For example, when it's 'true':
+ * - 'HM' type string pattern will match
+ * 'HashMap' and 'HtmlMapper' types,
+ * but not 'HashMapEntry'
+ * - 'HMap' type string pattern will match
+ * 'HashMap' type but not 'HtmlMapper'.
+ * . and, when it's 'false':
+ * - 'HM' type string pattern will match both
+ * 'HashMap' and 'HtmlMapper'
+ * and 'HashMapEntry'
+ * - 'HMap' type string pattern will match both
+ * 'HashMap' and 'HtmlMapper' types.
+ *
+ * @return true if the pattern matches the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(char[] pattern, char[] name, boolean exactMode) {
+...
+}
+
+/**
+ * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * Can match only subset of name/pattern, considering end positions as non-inclusive.
+ * The sub-pattern is defined by the patternStart and patternEnd positions.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
+ * must have exactly the same number of parts and if last part must be identical if it contains lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but still not 'HashMapEntry'.
+ * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ * Examples:
+ *
+ * 1. pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ *...
+ * 6. pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * 7. pattern = { 'H', M' }
+ * patternStart = 0
+ * patternEnd = 2
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * nameStart = 0
+ * nameEnd = 12
+ * result => (exactMode == false)
+ * 8. pattern = { 'H', M', 'a', 'p' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * nameStart = 0
+ * nameEnd = 9
+ * result => (exactMode == false)
+ *
+ * @param pattern the given pattern
+ * @param patternStart the start index of the pattern, inclusive
+ * @param patternEnd the end index of the pattern, exclusive
+ * @param name the given name
+ * @param nameStart the start index of the name, inclusive
+ * @param nameEnd the end index of the name, exclusive
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ * . For example, when it's 'true':
+ * - 'HM' type string pattern will match
+ * 'HashMap' and 'HtmlMapper' types,
+ * but not 'HashMapEntry'
+ * - 'HMap' type string pattern will match
+ * 'HashMap' type but not 'HtmlMapper'.
+ * . and, when it's 'false':
+ * - 'HM' type string pattern will match both
+ * 'HashMap' and 'HtmlMapper'
+ * and 'HashMapEntry'
+ * - 'HMap' type string pattern will match both
+ * 'HashMap' and 'HtmlMapper' types.
+ *
+ * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd, boolean exactMode) {
+...
+}
+
+
+
Problem Reports Fixed
-109695
+124624
+[search] Camelcase matching routines should support end character
+
109695
[search] Numbers should be treated as upper-case letters in CamelCase matching
186781
StackOverflowError while computing launch button tooltip
Index: compiler/org/eclipse/jdt/core/compiler/CharOperation.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java,v
retrieving revision 1.78
diff -u -r1.78 CharOperation.java
--- compiler/org/eclipse/jdt/core/compiler/CharOperation.java 16 Aug 2007 13:13:13 -0000 1.78
+++ compiler/org/eclipse/jdt/core/compiler/CharOperation.java 17 Aug 2007 17:03:23 -0000
@@ -58,7 +58,7 @@
*
*
*
- * @param array the array that is concanated with the suffix character
+ * @param array the array that is concatenated with the suffix character
* @param suffix the suffix character
* @return the new array
*/
@@ -72,8 +72,8 @@
}
/**
- * Append the given subarray to the target array starting at the given index in the target array.
- * The start of the subarray is inclusive, the end is exclusive.
+ * Append the given sub-array to the target array starting at the given index in the target array.
+ * The start of the sub-array is inclusive, the end is exclusive.
* Answers a new target array if it needs to grow, otherwise answers the same target array.
*
* For example:
@@ -180,18 +180,25 @@
/**
* Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
* char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
- *
+ *
* CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
* This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
* or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
* in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
* uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
* names follow the lower CamelCase convention.
- *
+ *
* The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
* appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
* or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
- *
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * Camel Case rules are applied permissively which means that the name may have more parts than the pattern or its
+ * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(char[], char[], boolean)}
+ * for more explanation on Camel Case strict/permissive mode.
+ *
* Examples:
*
*
@@ -224,6 +231,16 @@
* result => false
*
*
+ *
+ * pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
*
*
* @param pattern the given pattern
@@ -237,26 +254,122 @@
if (name == null)
return false; // null name cannot match
- return camelCaseMatch(pattern, 0, pattern.length, name, 0, name.length);
+ return camelCaseMatch(pattern, name, false/*prefix match for last part*/);
}
/**
- * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.
+ * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When the strict mode is specified, the given pattern and name
+ * must have exactly the same number of parts, and the last parts must be identical if they contain lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when the last part does not contain lowercase characters, then the name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but it will not match 'HashMapEntry'.
+ * Reversely, if the permissive mode is specified, the names do not need to have the same number of parts and the same last parts.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ *
+ * Examples:
+ *
+ * - pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ * - pattern = { 'n', p', 'e' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ * - pattern = { 'I', 'P', 'L', '3' }
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * result => true
+ * - pattern = { 'H', M' }
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * result => (exactMode == false)
+ * - pattern = { 'H', M', 'a', 'p' }
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * result => (exactMode == false)
+ *
+ *
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ *
+ * - For example, when it's
true
:
+ * - HM
type string pattern will match
+ * HashMap
and HtmlMapper
types,
+ * but not HashMapEntry
+ * - HMap
type string pattern will match
+ * HashMap
type but not HtmlMapper
.
+ *
+ * - and, when it's
false
:
+ * - HM
type string pattern will match both
+ * HashMap
and HtmlMapper
+ * and HashMapEntry
+ * - HMap
type string pattern will match both
+ * HashMap
and HtmlMapper
types.
+ *
+ *
+ * @return true if the pattern matches the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(char[] pattern, char[] name, boolean exactMode) {
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (name == null)
+ return false; // null name cannot match
+
+ return camelCaseMatch(pattern, 0, pattern.length, name, 0, name.length, exactMode);
+}
+
+/**
+ * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.
* char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
* Can match only subset of name/pattern, considering end positions as non-inclusive.
- * The subpattern is defined by the patternStart and patternEnd positions.
- *
+ * The sub-pattern is defined by the patternStart and patternEnd positions.
+ *
* CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
* This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
* or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
* in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
* uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
* names follow the lower CamelCase convention.
- *
+ *
* The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
* appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
* or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
- *
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * Camel Case rules are applied permissively which means that the name may have more parts than the pattern and its
+ * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)}
+ * for more explanation on Camel Case strict/permissive mode.
+ *
* Examples:
*
*
@@ -309,6 +422,16 @@
* result => false
*
*
+ *
+ * pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
*
*
* @param pattern the given pattern
@@ -317,10 +440,133 @@
* @param name the given name
* @param nameStart the start index of the name, inclusive
* @param nameEnd the end index of the name, exclusive
- * @return true if a sub-pattern matches the subpart of the given name, false otherwise
+ * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
* @since 3.2
+ * @deprecated Use {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)} instead
*/
public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd) {
+ return camelCaseMatch(pattern, patternStart, patternEnd, name, nameStart, nameEnd, false/*prefix match for last hunk*/);
+}
+
+/**
+ * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * Can match only subset of name/pattern, considering end positions as non-inclusive.
+ * The sub-pattern is defined by the patternStart and patternEnd positions.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When the strict mode is specified, the given pattern and name
+ * must have exactly the same number of parts, and the last parts must be identical if they contain lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when the last part does not contain lowercase characters, then the name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but it will not match 'HashMapEntry'.
+ * Reversely, if the permissive mode is specified, names do not need to have the same number of parts and the same last parts.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ *
+ * Examples:
+ *
+ * - pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * - pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => false
+ * - pattern = { 'n', p', 'e' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => false
+ * - pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * - pattern = { 'H', M' }
+ * patternStart = 0
+ * patternEnd = 2
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * nameStart = 0
+ * nameEnd = 12
+ * result => (exactMode == false)
+ * - pattern = { 'H', M', 'a', 'p' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * nameStart = 0
+ * nameEnd = 9
+ * result => (exactMode == false)
+ *
+ *
+ *
+ * @param pattern the given pattern
+ * @param patternStart the start index of the pattern, inclusive
+ * @param patternEnd the end index of the pattern, exclusive
+ * @param name the given name
+ * @param nameStart the start index of the name, inclusive
+ * @param nameEnd the end index of the name, exclusive
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ *
+ * - For example, when it's
true
:
+ * - HM
type string pattern will match
+ * HashMap
and HtmlMapper
types,
+ * but not HashMapEntry
+ * - HMap
type string pattern will match
+ * HashMap
type but not HtmlMapper
.
+ *
+ * - and, when it's
false
:
+ * - HM
type string pattern will match both
+ * HashMap
and HtmlMapper
+ * and HashMapEntry
+ * - HMap
type string pattern will match both
+ * HashMap
and HtmlMapper
types.
+ *
+ *
+ * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd, boolean exactMode) {
if (name == null)
return false; // null name cannot match
if (pattern == null)
@@ -346,9 +592,38 @@
iPattern++;
iName++;
- if (iPattern == patternEnd) {
- // We have exhausted pattern, so it's a match
- return true;
+ if (iPattern == patternEnd) { // we have exhausted pattern...
+ // it's a match if not exact mode or name is also exhausted
+ if (!exactMode || iName == nameEnd) return true;
+
+ // it's not a match if last pattern character is a lowercase
+ if ((patternChar = pattern[iPattern-1]) < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
+ return false;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar) && !Character.isDigit(patternChar)) {
+ return false;
+ }
+
+ // it's a match only if name has no more uppercase characters (exact mode)
+ while (true) {
+ if (iName == nameEnd) {
+ // we have exhausted name, so it's a match
+ return true;
+ }
+ nameChar = name[iName];
+ if (nameChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & ScannerHelper.C_UPPER_LETTER) != 0) {
+ // nameChar is uppercase, so it's not a match
+ return false;
+ }
+ }
+ else if (!Character.isJavaIdentifierPart(nameChar) || Character.isUpperCase(nameChar)) {
+ return false;
+ }
+ iName++;
+ }
}
if (iName == nameEnd){
Index: search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java,v
retrieving revision 1.47
diff -u -r1.47 BasicSearchEngine.java
--- search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 6 Jul 2007 12:25:50 -0000 1.47
+++ search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 17 Aug 2007 17:03:25 -0000
@@ -454,14 +454,18 @@
return false;
if (patternTypeName != null) {
+ boolean isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
int matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
if (!isCaseSensitive && !isCamelCase) {
patternTypeName = CharOperation.toLowerCase(patternTypeName);
}
boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0];
- if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName)) {
- return true;
+ if (isCamelCase || isStrictCamelCase) {
+ if (matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName, isStrictCamelCase)) {
+ return true;
+ }
+ if (isStrictCamelCase) return false;
}
switch(matchMode) {
case SearchPattern.R_EXACT_MATCH :
Index: search/org/eclipse/jdt/core/search/SearchPattern.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java,v
retrieving revision 1.69
diff -u -r1.69 SearchPattern.java
--- search/org/eclipse/jdt/core/search/SearchPattern.java 17 Aug 2007 06:14:50 -0000 1.69
+++ search/org/eclipse/jdt/core/search/SearchPattern.java 17 Aug 2007 17:03:25 -0000
@@ -141,7 +141,7 @@
/**
* Match rule: The search pattern contains a Camel Case expression.
- *
+ *
* Examples:
*
* NPE
type string pattern will match
@@ -149,13 +149,16 @@
* NuPoEx
type string pattern will only match
* NullPointerException
type.
*
- * @see CharOperation#camelCaseMatch(char[], char[]) for a detailed explanation
- * of Camel Case matching.
- *
- * Can be combined to {@link #R_PREFIX_MATCH} match rule. For example,
- * when prefix match rule is combined with Camel Case match rule,
- * "nPE"
pattern will match nPException
.
- *
+ *
+ * Camel Case match rule already behaves both as prefix match and case sensitive
+ * match rules (eg. HashMap
pattern using using Camel Case rule
+ * will match both 'HashMap'
and HashMapEntry'
).
+ * However, this rule still can be combined to prefix match rule to also behaves
+ * as prefix match and case insensitive match rules.
+ * For instance, when {@link #R_CAMELCASE_MATCH} | {@link #R_PREFIX_MATCH}
+ * flags are combined, "NULL"
pattern will still match
+ * NullPointerException
.
+ *
* Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
* will not be used simultaneously as they are mutually exclusive.
* Used match rule depends on whether string pattern contains specific pattern
@@ -164,11 +167,55 @@
* For example, with "NPE"
string pattern, search will only use
* Camel Case match rule, but with N*P*E*
string pattern, it will
* use only Pattern match rule.
+ *
+ * @see CharOperation#camelCaseMatch(char[], char[]) for a detailed explanation
+ * of Camel Case matching.
*
* @since 3.2
*/
public static final int R_CAMELCASE_MATCH = 0x0080;
+ /**
+ * Match rule: The search pattern contains a Camel Case expression with
+ * a strict number of parts and preventing automatic prefix matching for the last part
+ * (if it consists of multiple letters).
+ *
+ * Examples:
+ *
+ * HM
type string pattern will match
+ * HashMap
and HtmlMapper
types,
+ * but not HashMapEntry
+ *
+ * HMap
type string pattern will match
+ * HashMap
type but not HtmlMapper
.
+ *
+ *
+ *
+ * Camel Case match rule already behaves both as prefix match and case sensitive
+ * match rules (eg. HashMap
pattern using using Camel Case rule
+ * will match both 'HashMap'
and HashMapEntry'
).
+ * However, this rule still can be combined to prefix match rule to also behaves
+ * as prefix match and case insensitive match rules.
+ * For instance, when {@link #R_CAMELCASE_MATCH} | {@link #R_PREFIX_MATCH}
+ * flags are combined, "NULL"
pattern will still match
+ * NullPointerException
.
+ *
+ * Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
+ * will not be used simultaneously as they are mutually exclusive.
+ * Used match rule depends on whether string pattern contains specific pattern
+ * characters (e.g. '*' or '?') or not. If it does, then only Pattern match rule
+ * will be used, otherwise only Camel Case match will be used.
+ * For example, with "NPE"
string pattern, search will only use
+ * Camel Case match rule, but with N*P*E*
string pattern, it will
+ * use only Pattern match rule.
+ *
+ * @see CharOperation#camelCaseMatch(char[], char[], boolean) for a detailed explanation
+ * of Camel Case matching.
+ *
+ * @since 3.4
+ */
+ public static final int R_CAMELCASE_STRICT_MATCH = 0x0100;
+
private static final int MODE_MASK = R_EXACT_MATCH | R_PREFIX_MATCH | R_PATTERN_MATCH | R_REGEXP_MATCH;
private int matchRule;
@@ -198,9 +245,71 @@
/**
* Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
- * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * Camel Case rules are applied permissively which means that the name may have more parts than the pattern or its
+ * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(String, String, boolean)}
+ * for more explanation on Camel Case strict/permissive mode.
+ *
+ * Examples:
+ *
+ *
+ * pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ *
+ *
+ *
+ * pattern = { 'n', p', 'e' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ *
+ *
+ *
+ * pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
+ *
*
- * @see CharOperation#camelCaseMatch(char[], char[])
+ * @see #camelCaseMatch(String, int, int, String, int, int, boolean) for algorithm implementation
*
* @param pattern the given pattern
* @param name the given name
@@ -213,17 +322,187 @@
if (name == null)
return false; // null name cannot match
- return CharOperation.camelCaseMatch(pattern.toCharArray(), 0, pattern.length(), name.toCharArray(), 0, name.length());
+ return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length(), false/*prefix match for last part*/);
+}
+
+/**
+ * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When the strict mode is specified, the given pattern and name
+ * must have exactly the same number of parts, and the last parts must be identical if they contain lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when the last part does not contain lowercase characters, then the name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but it will not match 'HashMapEntry'.
+ * Reversely, if the permissive mode is specified, the names do not need to have the same number of parts and the same last parts.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ *
+ * Examples:
+ *
+ * - pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'P', 'E' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ * - pattern = { 'n', p', 'e' }
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * result => false
+ * - pattern = { 'I', 'P', 'L', '3' }
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * result => true
+ * - pattern = { 'H', M' }
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * result => (exactMode == false)
+ * - pattern = { 'H', M', 'a', 'p' }
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * result => (exactMode == false)
+ *
+ *
+ *
+ * @see #camelCaseMatch(String, int, int, String, int, int, boolean) for algorithm implementation
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ *
+ * - For example, when it's
true
:
+ * - HM
type string pattern will match
+ * HashMap
and HtmlMapper
types,
+ * but not HashMapEntry
+ * - HMap
type string pattern will match
+ * HashMap
type but not HtmlMapper
.
+ *
+ * - and, when it's
false
:
+ * - HM
type string pattern will match both
+ * HashMap
and HtmlMapper
+ * and HashMapEntry
+ * - HMap
type string pattern will match both
+ * HashMap
and HtmlMapper
types.
+ *
+ *
+ * @return true if the pattern matches the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(String pattern, String name, boolean exactMode) {
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (name == null)
+ return false; // null name cannot match
+
+ return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length(), exactMode);
}
/**
- * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.
+ * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.
* char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
* Can match only subset of name/pattern, considering end positions as non-inclusive.
- * The subpattern is defined by the patternStart and patternEnd positions.
- *
- * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int) for specification
- * and implementation of this algorithm.
+ * The sub-pattern is defined by the patternStart and patternEnd positions.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * Camel Case rules are applied permissively which means that the name may have more parts than the pattern and its
+ * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(String, int, int, String, int, int, boolean)}
+ * for more explanation on Camel Case strict/permissive mode.
+ *
+ * Examples:
+ *
+ *
+ * pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ *
+ *
+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => false
+ *
+ *
+ *
+ * pattern = { 'n', p', 'e' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => false
+ *
+ *
+ *
+ * pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
+ *
*
* @param pattern the given pattern
* @param patternStart the start index of the pattern, inclusive
@@ -231,11 +510,260 @@
* @param name the given name
* @param nameStart the start index of the name, inclusive
* @param nameEnd the end index of the name, exclusive
- * @return true if a sub-pattern matches the subpart of the given name, false otherwise
+ * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
* @since 3.2
+ * @deprecated Use {@link #camelCaseMatch(String, int, int, String, int, int, boolean)} instead
*/
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) {
- return CharOperation.camelCaseMatch(pattern.toCharArray(), patternStart, patternEnd, name.toCharArray(), nameStart, nameEnd);
+ return camelCaseMatch(pattern, patternStart, patternEnd, name, nameStart, nameEnd, false/*prefix match for last part*/);
+}
+
+/**
+ * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.
+ * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * Can match only subset of name/pattern, considering end positions as non-inclusive.
+ * The sub-pattern is defined by the patternStart and patternEnd positions.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
+ * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
+ *
+ * CamelCase rules can be applied strictly or permissively. When the strict mode is specified, the given pattern and name
+ * must have exactly the same number of parts, and the last parts must be identical if they contain lowercase characters.
+ * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
+ * Note that when the last part does not contain lowercase characters, then the name may end with lowercase characters.
+ * So, 'HM' pattern will match both 'HashMap' and 'HatMapper' but it will not match 'HashMapEntry'.
+ * Reversely, if the permissive mode is specified, names do not need to have the same number of parts and the same last parts.
+ * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' and'HashMapEntry'.
+ *
+ *
+ * Examples:
+ *
+ * - pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * - pattern = { 'N', 'P', 'E' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ * - pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
+ * patternStart = 0
+ * patternEnd = 6
+ * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => false
+ * - pattern = { 'n', p', 'e' }
+ * patternStart = 0
+ * patternEnd = 3
+ * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
+ * nameStart = 0
+ * nameEnd = 20
+ * result => false
+ * - pattern = { 'I', 'P', 'L', '3' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ * - pattern = { 'H', M' }
+ * patternStart = 0
+ * patternEnd = 2
+ * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
+ * nameStart = 0
+ * nameEnd = 12
+ * result => (exactMode == false)
+ * - pattern = { 'H', M', 'a', 'p' }
+ * patternStart = 0
+ * patternEnd = 4
+ * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
+ * nameStart = 0
+ * nameEnd = 9
+ * result => (exactMode == false)
+ *
+ *
+ *
+ * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int, boolean)
+ * from which algorithm implementation has been entirely copied.
+ * Array lengths have been replaced with call to {@link String#length()} and
+ * array direct access have been replaced with call to {@link String#charAt(int)}.
+ * WARNING: Do not change one of these method without changing the other the same way
+ * otherwise behavior differences may appear while using them...
+ *
+ * @param pattern the given pattern
+ * @param patternStart the start index of the pattern, inclusive
+ * @param patternEnd the end index of the pattern, exclusive
+ * @param name the given name
+ * @param nameStart the start index of the name, inclusive
+ * @param nameEnd the end index of the name, exclusive
+ * @param exactMode flag telling whether the name must have same
+ * number of parts and same last part (if it consists of multiple letters)
+ * as the pattern or not.
+ *
+ * - For example, when it's
true
:
+ * - HM
type string pattern will match
+ * HashMap
and HtmlMapper
types,
+ * but not HashMapEntry
+ * - HMap
type string pattern will match
+ * HashMap
type but not HtmlMapper
.
+ *
+ * - and, when it's
false
:
+ * - HM
type string pattern will match both
+ * HashMap
and HtmlMapper
+ * and HashMapEntry
+ * - HMap
type string pattern will match both
+ * HashMap
and HtmlMapper
types.
+ *
+ *
+ * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
+ * @since 3.4
+ */
+public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd, boolean exactMode) {
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (patternEnd < 0) patternEnd = pattern.length();
+ if (nameEnd < 0) nameEnd = name.length();
+
+ if (patternEnd <= patternStart) return nameEnd <= nameStart;
+ if (nameEnd <= nameStart) return false;
+ // check first pattern char
+ if (name.charAt(nameStart) != pattern.charAt(patternStart)) {
+ // first char must strictly match (upper/lower)
+ return false;
+ }
+
+ char patternChar, nameChar;
+ int iPattern = patternStart;
+ int iName = nameStart;
+
+ // Main loop is on pattern characters
+ while (true) {
+
+ iPattern++;
+ iName++;
+
+ if (iPattern == patternEnd) { // we have exhausted pattern...
+ // it's a match if not exact mode or name is also exhausted
+ if (!exactMode || iName == nameEnd) return true;
+
+ // it's not a match if last pattern character is a lowercase
+ if ((patternChar = pattern.charAt(iPattern-1)) < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
+ return false;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar) && !Character.isDigit(patternChar)) {
+ return false;
+ }
+
+ // it's a match only if name has no more uppercase characters (exact mode)
+ while (true) {
+ if (iName == nameEnd) {
+ // we have exhausted name, so it's a match
+ return true;
+ }
+ nameChar = name.charAt(iName);
+ if (nameChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & ScannerHelper.C_UPPER_LETTER) != 0) {
+ // nameChar is uppercase, so it's not a match
+ return false;
+ }
+ }
+ else if (!Character.isJavaIdentifierPart(nameChar) || Character.isUpperCase(nameChar)) {
+ return false;
+ }
+ iName++;
+ }
+ }
+
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ // For as long as we're exactly matching, bring it on (even if it's a lower case character)
+ if ((patternChar = pattern.charAt(iPattern)) == name.charAt(iName)) {
+ continue;
+ }
+
+ // If characters are not equals, then it's not a match if patternChar is lowercase
+ if (patternChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
+ return false;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar) && !Character.isDigit(patternChar)) {
+ return false;
+ }
+
+ // patternChar is uppercase, so let's find the next uppercase in name
+ while (true) {
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ nameChar = name.charAt(iName);
+ if (nameChar < ScannerHelper.MAX_OBVIOUS) {
+ int charNature = ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar];
+ if ((charNature & (ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_SPECIAL)) != 0) {
+ // nameChar is lowercase
+ iName++;
+ } else if ((charNature & ScannerHelper.C_DIGIT) != 0) {
+ // nameChar is digit => break if the digit is current pattern character otherwise consume it
+ if (patternChar == nameChar) break;
+ iName++;
+ // nameChar is uppercase...
+ } else if (patternChar != nameChar) {
+ //.. and it does not match patternChar, so it's not a match
+ return false;
+ } else {
+ //.. and it matched patternChar. Back to the big loop
+ break;
+ }
+ }
+ // Same tests for non-obvious characters
+ else if (Character.isJavaIdentifierPart(nameChar) && !Character.isUpperCase(nameChar)) {
+ iName++;
+ } else if (Character.isDigit(nameChar)) {
+ if (patternChar == nameChar) break;
+ iName++;
+ } else if (patternChar != nameChar) {
+ return false;
+ } else {
+ break;
+ }
+ }
+ // At this point, either name has been exhausted, or it is at an uppercase letter.
+ // Since pattern is also at an uppercase letter
+ }
}
/**
@@ -1601,6 +2129,7 @@
if (pattern == null) return true; // null is as if it was "*"
if (name != null) {
boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0;
+ boolean isStrictCamelCase = (this.matchRule & R_CAMELCASE_STRICT_MATCH) != 0;
boolean isCamelCase = (this.matchRule & R_CAMELCASE_MATCH) != 0;
int matchMode = this.matchRule & MODE_MASK;
boolean emptyPattern = pattern.length == 0;
@@ -1608,12 +2137,14 @@
boolean sameLength = pattern.length == name.length;
boolean canBePrefix = name.length >= pattern.length;
boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 && pattern[0] == name[0]);
- if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name)) {
- return true;
+ if (isCamelCase || isStrictCamelCase) {
+ if (matchFirstChar && CharOperation.camelCaseMatch(pattern, name, isStrictCamelCase)) {
+ return true;
+ }
+ if (isStrictCamelCase) return false;
}
switch (matchMode) {
case R_EXACT_MATCH :
- case R_FULL_MATCH :
if (!isCamelCase) {
if (sameLength && matchFirstChar) {
return CharOperation.equals(pattern, name, isCaseSensitive);
@@ -1643,7 +2174,7 @@
/**
* Validate compatibility between given string pattern and match rule.
*
- * Optimized (ie. returned match rule is modified) combinations are:
+ * Returned match rule is modified, when following combinations are observed in the given parameters:
*
* - {@link #R_PATTERN_MATCH} without any '*' or '?' in string pattern:
* pattern match bit is unset,
@@ -1695,11 +2226,12 @@
if ((matchRule & R_PATTERN_MATCH) != 0) {
// remove Camel Case and Prefix match bits if any
matchRule &= ~R_CAMELCASE_MATCH;
+ matchRule &= ~R_CAMELCASE_STRICT_MATCH;
matchRule &= ~R_PREFIX_MATCH;
}
// Verify Camel Case match rule
- if ((matchRule & R_CAMELCASE_MATCH) != 0) {
+ if ((matchRule & (R_CAMELCASE_MATCH | R_CAMELCASE_STRICT_MATCH)) != 0) {
// Verify sting pattern validity
int length = stringPattern.length();
boolean validCamelCase = true;
@@ -1723,6 +2255,7 @@
}
} else {
matchRule &= ~R_CAMELCASE_MATCH;
+ matchRule &= ~R_CAMELCASE_STRICT_MATCH;
if ((matchRule & R_PREFIX_MATCH) == 0) {
matchRule |= R_PREFIX_MATCH;
matchRule |= R_CASE_SENSITIVE;
Index: search/org/eclipse/jdt/internal/core/index/Index.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java,v
retrieving revision 1.27
diff -u -r1.27 Index.java
--- search/org/eclipse/jdt/internal/core/index/Index.java 15 Aug 2007 18:49:22 -0000 1.27
+++ search/org/eclipse/jdt/internal/core/index/Index.java 17 Aug 2007 17:03:25 -0000
@@ -57,9 +57,13 @@
if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*';
// First test camel case if necessary
+ boolean isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
- if (isCamelCase && pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word)) {
- return true;
+ if (isCamelCase || isStrictCamelCase) {
+ if (pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word, isStrictCamelCase)) {
+ return true;
+ }
+ if (isStrictCamelCase) return false;
}
// need to mask some bits of pattern rule (bug 79790)
#P org.eclipse.jdt.core.tests.model
Index: src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java,v
retrieving revision 1.165
diff -u -r1.165 JavaSearchTests.java
--- src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 19 Jul 2007 15:08:25 -0000 1.165
+++ src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 17 Aug 2007 17:03:32 -0000
@@ -3717,7 +3717,13 @@
* as they also test camel case in indexes...
*/
public void testCamelCaseTypePattern01() throws CoreException {
- search("RE", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH, getJavaSearchScope());
+ search("RE", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ ""+ getExternalJCLPathString() + " java.lang.RuntimeException"
+ );
+}
+public void testCamelCaseTypePattern01b() throws CoreException {
+ search("RE", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
"src/a3/References.java a3.References [References]\n" +
""+ getExternalJCLPathString() + " java.lang.RuntimeException"
@@ -3725,28 +3731,28 @@
}
public void testCamelCaseTypePattern02() throws CoreException {
- search("RException", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH, getJavaSearchScope());
+ search("RException", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults(
""+ getExternalJCLPathString() + " java.lang.RuntimeException"
);
}
public void testCamelCaseTypePattern03() throws CoreException {
- search("RuntimeException", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH, getJavaSearchScope());
+ search("RuntimeException", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults(
""+ getExternalJCLPathString() + " java.lang.RuntimeException"
);
}
public void testCamelCaseTypePattern04() throws CoreException {
- search("RUNTIMEEXCEPTION", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH, getJavaSearchScope());
+ search("RUNTIMEEXCEPTION", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults(
""+ getExternalJCLPathString() + " java.lang.RuntimeException"
);
}
public void testCamelCaseTypePattern05() throws CoreException {
- search("R*E*", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH, getJavaSearchScope());
+ search("R*E*", TYPE, DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults(
"src/a3/References.java a3.References [References]\n" +
""+ getExternalJCLPathString() + " java.lang.RuntimeException"
@@ -3838,6 +3844,48 @@
"q1.AA",
requestor);
}
+public void testCamelCaseTypePattern10() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearch/src/Test.java",
+ "class NullPointerException {}\n" +
+ "class NULLPointerException {}\n" +
+ "class NULLPOINTERException {}\n" +
+ "class NULLPOINTEREXCEPTION {}\n"
+ );
+ search("Null", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java NullPointerException [NullPointerException]"
+ );
+}
+public void testCamelCaseTypePattern11() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearch/src/Test.java",
+ "class NullPointerException {}\n" +
+ "class NULLPointerException {}\n" +
+ "class NULLPOINTERException {}\n" +
+ "class NULLPOINTEREXCEPTION {}\n"
+ );
+ search("Null", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE);
+ assertSearchResults(
+ "src/Test.java NullPointerException [NullPointerException]"
+ );
+}
+public void testCamelCaseTypePattern12() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearch/src/Test.java",
+ "class NullPointerException {}\n" +
+ "class NULLPointerException {}\n" +
+ "class NULLPOINTERException {}\n" +
+ "class NULLPOINTEREXCEPTION {}\n"
+ );
+ search("Null", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_PREFIX_MATCH);
+ assertSearchResults(
+ "src/Test.java NullPointerException [NullPointerException]\n" +
+ "src/Test.java NULLPointerException [NULLPointerException]\n" +
+ "src/Test.java NULLPOINTERException [NULLPOINTERException]\n" +
+ "src/Test.java NULLPOINTEREXCEPTION [NULLPOINTEREXCEPTION]"
+ );
+}
/**
* @bug 160323: [search] TypeNameMatch: support hashCode/equals
Index: src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java,v
retrieving revision 1.118
diff -u -r1.118 JavaSearchBugsTests.java
--- src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 17 Aug 2007 06:14:44 -0000 1.118
+++ src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 17 Aug 2007 17:03:31 -0000
@@ -103,18 +103,6 @@
}
return getWorkingCopy(path, source, this.wcOwner);
}
-protected void search(IJavaElement element, int limitTo) throws CoreException {
- search(element, limitTo, EXACT_RULE, getJavaSearchScope(), resultCollector);
-}
-protected void search(IJavaElement element, int limitTo, int matchRule) throws CoreException {
- search(element, limitTo, matchRule, getJavaSearchScope(), resultCollector);
-}
-protected void search(String patternString, int searchFor, int limitTo) throws CoreException {
- search(patternString, searchFor, limitTo, EXACT_RULE, getJavaSearchScope(), resultCollector);
-}
-protected void search(String patternString, int searchFor, int limitTo, int matchRule) throws CoreException {
- search(patternString, searchFor, limitTo, matchRule, getJavaSearchScope(), resultCollector);
-}
/* (non-Javadoc)
* @see org.eclipse.jdt.core.tests.model.SuiteOfTestCases#setUpSuite()
*/
@@ -4927,7 +4915,6 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern02() throws CoreException {
setUpBug110060_TypePattern();
search("AA", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -4942,7 +4929,6 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern03() throws CoreException {
setUpBug110060_TypePattern();
search("AAx", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -4951,7 +4937,6 @@
"src/b110060/Test.java b110060.Test.aaxx [AAxx] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern04() throws CoreException {
setUpBug110060_TypePattern();
search("Axx", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -4960,7 +4945,6 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern05() throws CoreException {
setUpBug110060_TypePattern();
search("Ax", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -4971,7 +4955,6 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern06() throws CoreException {
setUpBug110060_TypePattern();
search("A*A*", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -4987,13 +4970,11 @@
""+ getExternalJCLPathString("1.5") + " java.lang.annotation.Annotation EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern07() throws CoreException {
setUpBug110060_TypePattern();
search("aa", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults("");
}
-
public void testBug110060_TypePattern08() throws CoreException {
setUpBug110060_TypePattern();
search("aa", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_PREFIX_MATCH);
@@ -5004,7 +4985,6 @@
"src/b110060/Test.java b110060.Test.aaxx [AAxx] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern09() throws CoreException {
setUpBug110060_TypePattern();
search("AA", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_CASE_SENSITIVE);
@@ -5019,13 +4999,11 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern10() throws CoreException {
setUpBug110060_TypePattern();
search("AxAx", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
assertSearchResults("");
}
-
public void testBug110060_TypePattern11() throws CoreException {
setUpBug110060_TypePattern();
search("AxxA", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
@@ -5034,10 +5012,14 @@
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
);
}
-
public void testBug110060_TypePattern12() throws CoreException {
setUpBug110060_TypePattern();
search("AxXA", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults("");
+}
+public void testBug110060_TypePattern12b() throws CoreException {
+ setUpBug110060_TypePattern();
+ search("AxXA", TYPE, ALL_OCCURRENCES, SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
"src/b110060/AxxAyy.java b110060.AxxAyy [AxxAyy] EXACT_MATCH\n" +
"src/b110060/Test.java b110060.Test.axxayy [AxxAyy] EXACT_MATCH"
@@ -6418,6 +6400,269 @@
}
/**
+ * @bug 124624: [search] Camel case matching routines should support end character
+ * @test Ensure that camel case pattern may use end character
+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624"
+ */
+public void testBug124624_HM34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HM33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+public void testBug124624_HaM34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HaM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HaM33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HaM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+public void testBug124624_HashM34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HashM33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
+ );
+}
+public void testBug124624_HMa34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults("");
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HMa33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+public void testBug124624_HaMa34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HaMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults("");
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HaMa33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
+ );
+}
+public void testBug124624_HashMa34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults("");
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HashMa33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
+ );
+}
+public void testBug124624_HMap34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HMap33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+public void testBug124624_HaMap34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HaMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HaMap33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HaMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" +
+ "src/Test.java HatMappage [HatMappage] EXACT_MATCH"
+ );
+}
+public void testBug124624_HashMap34() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH"
+ );
+}
+// Same search than previous test but without full match (should work as 3.3)
+public void testBug124624_HashMap33() throws CoreException {
+ workingCopies = new ICompilationUnit[1];
+ workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
+ "class HashMap {}\n" +
+ "class HtmlMapper {}\n" +
+ "class HashMapEntry {}\n" +
+ "class HatMappage {}\n"
+ );
+ search("HashMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
+ assertSearchResults(
+ "src/Test.java HashMap [HashMap] EXACT_MATCH\n" +
+ "src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
+ );
+}
+
+/**
* @test Bug 124645: [search] for implementors does not find subclasses of binary classes
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=124645"
*/
@@ -6672,7 +6917,7 @@
* To get these tests search matches in a workspace, do NOT forget to modify files
* to set them as working copies.
*
- * @test Bug 137087: Open Type - missing matches when using mixed case pattern
+ * @bug 137087: Open Type - missing matches when using mixed case pattern
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=137087"
*/
public void testBug137087() throws CoreException {
@@ -6681,16 +6926,15 @@
String pattern = "runtimeEx";
search(pattern, TYPE, DECLARATIONS, matchRule);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH"
+ "" // no match as SearchPattern.R_PREFIX_MATCH was not specified
);
// Search like UI does (ie. replace it with prefix if it's not a valid CamelCase)
int validatedRule = SearchPattern.validateMatchRule(pattern, matchRule);
if (validatedRule != matchRule) {
matchRule = SearchPattern.R_PREFIX_MATCH;
}
- search(pattern, TYPE, DECLARATIONS, matchRule);
+ search(pattern, TYPE, DECLARATIONS, matchRule | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH\n" +
""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH"
);
}
@@ -6700,16 +6944,15 @@
String pattern = "Runtimeex";
search(pattern, TYPE, DECLARATIONS, matchRule);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH"
+ "" // no match as SearchPattern.R_PREFIX_MATCH was not specified
);
// Search like UI does (ie. replace it with prefix if it's not a valid CamelCase)
int validatedRule = SearchPattern.validateMatchRule(pattern, matchRule);
if (validatedRule != matchRule) {
matchRule = SearchPattern.R_PREFIX_MATCH;
}
- search(pattern, TYPE, DECLARATIONS, matchRule);
+ search(pattern, TYPE, DECLARATIONS, matchRule | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH\n" +
""+ getExternalJCLPathString("1.5") + " java.lang.RuntimeException EXACT_MATCH"
);
}
@@ -6829,16 +7072,15 @@
String pattern = "cloneNotsupportedEx";
search(pattern, TYPE, DECLARATIONS, matchRule);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
+ "" // no match as SearchPattern.R_PREFIX_MATCH was not specified
);
// Search like UI does (ie. replace it with prefix if it's not a valid CamelCase)
int validatedRule = SearchPattern.validateMatchRule(pattern, matchRule);
if (validatedRule != matchRule) {
matchRule = SearchPattern.R_PREFIX_MATCH;
}
- search(pattern, TYPE, DECLARATIONS, matchRule);
+ search(pattern, TYPE, DECLARATIONS, matchRule | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH\n" +
""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
);
}
@@ -6848,16 +7090,15 @@
String pattern = "ClonenotSupportedexc";
search(pattern, TYPE, DECLARATIONS, matchRule);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
+ "" // no match as SearchPattern.R_PREFIX_MATCH was not specified
);
// Search like UI does (ie. replace it with prefix if it's not a valid CamelCase)
int validatedRule = SearchPattern.validateMatchRule(pattern, matchRule);
if (validatedRule != matchRule) {
matchRule = SearchPattern.R_PREFIX_MATCH;
}
- search(pattern, TYPE, DECLARATIONS, matchRule);
+ search(pattern, TYPE, DECLARATIONS, matchRule | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH\n" +
""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
);
}
@@ -6867,16 +7108,15 @@
String pattern = "cloneNotSupportedExcep";
search(pattern, TYPE, DECLARATIONS, matchRule);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
+ "" // no match as SearchPattern.R_PREFIX_MATCH was not specified
);
// Search like UI does (ie. replace it with prefix if it's not a valid CamelCase)
int validatedRule = SearchPattern.validateMatchRule(pattern, matchRule);
if (validatedRule != matchRule) {
matchRule = SearchPattern.R_PREFIX_MATCH;
}
- search(pattern, TYPE, DECLARATIONS, matchRule);
+ search(pattern, TYPE, DECLARATIONS, matchRule | SearchPattern.R_PREFIX_MATCH);
assertSearchResults(
- ""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH\n" +
""+ getExternalJCLPathString("1.5") + " java.lang.CloneNotSupportedException EXACT_MATCH"
);
}
Index: src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java,v
retrieving revision 1.26
diff -u -r1.26 AbstractJavaSearchTests.java
--- src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java 16 Aug 2007 13:13:21 -0000 1.26
+++ src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java 17 Aug 2007 17:03:30 -0000
@@ -632,6 +632,18 @@
requestor,
null);
}
+ protected void search(IJavaElement element, int limitTo) throws CoreException {
+ search(element, limitTo, EXACT_RULE, getJavaSearchScope(), resultCollector);
+ }
+ protected void search(IJavaElement element, int limitTo, int matchRule) throws CoreException {
+ search(element, limitTo, matchRule, getJavaSearchScope(), resultCollector);
+ }
+ protected void search(String patternString, int searchFor, int limitTo) throws CoreException {
+ search(patternString, searchFor, limitTo, EXACT_RULE, getJavaSearchScope(), resultCollector);
+ }
+ protected void search(String patternString, int searchFor, int limitTo, int matchRule) throws CoreException {
+ search(patternString, searchFor, limitTo, matchRule, getJavaSearchScope(), resultCollector);
+ }
protected void searchAllTypeNames(String pattern, int matchRule, TypeNameRequestor requestor) throws JavaModelException {
new SearchEngine(this.workingCopies).searchAllTypeNames(
null,