View | Details | Raw Unified | Return to bug 124624 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/UtilTest.java (-1 / +131 lines)
Lines 13-18 Link Here
13
import java.io.File;
13
import java.io.File;
14
14
15
//import org.apache.tools.ant.types.selectors.SelectorUtils;
15
//import org.apache.tools.ant.types.selectors.SelectorUtils;
16
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.jdt.core.compiler.CharOperation;
17
import org.eclipse.jdt.core.compiler.CharOperation;
17
18
18
//import junit.framework.AssertionFailedError;
19
//import junit.framework.AssertionFailedError;
Lines 36-42 Link Here
36
 * If result is invalid then store warning in buffer and display it.
37
 * If result is invalid then store warning in buffer and display it.
37
 */
38
 */
38
void assertCamelCase(String pattern, String name, boolean match) {
39
void assertCamelCase(String pattern, String name, boolean match) {
39
	boolean camelCase = CharOperation.camelCaseMatch(pattern==null?null:pattern.toCharArray(), name==null?null:name.toCharArray());
40
	
41
}
42
/**
43
 * Assert that a pattern and a name matches or not.
44
 * If result is invalid then store warning in buffer and display it.
45
 */
46
void assertCamelCase(String pattern, String name, boolean exactEnd, boolean match) {
47
	boolean camelCase = CharOperation.camelCaseMatch(pattern==null?null:pattern.toCharArray(), name==null?null:name.toCharArray(), exactEnd);
40
	if (match != camelCase) {
48
	if (match != camelCase) {
41
		StringBuffer line = new StringBuffer("'");
49
		StringBuffer line = new StringBuffer("'");
42
		line.append(name);
50
		line.append(name);
Lines 608-613 Link Here
608
	// Verify that there were no unexpected results
616
	// Verify that there were no unexpected results
609
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
617
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
610
}
618
}
619
620
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=109695
621
public void test70() throws CoreException {
622
	assertCamelCase("IDE3", "IDocumentExtension", true /*exact end match*/, false /* should not match */);
623
	assertCamelCase("IDE3", "IDocumentExtension2", true /*exact end match*/, false /* should not match */);
624
	assertCamelCase("IDE3", "IDocumentExtension3", true /*exact end match*/, true /* should match */);
625
	assertCamelCase("IDE3", "IDocumentExtension135", true /*exact end match*/, true /* should match */);
626
	assertCamelCase("IDE3", "IDocumentExtension315", true /*exact end match*/, true /* should match */);
627
	assertCamelCase("IDPE3", "IDocumentProviderExtension", true /*exact end match*/, false /* should not match */);
628
	assertCamelCase("IDPE3", "IDocumentProviderExtension2", true /*exact end match*/, false /* should not match */);
629
	assertCamelCase("IDPE3", "IDocumentProviderExtension4", true /*exact end match*/, false /* should not match */);
630
	assertCamelCase("IDPE3", "IDocumentProviderExtension3", true /*exact end match*/, true /* should match */);
631
	assertCamelCase("IDPE3", "IDocumentProviderExtension5", true /*exact end match*/, false /* should not match */);
632
	assertCamelCase("IDPE3", "IDocumentProviderExtension54321", true /*exact end match*/, true /* should match */);
633
	assertCamelCase("IDPE3", "IDocumentProviderExtension12345", true /*exact end match*/, true /* should match */);
634
	assertCamelCase("IPL3", "IPerspectiveListener", true /*exact end match*/, false /* should not match */);
635
	assertCamelCase("IPL3", "IPerspectiveListener2", true /*exact end match*/, false /* should not match */);
636
	assertCamelCase("IPL3", "IPerspectiveListener3", true /*exact end match*/, true /* should match */);
637
	assertCamelCase("IPS2", "IPropertySource", true /*exact end match*/, false /* should not match */);
638
	assertCamelCase("IPS2", "IPropertySource2", true /*exact end match*/, true /* should match */);
639
	assertCamelCase("IWWPD2", "IWorkbenchWindowPulldownDelegate", true /*exact end match*/, false /* should not match */);
640
	assertCamelCase("IWWPD2", "IWorkbenchWindowPulldownDelegate2", true /*exact end match*/, true /* should match */);
641
	assertCamelCase("UTF16DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
642
	assertCamelCase("UTF16DSS", "UTF1DocScannerSupport", true /*exact end match*/, false /* should not match */);
643
	assertCamelCase("UTF16DSS", "UTF6DocScannerSupport", true /*exact end match*/, false /* should not match */);
644
	assertCamelCase("UTF16DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
645
	assertCamelCase("UTF1DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
646
	assertCamelCase("UTF1DSS", "UTF1DocScannerSupport", true /*exact end match*/, true /* should match */);
647
	assertCamelCase("UTF1DSS", "UTF6DocScannerSupport", true /*exact end match*/, false /* should not match */);
648
	assertCamelCase("UTF1DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
649
	assertCamelCase("UTF6DSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
650
	assertCamelCase("UTF6DSS", "UTF1DocScannerSupport", true /*exact end match*/, false /* should not match */);
651
	assertCamelCase("UTF6DSS", "UTF6DocScannerSupport", true /*exact end match*/, true /* should match */);
652
	assertCamelCase("UTF6DSS", "UTFDocScannerSupport", true /*exact end match*/, false /* should not match */);
653
	assertCamelCase("UTFDSS", "UTF16DocumentScannerSupport", true /*exact end match*/, true /* should match */);
654
	assertCamelCase("UTFDSS", "UTF1DocScannerSupport", true /*exact end match*/, true /* should match */);
655
	assertCamelCase("UTFDSS", "UTF6DocScannerSupport", true /*exact end match*/, true /* should match */);
656
	assertCamelCase("UTFDSS", "UTFDocScannerSupport", true /*exact end match*/, true /* should match */);
657
	// Verify that there were no unexpected results
658
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
659
}
660
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
661
public void test71() {
662
	assertCamelCase("HM", "HashMap", true /*exact end match*/, true /*should match*/);
663
	assertCamelCase("HM", "HtmlMapper", true /*exact end match*/, true /*should match*/);
664
	assertCamelCase("HM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
665
	assertCamelCase("HaM", "HashMap", true /*exact end match*/, true /* should match */);
666
	assertCamelCase("HaM", "HtmlMapper", true /*exact end match*/, false /* should not match */);
667
	assertCamelCase("HaM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
668
	assertCamelCase("HashM", "HashMap", true /*exact end match*/, true /* should match */);
669
	assertCamelCase("HashM", "HtmlMapper", true /*exact end match*/, false /* should not match */);
670
	assertCamelCase("HashM", "HashMapEntry", true /*exact end match*/, false /* should not match */);
671
	// Verify that there were no unexpected results
672
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
673
}
674
public void test71b() { // previous test cases but with 3.3 behavior
675
	assertCamelCase("HM", "HashMap", true /*should match*/);
676
	assertCamelCase("HM", "HtmlMapper", true /*should match*/);
677
	assertCamelCase("HM", "HashMapEntry", true /*should match*/);
678
	assertCamelCase("HaM", "HashMap", true /* should match */);
679
	assertCamelCase("HaM", "HtmlMapper", true /*should match*/);
680
	assertCamelCase("HaM", "HashMapEntry", true /*should match*/);
681
	assertCamelCase("HashM", "HashMap", true /* should match */);
682
	assertCamelCase("HashM", "HtmlMapper", true /*should match*/);
683
	assertCamelCase("HashM", "HashMapEntry", true /*should match*/);
684
	// Verify that there were no unexpected results
685
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
686
}
687
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
688
public void test72() {
689
	assertCamelCase("HMa", "HashMap", true /*exact end match*/, false /* should not match */);
690
	assertCamelCase("HMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
691
	assertCamelCase("HMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
692
	assertCamelCase("HaMa", "HashMap", true /*exact end match*/, false /* should not match */);
693
	assertCamelCase("HaMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
694
	assertCamelCase("HaMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
695
	assertCamelCase("HashMa", "HashMap", true /*exact end match*/, false /* should not match */);
696
	assertCamelCase("HashMa", "HtmlMapper", true /*exact end match*/, false /* should not match */);
697
	assertCamelCase("HashMa", "HashMapEntry", true /*exact end match*/, false /* should not match */);
698
	// Verify that there were no unexpected results
699
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
700
}
701
public void test72b() { // previous test cases but with 3.3 behavior
702
	assertCamelCase("HMa", "HashMap", true /*should match*/);
703
	assertCamelCase("HMa", "HtmlMapper", true /*should match*/);
704
	assertCamelCase("HMa", "HashMapEntry", true /*should match*/);
705
	assertCamelCase("HaMa", "HashMap", true /* should match */);
706
	assertCamelCase("HaMa", "HtmlMapper", true /*should match*/);
707
	assertCamelCase("HaMa", "HashMapEntry", true /*should match*/);
708
	assertCamelCase("HashMa", "HashMap", true /* should match */);
709
	assertCamelCase("HashMa", "HtmlMapper", true /*should match*/);
710
	assertCamelCase("HashMa", "HashMapEntry", true /*should match*/);
711
	// Verify that there were no unexpected results
712
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
713
}
714
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624
715
public void test73() {
716
	assertCamelCase("HMap", "HashMap", true /*exact end match*/, true /*should match*/);
717
	assertCamelCase("HMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
718
	assertCamelCase("HMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
719
	assertCamelCase("HaMap", "HashMap", true /*exact end match*/, true /* should match */);
720
	assertCamelCase("HaMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
721
	assertCamelCase("HaMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
722
	assertCamelCase("HashMap", "HashMap", true /*exact end match*/, true /* should match */);
723
	assertCamelCase("HashMap", "HtmlMapper", true /*exact end match*/, false /* should not match */);
724
	assertCamelCase("HashMap", "HashMapEntry", true /*exact end match*/, false /* should not match */);
725
	// Verify that there were no unexpected results
726
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
727
}
728
public void test73b() { // previous test cases but with 3.3 behavior
729
	assertCamelCase("HMap", "HashMap", true /*should match*/);
730
	assertCamelCase("HMap", "HtmlMapper", true /*should match*/);
731
	assertCamelCase("HMap", "HashMapEntry", true /*should match*/);
732
	assertCamelCase("HaMap", "HashMap", true /* should match */);
733
	assertCamelCase("HaMap", "HtmlMapper", true /*should match*/);
734
	assertCamelCase("HaMap", "HashMapEntry", true /*should match*/);
735
	assertCamelCase("HashMap", "HashMap", true /* should match */);
736
	assertCamelCase("HashMap", "HtmlMapper", true /*should match*/);
737
	assertCamelCase("HashMap", "HashMapEntry", true /*should match*/);
738
	// Verify that there were no unexpected results
739
    assertTrue(this.camelCaseErrors.toString(), this.camelCaseErrors.length()==0);
740
}
611
public static Class testClass() {
741
public static Class testClass() {
612
	return UtilTest.class;
742
	return UtilTest.class;
613
}
743
}
(-)search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java (-1 / +1 lines)
Lines 75-81 Link Here
75
		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=81377
75
		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=81377
76
		int rule = getMatchRule();
76
		int rule = getMatchRule();
77
		this.isCaseSensitive = (rule & R_CASE_SENSITIVE) != 0;
77
		this.isCaseSensitive = (rule & R_CASE_SENSITIVE) != 0;
78
		this.isCamelCase = (rule & R_CAMELCASE_MATCH) != 0;
78
		this.isCamelCase = (rule & (R_CAMELCASE_MATCH | R_CAMELCASE_STRICT_MATCH)) != 0;
79
		this.matchCompatibility = rule & MATCH_COMPATIBILITY_MASK;
79
		this.matchCompatibility = rule & MATCH_COMPATIBILITY_MASK;
80
		this.matchMode = rule & MATCH_MODE_MASK;
80
		this.matchMode = rule & MATCH_MODE_MASK;
81
	}
81
	}
(-)search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java (-1 / +1 lines)
Lines 98-104 Link Here
98
	char[] packageName = null;
98
	char[] packageName = null;
99
	if (this.isCamelCase) {
99
	if (this.isCamelCase) {
100
		packageName = CharOperation.concatWith(tokens, '.');
100
		packageName = CharOperation.concatWith(tokens, '.');
101
		if (CharOperation.camelCaseMatch(this.pattern.pkgName, packageName)) {
101
		if (CharOperation.camelCaseMatch(this.pattern.pkgName, packageName, this.isStrictCamelCase)) {
102
			return POSSIBLE_MATCH;
102
			return POSSIBLE_MATCH;
103
		}
103
		}
104
	}
104
	}
(-)search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java (-3 / +5 lines)
Lines 24-29 Link Here
24
protected int matchMode;
24
protected int matchMode;
25
protected boolean isCaseSensitive;
25
protected boolean isCaseSensitive;
26
protected boolean isCamelCase;
26
protected boolean isCamelCase;
27
protected boolean isStrictCamelCase;
27
protected boolean isEquivalentMatch;
28
protected boolean isEquivalentMatch;
28
protected boolean isErasureMatch;
29
protected boolean isErasureMatch;
29
protected boolean mustResolve;
30
protected boolean mustResolve;
Lines 118-124 Link Here
118
public PatternLocator(SearchPattern pattern) {
119
public PatternLocator(SearchPattern pattern) {
119
	int matchRule = pattern.getMatchRule();
120
	int matchRule = pattern.getMatchRule();
120
	this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
121
	this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
121
	this.isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
122
	this.isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
123
	this.isCamelCase = this.isStrictCamelCase || (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
122
	this.isErasureMatch = (matchRule & SearchPattern.R_ERASURE_MATCH) != 0;
124
	this.isErasureMatch = (matchRule & SearchPattern.R_ERASURE_MATCH) != 0;
123
	this.isEquivalentMatch = (matchRule & SearchPattern.R_EQUIVALENT_MATCH) != 0;
125
	this.isEquivalentMatch = (matchRule & SearchPattern.R_EQUIVALENT_MATCH) != 0;
124
	this.matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
126
	this.matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
Lines 282-288 Link Here
282
	boolean matchFirstChar = !this.isCaseSensitive || pattern[0] == name[0];
284
	boolean matchFirstChar = !this.isCaseSensitive || pattern[0] == name[0];
283
	boolean sameLength = pattern.length == name.length;
285
	boolean sameLength = pattern.length == name.length;
284
	boolean canBePrefix = name.length >= pattern.length;
286
	boolean canBePrefix = name.length >= pattern.length;
285
	if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name)) {
287
	if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name, this.isStrictCamelCase)) {
286
		return POSSIBLE_MATCH;
288
		return POSSIBLE_MATCH;
287
	}
289
	}
288
	switch (this.matchMode) {
290
	switch (this.matchMode) {
Lines 718-724 Link Here
718
	}
720
	}
719
	if (this.isCamelCase) {
721
	if (this.isCamelCase) {
720
		if (!this.isCaseSensitive || (qualifiedPattern.length>0 && sourceName.length>0 && qualifiedPattern[0] == sourceName[0])) {
722
		if (!this.isCaseSensitive || (qualifiedPattern.length>0 && sourceName.length>0 && qualifiedPattern[0] == sourceName[0])) {
721
			if (CharOperation.camelCaseMatch(qualifiedPattern, sourceName)) {
723
			if (CharOperation.camelCaseMatch(qualifiedPattern, sourceName, this.isStrictCamelCase)) {
722
				return ACCURATE_MATCH;
724
				return ACCURATE_MATCH;
723
			}
725
			}
724
		}
726
		}
(-)search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java (-1 / +1 lines)
Lines 112-118 Link Here
112
			return IMPOSSIBLE_MATCH;
112
			return IMPOSSIBLE_MATCH;
113
		}
113
		}
114
		boolean matchFirstChar = !this.isCaseSensitive || (qualifiedPattern[0] == qualifiedTypeName[0]);
114
		boolean matchFirstChar = !this.isCaseSensitive || (qualifiedPattern[0] == qualifiedTypeName[0]);
115
		if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName)) {
115
		if (this.isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName, this.isStrictCamelCase)) {
116
			return POSSIBLE_MATCH;
116
			return POSSIBLE_MATCH;
117
		}
117
		}
118
		switch (this.matchMode) {
118
		switch (this.matchMode) {
(-)buildnotes_jdt-core.html (-1 / +202 lines)
Lines 50-59 Link Here
50
<li>New fix for <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=186781">bug 186781</a> required the index version to be incremented.
50
<li>New fix for <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=186781">bug 186781</a> required the index version to be incremented.
51
     Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).
51
     Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).
52
</li>
52
</li>
53
<li>Add strict mode for Camel Case matching (see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=124624">bug 124624</a>).<br>
54
Currently Camel Case rules are permissive as it accept prefix match for the last part.
55
For instance, <code>'HM'</code> pattern will match <code>'HashMap'</code> but also <code>'HashMapEntry'</code>.
56
Or <code>'HaMap'</code> pattern will match <code>'HashMap'</code> but also <code>'HatMapper'</code>.<br>
57
Some users now needs a more strict mode for Camel Case rule which forces a exact match for the last part of the pattern.<br><br>
58
To implement this functionality, following API methods/constants have been added in JDT/Core:
59
<pre><ul><li>On org.eclipse.jdt.core.search.SearchPattern
60
	/**
61
	 * Match rule: The search pattern contains a Camel Case expression with
62
	 * a strict number of parts and preventing automatic prefix matching for the last part
63
	 * (if it consists of multiple letters).
64
	 *
65
	 * Examples:
66
	 * 	. <code>'HM'</code> type string pattern will match
67
	 * 	  <code>'HashMap'</code> and <code>'HtmlMapper'</code> types,
68
	 * 	  but not <code>'HashMapEntry'</code>
69
	 * 	. <code>'HMap'</code> type string pattern will match
70
	 * 	  <code>'HashMap'</code> type but not <code>'HtmlMapper'</code>.
71
	 *
72
	 * @see CharOperation#camelCaseMatch(char[], char[], boolean) for a detailed explanation
73
	 * of Camel Case matching.
74
	 *
75
	 * Can be combined to {@link #R_PREFIX_MATCH} match rule. For example,
76
	 * when prefix match rule is combined with Camel Case match rule,
77
	 * <code>"nPE"</code> pattern will match <code>nPException</code>.
78
	 *
79
	 * Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
80
	 * will not be used simultaneously as they are mutually exclusive.
81
	 * Used match rule depends on whether string pattern contains specific pattern 
82
	 * characters (e.g. '*' or '?') or not. If it does, then only Pattern match rule
83
	 * will be used, otherwise only Camel Case match will be used.
84
	 * For example, with <code>"NPE"</code> string pattern, search will only use
85
	 * Camel Case match rule, but with <code>N*P*E*</code> string pattern, it will 
86
	 * use only Pattern match rule.
87
	 * 
88
	 * @since 3.4
89
	 */
90
	public static final int R_CAMELCASE_STRICT_MATCH = 0x0100;
91
</li>
92
<li>On org.eclipse.jdt.core.compiler.CharOperation:
93
94
/**
95
 * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. 
96
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
97
 *
98
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
99
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
100
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
101
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
102
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
103
 * names follow the lower CamelCase convention.
104
 *
105
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
106
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
107
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
108
 *
109
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
110
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
111
 *
112
 * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
113
 * must have <b>exactly</b> the same number of parts and if last part must be identical if it contains lowercase characters.
114
 * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
115
 * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
116
 * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but still not 'HashMapEntry'.
117
 * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
118
 * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' <b>and</b>'HashMapEntry'.
119
 *
120
 * Examples:
121
 *
122
 * 1. pattern = { 'N', 'P', 'E' }
123
 *    name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
124
 *    result => true
125
 *...
126
 * 6. pattern = { 'I', 'P', 'L', '3' }
127
 *    name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
128
 *    result => true
129
 * 7. pattern = { 'H', M' }
130
 *    name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
131
 *    result => (exactMode == false)
132
 * 8. pattern = { 'H', M', 'a', 'p' }
133
 *    name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
134
 *    result => (exactMode == false)
135
 * 
136
 * @param pattern the given pattern
137
 * @param name the given name
138
 * @param exactMode flag telling whether the name must have same
139
 * 	number of parts and same last part (if it consists of multiple letters)
140
 * 	as the pattern or not.
141
 * 		. For example, when it's 'true':
142
 * 			- 'HM' type string pattern will match
143
 * 			  'HashMap' and 'HtmlMapper' types,
144
 * 			  but not 'HashMapEntry'
145
 * 			- 'HMap' type string pattern will match
146
 * 			  'HashMap' type but not 'HtmlMapper'.
147
 * 		. and, when it's 'false':
148
 * 			- 'HM' type string pattern will match both 
149
 * 			  'HashMap' and 'HtmlMapper'
150
 * 			  and 'HashMapEntry'
151
 * 			- 'HMap' type string pattern will match both
152
 * 			  'HashMap' and 'HtmlMapper' types.
153
 *
154
 * @return true if the pattern matches the given name, false otherwise
155
 * @since 3.4
156
 */
157
public static final boolean camelCaseMatch(char[] pattern, char[] name, boolean exactMode) {
158
...
159
}
160
161
/**
162
 * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.  
163
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
164
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
165
 * The sub-pattern is defined by the patternStart and patternEnd positions.
166
 *
167
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
168
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
169
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
170
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
171
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
172
 * names follow the lower CamelCase convention.
173
 *
174
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
175
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
176
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
177
 *
178
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
179
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
180
 *
181
 * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
182
 * must have <b>exactly</b> the same number of parts and if last part must be identical if it contains lowercase characters.
183
 * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
184
 * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
185
 * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but still not 'HashMapEntry'.
186
 * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
187
 * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' <b>and</b>'HashMapEntry'.
188
 *
189
 * Examples:
190
 *
191
 * 1. pattern = { 'N', 'P', 'E' }
192
 *    patternStart = 0
193
 *    patternEnd = 3
194
 *    name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
195
 *    nameStart = 0
196
 *    nameEnd = 20
197
 *    result => true
198
 *...
199
 * 6. pattern = { 'I', 'P', 'L', '3' }
200
 *    patternStart = 0
201
 *    patternEnd = 4
202
 *    name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
203
 *    nameStart = 0
204
 *    nameEnd = 21
205
 *    result => true
206
 * 7. pattern = { 'H', M' }
207
 *    patternStart = 0
208
 *    patternEnd = 2
209
 *    name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
210
 *    nameStart = 0
211
 *    nameEnd = 12
212
 *    result => (exactMode == false)
213
 * 8. pattern = { 'H', M', 'a', 'p' }
214
 *    patternStart = 0
215
 *    patternEnd = 4
216
 *    name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
217
 *    nameStart = 0
218
 *    nameEnd = 9
219
 *    result => (exactMode == false)
220
 * 
221
 * @param pattern the given pattern
222
 * @param patternStart the start index of the pattern, inclusive
223
 * @param patternEnd the end index of the pattern, exclusive
224
 * @param name the given name
225
 * @param nameStart the start index of the name, inclusive
226
 * @param nameEnd the end index of the name, exclusive
227
 * @param exactMode flag telling whether the name must have same
228
 * 	number of parts and same last part (if it consists of multiple letters)
229
 * 	as the pattern or not.
230
 * 		. For example, when it's 'true':
231
 * 			- 'HM' type string pattern will match
232
 * 			  'HashMap' and 'HtmlMapper' types,
233
 * 			  but not 'HashMapEntry'
234
 * 			- 'HMap' type string pattern will match
235
 * 			  'HashMap' type but not 'HtmlMapper'.
236
 * 		. and, when it's 'false':
237
 * 			- 'HM' type string pattern will match both 
238
 * 			  'HashMap' and 'HtmlMapper'
239
 * 			  and 'HashMapEntry'
240
 * 			- 'HMap' type string pattern will match both
241
 * 			  'HashMap' and 'HtmlMapper' types.
242
 *
243
 * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
244
 * @since 3.4
245
 */
246
public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd, boolean exactMode) {
247
...
248
}
249
</li>
250
</pre>
251
</li>
53
</ul>
252
</ul>
54
253
55
<h3>Problem Reports Fixed</h3>
254
<h3>Problem Reports Fixed</h3>
56
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=109695">109695</a>
255
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=124624">124624</a>
256
[search] Camelcase matching routines should support end character
257
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=109695">109695</a>
57
[search] Numbers should be treated as upper-case letters in CamelCase matching
258
[search] Numbers should be treated as upper-case letters in CamelCase matching
58
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=186781">186781</a>
259
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=186781">186781</a>
59
StackOverflowError while computing launch button tooltip
260
StackOverflowError while computing launch button tooltip
(-)compiler/org/eclipse/jdt/core/compiler/CharOperation.java (-14 / +289 lines)
Lines 58-64 Link Here
58
 * </pre></li>
58
 * </pre></li>
59
 * </ol>
59
 * </ol>
60
 * 
60
 * 
61
 * @param array the array that is concanated with the suffix character
61
 * @param array the array that is concatenated with the suffix character
62
 * @param suffix the suffix character
62
 * @param suffix the suffix character
63
 * @return the new array
63
 * @return the new array
64
 */
64
 */
Lines 72-79 Link Here
72
}
72
}
73
73
74
/**
74
/**
75
 * Append the given subarray to the target array starting at the given index in the target array.
75
 * Append the given sub-array to the target array starting at the given index in the target array.
76
 * The start of the subarray is inclusive, the end is exclusive.
76
 * The start of the sub-array is inclusive, the end is exclusive.
77
 * Answers a new target array if it needs to grow, otherwise answers the same target array.
77
 * Answers a new target array if it needs to grow, otherwise answers the same target array.
78
 * <br>
78
 * <br>
79
 * For example:<br>
79
 * For example:<br>
Lines 180-197 Link Here
180
/**
180
/**
181
 * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. 
181
 * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. 
182
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
182
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
183
 * <br>
183
 * <br><br>
184
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
184
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
185
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
185
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
186
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
186
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
187
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
187
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
188
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
188
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
189
 * names follow the lower CamelCase convention.
189
 * names follow the lower CamelCase convention.
190
 * <br>
190
 * <br><br>
191
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
191
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
192
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
192
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
193
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
193
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
194
 * <br><br>
194
 * <br><br>
195
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
196
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
197
 * <br><br>
198
 * Camel Case rules are applied permissively which means that name may have more parts than the pattern or its
199
 * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)}
200
 * for more explanation on Camel Case strict/permissive mode.
201
 * <br><br>
195
 * Examples:
202
 * Examples:
196
 * <ol>
203
 * <ol>
197
 * <li><pre>
204
 * <li><pre>
Lines 224-229 Link Here
224
 *    result => false
231
 *    result => false
225
 * </pre>
232
 * </pre>
226
 * </li>
233
 * </li>
234
 * <li><pre>
235
 *    pattern = { 'I', 'P', 'L', '3' }
236
 *    patternStart = 0
237
 *    patternEnd = 4
238
 *    name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
239
 *    nameStart = 0
240
 *    nameEnd = 21
241
 *    result => true
242
 * </pre>
243
 * </li>
227
 * </ol>
244
 * </ol>
228
 * 
245
 * 
229
 * @param pattern the given pattern
246
 * @param pattern the given pattern
Lines 237-262 Link Here
237
	if (name == null)
254
	if (name == null)
238
		return false; // null name cannot match
255
		return false; // null name cannot match
239
256
240
	return camelCaseMatch(pattern, 0, pattern.length, name, 0, name.length);
257
	return camelCaseMatch(pattern, name, false/*prefix match for last hunk*/);
258
}
259
260
/**
261
 * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. 
262
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
263
 * <br><br>
264
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
265
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
266
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
267
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
268
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
269
 * names follow the lower CamelCase convention.
270
 * <br><br>
271
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
272
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
273
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
274
 * <br><br>
275
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
276
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
277
 * <br><br>
278
 * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
279
 * must have <b>exactly</b> the same number of parts and if last part must be identical if it contains lowercase characters.
280
 * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
281
 * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
282
 * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but still not 'HashMapEntry'.
283
 * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
284
 * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' <b>and</b>'HashMapEntry'.
285
 * <br><br>
286
 * <pre>
287
 * Examples:
288
 * <ol>
289
 * <li> pattern = { 'N', 'P', 'E' }
290
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
291
 * result => true</li>
292
 * <li> pattern = { 'N', 'P', 'E' }
293
 * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
294
 * result => true</li>
295
 * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
296
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
297
 * result => true</li>
298
 * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
299
 * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
300
 * result => false</li>
301
 * <li> pattern = { 'n', p', 'e' }
302
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
303
 * result => false</li>
304
 * <li> pattern = { 'I', 'P', 'L', '3' }
305
 * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
306
 * result => true</li>
307
 * <li> pattern = { 'H', M' }
308
 * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
309
 * result => (exactMode == false)</li>
310
 * <li>pattern = { 'H', M', 'a', 'p' }
311
 * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
312
 * result => (exactMode == false)</li>
313
 * </ol>
314
 * </pre>
315
 * 
316
 * @param pattern the given pattern
317
 * @param name the given name
318
 * @param exactMode flag telling whether the name must have same
319
 * 	number of parts and same last part (if it consists of multiple letters)
320
 * 	as the pattern or not.
321
 * 	<ul>
322
 * 		<li>For example, when it's <code>true</code>:<br>
323
 * 			- <code>HM</code> type string pattern will match
324
 * 			  <code>HashMap</code> and <code>HtmlMapper</code> types,
325
 * 			  but not <code>HashMapEntry</code><br>
326
 * 			- <code>HMap</code> type string pattern will match
327
 * 			  <code>HashMap</code> type but not <code>HtmlMapper</code>.
328
 * 		</li>
329
 * 		<li>and, when it's <code>false</code>:<br>
330
 * 			- <code>HM</code> type string pattern will match both 
331
 * 			  <code>HashMap</code> and <code>HtmlMapper</code>
332
 * 			  and <code>HashMapEntry</code><br>
333
 * 			- <code>HMap</code> type string pattern will match both
334
 * 			  <code>HashMap</code> and <code>HtmlMapper</code> types.
335
 * 		</li>
336
 * 	</ul>
337
 * @return true if the pattern matches the given name, false otherwise
338
 * @since 3.4
339
 */
340
public static final boolean camelCaseMatch(char[] pattern, char[] name, boolean exactMode) {
341
	if (pattern == null)
342
		return true; // null pattern is equivalent to '*'
343
	if (name == null)
344
		return false; // null name cannot match
345
346
	return camelCaseMatch(pattern, 0, pattern.length, name, 0, name.length, exactMode);
241
}
347
}
242
348
243
/**
349
/**
244
 * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.  
350
 * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.  
245
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
351
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
246
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
352
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
247
 * The subpattern is defined by the patternStart and patternEnd positions.
353
 * The sub-pattern is defined by the patternStart and patternEnd positions.
248
 * <br>
354
 * <br><br>
249
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
355
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
250
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
356
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
251
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
357
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
252
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
358
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
253
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
359
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
254
 * names follow the lower CamelCase convention.
360
 * names follow the lower CamelCase convention.
255
 * <br>
361
 * <br><br>
256
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
362
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
257
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
363
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
258
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
364
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
259
 * <br><br>
365
 * <br><br>
366
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
367
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
368
 * <br><br>
369
 * Camel Case rules are applied permissively which means that name may have more parts than the pattern and its
370
 * last part may be a prefix of the pattern's last part (see {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)}
371
 * for more explanation on Camel Case strict/permissive mode.
372
 * <br><br>
260
 * Examples:
373
 * Examples:
261
 * <ol>
374
 * <ol>
262
 * <li><pre>
375
 * <li><pre>
Lines 309-314 Link Here
309
 *    result => false
422
 *    result => false
310
 * </pre>
423
 * </pre>
311
 * </li>
424
 * </li>
425
 * <li><pre>
426
 *    pattern = { 'I', 'P', 'L', '3' }
427
 *    patternStart = 0
428
 *    patternEnd = 4
429
 *    name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
430
 *    nameStart = 0
431
 *    nameEnd = 21
432
 *    result => true
433
 * </pre>
434
 * </li>
312
 * </ol>
435
 * </ol>
313
 * 
436
 * 
314
 * @param pattern the given pattern
437
 * @param pattern the given pattern
Lines 317-326 Link Here
317
 * @param name the given name
440
 * @param name the given name
318
 * @param nameStart the start index of the name, inclusive
441
 * @param nameStart the start index of the name, inclusive
319
 * @param nameEnd the end index of the name, exclusive
442
 * @param nameEnd the end index of the name, exclusive
320
 * @return true if a sub-pattern matches the subpart of the given name, false otherwise
443
 * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
321
 * @since 3.2
444
 * @since 3.2
445
 * @deprecated Use {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)} instead
322
 */
446
 */
323
public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd) {
447
public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd) {
448
	return camelCaseMatch(pattern, patternStart, patternEnd, name, nameStart, nameEnd, false/*prefix match for last hunk*/);
449
}
450
451
/**
452
 * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.  
453
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
454
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
455
 * The sub-pattern is defined by the patternStart and patternEnd positions.
456
 * <br><br>
457
 * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
458
 * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
459
 * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
460
 * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
461
 * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
462
 * names follow the lower CamelCase convention.
463
 * <br><br>
464
 * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
465
 * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
466
 * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
467
 * <br><br>
468
 * Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading
469
 * character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
470
 * <br><br>
471
 * CamelCase rules can be applied strictly or permissively. When strict mode is specified, pattern and name
472
 * must have <b>exactly</b> the same number of parts and if last part must be identical if it contains lowercase characters.
473
 * For instance, 'HMap<' and 'HaMap' patterns will match 'HashMap' but neither 'HashMapEntry' nor 'HatMapper'.
474
 * Note that when last part does not contain lowercase characters, then name may end with lowercase characters.
475
 * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but still not 'HashMapEntry'.
476
 * Reversely, if permissive mode is specified, names do not need to have same number of parts and same last part.
477
 * Then, both 'HM' and 'HMap' will match 'HashMap', 'HatMapper' <b>and</b>'HashMapEntry'.
478
 * <br><br>
479
 * <pre>
480
 * Examples:
481
 * <ol>
482
 * <li> pattern = { 'N', 'P', 'E' }
483
 * patternStart = 0
484
 * patternEnd = 3
485
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
486
 * nameStart = 0
487
 * nameEnd = 20
488
 * result => true</li>
489
 * <li> pattern = { 'N', 'P', 'E' }
490
 * patternStart = 0
491
 * patternEnd = 3
492
 * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
493
 * nameStart = 0
494
 * nameEnd = 21
495
 * result => true</li>
496
 * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
497
 * patternStart = 0
498
 * patternEnd = 6
499
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
500
 * nameStart = 0
501
 * nameEnd = 20
502
 * result => true</li>
503
 * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
504
 * patternStart = 0
505
 * patternEnd = 6
506
 * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
507
 * nameStart = 0
508
 * nameEnd = 21
509
 * result => false</li>
510
 * <li> pattern = { 'n', p', 'e' }
511
 * patternStart = 0
512
 * patternEnd = 3
513
 * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
514
 * nameStart = 0
515
 * nameEnd = 20
516
 * result => false</li>
517
 * <li> pattern = { 'I', 'P', 'L', '3' }
518
 * patternStart = 0
519
 * patternEnd = 4
520
 * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
521
 * nameStart = 0
522
 * nameEnd = 21
523
 * result => true</li>
524
 * <li> pattern = { 'H', M' }
525
 * patternStart = 0
526
 * patternEnd = 2
527
 * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
528
 * nameStart = 0
529
 * nameEnd = 12
530
 * result => (exactMode == false)</li>
531
 * <li> pattern = { 'H', M', 'a', 'p' }
532
 * patternStart = 0
533
 * patternEnd = 4
534
 * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
535
 * nameStart = 0
536
 * nameEnd = 9
537
 * result => (exactMode == false)</li>
538
 * </ol>
539
 * </pre>
540
 * 
541
 * @param pattern the given pattern
542
 * @param patternStart the start index of the pattern, inclusive
543
 * @param patternEnd the end index of the pattern, exclusive
544
 * @param name the given name
545
 * @param nameStart the start index of the name, inclusive
546
 * @param nameEnd the end index of the name, exclusive
547
 * @param exactMode flag telling whether the name must have same
548
 * 	number of parts and same last part (if it consists of multiple letters)
549
 * 	as the pattern or not.
550
 * 	<ul>
551
 * 		<li>For example, when it's <code>true</code>:<br>
552
 * 			- <code>HM</code> type string pattern will match
553
 * 			  <code>HashMap</code> and <code>HtmlMapper</code> types,
554
 * 			  but not <code>HashMapEntry</code><br>
555
 * 			- <code>HMap</code> type string pattern will match
556
 * 			  <code>HashMap</code> type but not <code>HtmlMapper</code>.
557
 * 		</li>
558
 * 		<li>and, when it's <code>false</code>:<br>
559
 * 			- <code>HM</code> type string pattern will match both 
560
 * 			  <code>HashMap</code> and <code>HtmlMapper</code>
561
 * 			  and <code>HashMapEntry</code><br>
562
 * 			- <code>HMap</code> type string pattern will match both
563
 * 			  <code>HashMap</code> and <code>HtmlMapper</code> types.
564
 * 		</li>
565
 * 	</ul>
566
 * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
567
 * @since 3.4
568
 */
569
public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd, boolean exactMode) {
324
	if (name == null)
570
	if (name == null)
325
		return false; // null name cannot match
571
		return false; // null name cannot match
326
	if (pattern == null)
572
	if (pattern == null)
Lines 346-354 Link Here
346
		iPattern++;
592
		iPattern++;
347
		iName++;
593
		iName++;
348
594
349
		if (iPattern == patternEnd) {
595
		if (iPattern == patternEnd) { // we have exhausted pattern...
350
			// We have exhausted pattern, so it's a match
596
			// it's a match if not exact mode or name is also exhausted
351
			return true;
597
			if (!exactMode || iName == nameEnd) return true;
598
599
			// it's not a match if last pattern character is a lowercase
600
			if ((patternChar = pattern[iPattern-1]) < ScannerHelper.MAX_OBVIOUS) {
601
				if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
602
					return false;
603
				}
604
			}
605
			else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar) && !Character.isDigit(patternChar)) {
606
				return false;
607
			}
608
609
			// it's a match only if name has no more uppercase characters (exact mode)
610
			while (true) {
611
				if (iName == nameEnd) {
612
					// we have exhausted name, so it's a match
613
					return true;
614
				}
615
				nameChar = name[iName];
616
				if (nameChar < ScannerHelper.MAX_OBVIOUS) {
617
					if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & ScannerHelper.C_UPPER_LETTER) != 0) {
618
						// nameChar is uppercase, so it's not a match
619
						return false;
620
					}
621
				}
622
				else if (!Character.isJavaIdentifierPart(nameChar) || Character.isUpperCase(nameChar)) {
623
					return false;
624
				}
625
				iName++;
626
			}
352
		}
627
		}
