KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > rename > RefactoringScanner


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.rename;
12
13 import java.util.HashSet JavaDoc;
14 import java.util.Set JavaDoc;
15
16 import org.eclipse.core.runtime.Assert;
17
18 import org.eclipse.jdt.core.ICompilationUnit;
19 import org.eclipse.jdt.core.JavaModelException;
20 import org.eclipse.jdt.core.ToolFactory;
21 import org.eclipse.jdt.core.compiler.IScanner;
22 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
23 import org.eclipse.jdt.core.compiler.InvalidInputException;
24
25
26 public class RefactoringScanner {
27     
28     private static int NO_MATCH= 0;
29     private static int MATCH_QUALIFIED= 1;
30     private static int MATCH_UNQUALIFIED= 2;
31
32     public static class TextMatch {
33
34         private int fStartPosition;
35         private boolean fQualified;
36
37         private TextMatch(int startPosition, boolean qualified) {
38             fStartPosition= startPosition;
39             fQualified= qualified;
40         }
41
42         /**
43          * @return the offset where the unqualified name starts
44          */

45         public int getStartPosition() {
46             return fStartPosition;
47         }
48
49         public boolean isQualified() {
50             return fQualified;
51         }
52     }
53
54     private final String JavaDoc fName;
55     private final String JavaDoc fQualifier;
56     
57     private IScanner fScanner;
58     private Set JavaDoc fMatches; //Set<TextMatch>
59

60     
61     public RefactoringScanner(String JavaDoc name, String JavaDoc qualifier) {
62         Assert.isNotNull(name);
63         Assert.isNotNull(qualifier);
64         fName= name;
65         fQualifier= qualifier;
66     }
67     
68     public void scan(ICompilationUnit cu) throws JavaModelException {
69         char[] chars= cu.getBuffer().getCharacters();
70         fMatches= new HashSet JavaDoc();
71         fScanner= ToolFactory.createScanner(true, true, false, true);
72         fScanner.setSource(chars);
73
74 // IImportContainer importContainer= cu.getImportContainer();
75
// if (importContainer.exists())
76
// fNoFlyZone= importContainer.getSourceRange();
77
// else
78
// fNoFlyZone= null;
79

80         doScan();
81         fScanner= null;
82     }
83
84     /** only for testing */
85     public void scan(String JavaDoc text) {
86         char[] chars= text.toCharArray();
87         fMatches= new HashSet JavaDoc();
88         fScanner= ToolFactory.createScanner(true, true, false, true);
89         fScanner.setSource(chars);
90         doScan();
91         fScanner= null;
92     }
93
94     private void doScan() {
95         try{
96             int token = fScanner.getNextToken();
97             while (token != ITerminalSymbols.TokenNameEOF) {
98                 switch (token) {
99                     case ITerminalSymbols.TokenNameStringLiteral :
100                     case ITerminalSymbols.TokenNameCOMMENT_JAVADOC :
101                     case ITerminalSymbols.TokenNameCOMMENT_LINE :
102                     case ITerminalSymbols.TokenNameCOMMENT_BLOCK :
103                         parseCurrentToken();
104                 }
105                 token = fScanner.getNextToken();
106             }
107         } catch (InvalidInputException e){
108             //ignore
109
}
110     }
111
112     private static boolean isWholeWord(String JavaDoc value, int from, int to){
113         if (from > 0) {
114             char ch= value.charAt(from - 1);
115             if (Character.isLetterOrDigit(ch) || ch == '_') {
116                 return false;
117             }
118         }
119         if (to < value.length()) {
120             char ch= value.charAt(to);
121             if (Character.isLetterOrDigit(ch) || ch == '_' ) {
122                 return false;
123             }
124         }
125         return true;
126     }
127     
128     private void parseCurrentToken() {
129         // only works for references without whitespace
130
String JavaDoc value = new String JavaDoc(fScanner.getRawTokenSource());
131         int start= fScanner.getCurrentTokenStartPosition();
132         int index= value.indexOf(fName);
133         while (index != -1) {
134             if (isWholeWord(value, index, index + fName.length())) {
135                 int ok= isQualifierOK(value, index);
136                 if (ok > NO_MATCH)
137                     addMatch(start + index, ok);
138             }
139             index= value.indexOf(fName, index + 1);
140         }
141     }
142
143     private int isQualifierOK(String JavaDoc value, int nameStart) {
144         // only works for references without whitespace
145
int qualifierAfter= nameStart - 1;
146         if (qualifierAfter < 0)
147             // there is absolutely nothing before the name itself in the string
148
return MATCH_UNQUALIFIED;
149         
150         char charBeforeName= value.charAt(qualifierAfter);
151         if (! isQualifierSeparator(charBeforeName))
152             // the char before the name is not a # or . - should not get here anyway
153
return MATCH_UNQUALIFIED; // NO_MATCH ?
154

155         boolean canFinish= charBeforeName == '#';
156         // work through the qualifier from back to front
157
for (int i= 0; i < fQualifier.length() ; i++) {
158             int qualifierCharPos= qualifierAfter - 1 - i;
159             if (qualifierCharPos < 0)
160                 // the position does not exist, return OK if last read char was a non-separator
161
return canFinish ? MATCH_UNQUALIFIED : NO_MATCH;
162             
163             char qualifierChar= value.charAt(qualifierCharPos);
164             char goalQualifierChar= fQualifier.charAt(fQualifier.length() - 1 - i);
165             if (qualifierChar != goalQualifierChar)
166                 // the chars do not match. return OK if last read char was a non-separator and the current one a non-qualifier
167
return (canFinish && !isQualifierPart(qualifierChar)) ? MATCH_UNQUALIFIED : NO_MATCH;
168             
169             canFinish= ! isQualifierSeparator(qualifierChar);
170         }
171         int beforeQualifierPos= qualifierAfter - fQualifier.length() - 1;
172         if (beforeQualifierPos >= 0) {
173             char beforeQualifierChar= value.charAt(beforeQualifierPos);
174             if (Character.isJavaIdentifierPart(beforeQualifierChar)) {
175                 return NO_MATCH;
176             }
177             if (isQualifierSeparator(beforeQualifierChar)) {
178                 if (beforeQualifierPos > 0) {
179                     /*
180                      * https://bugs.eclipse.org/bugs/show_bug.cgi?id=142508 :
181                      * If the character before the qualifier separator is not
182                      * an identifier part, then accept the match.
183                      */

184                     char precedingOne= value.charAt(beforeQualifierPos - 1);
185                     if (Character.isJavaIdentifierPart(precedingOne)) {
186                         return NO_MATCH;
187                     }
188                 }
189             }
190             return MATCH_QUALIFIED;
191             
192         }
193         return MATCH_QUALIFIED;
194     }
195
196     private boolean isQualifierPart(char ch) {
197         return Character.isJavaIdentifierPart(ch) || isQualifierSeparator(ch);
198     }
199
200     private boolean isQualifierSeparator(char c) {
201         return ".#".indexOf(c) != -1; //$NON-NLS-1$
202
}
203
204     private void addMatch(int matchStart, int matchCode) {
205         fMatches.add(new TextMatch(matchStart, matchCode == MATCH_QUALIFIED));
206     }
207
208     /**
209      * @return Set of TextMatch
210      */

211     public Set JavaDoc getMatches() {
212         return fMatches;
213     }
214 }
215
216
Popular Tags