/******************************************************************************* | |
* Copyright (c) 2000, 2004 IBM Corporation and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Common Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/cpl-v10.html | |
* | |
* Contributors: | |
* IBM Corporation - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.wst.jsdt.internal.compiler.problem; | |
import org.eclipse.wst.jsdt.core.compiler.IProblem; | |
import org.eclipse.wst.jsdt.internal.compiler.CompilationResult; | |
import org.eclipse.wst.jsdt.internal.compiler.IErrorHandlingPolicy; | |
import org.eclipse.wst.jsdt.internal.compiler.IProblemFactory; | |
import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions; | |
import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext; | |
/* | |
* Compiler error handler, responsible to determine whether | |
* a problem is actually a warning or an error; also will | |
* decide whether the compilation task can be processed further or not. | |
* | |
* Behavior : will request its current policy if need to stop on | |
* first error, and if should proceed (persist) with problems. | |
*/ | |
public class ProblemHandler implements ProblemSeverities { | |
public final static String[] NoArgument = new String[0]; | |
final public IErrorHandlingPolicy policy; | |
public final IProblemFactory problemFactory; | |
public final CompilerOptions options; | |
/* | |
* Problem handler can be supplied with a policy to specify | |
* its behavior in error handling. Also see static methods for | |
* built-in policies. | |
* | |
*/ | |
public ProblemHandler(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) { | |
this.policy = policy; | |
this.problemFactory = problemFactory; | |
this.options = options; | |
} | |
/* | |
* Given the current configuration, answers which category the problem | |
* falls into: | |
* Error | Warning | Ignore | |
*/ | |
public int computeSeverity(int problemId){ | |
return Error; // by default all problems are errors | |
} | |
public IProblem createProblem( | |
char[] fileName, | |
int problemId, | |
String[] problemArguments, | |
String[] messageArguments, | |
int severity, | |
int problemStartPosition, | |
int problemEndPosition, | |
int lineNumber) { | |
return this.problemFactory.createProblem( | |
fileName, | |
problemId, | |
problemArguments, | |
messageArguments, | |
severity, | |
problemStartPosition, | |
problemEndPosition, | |
lineNumber); | |
} | |
public void handle( | |
int problemId, | |
String[] problemArguments, | |
String[] messageArguments, | |
int severity, | |
int problemStartPosition, | |
int problemEndPosition, | |
ReferenceContext referenceContext, | |
CompilationResult unitResult) { | |
if (severity == Ignore) | |
return; | |
// if no reference context, we need to abort from the current compilation process | |
if (referenceContext == null) { | |
if ((severity & Error) != 0) { // non reportable error is fatal | |
IProblem problem = this.createProblem(null, problemId, problemArguments, messageArguments, severity, 0, 0, 0); | |
throw new AbortCompilation(null, problem); | |
} else { | |
return; // ignore non reportable warning | |
} | |
} | |
IProblem problem = | |
this.createProblem( | |
unitResult.getFileName(), | |
problemId, | |
problemArguments, | |
messageArguments, | |
severity, | |
problemStartPosition, | |
problemEndPosition, | |
problemStartPosition >= 0 | |
? searchLineNumber(unitResult.lineSeparatorPositions, problemStartPosition) | |
: 0); | |
if (problem == null) return; // problem couldn't be created, ignore | |
switch (severity & Error) { | |
case Error : | |
this.record(problem, unitResult, referenceContext); | |
referenceContext.tagAsHavingErrors(); | |
// should abort ? | |
int abortLevel; | |
if ((abortLevel = | |
(this.policy.stopOnFirstError() ? AbortCompilation : severity & Abort)) != 0) { | |
referenceContext.abort(abortLevel, problem); | |
} | |
break; | |
case Warning : | |
this.record(problem, unitResult, referenceContext); | |
break; | |
} | |
} | |
/** | |
* Standard problem handling API, the actual severity (warning/error/ignore) is deducted | |
* from the problem ID and the current compiler options. | |
*/ | |
public void handle( | |
int problemId, | |
String[] problemArguments, | |
String[] messageArguments, | |
int problemStartPosition, | |
int problemEndPosition, | |
ReferenceContext referenceContext, | |
CompilationResult unitResult) { | |
this.handle( | |
problemId, | |
problemArguments, | |
messageArguments, | |
this.computeSeverity(problemId), // severity inferred using the ID | |
problemStartPosition, | |
problemEndPosition, | |
referenceContext, | |
unitResult); | |
} | |
public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) { | |
unitResult.record(problem, referenceContext); | |
} | |
/** | |
* Search the line number corresponding to a specific position | |
*/ | |
public static final int searchLineNumber(int[] startLineIndexes, int position) { | |
if (startLineIndexes == null) | |
return 1; | |
int length = startLineIndexes.length; | |
if (length == 0) | |
return 1; | |
int g = 0, d = length - 1; | |
int m = 0; | |
while (g <= d) { | |
m = (g + d) /2; | |
if (position < startLineIndexes[m]) { | |
d = m-1; | |
} else if (position > startLineIndexes[m]) { | |
g = m+1; | |
} else { | |
return m + 1; | |
} | |
} | |
if (position < startLineIndexes[m]) { | |
return m+1; | |
} | |
return m+2; | |
} | |
} |