353
628
354
		if (iName == nameEnd){
629
		if (iName == nameEnd){
(-)search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java (-2 / +3 lines)
Lines 454-466 Link Here
454
				return false;
454
				return false;
455
		
455
		
456
		if (patternTypeName != null) {
456
		if (patternTypeName != null) {
457
			boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
457
			boolean isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
458
			boolean isCamelCase = isStrictCamelCase || (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
458
			int matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
459
			int matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
459
			if (!isCaseSensitive && !isCamelCase) {
460
			if (!isCaseSensitive && !isCamelCase) {
460
				patternTypeName = CharOperation.toLowerCase(patternTypeName);
461
				patternTypeName = CharOperation.toLowerCase(patternTypeName);
461
			}
462
			}
462
			boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0];
463
			boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0];
463
			if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName)) {
464
			if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName, isStrictCamelCase)) {
464
				return true;
465
				return true;
465
			}
466
			}
466
			switch(matchMode) {
467
			switch(matchMode) {
(-)search/org/eclipse/jdt/core/search/SearchPattern.java (-9 / +93 lines)
Lines 169-174 Link Here
169
	 */
169
	 */
170
	public static final int R_CAMELCASE_MATCH = 0x0080;
170
	public static final int R_CAMELCASE_MATCH = 0x0080;
171
171
172
	/**
173
	 * Match rule: The search pattern contains a Camel Case expression with
174
	 * a strict number of parts and preventing automatic prefix matching for the last part
175
	 * (if it consists of multiple letters).
176
	 * <br>
177
	 * Examples:
178
	 * <ul>
179
	 * 	<li><code>HM</code> type string pattern will match
180
	 * 		<code>HashMap</code> and <code>HtmlMapper</code> types,
181
	 * 		but not <code>HashMapEntry</code>
182
	 * 	</li>
183
	 * 	<li><code>HMap</code> type string pattern will match
184
	 * 		<code>HashMap</code> type but not <code>HtmlMapper</code>.
185
	 * 	</li>
186
	 * </ul>
187
	 * @see CharOperation#camelCaseMatch(char[], char[], boolean) for a detailed explanation
188
	 * of Camel Case matching.
189
	 *<br>
190
	 * Can be combined to {@link #R_PREFIX_MATCH} match rule. For example,
191
	 * when prefix match rule is combined with Camel Case match rule,
192
	 * <code>"nPE"</code> pattern will match <code>nPException</code>.
193
	 *<br>
194
	 * Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
195
	 * will not be used simultaneously as they are mutually exclusive.
196
	 * Used match rule depends on whether string pattern contains specific pattern 
197
	 * characters (e.g. '*' or '?') or not. If it does, then only Pattern match rule
198
	 * will be used, otherwise only Camel Case match will be used.
199
	 * For example, with <code>"NPE"</code> string pattern, search will only use
200
	 * Camel Case match rule, but with <code>N*P*E*</code> string pattern, it will 
201
	 * use only Pattern match rule.
202
	 * 
203
	 * @since 3.4
204
	 */
205
	public static final int R_CAMELCASE_STRICT_MATCH = 0x0100;
206
172
	private static final int MODE_MASK = R_EXACT_MATCH | R_PREFIX_MATCH | R_PATTERN_MATCH | R_REGEXP_MATCH;
207
	private static final int MODE_MASK = R_EXACT_MATCH | R_PREFIX_MATCH | R_PATTERN_MATCH | R_REGEXP_MATCH;
173
208
174
	private int matchRule;
209
	private int matchRule;
Lines 213-228 Link Here
213
	if (name == null)
248
	if (name == null)
214
		return false; // null name cannot match
249
		return false; // null name cannot match
215
250
216
	return CharOperation.camelCaseMatch(pattern.toCharArray(), 0, pattern.length(), name.toCharArray(), 0, name.length());
251
	return CharOperation.camelCaseMatch(pattern.toCharArray(), 0, pattern.length(), name.toCharArray(), 0, name.length(), false/*prefix match for last hunk*/);
217
}
252
}
218
253
219
/**
254
/**
220
 * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.  
255
 * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. 
256
 * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
257
 * 
258
 * @see CharOperation#camelCaseMatch(char[], char[])
259
 * 
260
 * @param pattern the given pattern
261
 * @param name the given name
262
 * @param exactEndMatch when pattern last hunk has lowercase
263
 * 	this parameter indicates whether the name must end exactly
264
 * 	or can be only a prefix of it.
265
 * @return true if the pattern matches the given name, false otherwise
266
 * @since 3.4
267
 */
