Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipse-dev] New CamelCase implementation in CharOperation


Please don't use this general eclipse developer's mailing list for such discussions.
Luiz, please file a bug (bugs.eclipse.org, Severity: Enhancement) for JDT/Core and attach your patch.

Note: apart from SearchPattern.camelCaseMatch(..), you will probably also have to fix
SearchPattern.validateMatchRule(..) to make the Open Type dialog work.

Thanks,
Markus



Dirk Baeumer/Zurich/IBM@IBMCH
Sent by: eclipse-dev-bounces@xxxxxxxxxxx

2006-02-15 10:25

Please respond to
"General development mailing list of the Eclipse project." <eclipse-dev@xxxxxxxxxxx>

To
eclipse-dev@xxxxxxxxxxx
cc
Subject
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


_______________________________________________
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


Back to the top