KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > CorrectionEngine


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.core;
12
13 import java.util.Hashtable JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.core.resources.*;
17 import org.eclipse.jdt.core.compiler.*;
18 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
19 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
20 import org.eclipse.jdt.internal.compiler.parser.*;
21 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
22 import org.eclipse.jdt.internal.core.util.Messages;
23 import org.eclipse.jdt.internal.core.util.Util;
24
25 /**
26  * This class is the entry point for source corrections.
27  *
28  * This class is not intended to be subclassed by clients. This class is intended to be instantiated by clients.
29  *
30  * @since 2.0
31  */

32 public class CorrectionEngine implements ProblemReasons {
33     
34     /**
35      * This field is not intended to be used by client.
36      */

37     protected int correctionStart;
38     /**
39      * This field is not intended to be used by client.
40      */

41     protected int correctionEnd;
42     /**
43      * This field is not intended to be used by client.
44      */

45     protected int prefixLength;
46     /**
47      * This field is not intended to be used by client.
48      */

49     protected ICompilationUnit compilationUnit;
50     /**
51      * This field is not intended to be used by client.
52      */

53     protected ICorrectionRequestor correctionRequestor;
54     /**
55      * This field is not intended to be used by client.
56      */

57     protected static final int CLASSES = 0x00000001;
58     /**
59      * This field is not intended to be used by client.
60      */

61     protected static final int INTERFACES = 0x00000002;
62     /**
63      * This field is not intended to be used by client.
64      */

65     protected static final int IMPORT = 0x00000004;
66     /**
67      * This field is not intended to be used by client.
68      */

69     protected static final int METHOD = 0x00000008;
70     /**
71      * This field is not intended to be used by client.
72      */

73     protected static final int FIELD = 0x00000010;
74     /**
75      * This field is not intended to be used by client.
76      */

77     protected static final int LOCAL = 0x00000020;
78     /**
79      * This field is not intended to be used by client.
80      */

81     protected int filter;
82         
83     /**
84      * The CorrectionEngine is responsible for computing problem corrections.
85      *
86      * @param setting java.util.Map
87      * set of options used to configure the code correction engine.
88      * CURRENTLY THERE IS NO CORRECTION SPECIFIC SETTINGS.
89      */

90     public CorrectionEngine(Map JavaDoc setting) {
91         // settings ignored for now
92
}
93     
94     /**
95      * Performs code correction for the given marker,
96      * reporting results to the given correction requestor.
97      *
98      * Correction results are answered through a requestor.
99      *
100      * @param marker
101      * the marker which describe the problem to correct.
102      * @param targetUnit
103      * replace the compilation unit given by the marker. Ignored if null.
104      * @param positionOffset
105      * the offset of position given by the marker.
106      * @param requestor
107      * the given correction requestor
108      * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
109      * @exception JavaModelException currently this exception is never thrown, but the opportunity to thrown an exception
110      * when the correction failed is kept for later.
111      * @since 2.0
112      */

113     public void computeCorrections(IMarker marker, ICompilationUnit targetUnit, int positionOffset, ICorrectionRequestor requestor) throws JavaModelException {
114         
115         IJavaElement element = targetUnit == null ? JavaCore.create(marker.getResource()) : targetUnit;
116         
117         if(!(element instanceof ICompilationUnit))
118             return;
119             
120         ICompilationUnit unit = (ICompilationUnit) element;
121         
122         int id = marker.getAttribute(IJavaModelMarker.ID, -1);
123         String JavaDoc[] args = Util.getProblemArgumentsFromMarker(marker.getAttribute(IJavaModelMarker.ARGUMENTS, "")); //$NON-NLS-1$
124
int start = marker.getAttribute(IMarker.CHAR_START, -1);
125         int end = marker.getAttribute(IMarker.CHAR_END, -1);
126         
127         computeCorrections(unit, id, start + positionOffset, end + positionOffset, args, requestor);
128     }
129     
130     /**
131      * Performs code correction for the given IProblem,
132      * reporting results to the given correction requestor.
133      *
134      * Correction results are answered through a requestor.
135      *
136      * @param problem
137      * the problem which describe the problem to correct.
138      * @param targetUnit
139      * denote the compilation unit in which correction occurs. Cannot be null.
140      * @param requestor
141      * the given correction requestor
142      * @exception IllegalArgumentException if <code>targetUnit</code> or <code>requestor</code> is <code>null</code>
143      * @exception JavaModelException currently this exception is never thrown, but the opportunity to thrown an exception
144      * when the correction failed is kept for later.
145      * @since 2.0
146      */

147     public void computeCorrections(IProblem problem, ICompilationUnit targetUnit, ICorrectionRequestor requestor) throws JavaModelException {
148         if (requestor == null) {
149             throw new IllegalArgumentException JavaDoc(Messages.correction_nullUnit);
150         }
151         this.computeCorrections(
152             targetUnit, problem.getID(),
153             problem.getSourceStart(),
154             problem.getSourceEnd(),
155             problem.getArguments(),
156             requestor);
157     }
158
159     /*
160      * Ask the engine to compute a correction for the specified problem
161      * of the given compilation unit.
162      * Correction results are answered through a requestor.
163      *
164      * @param unit org.eclipse.jdt.internal.core.ICompilationUnit
165      * the compilation unit.
166      *
167      * @param id int
168      * the id of the problem.
169      *
170      * @param start int
171      * a position in the source where the error begin.
172      *
173      * @param end int
174      * a position in the source where the error finish.
175      *
176      * @param arguments String[]
177      * arguments of the problem.
178      *
179      * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
180      * @exception JavaModelException currently this exception is never thrown, but the opportunity to thrown an exception
181      * when the correction failed is kept for later.
182      * @since 2.0
183      */

184     private void computeCorrections(ICompilationUnit unit, int id, int start, int end, String JavaDoc[] arguments, ICorrectionRequestor requestor) {
185
186         if(id == -1 || arguments == null || start == -1 || end == -1)
187             return;
188         if (requestor == null) {
189             throw new IllegalArgumentException JavaDoc(Messages.correction_nullRequestor);
190         }
191         
192         this.correctionRequestor = requestor;
193         this.correctionStart = start;
194         this.correctionEnd = end;
195         this.compilationUnit = unit;
196         
197         String JavaDoc argument = null;
198         try {
199             switch (id) {
200                 // Type correction
201
case IProblem.ImportNotFound :
202                     this.filter = IMPORT;
203                     argument = arguments[0];
204                     break;
205                 case IProblem.UndefinedType :
206                     this.filter = CLASSES | INTERFACES;
207                     argument = arguments[0];
208                     break;
209                     
210                 // Method correction
211
case IProblem.UndefinedMethod :
212                     this.filter = METHOD;
213                     argument = arguments[1];
214                     break;
215                     
216                 // Field and local variable correction
217
case IProblem.UndefinedField :
218                     this.filter = FIELD;
219                     argument = arguments[0];
220                     break;
221                 case IProblem.UndefinedName :
222                     this.filter = FIELD | LOCAL;
223                     argument = arguments[0];
224                     break;
225             }
226         } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
227             return;
228         }
229         if(argument != null) {
230             correct(argument.toCharArray());
231         }
232     }
233
234     private void correct(char[] argument) {
235         try {
236             String JavaDoc source = this.compilationUnit.getSource();
237             Scanner scanner = new Scanner();
238             scanner.setSource(source.toCharArray());
239             
240             scanner.resetTo(this.correctionStart, this.correctionEnd);
241             int token = 0;
242             char[] argumentSource = CharOperation.NO_CHAR;
243             
244             // search last segment position
245
while(true) {
246                 token = scanner.getNextToken();
247                 if (token == TerminalTokens.TokenNameEOF) return;
248                 
249                 char[] tokenSource = scanner.getCurrentTokenSource();
250                 
251                 argumentSource = CharOperation.concat(argumentSource, tokenSource);
252                 if(!CharOperation.prefixEquals(argumentSource, argument))
253                     return;
254                 
255                 if(CharOperation.equals(argument, argumentSource)) {
256                     this.correctionStart = scanner.startPosition;
257                     this.correctionEnd = scanner.currentPosition;
258                     this.prefixLength = CharOperation.lastIndexOf('.', argument) + 1;
259                     break;
260                 }
261                 
262             }
263         
264             // search completion position
265
int completionPosition = this.correctionStart;
266             scanner.resetTo(completionPosition, this.correctionEnd);
267             int position = completionPosition;
268             
269             for (int i = 0; i < 4; i++) {
270                 if(scanner.getNextCharAsJavaIdentifierPart()) {
271                     completionPosition = position;
272                     position = scanner.currentPosition;
273                 } else {
274                     break;
275                 }
276             }
277             Hashtable JavaDoc oldOptions = JavaCore.getOptions();
278             try {
279                 Hashtable JavaDoc options = new Hashtable JavaDoc(oldOptions);
280                 options.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.DISABLED);
281                 JavaCore.setOptions(options);
282                 
283                 this.compilationUnit.codeComplete(
284                     completionPosition,
285                     this.completionRequestor
286                 );
287             } finally {
288                 JavaCore.setOptions(oldOptions);
289             }
290         } catch (JavaModelException e) {
291             return;
292         } catch (InvalidInputException e) {
293             return;
294         }
295     }
296
297     /**
298      * This field is not intended to be used by client.
299      */