268
public static final boolean camelCaseMatch(String pattern, String name, boolean exactEndMatch) {
269
	if (pattern == null)
270
		return true; // null pattern is equivalent to '*'
271
	if (name == null)
272
		return false; // null name cannot match
273
274
	return CharOperation.camelCaseMatch(pattern.toCharArray(), 0, pattern.length(), name.toCharArray(), 0, name.length(), exactEndMatch);
275
}
276
277
/**
278
 * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.  
221
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
279
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
222
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
280
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
223
 * The subpattern is defined by the patternStart and patternEnd positions.
281
 * The sub-pattern is defined by the patternStart and patternEnd positions.
224
 * 
282
 * 
225
 * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int) for specification
283
 * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int, boolean) for specification
226
 * and implementation of this algorithm.
284
 * and implementation of this algorithm.
227
 * 
285
 * 
228
 * @param pattern the given pattern
286
 * @param pattern the given pattern
Lines 231-241 Link Here
231
 * @param name the given name
289
 * @param name the given name
232
 * @param nameStart the start index of the name, inclusive
290
 * @param nameStart the start index of the name, inclusive
233
 * @param nameEnd the end index of the name, exclusive
291
 * @param nameEnd the end index of the name, exclusive
234
 * @return true if a sub-pattern matches the subpart of the given name, false otherwise
292
 * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
235
 * @since 3.2
293
 * @since 3.2
294
 * @deprecated Use {@link #camelCaseMatch(String, int, int, String, int, int, boolean)} instead
236
 */
