Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Syntax highlighting of preprocessor directives - improvements

Title: Message
        Hello!
   
    I've been playing around with CDT, and found a minor problem with syntax highlighting of preprocessor directives: it doesn't handle whitespaces around # sign (internal parser seems to work fine, though). And some people write conditional code like this:
 
#ifdef blabla
#    define A
#endif
 
or
 
#ifdef blabla
    #define A
#endif
 
    Feeling that this is my opportunity to contribute ;)) I've patched UI code to add a new rule for handling preprocessor directives, PreprocessorRule class (extends WordRule). And here I noticed that CppCodeScanner uses private class CWordRule, while CCodeScanner uses standard WordRule. They seem to do exactly the same thing, but CWordRule additionally checks for # sign to be the first character on the line.  As now preprocessor directives are handled by PreprocessorRule class, CWordRule can be removed and replaced with WordRule; also, there is no need for CWordDetector to pick up # sign as a valid word start.
 
                     /Vic
 
 
 
Index: src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java,v
retrieving revision 1.5
diff -u -r1.5 CCodeScanner.java
--- src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java 16 Oct 2002 20:14:10 -0000 1.5
+++ src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java 28 May 2003 18:04:03 -0000
@@ -12,7 +12,6 @@
 import org.eclipse.cdt.internal.ui.text.util.CWordDetector;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.rules.IRule;
-import org.eclipse.jface.text.rules.PatternRule;
 import org.eclipse.jface.text.rules.SingleLineRule;
 import org.eclipse.jface.text.rules.Token;
 import org.eclipse.jface.text.rules.WordRule;
@@ -87,7 +86,6 @@
   
   // Add generic whitespace rule.
   //rules.add(new WhitespaceRule(new CWhitespaceDetector()));
-
   
   // Add word rule for keywords, types, and constants.
   token= getToken(ICColorConstants.C_DEFAULT);
@@ -101,17 +99,16 @@
    wordRule.addWord(fgTypes[i], token);
   for (int i=0; i<fgConstants.length; i++)
    wordRule.addWord(fgConstants[i], token);
-  for (int i=0; i<fgPreprocessor.length; i++)
-   wordRule.addWord(fgPreprocessor[i], token);
   rules.add(wordRule);
-     
-  PatternRule patternRule;
+  
+  token = getToken(ICColorConstants.C_TYPE);
+  PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), token);
+  
   for (int i=0; i<fgPreprocessor.length; i++) {
-   patternRule = new PatternRule(fgPreprocessor[i], " ", getToken(ICColorConstants.C_TYPE), (char)0, true);
-   patternRule.setColumnConstraint(0); // For now, until we have a better rule
-   //rules.add(patternRule);
+   preprocessorRule.addWord(fgPreprocessor[i], token);
   }
-  
+  rules.add(preprocessorRule);
+       
   setDefaultReturnToken(getToken(ICColorConstants.C_DEFAULT));
   return rules;
  }
Index: src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java,v
retrieving revision 1.3
diff -u -r1.3 CppCodeScanner.java
--- src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java 11 Oct 2002 13:40:45 -0000 1.3
+++ src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java 28 May 2003 18:04:03 -0000
@@ -7,19 +7,13 @@
 
 import org.eclipse.cdt.internal.ui.text.util.CWordDetector;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
-import java.util.Map;
 import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.jface.text.rules.ICharacterScanner;
 import org.eclipse.jface.text.rules.IRule;
-import org.eclipse.jface.text.rules.IToken;
-import org.eclipse.jface.text.rules.IWordDetector;
-import org.eclipse.jface.text.rules.PatternRule;
 import org.eclipse.jface.text.rules.SingleLineRule;
 import org.eclipse.jface.text.rules.Token;
-import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.text.rules.WordRule;
 import org.eclipse.jface.util.PropertyChangeEvent;
 
 
