Changeset 10982


Ignore:
Timestamp:
02/04/06 21:00:26 (18 years ago)
Author:
piso
Message:

Reformatted source.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/j/src/org/armedbear/j/JavaTagger.java

    r5285 r10982  
    22 * JavaTagger.java
    33 *
    4  * Copyright (C) 1998-2002 Peter Graves
    5  * $Id: JavaTagger.java,v 1.6 2003-12-30 19:24:02 piso Exp $
     4 * Copyright (C) 1998-2006 Peter Graves
     5 * $Id: JavaTagger.java,v 1.7 2006-02-04 21:00:26 piso Exp $
    66 *
    77 * This program is free software; you can redistribute it and/or
     
    2727public class JavaTagger extends Tagger implements Constants
    2828{
    29     // States.
    30     private static final int NEUTRAL            =  0;
    31     private static final int INTERFACE_NAME     =  1;
    32     private static final int CLASS_NAME         =  2;
    33     private static final int CLASS_PROLOG       =  3; // After name, before opening brace.
    34     private static final int EXTENDS            =  4;
    35     private static final int IMPLEMENTS         =  5;
    36     private static final int METHOD_NAME        =  6;
    37     private static final int METHOD_PROLOG      =  7;
    38     private static final int STATIC_INITIALIZER =  8;
    39     private static final int NEW                =  9;
    40     private static final int FIELD_INITIALIZER  = 10; // After '=' in a variable declaration.
    41 
    42     protected Position pos;
    43     protected String token;
    44     protected Position tokenStart;
    45 
    46     private ArrayList tags;
    47     private JavaClass currentClass;
    48     private int visibility; // TAG_PUBLIC, TAG_PRIVATE, TAG_PROTECTED
    49 
    50     public JavaTagger(SystemBuffer buffer)
    51     {
    52         super(buffer);
    53     }
    54 
    55     public synchronized void run()
    56     {
    57         pos = new Position(buffer.getFirstLine(), 0);
    58         token = null;
    59         tokenStart = null;
    60         tags = new ArrayList();
    61         currentClass = null;
    62         visibility = 0;
    63         final boolean beanShell = buffer.getModeId() == BEANSHELL_MODE;
    64         final boolean javaScript = buffer.getModeId() == JAVASCRIPT_MODE;
    65         final Stack stack = new Stack();
    66         int state = NEUTRAL;
    67         while (!pos.atEnd()) {
    68             char c = pos.getChar();
    69             if (Character.isWhitespace(c)) {
    70                 pos.skipWhitespace();
    71                 continue;
    72             }
    73             if (c == '\'' || c == '"') {
    74                 pos.skipQuote();
    75                 continue;
    76             }
    77             if (pos.lookingAt("/*")) {
    78                 skipComment(pos);
    79                 continue;
    80             }
    81             if (pos.lookingAt("//")) {
    82                 skipSingleLineComment(pos);
    83                 continue;
    84             }
    85             if (state == STATIC_INITIALIZER) {
    86                 if (c == '{') {
    87                     skipBrace();
    88                     state = NEUTRAL;
    89                     continue;
    90                 }
    91                 // Anything else...
    92                 state = NEUTRAL;
    93                 // Fall through...
    94             }
    95             if (state == METHOD_NAME) {
    96                 if (c == '{') {
     29  // States.
     30  private static final int NEUTRAL            =  0;
     31  private static final int INTERFACE_NAME     =  1;
     32  private static final int CLASS_NAME         =  2;
     33  private static final int CLASS_PROLOG       =  3; // After name, before opening brace.
     34  private static final int EXTENDS            =  4;
     35  private static final int IMPLEMENTS         =  5;
     36  private static final int METHOD_NAME        =  6;
     37  private static final int METHOD_PROLOG      =  7;
     38  private static final int STATIC_INITIALIZER =  8;
     39  private static final int NEW                =  9;
     40  private static final int FIELD_INITIALIZER  = 10; // After '=' in a variable declaration.
     41
     42  protected Position pos;
     43  protected String token;
     44  protected Position tokenStart;
     45
     46  private ArrayList tags;
     47  private JavaClass currentClass;
     48  private int visibility; // TAG_PUBLIC, TAG_PRIVATE, TAG_PROTECTED
     49
     50  public JavaTagger(SystemBuffer buffer)
     51  {
     52    super(buffer);
     53  }
     54
     55  public synchronized void run()
     56  {
     57    pos = new Position(buffer.getFirstLine(), 0);
     58    token = null;
     59    tokenStart = null;
     60    tags = new ArrayList();
     61    currentClass = null;
     62    visibility = 0;
     63    final boolean beanShell = buffer.getModeId() == BEANSHELL_MODE;
     64    final boolean javaScript = buffer.getModeId() == JAVASCRIPT_MODE;
     65    final Stack stack = new Stack();
     66    int state = NEUTRAL;
     67    while (!pos.atEnd())
     68      {
     69        char c = pos.getChar();
     70        if (Character.isWhitespace(c))
     71          {
     72            pos.skipWhitespace();
     73            continue;
     74          }
     75        if (c == '\'' || c == '"')
     76          {
     77            pos.skipQuote();
     78            continue;
     79          }
     80        if (pos.lookingAt("/*"))
     81          {
     82            skipComment(pos);
     83            continue;
     84          }
     85        if (pos.lookingAt("//"))
     86          {
     87            skipSingleLineComment(pos);
     88            continue;
     89          }
     90        if (state == STATIC_INITIALIZER)
     91          {
     92            if (c == '{')
     93              {
     94                skipBrace();
     95                state = NEUTRAL;
     96                continue;
     97              }
     98            // Anything else...
     99            state = NEUTRAL;
     100            // Fall through...
     101          }
     102        if (state == METHOD_NAME)
     103          {
     104            if (c == '{')
     105              {
     106                addTag(TAG_METHOD);
     107                visibility = 0;
     108                skipBrace();
     109                state = NEUTRAL;
     110                continue;
     111              }
     112            if (c == ';')
     113              {
     114                if (beanShell)
     115                  {
     116                    ; // It's just a function call.
     117                  }
     118                else
     119                  {
     120                    // Abstract or native method.
    97121                    addTag(TAG_METHOD);
    98122                    visibility = 0;
    99                     skipBrace();
    100                     state = NEUTRAL;
    101                     continue;
    102                 }
    103                 if (c == ';') {
    104                     if (beanShell) {
    105                         ; // It's just a function call.
    106                     } else {
    107                         // Abstract or native method.
    108                         addTag(TAG_METHOD);
    109                         visibility = 0;
    110                     }
    111                     state = NEUTRAL;
    112                     pos.next();
    113                     continue;
    114                 }
    115                 if (pos.lookingAt("throws")) {
     123                  }
     124                state = NEUTRAL;
     125                pos.next();
     126                continue;
     127              }
     128            if (pos.lookingAt("throws"))
     129              {
     130                addTag(TAG_METHOD);
     131                // Set token to null here so we don't try to add this method again.
     132                token = null;
     133                visibility = 0;
     134                state = METHOD_PROLOG;
     135                pos.skip(6); // Skip over "throws".
     136                continue;
     137              }
     138            state = NEUTRAL;
     139            // Fall through...
     140          }
     141        if (state == CLASS_PROLOG)
     142          {
     143            if (pos.lookingAt("extends"))
     144              {
     145                state = EXTENDS;
     146                pos.skip(7); // Skip over "extends".
     147                continue;
     148              }
     149            if (pos.lookingAt("implements"))
     150              {
     151                state = IMPLEMENTS;
     152                pos.skip(10);
     153                continue;
     154              }
     155            if (c == '{')
     156              state = NEUTRAL;
     157            pos.next();
     158            continue;
     159          }
     160        if (state == IMPLEMENTS)
     161          {
     162            if (c == '{')
     163              {
     164                state = NEUTRAL;
     165                pos.next();
     166                continue;
     167              }
     168            // else fall through...
     169          }
     170        if (state == METHOD_PROLOG)
     171          {
     172            // Wait for a semicolon or the opening brace of the method body.
     173            if (c == '{')
     174              {
     175                skipBrace();
     176                state = NEUTRAL;
     177              }
     178            else if (c == ';')
     179              {
     180                // Abstract or native method. If token is null, we've
     181                // added it already.
     182                if (token != null)
     183                  {
    116184                    addTag(TAG_METHOD);
    117                     // Set token to null here so we don't try to add this method again.
    118                     token = null;
    119185                    visibility = 0;
    120                     state = METHOD_PROLOG;
    121                     pos.skip(6); // Skip over "throws".
    122                     continue;
    123                 }
    124                 state = NEUTRAL;
    125                 // Fall through...
    126             }
    127             if (state == CLASS_PROLOG) {
    128                 if (pos.lookingAt("extends")) {
    129                      state = EXTENDS;
    130                      pos.skip(7); // Skip over "extends".
    131                      continue;
    132                 }
    133                 if (pos.lookingAt("implements")) {
    134                     state = IMPLEMENTS;
    135                     pos.skip(10);
    136                     continue;
    137                 }
    138                 if (c == '{')
    139                     state = NEUTRAL;
     186                  }
     187                state = NEUTRAL;
    140188                pos.next();
    141                 continue;
    142             }
    143             if (state == IMPLEMENTS) {
    144                 if (c == '{') {
    145                     state = NEUTRAL;
    146                     pos.next();
    147                     continue;
    148                 }
    149                 // else fall through...
    150             }
    151             if (state == METHOD_PROLOG) {
    152                 // Wait for a semicolon or the opening brace of the method body.
    153                 if (c == '{') {
    154                     skipBrace();
    155                     state = NEUTRAL;
    156                 } else if (c == ';') {
    157                     // Abstract or native method. If token is null, we've
    158                     // added it already.
    159                     if (token != null) {
    160                         addTag(TAG_METHOD);
    161                         visibility = 0;
    162                     }
    163                     state = NEUTRAL;
    164                     pos.next();
    165                 } else
    166                     pos.next();
    167                 continue;
    168             }
    169             if (state == NEW) {
    170                 if (c == '(') {
    171                     skipParen();
    172                     continue;
    173                 } else if (c == '{') {
    174                     skipBrace();
    175                     continue;
    176                 } else if (c == ';')
    177                     state = NEUTRAL;
     189              }
     190            else
     191              pos.next();
     192            continue;
     193          }
     194        if (state == NEW)
     195          {
     196            if (c == '(')
     197              {
     198                skipParen();
     199                continue;
     200              }
     201            else if (c == '{')
     202              {
     203                skipBrace();
     204                continue;
     205              }
     206            else if (c == ';')
     207              state = NEUTRAL;
     208            pos.next();
     209            continue;
     210          }
     211        if (state == FIELD_INITIALIZER)
     212          {
     213            if (c == '(')
     214              {
     215                skipParen();
     216                continue;
     217              }
     218            if (c == '{')
     219              {
     220                skipBrace();
     221                if (javaScript)
     222                  state = NEUTRAL;
     223                continue;
     224              }
     225            if (c == ',')
     226              state = NEUTRAL;
     227            else if (c == ';')
     228              {
     229                state = NEUTRAL;
     230                visibility = 0;
     231              }
     232            pos.next();
     233            continue;
     234          }
     235        if (state == IMPLEMENTS)
     236          {
     237            if (c == ',')
     238              {
    178239                pos.next();
    179240                continue;
    180             }
    181             if (state == FIELD_INITIALIZER) {
    182                 if (c == '(') {
    183                     skipParen();
    184                     continue;
    185                 }
    186                 if (c == '{') {
    187                     skipBrace();
    188                     if (javaScript)
    189                         state = NEUTRAL;
    190                     continue;
    191                 }
    192                 if (c == ',')
    193                     state = NEUTRAL;
    194                 else if (c == ';') {
    195                     state = NEUTRAL;
    196                     visibility = 0;
    197                 }
    198                 pos.next();
    199                 continue;
    200             }
    201             if (state == IMPLEMENTS) {
    202                 if (c == ',') {
    203                     pos.next();
    204                     continue;
    205                 }
    206             }
    207             if (c == '}') {
    208                 if (!stack.empty())
    209                     currentClass = (JavaClass) stack.pop();
    210                 else
    211                     currentClass = null;
    212                 pos.next();
    213                 continue;
    214             }
    215             if (Character.isJavaIdentifierStart(c)) {
    216                 // If we're in an "extends" or "implements" clause, the token
    217                 // may be a canonical class name (like "java.lang.String").
    218                 // Otherwise the token is a simple identifier.
    219                 gatherToken(state == EXTENDS || state == IMPLEMENTS);
    220                 if (state == INTERFACE_NAME) {
    221                     if (currentClass != null)
    222                         stack.push(currentClass);
    223                     final JavaClass parentClass = currentClass;
    224                     currentClass = new JavaClass(token, TAG_INTERFACE);
    225                     state = CLASS_PROLOG;
    226                     // Add a tag for the class itself.
    227                     tags.add(new JavaTag("interface ".concat(token),
    228                         tokenStart,TAG_INTERFACE, visibility, parentClass));
    229                     visibility = 0;
    230                 } else if (state == CLASS_NAME) {
    231                     if (currentClass != null)
    232                         stack.push(currentClass);
    233                     final JavaClass parentClass = currentClass;
    234                     currentClass = new JavaClass(token, TAG_CLASS);
    235                     state = CLASS_PROLOG;
    236                     // Add a tag for the class itself.
    237                     tags.add(new JavaTag("class ".concat(token), tokenStart,
    238                         TAG_CLASS, visibility, parentClass));
    239                     visibility = 0;
    240                 } else if (state == EXTENDS) {
    241                     tags.add(new JavaTag(token, tokenStart, TAG_EXTENDS,
    242                         visibility, currentClass));
    243                     state = CLASS_PROLOG;
    244                 } else if (state == IMPLEMENTS)
    245                     tags.add(new JavaTag(token, tokenStart, TAG_IMPLEMENTS,
    246                         visibility, currentClass));
    247                 else if (token.equals("package") || token.equals("import"))
    248                     skipSemi();
    249                 else if (token.equals("interface"))
    250                     state = INTERFACE_NAME;
    251                 else if (token.equals("class"))
    252                     state = CLASS_NAME;
    253                 else if (token.equals("static"))
    254                     state = STATIC_INITIALIZER;
    255                 else if (token.equals("new"))
    256                     // Don't be confused by lines like "Runnable r = new Runnable() { ... };"
    257                     state = NEW;
    258                 else if (token.equals("public"))
    259                     visibility |= TAG_PUBLIC;
    260                 else if (token.equals("protected"))
    261                     visibility |= TAG_PROTECTED;
    262                 else if (token.equals("private"))
    263                     visibility |= TAG_PRIVATE;
    264                 continue;
    265             }
    266             if (c == '(') {
    267                 skipParen();
    268                 state = METHOD_NAME;
    269                 continue;
    270             }
    271             if (c == '=') {
    272                 addTag(TAG_FIELD);
    273                 state = FIELD_INITIALIZER;
    274                 pos.next();
    275                 continue;
    276             }
    277             // "int x, y;"
    278             if (c == ';' || c == ',') {
    279                 if (token != null)
    280                     addTag(TAG_FIELD);
    281                 // Don't reset the visibility until we see the semicolon.
    282                 if (c == ';')
    283                     visibility = 0;
    284             }
     241              }
     242          }
     243        if (c == '}')
     244          {
     245            if (!stack.empty())
     246              currentClass = (JavaClass) stack.pop();
     247            else
     248              currentClass = null;
    285249            pos.next();
    286         }
    287         buffer.setTags(tags);
    288     }
    289 
    290     private void addTag(int type)
    291     {
    292         if (currentClass != null) {
    293             FastStringBuffer sb = new FastStringBuffer(currentClass.getName());
    294             sb.append('.');
    295             sb.append(token);
    296             tags.add(new JavaTag(sb.toString(), tokenStart, type, visibility, currentClass));
    297         } else
    298             tags.add(new JavaTag(token, tokenStart, type, visibility));
    299     }
    300 
    301     protected static final void skipComment(Position pos)
    302     {
    303         while (true) {
    304             if (pos.lookingAt("*/")) {
    305                 pos.skip(2);
    306                 return;
    307             }
     250            continue;
     251          }
     252        if (Character.isJavaIdentifierStart(c))
     253          {
     254            // If we're in an "extends" or "implements" clause, the token
     255            // may be a canonical class name (like "java.lang.String").
     256            // Otherwise the token is a simple identifier.
     257            gatherToken(state == EXTENDS || state == IMPLEMENTS);
     258            if (state == INTERFACE_NAME)
     259              {
     260                if (currentClass != null)
     261                  stack.push(currentClass);
     262                final JavaClass parentClass = currentClass;
     263                currentClass = new JavaClass(token, TAG_INTERFACE);
     264                state = CLASS_PROLOG;
     265                // Add a tag for the class itself.
     266                tags.add(new JavaTag("interface ".concat(token),
     267                                     tokenStart,TAG_INTERFACE, visibility, parentClass));
     268                visibility = 0;
     269              }
     270            else if (state == CLASS_NAME)
     271              {
     272                if (currentClass != null)
     273                  stack.push(currentClass);
     274                final JavaClass parentClass = currentClass;
     275                currentClass = new JavaClass(token, TAG_CLASS);
     276                state = CLASS_PROLOG;
     277                // Add a tag for the class itself.
     278                tags.add(new JavaTag("class ".concat(token), tokenStart,
     279                                     TAG_CLASS, visibility, parentClass));
     280                visibility = 0;
     281              }
     282            else if (state == EXTENDS)
     283              {
     284                tags.add(new JavaTag(token, tokenStart, TAG_EXTENDS,
     285                                     visibility, currentClass));
     286                state = CLASS_PROLOG;
     287              }
     288            else if (state == IMPLEMENTS)
     289              tags.add(new JavaTag(token, tokenStart, TAG_IMPLEMENTS,
     290                                   visibility, currentClass));
     291            else if (token.equals("package") || token.equals("import"))
     292              skipSemi();
     293            else if (token.equals("interface"))
     294              state = INTERFACE_NAME;
     295            else if (token.equals("class"))
     296              state = CLASS_NAME;
     297            else if (token.equals("static"))
     298              state = STATIC_INITIALIZER;
     299            else if (token.equals("new"))
     300              // Don't be confused by lines like "Runnable r = new Runnable() { ... };"
     301              state = NEW;
     302            else if (token.equals("public"))
     303              visibility |= TAG_PUBLIC;
     304            else if (token.equals("protected"))
     305              visibility |= TAG_PROTECTED;
     306            else if (token.equals("private"))
     307              visibility |= TAG_PRIVATE;
     308            continue;
     309          }
     310        if (c == '(')
     311          {
     312            skipParen();
     313            state = METHOD_NAME;
     314            continue;
     315          }
     316        if (c == '=')
     317          {
     318            addTag(TAG_FIELD);
     319            state = FIELD_INITIALIZER;
     320            pos.next();
     321            continue;
     322          }
     323        // "int x, y;"
     324        if (c == ';' || c == ',')
     325          {
     326            if (token != null)
     327              addTag(TAG_FIELD);
     328            // Don't reset the visibility until we see the semicolon.
     329            if (c == ';')
     330              visibility = 0;
     331          }
     332        pos.next();
     333      }
     334    buffer.setTags(tags);
     335  }
     336
     337  private void addTag(int type)
     338  {
     339    if (currentClass != null)
     340      {
     341        FastStringBuffer sb = new FastStringBuffer(currentClass.getName());
     342        sb.append('.');
     343        sb.append(token);
     344        tags.add(new JavaTag(sb.toString(), tokenStart, type, visibility, currentClass));
     345      }
     346    else
     347      tags.add(new JavaTag(token, tokenStart, type, visibility));
     348  }
     349
     350  protected static final void skipComment(Position pos)
     351  {
     352    while (true)
     353      {
     354        if (pos.lookingAt("*/"))
     355          {
     356            pos.skip(2);
     357            return;
     358          }
     359        if (!pos.next())
     360          return;
     361      }
     362  }
     363
     364  protected final void skipSingleLineComment(Position pos)
     365  {
     366    checkForExplicitTag(pos);
     367    Line next = pos.getNextLine();
     368    if (next != null)
     369      pos.moveTo(next, 0);
     370    else
     371      pos.setOffset(pos.getLineLength());
     372  }
     373
     374  private final void checkForExplicitTag(Position pos)
     375  {
     376    if (tags == null)
     377      return; // Only supported for Java and JavaScript for now.
     378    final String explicitTag =
     379      Editor.preferences().getStringProperty(Property.EXPLICIT_TAG);
     380    if (explicitTag != null && explicitTag.length() > 0)
     381      {
     382        pos = pos.copy();
     383        String s = pos.getString(); // Substring to end of line.
     384        int index = s.indexOf(explicitTag);
     385        if (index >= 0)
     386          {
     387            pos.skip(index + explicitTag.length());
     388            pos.skipWhitespace();
     389            // Now we're looking at the first character of the tag.
     390            FastStringBuffer sb = new FastStringBuffer();
     391            char c = pos.getChar();
     392            if (c == '"')
     393              {
     394                while (pos.next())
     395                  {
     396                    c = pos.getChar();
     397                    if (c == '"')
     398                      break;
     399                    sb.append(c);
     400                  }
     401              }
     402            else
     403              {
     404                // By default, explicit tags are whitespace-delimited, so
     405                // they can contain characters that are not legal in Java
     406                // identifiers ("symbol-value").
     407                sb.append(c);
     408                while (pos.next())
     409                  {
     410                    c = pos.getChar();
     411                    if (Character.isWhitespace(c))
     412                      break;
     413                    sb.append(c);
     414                  }
     415              }
     416            final String tag = sb.toString();
     417            // Exact location of tag is beginning of text on line
     418            // containing tag.
     419            pos.setOffset(0);
     420            pos.skipWhitespace();
     421            tags.add(new JavaTag(tag, pos, TAG_EXPLICIT, 0, currentClass));
     422          }
     423      }
     424  }
     425
     426  // If canonical is true, strings like "java.lang.String" are considered to
     427  // be a single token. Used for "extends" and "implements" clauses.
     428  private void gatherToken(boolean canonical)
     429  {
     430    tokenStart = new Position(pos);
     431    FastStringBuffer sb = new FastStringBuffer();
     432    char c;
     433    if (canonical)
     434      {
     435        while (Character.isJavaIdentifierPart(c = pos.getChar()) || c == '.')
     436          {
     437            sb.append(c);
    308438            if (!pos.next())
    309                 return;
    310         }
    311     }
    312 
    313     protected final void skipSingleLineComment(Position pos)
    314     {
    315         checkForExplicitTag(pos);
    316         Line next = pos.getNextLine();
    317         if (next != null)
    318             pos.moveTo(next, 0);
     439              break;
     440          }
     441      }
     442    else
     443      {
     444        while (Character.isJavaIdentifierPart(c = pos.getChar()))
     445          {
     446            sb.append(c);
     447            if (!pos.next())
     448              break;
     449          }
     450      }
     451    token = sb.toString();
     452  }
     453
     454  protected void skipParen()
     455  {
     456    if (pos.next())
     457      {
     458        int count = 1;
     459        while (true)
     460          {
     461            if (pos.lookingAt("/*"))
     462              {
     463                skipComment(pos);
     464                continue;
     465              }
     466            if (pos.lookingAt("//"))
     467              {
     468                skipSingleLineComment(pos);
     469                continue;
     470              }
     471            char c = pos.getChar();
     472            if (c == '"' || c == '\'')
     473              {
     474                pos.skipQuote();
     475                continue;
     476              }
     477            if (c == '(')
     478              ++count;
     479            else if (c == ')')
     480              --count;
     481            if (!pos.next())
     482              break;
     483            if (count == 0)
     484              break;
     485          }
     486      }
     487  }
     488
     489  protected void skipBrace()
     490  {
     491    if (pos.next())
     492      {
     493        int count = 1;
     494        while (true)
     495          {
     496            if (pos.lookingAt("/*"))
     497              {
     498                skipComment(pos);
     499                continue;
     500              }
     501            if (pos.lookingAt("//"))
     502              {
     503                skipSingleLineComment(pos);
     504                continue;
     505              }
     506            char c = pos.getChar();
     507            if (c == '"' || c == '\'')
     508              {
     509                pos.skipQuote();
     510                continue;
     511              }
     512            if (c == '\\')
     513              {
     514                // Escape. Ignore this char and the next.
     515                if (!pos.next())
     516                  break;
     517                if (!pos.next())
     518                  break;
     519                continue;
     520              }
     521            if (c == '{')
     522              ++count;
     523            else if (c == '}')
     524              --count;
     525            if (!pos.next())
     526              break;
     527            if (count == 0)
     528              break;
     529          }
     530      }
     531  }
     532
     533  private void skipSemi()
     534  {
     535    while (!pos.atEnd())
     536      {
     537        if (pos.lookingAt("/*"))
     538          {
     539            skipComment(pos);
     540            continue;
     541          }
     542        if (pos.lookingAt("//"))
     543          {
     544            skipSingleLineComment(pos);
     545            continue;
     546          }
     547        char c = pos.getChar();
     548        if (c == '"' || c == '\'')
     549          {
     550            pos.skipQuote();
     551            continue;
     552          }
     553        else if (c == ';')
     554          {
     555            pos.next();
     556            break;
     557          }
    319558        else
    320             pos.setOffset(pos.getLineLength());
    321     }
    322 
    323     private final void checkForExplicitTag(Position pos)
    324     {
    325         if (tags == null)
    326             return; // Only supported for Java and JavaScript for now.
    327         final String explicitTag =
    328             Editor.preferences().getStringProperty(Property.EXPLICIT_TAG);
    329         if (explicitTag != null && explicitTag.length() > 0) {
    330             pos = pos.copy();
    331             String s = pos.getString(); // Substring to end of line.
    332             int index = s.indexOf(explicitTag);
    333             if (index >= 0) {
    334                 pos.skip(index + explicitTag.length());
    335                 pos.skipWhitespace();
    336                 // Now we're looking at the first character of the tag.
    337                 FastStringBuffer sb = new FastStringBuffer();
    338                 char c = pos.getChar();
    339                 if (c == '"') {
    340                     while (pos.next()) {
    341                         c = pos.getChar();
    342                         if (c == '"')
    343                             break;
    344                         sb.append(c);
    345                     }
    346                 } else {
    347                     // By default, explicit tags are whitespace-delimited, so
    348                     // they can contain characters that are not legal in Java
    349                     // identifiers ("symbol-value").
    350                     sb.append(c);
    351                     while (pos.next()) {
    352                         c = pos.getChar();
    353                         if (Character.isWhitespace(c))
    354                             break;
    355                         sb.append(c);
    356                     }
    357                 }
    358                 final String tag = sb.toString();
    359                 // Exact location of tag is beginning of text on line
    360                 // containing tag.
    361                 pos.setOffset(0);
    362                 pos.skipWhitespace();
    363                 tags.add(new JavaTag(tag, pos, TAG_EXPLICIT, 0, currentClass));
    364             }
    365         }
    366     }
    367 
    368     // If canonical is true, strings like "java.lang.String" are considered to
    369     // be a single token. Used for "extends" and "implements" clauses.
    370     private void gatherToken(boolean canonical)
    371     {
    372         tokenStart = new Position(pos);
    373         FastStringBuffer sb = new FastStringBuffer();
    374         char c;
    375         if (canonical) {
    376             while (Character.isJavaIdentifierPart(c = pos.getChar()) || c == '.') {
    377                 sb.append(c);
    378                 if (!pos.next())
    379                     break;
    380             }
    381         } else {
    382             while (Character.isJavaIdentifierPart(c = pos.getChar())) {
    383                 sb.append(c);
    384                 if (!pos.next())
    385                     break;
    386             }
    387         }
    388         token = sb.toString();
    389     }
    390 
    391     protected void skipParen()
    392     {
    393         if (pos.next()) {
    394             int count = 1;
    395             while (true) {
    396                 if (pos.lookingAt("/*")) {
    397                     skipComment(pos);
    398                     continue;
    399                 }
    400                 if (pos.lookingAt("//")) {
    401                     skipSingleLineComment(pos);
    402                     continue;
    403                 }
    404                 char c = pos.getChar();
    405                 if (c == '"' || c == '\'') {
    406                     pos.skipQuote();
    407                     continue;
    408                 }
    409                 if (c == '(')
    410                     ++count;
    411                 else if (c == ')')
    412                     --count;
    413                 if (!pos.next())
    414                     break;
    415                 if (count == 0)
    416                     break;
    417             }
    418         }
    419     }
    420 
    421     protected void skipBrace()
    422     {
    423         if (pos.next()) {
    424             int count = 1;
    425             while (true) {
    426                 if (pos.lookingAt("/*")) {
    427                     skipComment(pos);
    428                     continue;
    429                 }
    430                 if (pos.lookingAt("//")) {
    431                     skipSingleLineComment(pos);
    432                     continue;
    433                 }
    434                 char c = pos.getChar();
    435                 if (c == '"' || c == '\'') {
    436                     pos.skipQuote();
    437                     continue;
    438                 }
    439                 if (c == '\\') {
    440                     // Escape. Ignore this char and the next.
    441                     if (!pos.next())
    442                         break;
    443                     if (!pos.next())
    444                         break;
    445                     continue;
    446                 }
    447                 if (c == '{')
    448                     ++count;
    449                 else if (c == '}')
    450                     --count;
    451                 if (!pos.next())
    452                     break;
    453                 if (count == 0)
    454                     break;
    455             }
    456         }
    457     }
    458 
    459     private void skipSemi()
    460     {
    461         while (!pos.atEnd()) {
    462             if (pos.lookingAt("/*")) {
    463                 skipComment(pos);
    464                 continue;
    465             }
    466             if (pos.lookingAt("//")) {
    467                 skipSingleLineComment(pos);
    468                 continue;
    469             }
    470             char c = pos.getChar();
    471             if (c == '"' || c == '\'') {
    472                 pos.skipQuote();
    473                 continue;
    474             } else if (c == ';') {
    475                 pos.next();
    476                 break;
    477             } else
    478                 pos.next();
    479         }
    480     }
    481 
    482     // Used by the C, C++ and Objective C taggers.
    483     protected static final void skipPreprocessor(Position pos)
    484     {
    485         while (true) {
    486             Line line = pos.getLine();
    487             Line nextLine = line.next();
    488             if (nextLine == null) {
    489                 pos.setOffset(line.length());
    490                 return;
    491             }
    492             pos.moveTo(nextLine, 0);
    493             if (line.length() == 0 || line.charAt(line.length()-1) != '\\')
    494                 return;
    495         }
    496     }
     559          pos.next();
     560      }
     561  }
     562
     563  // Used by the C, C++ and Objective C taggers.
     564  protected static final void skipPreprocessor(Position pos)
     565  {
     566    while (true)
     567      {
     568        Line line = pos.getLine();
     569        Line nextLine = line.next();
     570        if (nextLine == null)
     571          {
     572            pos.setOffset(line.length());
     573            return;
     574          }
     575        pos.moveTo(nextLine, 0);
     576        if (line.length() == 0 || line.charAt(line.length()-1) != '\\')
     577          return;
     578      }
     579  }
    497580}
Note: See TracChangeset for help on using the changeset viewer.