295
 */
237
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) {
296
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) {
238
	return CharOperation.camelCaseMatch(pattern.toCharArray(), patternStart, patternEnd, name.toCharArray(), nameStart, nameEnd);
297
	return CharOperation.camelCaseMatch(pattern.toCharArray(), patternStart, patternEnd, name.toCharArray(), nameStart, nameEnd, false/*prefix match for last hunk*/);
298
}	
299
300
/**
301
 * Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise.  
302
 * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
303
 * Can match only subset of name/pattern, considering end positions as non-inclusive.
304
 * The sub-pattern is defined by the patternStart and patternEnd positions.
305
 * 
306
 * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int, boolean) for specification
307
 * and implementation of this algorithm.
308
 * 
309
 * @param pattern the given pattern
310
 * @param patternStart the start index of the pattern, inclusive
311
 * @param patternEnd the end index of the pattern, exclusive
312
 * @param name the given name
313
 * @param nameStart the start index of the name, inclusive
314
 * @param nameEnd the end index of the name, exclusive
315
 * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
316
 * @param exactEndMatch when pattern last hunk has lowercase
317
 * 	this parameter indicates whether the name must end exactly
318
 * 	or can be only a prefix of it.
319
 * @since 3.4
320
 */
321
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd, boolean exactEndMatch) {
322
	return CharOperation.camelCaseMatch(pattern.toCharArray(), patternStart, patternEnd, name.toCharArray(), nameStart, nameEnd, exactEndMatch);
239
}	
323
}	
240
324
241
/**
325
/**
Lines 1601-1619 Link Here
1601
	if (pattern == null) return true; // null is as if it was "*"
1685
	if (pattern == null) return true; // null is as if it was "*"
1602
	if (name != null) {
1686
	if (name != null) {
1603
		boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0;
1687
		boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0;
1604
		boolean isCamelCase = (this.matchRule & R_CAMELCASE_MATCH) != 0;
1688
		boolean isStrictCamelCase = (this.matchRule & R_CAMELCASE_STRICT_MATCH) != 0;
1689
		boolean isCamelCase = isStrictCamelCase || (this.matchRule & R_CAMELCASE_MATCH) != 0;
1605
		int matchMode = this.matchRule & MODE_MASK;
1690
		int matchMode = this.matchRule & MODE_MASK;
1606
		boolean emptyPattern = pattern.length == 0;
1691
		boolean emptyPattern = pattern.length == 0;
1607
		if (matchMode == R_PREFIX_MATCH && emptyPattern) return true;
1692
		if (matchMode == R_PREFIX_MATCH && emptyPattern) return true;
1608
		boolean sameLength = pattern.length == name.length;
1693
		boolean sameLength = pattern.length == name.length;
1609
		boolean canBePrefix = name.length >= pattern.length;
1694
		boolean canBePrefix = name.length >= pattern.length;
1610
		boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 &&  pattern[0] == name[0]);
1695
		boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 &&  pattern[0] == name[0]);
1611
		if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name)) {
1696
		if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name, isStrictCamelCase)) {
1612
			return true;
1697
			return true;
1613
		}
1698
		}
1614
		switch (matchMode) {
1699
		switch (matchMode) {
1615
			case R_EXACT_MATCH :
1700
			case R_EXACT_MATCH :
1616
			case R_FULL_MATCH :
1617
				if (!isCamelCase) {
1701
				if (!isCamelCase) {
1618
					if (sameLength && matchFirstChar) {
1702
					if (sameLength && matchFirstChar) {
1619
						return CharOperation.equals(pattern, name, isCaseSensitive);
1703
						return CharOperation.equals(pattern, name, isCaseSensitive);
(-)search/org/eclipse/jdt/internal/core/index/Index.java (-2 / +3 lines)
Lines 57-64 Link Here
57
	if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*';
57
	if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*';
58
58
59
	// First test camel case if necessary
59
	// First test camel case if necessary
60
	boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
60
	boolean isStrictCamelCase = (matchRule & SearchPattern.R_CAMELCASE_STRICT_MATCH) != 0;
61
	if (isCamelCase &&  pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word)) {
61
	boolean isCamelCase = isStrictCamelCase || (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
62
	if (isCamelCase &&  pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word, isStrictCamelCase)) {
62
		return true;
63
		return true;
63
	}
64
	}
64
65
(-)src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java (+263 lines)
Lines 6418-6423 Link Here
6418
}
6418
}
6419
6419
6420
/**
6420
/**
6421
 *	@bug 124624: [search] Camel case matching routines should support end character
6422
 *	@test Ensure that camel case pattern may use end character
6423
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=124624"
6424
 */
