package org.eclipse.jdt.core; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import java.util.Map; | |
import org.eclipse.core.resources.*; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.jdt.core.compiler.*; | |
import org.eclipse.jdt.core.compiler.InvalidInputException; | |
import org.eclipse.jdt.core.compiler.IProblem; | |
import org.eclipse.jdt.internal.compiler.*; | |
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; | |
import org.eclipse.jdt.internal.compiler.parser.*; | |
import org.eclipse.jdt.internal.compiler.util.CharOperation; | |
import org.eclipse.jdt.internal.core.*; | |
/** | |
* This class is the entry point for source corrections. | |
* | |
* @since 2.0 | |
*/ | |
public class CorrectionEngine implements ProblemReasons { | |
protected int correctionStart; | |
protected int correctionEnd; | |
protected int prefixLength; | |
protected ICompilationUnit unit; | |
protected ICorrectionRequestor requestor; | |
protected static final int CLASSES = 0x00000001; | |
protected static final int INTERFACES = 0x00000002; | |
protected static final int IMPORT = 0x00000004; | |
protected static final int METHOD = 0x00000008; | |
protected static final int FIELD = 0x00000010; | |
protected static final int LOCAL = 0x00000020; | |
protected int filter; | |
/** | |
* The CorrectionEngine is responsible for computing problem corrections. | |
* | |
* @param setting java.util.Map | |
* set of options used to configure the code correction engine. | |
* CURRENTLY THERE IS NO CORRECTION SPECIFIC SETTINGS. | |
*/ | |
public CorrectionEngine(Map setting) { | |
} | |
/** | |
* Performs code correction for the given marker, | |
* reporting results to the given correction requestor. | |
* | |
* @return void | |
* correction results are answered through a requestor. | |
* | |
* @param marker | |
* the marker which describe the problem to correct. | |
* | |
* @param targetUnit | |
* replace the compilation unit given by the marker. Ignored if null. | |
* | |
* @param positionOffset | |
* the offset of position given by the marker. | |
* | |
* @exception IllegalArgumentException if <code>requestor</code> is <code>null</code> | |
* @since 2.0 | |
*/ | |
public void computeCorrections(IMarker marker, ICompilationUnit targetUnit, int positionOffset, ICorrectionRequestor requestor) throws JavaModelException { | |
IJavaElement element = targetUnit == null ? JavaCore.create(marker.getResource()) : targetUnit; | |
if(!(element instanceof ICompilationUnit)) | |
return; | |
ICompilationUnit unit = (ICompilationUnit) element; | |
int id = marker.getAttribute(IJavaModelMarker.ID, -1); | |
String[] args = Util.getProblemArgumentsFromMarker(marker.getAttribute(IJavaModelMarker.ARGUMENTS, "")); //$NON-NLS-1$ | |
int start = marker.getAttribute(IMarker.CHAR_START, -1); | |
int end = marker.getAttribute(IMarker.CHAR_END, -1); | |
computeCorrections(unit, id, start + positionOffset, end + positionOffset, args, requestor); | |
} | |
/** | |
* Performs code correction for the given IProblem, | |
* reporting results to the given correction requestor. | |
* | |
* @return void | |
* correction results are answered through a requestor. | |
* | |
* @param problem | |
* the problem which describe the problem to correct. | |
* | |
* @param targetUnit | |
* denote the compilation unit in which correction occurs. Cannot be null. | |
* | |
* @exception IllegalArgumentException if <code>targetUnit</code> or <code>requestor</code> is <code>null</code> | |
* @since 2.0 | |
*/ | |
public void computeCorrections(IProblem problem, ICompilationUnit targetUnit, ICorrectionRequestor requestor) throws JavaModelException { | |
if (requestor == null) { | |
throw new IllegalArgumentException(Util.bind("correction.nullUnit")); //$NON-NLS-1$ | |
} | |
this.computeCorrections( | |
targetUnit, problem.getID(), | |
problem.getSourceStart(), | |
problem.getSourceEnd(), | |
problem.getArguments(), | |
requestor); | |
} | |
/** | |
* Ask the engine to compute a correction for the specified problem | |
* of the given compilation unit. | |
* | |
* @return void | |
* correction results are answered through a requestor. | |
* | |
* @param unit org.eclipse.jdt.internal.core.ICompilationUnit | |
* the compilation unit. | |
* | |
* @param id int | |
* the id of the problem. | |
* | |
* @param start int | |
* a position in the source where the error begin. | |
* | |
* @param end int | |
* a position in the source where the error finish. | |
* | |
* @param arguments String[] | |
* arguments of the problem. | |
* | |
* @exception IllegalArgumentException if <code>requestor</code> is <code>null</code> | |
* @since 2.0 | |
*/ | |
private void computeCorrections(ICompilationUnit unit, int id, int start, int end, String[] arguments, ICorrectionRequestor requestor) throws JavaModelException{ | |
if(id == -1 || arguments == null || start == -1 || end == -1) | |
return; | |
if (requestor == null) { | |
throw new IllegalArgumentException(Util.bind("correction.nullRequestor")); //$NON-NLS-1$ | |
} | |
this.requestor = requestor; | |
this.correctionStart = start; | |
this.correctionEnd = end; | |
this.unit = unit; | |
String argument = null; | |
try { | |
switch (id) { | |
// Type correction | |
case IProblem.FieldTypeNotFound : | |
case IProblem.ArgumentTypeNotFound : | |
filter = CLASSES | INTERFACES; | |
argument = arguments[2]; | |
break; | |
case IProblem.SuperclassNotFound : | |
filter = CLASSES; | |
argument = arguments[0]; | |
break; | |
case IProblem.InterfaceNotFound : | |
filter = INTERFACES; | |
argument = arguments[0]; | |
break; | |
case IProblem.ExceptionTypeNotFound : | |
filter = CLASSES; | |
argument = arguments[1]; | |
break; | |
case IProblem.ReturnTypeNotFound : | |
filter = CLASSES | INTERFACES; | |
argument = arguments[1]; | |
break; | |
case IProblem.ImportNotFound : | |
filter = IMPORT; | |
argument = arguments[0]; | |
break; | |
case IProblem.UndefinedType : | |
filter = CLASSES | INTERFACES; | |
argument = arguments[0]; | |
break; | |
// Method correction | |
case IProblem.UndefinedMethod : | |
filter = METHOD; | |
argument = arguments[1]; | |
break; | |
// Field and local variable correction | |
case IProblem.UndefinedField : | |
filter = FIELD; | |
argument = arguments[0]; | |
break; | |
case IProblem.UndefinedName : | |
filter = FIELD | LOCAL; | |
argument = arguments[0]; | |
break; | |
} | |
} catch (ArrayIndexOutOfBoundsException e) { | |
return; | |
} | |
if(argument != null) { | |
correct(argument.toCharArray()); | |
} | |
} | |
private void correct(char[] argument) throws JavaModelException { | |
try { | |
String source = unit.getSource(); | |
Scanner scanner = new Scanner(); | |
scanner.setSource(source.toCharArray()); | |
scanner.resetTo(correctionStart, correctionEnd); | |
int token = 0; | |
char[] argumentSource = new char[0]; | |
// search last segment position | |
while(true) { | |
token = scanner.getNextToken(); | |
if (token == ITerminalSymbols.TokenNameEOF) return; | |
char[] tokenSource = scanner.getCurrentTokenSource(); | |
argumentSource = CharOperation.concat(argumentSource, tokenSource); | |
if(!CharOperation.startsWith(argument, argumentSource)) | |
return; | |
if(CharOperation.equals(argument, argumentSource)) { | |
correctionStart = scanner.startPosition; | |
correctionEnd = scanner.currentPosition; | |
prefixLength = CharOperation.lastIndexOf('.', argument) + 1; | |
break; | |
} | |
} | |
// search completion position | |
int completionPosition = correctionStart; | |
scanner.resetTo(completionPosition, correctionEnd); | |
int position = completionPosition; | |
for (int i = 0; i < 4; i++) { | |
if(scanner.getNextCharAsJavaIdentifierPart()) { | |
completionPosition = position; | |
position = scanner.currentPosition; | |
} else { | |
break; | |
} | |
} | |
unit.codeComplete( | |
completionPosition, | |
completionRequestor | |
); | |
} catch (JavaModelException e) { | |
return; | |
} catch (InvalidInputException e) { | |
return; | |
} | |
} | |
protected ICompletionRequestor completionRequestor = new ICompletionRequestor() { | |
public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {} | |
public void acceptClass(char[] packageName,char[] className,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { | |
if((filter & (CLASSES | INTERFACES)) != 0) { | |
requestor.acceptClass( | |
packageName, | |
className, | |
CharOperation.subarray(completionName, prefixLength, completionName.length), | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} else if((filter & IMPORT) != 0) { | |
char[] fullName = CharOperation.concat(packageName, className, '.'); | |
requestor.acceptClass( | |
packageName, | |
className, | |
CharOperation.subarray(fullName, prefixLength, fullName.length), | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptError(IProblem error) {} | |
public void acceptField(char[] declaringTypePackageName,char[] declaringTypeName,char[] name,char[] typePackageName,char[] typeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { | |
if((filter & FIELD) != 0) { | |
requestor.acceptField( | |
declaringTypePackageName, | |
declaringTypeName, | |
name, | |
typePackageName, | |
typeName, | |
name, | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { | |
if((filter & (CLASSES | INTERFACES)) != 0) { | |
requestor.acceptInterface( | |
packageName, | |
interfaceName, | |
CharOperation.subarray(completionName, prefixLength, completionName.length), | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} else if((filter & IMPORT) != 0) { | |
char[] fullName = CharOperation.concat(packageName, interfaceName, '.'); | |
requestor.acceptInterface( | |
packageName, | |
interfaceName, | |
CharOperation.subarray(fullName, prefixLength, fullName.length), | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance) {} | |
public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance) {} | |
public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance) { | |
if((filter & LOCAL) != 0) { | |
requestor.acceptLocalVariable( | |
name, | |
typePackageName, | |
typeName, | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { | |
if((filter & METHOD) != 0) { | |
requestor.acceptMethod( | |
declaringTypePackageName, | |
declaringTypeName, | |
selector, | |
parameterPackageNames, | |
parameterTypeNames, | |
parameterNames, | |
returnTypePackageName, | |
returnTypeName, | |
selector, | |
modifiers, | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {} | |
public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance) {} | |
public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance) { | |
if((filter & (CLASSES | INTERFACES | IMPORT)) != 0) { | |
requestor.acceptPackage( | |
packageName, | |
CharOperation.subarray(packageName, prefixLength, packageName.length), | |
correctionStart, | |
correctionEnd); | |
} | |
} | |
public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance) {} | |
public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance) {} | |
}; | |
} |