@@ -28,116 +22,6 @@
  */
 public final class CppCodeScanner extends AbstractCScanner {
  
- private class CWordRule implements IRule {
-  
-  protected static final int UNDEFINED= -1;
-  
-  /** The word detector used by this rule */
-  protected IWordDetector fDetector;
-  /** The default token to be returned on success and if nothing else has been specified. */
-  protected IToken fDefaultToken;
-  /** The column constraint */
-  protected int fColumn= UNDEFINED;
-  /** The table of predefined words and token for this rule */
-  protected Map fWords= new HashMap();
-  
-  private StringBuffer fBuffer= new StringBuffer();

-  /**
-   * Creates a rule which, with the help of an word detector, will return the token
-   * associated with the detected word. If no token has been associated, the scanner
-   * will be rolled back and an undefined token will be returned in order to allow
-   * any subsequent rules to analyze the characters.
-   *
-   * @param detector the word detector to be used by this rule, may not be <code>null</code>
-   *
-   * @see #addWord
-   */
-  public CWordRule(IWordDetector detector) {
-   this(detector, Token.UNDEFINED);
-  }
-  /**
-   * Creates a rule which, with the help of an word detector, will return the token
-   * associated with the detected word. If no token has been associated, the
-   * specified default token will be returned.
-   *
-   * @param detector the word detector to be used by this rule, may not be <code>null</code>
-   * @param defaultToken the default token to be returned on success
-   *  if nothing else is specified, may not be <code>null</code>
-   *
-   * @see #addWord
-   */
-  public CWordRule(IWordDetector detector, IToken defaultToken) {
-   
-   Assert.isNotNull(detector);
-   Assert.isNotNull(defaultToken);
-   
-   fDetector= detector;
-   fDefaultToken= defaultToken;
-  }
-  /**
-   * Adds a word and the token to be returned if it is detected.
-   *
-   * @param word the word this rule will search for, may not be <code>null</code>
-   * @param token the token to be returned if the word has been found, may not be <code>null</code>
-   */
-  public void addWord(String word, IToken token) {
-   Assert.isNotNull(word);
-   Assert.isNotNull(token);  
-  
-   fWords.put(word, token);
-  }
-  /*
-   * @see IRule#evaluate
-   */
-  public IToken evaluate(ICharacterScanner scanner) {
-   
-   int c= scanner.read();
-   if (Character.isJavaIdentifierStart((char) c) || (c == '#' && scanner.getColumn() == 1)) { 
-    fBuffer.setLength(0);
-    do {
-     fBuffer.append((char) c);
-     c= scanner.read();
-    } while (Character.isJavaIdentifierPart((char) c));
-    scanner.unread();
-    
-    IToken token= (IToken) fWords.get(fBuffer.toString());
-    if (token != null)
-     return token;
-     
-    //if (fDefaultToken.isUndefined())
-    // unreadBuffer(scanner);
-     
-    return fDefaultToken;
-   }
-   
-   scanner.unread();
-   return Token.UNDEFINED;
-  }
-  /**
-   * Sets a column constraint for this rule. If set, the rule's token
-   * will only be returned if the pattern is detected starting at the
-   * specified column. If the column is smaller then 0, the column
-   * constraint is considered removed.
-   *
-   * @param column the column in which the pattern starts
-   */
-  public void setColumnConstraint(int column) {
-   if (column < 0)
-    column= UNDEFINED;
-   fColumn= column;
-  }
-  /**
-   * Returns the characters in the buffer to the scanner.
-   *
-   * @param scanner the scanner to be used
-   */
-  protected void unreadBuffer(ICharacterScanner scanner) {
-   for (int i= fBuffer.length() - 1; i >= 0; i--)
-    scanner.unread();
-  }
- };
-
  private static String[] fgKeywords= {
    "and", "and_eq", "asm", "auto",
    "bitand", "bitor", "break",
@@ -210,7 +94,7 @@
   
   // Add word rule for keywords, types, and constants.
   token= getToken(ICColorConstants.C_DEFAULT);
-  CWordRule wordRule= new CWordRule(new CWordDetector(), token);
+  WordRule wordRule = new WordRule(new CWordDetector(), token);
   
   token= getToken(ICColorConstants.C_KEYWORD);
   for (int i=0; i<fgKeywords.length; i++)
@@ -220,16 +104,15 @@
    wordRule.addWord(fgTypes[i], token);
   for (int i=0; i<fgConstants.length; i++)
    wordRule.addWord(fgConstants[i], token);
-  for (int i=0; i<fgPreprocessor.length; i++)
-   wordRule.addWord(fgPreprocessor[i], token);
   rules.add(wordRule);
-     
-  PatternRule patternRule;
+      
+  token = getToken(ICColorConstants.C_TYPE);
+  PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), token);
+  
   for (int i=0; i<fgPreprocessor.length; i++) {
-   patternRule = new PatternRule(fgPreprocessor[i], " ", getToken(ICColorConstants.C_TYPE), (char)0, true);
-   patternRule.setColumnConstraint(0); // For now, until we have a better rule
-   //rules.add(patternRule);
+   preprocessorRule.addWord(fgPreprocessor[i], token);
   }