6425
public void testBug124624_HM34() throws CoreException {
6426
	workingCopies = new ICompilationUnit[1];
6427
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6428
		"class HashMap {}\n" + 
6429
		"class HtmlMapper {}\n" + 
6430
		"class HashMapEntry {}\n" + 
6431
		"class HatMappage {}\n"
6432
	);
6433
	search("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6434
	assertSearchResults(
6435
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6436
		"src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" + 
6437
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6438
	);
6439
}
6440
// Same search than previous test but without full match (should work as 3.3)
6441
public void testBug124624_HM33() throws CoreException {
6442
	workingCopies = new ICompilationUnit[1];
6443
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6444
		"class HashMap {}\n" + 
6445
		"class HtmlMapper {}\n" + 
6446
		"class HashMapEntry {}\n" + 
6447
		"class HatMappage {}\n"
6448
	);
6449
	search("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6450
	assertSearchResults(
6451
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6452
		"src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" + 
6453
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" + 
6454
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6455
	);
6456
}
6457
public void testBug124624_HaM34() throws CoreException {
6458
	workingCopies = new ICompilationUnit[1];
6459
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6460
		"class HashMap {}\n" + 
6461
		"class HtmlMapper {}\n" + 
6462
		"class HashMapEntry {}\n" + 
6463
		"class HatMappage {}\n"
6464
	);
