[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [eclipse-dev] New CamelCase implementation in CharOperation
|
The Open Type dialog uses SearchPattern.camelCaseMatch which is the camel
case
implementation using strings instead of char[]. The SearchPattern method
doesn't
forward to the CharOperation method to avoid unnecessary char[] creation.
Dirk
Luiz-Otavio
Zorzella
<z0200@zorzella.c To
om> eclipse-dev@xxxxxxxxxxx
Sent by: cc
eclipse-dev-bounc
es@xxxxxxxxxxx Subject
[eclipse-dev] New CamelCase
implementation in CharOperation
14/02/2006 05:39
PM
Please respond to
"General
development
mailing list of
the Eclipse
project."
<eclipse-dev@ecli
pse.org>
I've never submitted a patch before. Please let me know if there is a
better way (e.g. file a bug report). I thought the list would be a
better place to get some feedback.
I've re-written the camelcase match procedure on CharOperation. This is
the one used by CTRL-SPC completion (though, I think, not for "Open
Type". I don't know why there are two implementations -- I'll look into
it later).
The new method is much more straightforward (I think), and it works
correctly for a more useful definition of camel case, where lowercase
may be used between the uppercases, and not only in the end. E.g.,
before, "TZon" would match "TimeZone", but "TiZo" would not!
I've also created a unit test for the method (for which I could not find
a unit test). The MATCHES and MIS_MATCHES in the test (also pasted
below) provide concrete examples of usage for the new method.
Find a patch attached.
Feedback is welcomed, of course, and help on how to take it from here.
String[][] MATCHES = {
{"TZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TiZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TiZon","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TZon","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TZone","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TimeZone","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TimeZ","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
{"TZ","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
{"T","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
{"T","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"TZ","TZ"}, //$NON-NLS-1$//$NON-NLS-2$
{"aT","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTi","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTiZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aT","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTi","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTiZ","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTZ","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
};
String[][] MIS_MATCHES = {
{"TZ","Timezone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aTZ","TZ"}, //$NON-NLS-1$//$NON-NLS-2$
{"arT","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"arTi","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"arTiZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"arTZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
{"aT","atimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
Z
### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core.tests.compiler
Index:
src/org/eclipse/jdt/core/tests/compiler/regression/CharOperationTest.java
===================================================================
RCS file:
/cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CharOperationTest.java,v
retrieving revision 1.1
diff -u -r1.1 CharOperationTest.java
---
src/org/eclipse/jdt/core/tests/compiler/regression/CharOperationTest.java
25 Nov 2005 17:26:24 -0000 1.1
+++
src/org/eclipse/jdt/core/tests/compiler/regression/CharOperationTest.java
14 Feb 2006 00:12:16 -0000
@@ -11,6 +11,7 @@
package org.eclipse.jdt.core.tests.compiler.regression;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import junit.framework.Test;
@@ -77,4 +78,51 @@
public static Class testClass() {
return CharOperationTest.class;
}
+
+public void testCamel() {
+ String[][] MATCHES = {
+ {"TZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TiZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TiZon","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TZon","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TZone","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TimeZone","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TimeZ","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TZ","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"T","TimeZ"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"T","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"TZ","TZ"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aT","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTi","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTiZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aT","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTi","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTiZ","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTZ","artTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ };
+
+ for (int i = 0; i<MATCHES.length ; i++) {
+ String[] match = MATCHES[i];
+ assertTrue (match[0] + ":" + match[1],
CharOperation.camelCaseMatch(match[0].toCharArray(),
match[1].toCharArray())); //$NON-NLS-1$
+ }
+
+ String[][] MIS_MATCHES = {
+ {"TZ","Timezone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTZ","TimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aTZ","TZ"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"arT","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"arTi","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"arTiZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"arTZ","aTimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ {"aT","atimeZone"}, //$NON-NLS-1$//$NON-NLS-2$
+ };
+
+ for (int i = 0; i<MIS_MATCHES.length ; i++) {
+ String[] match = MIS_MATCHES[i];
+ assertFalse (match[0] + ":" + match[1],
CharOperation.camelCaseMatch(match[0].toCharArray(),
match[1].toCharArray())); //$NON-NLS-1$
+ }
+
+}
+
}
#P org.eclipse.jdt.core
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.64
diff -u -r1.64 CharOperation.java
--- compiler/org/eclipse/jdt/core/compiler/CharOperation.java 10
Feb 2006 16:14:04 -0000 1.64
+++ compiler/org/eclipse/jdt/core/compiler/CharOperation.java 14
Feb 2006 00:12:19 -0000
@@ -284,64 +284,79 @@
return false;
}
char patternChar, nameChar;
- int iPattern = patternStart+1;
- int iName = nameStart+1;
- nextPatternChar: while (iPattern < patternEnd) {
- // check patternChar, keep camelCasing only if
uppercase
- if ((patternChar = pattern[iPattern]) <
ScannerHelper.MAX_OBVIOUS) {
- switch
(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar]) {
- case
ScannerHelper.C_UPPER_LETTER :
- // still
uppercase
- break;
- default:
- // end of
camelCase part of pattern
- break
nextPatternChar;
- }
- } else if
(Character.isJavaIdentifierPart(patternChar)
- &&
!Character.isUpperCase(patternChar)) {
- // end of camelCase part of pattern
- break nextPatternChar;
- }
- nextNameChar: while (iName < nameEnd) {
- if ((nameChar = name[iName]) !=
patternChar) {
- if (nameChar <
ScannerHelper.MAX_OBVIOUS) {
- switch
(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar]) {
-
case ScannerHelper.C_LOWER_LETTER :
-
case ScannerHelper.C_IDENT_PART :
-
case ScannerHelper.C_DIGIT :
-
// lowercase/digit char is ignored
-
iName++;
-
continue nextNameChar;
- }
- } else if
(Character.isJavaIdentifierPart(nameChar)
-
&& !Character.isUpperCase(nameChar)) {
- // lowercase
name char is ignored
- iName++;
- continue
nextNameChar;
- }
- // mismatch, either
uppercase in name or non case char ('/' etc)--> reject
- return false;
- } else {
- // pattern char == name
char (uppercase)
- iName++;
- iPattern++;
- continue nextPatternChar;
- }
- }
- if (iPattern == patternEnd) return true;
- if (iName == nameEnd) return false;
- continue nextPatternChar;
- }
+
+ int iPattern = patternStart;
+ int iName = nameStart;
+
+ while (true) {
- // check trailing part in case sensitive way
- while (iPattern < patternEnd && iName < nameEnd) {
- if (pattern[iPattern] != name[iName]) {
- return false;
- }
iPattern++;
iName++;
+
+ if (iPattern == patternEnd) {
+ // We have exhausted pattern, so it's
a match
+ return true;
+ }
+
+ if (iName == nameEnd){
+ // We have exhausted name (and not
pattern), so it's not a match
+ return false;
+ }
+
+ patternChar = pattern[iPattern];
+
+ // For as long as we're exactly matching, bring it
on
+ if (patternChar == name[iName])
+ continue;
+
+ if (
+ (patternChar < ScannerHelper.MAX_OBVIOUS
+ &&
+ ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] !=
ScannerHelper.C_UPPER_LETTER)
+ ||
+ (Character.isJavaIdentifierPart(patternChar)
+ &&
+ !Character.isUpperCase(patternChar))
+ ) {
+ // patternChar is lowercase, and it
does not match name, so it's not a match
+ 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[iName];
+
+ if (
+ (nameChar <
ScannerHelper.MAX_OBVIOUS
+ &&
+
ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] !=
ScannerHelper.C_UPPER_LETTER)
+ ||
+
(Character.isJavaIdentifierPart(nameChar)
+ &&
+ !Character.isUpperCase(nameChar))
+ ) {
+ // nameChar is lowercase
+ iName++;
+ } else {
+ // nameChar is
uppercase...
+ if (patternChar !=
nameChar)
+ //.. and it
does not match patternChar, so it's not a match
+ return false;
+
+ //.. and it matched
patternChar. Back to the big loop
+ break;
+ }
+ }
+
+ // At this point, either name has been exhausted,
or it is at an uppercase letter.
+ // Since pattern is also at an
+
}
- return iPattern == patternEnd;
}
/**
_______________________________________________
eclipse-dev mailing list
eclipse-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe
from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipse-dev