+  rules.add(preprocessorRule);
   
   setDefaultReturnToken(getToken(ICColorConstants.C_DEFAULT));
   return rules;
Index: src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java
===================================================================
RCS file: src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java
diff -N src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java 28 May 2003 18:04:03 -0000
@@ -0,0 +1,94 @@
+package org.eclipse.cdt.internal.ui.text;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+
+/**
+ * Implementation of <code>IRule</code> for C/C++ preprocessor scanning.
+ * It is capable of detecting a pattern which begins with 0 or more whitespaces
+ * at the beginning of the string, then '#' sign, then 0 or more whitespaces
+ * again, and then directive itself.
+ */
+public class PreprocessorRule extends WordRule implements IRule {
+  
+ private StringBuffer fBuffer = new StringBuffer();

+ /**
+  * Creates a rule which, with the help of a word detector, will return the token
+  * associated with the detected word. If no token has been associated, the scanner
+  * will be rolled back and an undefined token will be returned in order to allow
+  * any subsequent rules to analyze the characters.
+  *
+  * @param detector the word detector to be used by this rule, may not be <code>null</code>
+  *
+  * @see #addWord
+  */
+ public PreprocessorRule(IWordDetector detector) {
+  this(detector, Token.UNDEFINED);
+ }

+ /**
+  * Creates a rule which, with the help of an word detector, will return the token
+  * associated with the detected word. If no token has been associated, the
+  * specified default token will be returned.
+  *
+  * @param detector the word detector to be used by this rule, may not be <code>null</code>
+  * @param defaultToken the default token to be returned on success
+  *  if nothing else is specified, may not be <code>null</code>
+  *
+  * @see #addWord
+  */
+ public PreprocessorRule(IWordDetector detector, IToken defaultToken) {
+  super(detector, defaultToken);
+ }


+ /*
+  * @see IRule#evaluate
+  */
+ public IToken evaluate(ICharacterScanner scanner) {
+  int c;
+  int nCharsToRollback = 0;
+  
+  if (scanner.getColumn() > 0) return Token.UNDEFINED;
+   
+  do {
+   c = scanner.read(); nCharsToRollback++;
+  } while (Character.isWhitespace((char)c));
+    
+  if (c == '#') {
+   
+   do {
+    c = scanner.read();
+   } while (Character.isWhitespace((char)c));

+   fBuffer.setLength(0);
+   
+   do {
+    fBuffer.append((char) c);
+    c = scanner.read();
+   } while (Character.isJavaIdentifierPart((char) c));
+   
+   scanner.unread();
+   
+   IToken token= (IToken) fWords.get("#" + fBuffer.toString());
+   if (token != null)
+    return token;
+    
+   return fDefaultToken;
+   
+  } else { // Doesn't start with '#', roll back scanner
+   
+   for (int i=0; i<nCharsToRollback; i++) {
+    scanner.unread();
+   }
+  }
+  
+  return Token.UNDEFINED;
+ }
+}
Index: src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java,v
retrieving revision 1.2
diff -u -r1.2 CWordDetector.java
--- src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java 24 Sep 2002 13:36:38 -0000 1.2
+++ src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java 28 May 2003 18:04:04 -0000
@@ -17,7 +17,7 @@
   * @see IWordDetector#isWordIdentifierStart
   */
  public boolean isWordStart(char c) {
-  return Character.isJavaIdentifierStart(c) || c == '#';
+  return Character.isJavaIdentifierStart(c);
  }
  
  /**

Back to the top