6465
	search("HaM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6466
	assertSearchResults(
6467
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6468
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6469
	);
6470
}
6471
// Same search than previous test but without full match (should work as 3.3)
6472
public void testBug124624_HaM33() throws CoreException {
6473
	workingCopies = new ICompilationUnit[1];
6474
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6475
		"class HashMap {}\n" + 
6476
		"class HtmlMapper {}\n" + 
6477
		"class HashMapEntry {}\n" + 
6478
		"class HatMappage {}\n"
6479
	);
6480
	search("HaM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6481
	assertSearchResults(
6482
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6483
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" + 
6484
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6485
	);
6486
}
6487
public void testBug124624_HashM34() throws CoreException {
6488
	workingCopies = new ICompilationUnit[1];
6489
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6490
		"class HashMap {}\n" + 
6491
		"class HtmlMapper {}\n" + 
6492
		"class HashMapEntry {}\n" + 
6493
		"class HatMappage {}\n"
6494
	);
6495
	search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6496
	assertSearchResults(
6497
		"src/Test.java HashMap [HashMap] EXACT_MATCH"
6498
	);
6499
}
6500
// Same search than previous test but without full match (should work as 3.3)
6501
public void testBug124624_HashM33() throws CoreException {
6502
	workingCopies = new ICompilationUnit[1];
6503
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6504
		"class HashMap {}\n" + 
6505
		"class HtmlMapper {}\n" + 
6506
		"class HashMapEntry {}\n" + 
6507
		"class HatMappage {}\n"
6508
	);