300     protected CompletionRequestor completionRequestor = new CompletionRequestor() {
301         public void accept(CompletionProposal proposal) {
302             switch (proposal.getKind()) {
303                 case CompletionProposal.TYPE_REF:
304                     int flags = proposal.getFlags();
305                     if (!(Flags.isEnum(flags) || Flags.isAnnotation(flags))) {
306                         if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
307                             char[] completionName = proposal.getCompletion();
308                             CorrectionEngine.this.correctionRequestor.acceptClass(
309                                 proposal.getDeclarationSignature(),
310                                 Signature.getSignatureSimpleName(proposal.getSignature()),
311                                 CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
312                                 proposal.getFlags(),
313                                 CorrectionEngine.this.correctionStart,
314                                 CorrectionEngine.this.correctionEnd);
315                         } else if((CorrectionEngine.this.filter & IMPORT) != 0) {
316                             char[] packageName = proposal.getDeclarationSignature();
317                             char[] className = Signature.getSignatureSimpleName(proposal.getSignature());
318                             char[] fullName = CharOperation.concat(packageName, className, '.');
319                             CorrectionEngine.this.correctionRequestor.acceptClass(
320                                 packageName,
321                                 className,
322                                 CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
323                                 proposal.getFlags(),
324                                 CorrectionEngine.this.correctionStart,
325                                 CorrectionEngine.this.correctionEnd);
326                         }
327                     }
328                     break;
329                 case CompletionProposal.FIELD_REF:
330                     if((CorrectionEngine.this.filter & FIELD) != 0) {
331                         char[] declaringSignature = proposal.getDeclarationSignature();
332                         char[] signature = proposal.getSignature();
333                         CorrectionEngine.this.correctionRequestor.acceptField(
334                             Signature.getSignatureQualifier(declaringSignature),
335                             Signature.getSignatureSimpleName(declaringSignature),
336                             proposal.getName(),
337                             Signature.getSignatureQualifier(signature),
338                             Signature.getSignatureSimpleName(signature),
339                             proposal.getName(),
340                             proposal.getFlags(),
341                             CorrectionEngine.this.correctionStart,
342                             CorrectionEngine.this.correctionEnd);
343                     }
344                     break;
345                 case CompletionProposal.LOCAL_VARIABLE_REF:
346                     if((CorrectionEngine.this.filter & LOCAL) != 0) {
347                         char[] signature = proposal.getSignature();
348                         CorrectionEngine.this.correctionRequestor.acceptLocalVariable(
349                             proposal.getName(),
350                             Signature.getSignatureQualifier(signature),
351                             Signature.getSignatureSimpleName(signature),
352                             proposal.getFlags(),
353                             CorrectionEngine.this.correctionStart,
354                             CorrectionEngine.this.correctionEnd);
355                     }
356                     break;
357                 case CompletionProposal.METHOD_REF:
358                     if((CorrectionEngine.this.filter & METHOD) != 0) {
359                         char[] declaringSignature = proposal.getDeclarationSignature();
360                         char[] signature = proposal.getSignature();
361                         char[][] parameterTypeSignatures = Signature.getParameterTypes(signature);
362                         int length = parameterTypeSignatures.length;
363                         char[][] parameterPackageNames = new char[length][];
364                         char[][] parameterTypeNames = new char[length][];
365                         for (int i = 0; i < length; i++) {
366                             parameterPackageNames[i] = Signature.getSignatureQualifier(parameterTypeSignatures[i]);
367                             parameterTypeNames[i] = Signature.getSignatureSimpleName(parameterTypeSignatures[i]);
368                         }
369                         char[] returnTypeSignature = Signature.getReturnType(signature);
370                         CorrectionEngine.this.correctionRequestor.acceptMethod(
371                             Signature.getSignatureQualifier(declaringSignature),
372                             Signature.getSignatureSimpleName(declaringSignature),
373                             proposal.getName(),
374                             parameterPackageNames,
375                             parameterTypeNames,
376                             proposal.findParameterNames(null),
377                             Signature.getSignatureQualifier(returnTypeSignature),
378                             Signature.getSignatureSimpleName(returnTypeSignature),
379                             proposal.getName(),
380                             proposal.getFlags(),
381                             CorrectionEngine.this.correctionStart,
382                             CorrectionEngine.this.correctionEnd);
383                     }
384                     break;
385                 case CompletionProposal.PACKAGE_REF:
386                     if((CorrectionEngine.this.filter & (CLASSES | INTERFACES | IMPORT)) != 0) {
387                         char[] packageName = proposal.getDeclarationSignature();
388                         CorrectionEngine.this.correctionRequestor.acceptPackage(
389                             packageName,
390                             CharOperation.subarray(packageName, CorrectionEngine.this.prefixLength, packageName.length),
391                             CorrectionEngine.this.correctionStart,
392                             CorrectionEngine.this.correctionEnd);
393                     }
394                     break;
395             }
396         }
397     };
398
399     
400     /**
401      * Return an array of strings which contains one entry per warning token
402      * accepted by the <code>@SuppressWarnings</code> annotation. This array is
403      * neither null nor empty, it contains at least the String <code>all</code>.
404      * It should not be modified by the caller (please take a copy if modifications
405      * are needed).<br>
406      * <b>Note:</b> The tokens returned are not necessarily standardized across Java
407      * compilers. If you were to use one of these tokens in a <code>@SuppressWarnings</code>
408      * annotation in the Java source code, the effects (if any) may vary from
409      * compiler to compiler.
410      *
411      * @return an array of strings which contains one entry per warning token
412      * accepted by the <code>@SuppressWarnings</code> annotation.
413      * @since 3.2
414      */