6509
	search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6510
	assertSearchResults(
6511
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6512
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
6513
	);
6514
}
6515
public void testBug124624_HMa34() throws CoreException {
6516
	workingCopies = new ICompilationUnit[1];
6517
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6518
		"class HashMap {}\n" + 
6519
		"class HtmlMapper {}\n" + 
6520
		"class HashMapEntry {}\n" + 
6521
		"class HatMappage {}\n"
6522
	);
6523
	search("HMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6524
	assertSearchResults("");
6525
}
6526
// Same search than previous test but without full match (should work as 3.3)
6527
public void testBug124624_HMa33() throws CoreException {
6528
	workingCopies = new ICompilationUnit[1];
6529
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6530
		"class HashMap {}\n" + 
6531
		"class HtmlMapper {}\n" + 
6532
		"class HashMapEntry {}\n" + 
6533
		"class HatMappage {}\n"
6534
	);
6535
	search("HMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6536
	assertSearchResults(
6537
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6538
		"src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" + 
6539
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" + 
6540
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6541
	);
6542
}
6543
public void testBug124624_HaMa34() throws CoreException {
6544
	workingCopies = new ICompilationUnit[1];
6545
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6546
		"class HashMap {}\n" + 
6547
		"class HtmlMapper {}\n" + 
6548
		"class HashMapEntry {}\n" + 
6549
		"class HatMappage {}\n"
6550
	);
6551
	search("HaMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6552
	assertSearchResults("");
6553
}
6554
// Same search than previous test but without full match (should work as 3.3)
6555
public void testBug124624_HaMa33() throws CoreException {
6556
	workingCopies = new ICompilationUnit[1];
6557
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6558
		"class HashMap {}\n" + 
6559
		"class HtmlMapper {}\n" + 
6560
		"class HashMapEntry {}\n" + 
6561
		"class HatMappage {}\n"
6562
	);
6563
	search("HashMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6564
	assertSearchResults(
6565
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6566
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
6567
	);
6568
}
6569
public void testBug124624_HashMa34() throws CoreException {
6570
	workingCopies = new ICompilationUnit[1];
6571
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6572
		"class HashMap {}\n" + 
6573
		"class HtmlMapper {}\n" + 
6574
		"class HashMapEntry {}\n" + 
6575
		"class HatMappage {}\n"
6576
	);
6577
	search("HashMa", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6578
	assertSearchResults("");
6579
}
6580
// Same search than previous test but without full match (should work as 3.3)
6581
public void testBug124624_HashMa33() throws CoreException {
6582
	workingCopies = new ICompilationUnit[1];
6583
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6584
		"class HashMap {}\n" + 
6585
		"class HtmlMapper {}\n" + 
6586
		"class HashMapEntry {}\n" + 
6587
		"class HatMappage {}\n"
6588
	);
6589
	search("HashM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6590
	assertSearchResults(
6591
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6592
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
6593
	);
6594
}
6595
public void testBug124624_HMap34() throws CoreException {
6596
	workingCopies = new ICompilationUnit[1];
6597
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6598
		"class HashMap {}\n" + 
6599
		"class HtmlMapper {}\n" + 
6600
		"class HashMapEntry {}\n" + 
6601
		"class HatMappage {}\n"
6602
	);
6603
	search("HMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6604
	assertSearchResults(
6605
		"src/Test.java HashMap [HashMap] EXACT_MATCH"
6606
	);
6607
}
6608
// Same search than previous test but without full match (should work as 3.3)
6609
public void testBug124624_HMap33() throws CoreException {
6610
	workingCopies = new ICompilationUnit[1];
6611
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6612
		"class HashMap {}\n" + 
6613
		"class HtmlMapper {}\n" + 
6614
		"class HashMapEntry {}\n" + 
6615
		"class HatMappage {}\n"
6616
	);
6617
	search("HMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6618
	assertSearchResults(
6619
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6620
		"src/Test.java HtmlMapper [HtmlMapper] EXACT_MATCH\n" + 
6621
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" + 
6622
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6623
	);
6624
}
6625
public void testBug124624_HaMap34() throws CoreException {
6626
	workingCopies = new ICompilationUnit[1];
6627
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6628
		"class HashMap {}\n" + 
6629
		"class HtmlMapper {}\n" + 
6630
		"class HashMapEntry {}\n" + 
6631
		"class HatMappage {}\n"
6632
	);
6633
	search("HaMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6634
	assertSearchResults(
6635
		"src/Test.java HashMap [HashMap] EXACT_MATCH"
6636
	);
6637
}
6638
// Same search than previous test but without full match (should work as 3.3)
6639
public void testBug124624_HaMap33() throws CoreException {
6640
	workingCopies = new ICompilationUnit[1];
6641
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6642
		"class HashMap {}\n" + 
6643
		"class HtmlMapper {}\n" + 
6644
		"class HashMapEntry {}\n" + 
6645
		"class HatMappage {}\n"
6646
	);
6647
	search("HaMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6648
	assertSearchResults(
6649
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6650
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH\n" + 
6651
		"src/Test.java HatMappage [HatMappage] EXACT_MATCH"
6652
	);
6653
}
6654
public void testBug124624_HashMap34() throws CoreException {
6655
	workingCopies = new ICompilationUnit[1];
6656
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6657
		"class HashMap {}\n" + 
6658
		"class HtmlMapper {}\n" + 
6659
		"class HashMapEntry {}\n" + 
6660
		"class HatMappage {}\n"
6661
	);
6662
	search("HashMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_STRICT_MATCH);
6663
	assertSearchResults(
6664
		"src/Test.java HashMap [HashMap] EXACT_MATCH"
6665
	);
6666
}
6667
// Same search than previous test but without full match (should work as 3.3)
6668
public void testBug124624_HashMap33() throws CoreException {
6669
	workingCopies = new ICompilationUnit[1];
6670
	workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java",
6671
		"class HashMap {}\n" + 
6672
		"class HtmlMapper {}\n" + 
6673
		"class HashMapEntry {}\n" + 
6674
		"class HatMappage {}\n"
6675
	);
6676
	search("HashMap", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_MATCH);
6677
	assertSearchResults(
6678
		"src/Test.java HashMap [HashMap] EXACT_MATCH\n" + 
6679
		"src/Test.java HashMapEntry [HashMapEntry] EXACT_MATCH"
6680
	);
6681
}
6682
6683
/**
6421
 * @test Bug 124645: [search] for implementors does not find subclasses of binary classes
6684
 * @test Bug 124645: [search] for implementors does not find subclasses of binary classes
6422
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=124645"
6685
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=124645"
6423
 */
6686
 */

Return to bug 124624