415     public static String JavaDoc[] getAllWarningTokens() {
416         return CompilerOptions.warningTokens;
417     }
418     
419     /**
420      * Helper method for decoding problem marker attributes. Returns an array of String arguments
421      * extracted from the problem marker "arguments" attribute, or <code>null</code> if the marker
422      * "arguments" attribute is missing or ill-formed.
423      *
424      * @param problemMarker
425      * the problem marker to decode arguments from.
426      * @return an array of String arguments, or <code>null</code> if unable to extract arguments
427      * @since 2.1
428      */

429     public static String JavaDoc[] getProblemArguments(IMarker problemMarker){
430         String JavaDoc argumentsString = problemMarker.getAttribute(IJavaModelMarker.ARGUMENTS, null);
431         return Util.getProblemArgumentsFromMarker(argumentsString);
432     }
433     
434     /**
435      * Returns a token which can be used to suppress a given warning using
436      * <code>@SuppressWarnings</code> annotation, for a given problem ID
437      * ({@link IProblem }). If a particular problem is not suppressable,
438      * <code>null</code> will be returned.
439      * <p>
440      * <b>Note:</b> <code>@SuppressWarnings</code> can only suppress warnings,
441      * which means that if some problems got promoted to ERROR using custom compiler
442      * settings ({@link IJavaProject#setOption(String, String)}), the
443      * <code>@SuppressWarnings</code> annotation will be ineffective.
444      * </p>
445      * <p>
446      * <b>Note:</b> <code>@SuppressWarnings</code> can be argumented with
447      * <code>"all"</code> so as to suppress all possible warnings at once.
448      * </p>
449      * <p>
450      * <b>Note:</b> The tokens returned are not necessarily standardized across Java
451      * compilers. If you were to use one of these tokens in an @SuppressWarnings
452      * annotation in the Java source code, the effects (if any) may vary from
453      * compiler to compiler.
454      * </p>
455      * @param problemID
456      * the ID of a given warning to suppress
457      * @return a String which can be used in <code>@SuppressWarnings</code> annotation,
458      * or <code>null</code> if unable to suppress this warning.
459      * @since 3.1
460      */

461     public static String JavaDoc getWarningToken(int problemID){
462         long irritant = ProblemReporter.getIrritant(problemID);
463         if (irritant != 0) {
464             return CompilerOptions.warningTokenFromIrritant(irritant);
465         }
466         return null;
467     }
468 }
469
Popular Tags