org.eclipse.jdt.internal.compiler.problem.ProblemHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ecj Show documentation
Show all versions of ecj Show documentation
Eclipse Compiler for Java(TM)
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 458396 - NPE in CodeStream.invoke()
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.problem;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.util.Util;
/*
* 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 {
public final static String[] NoArgument = CharOperation.NO_STRINGS;
public IErrorHandlingPolicy policy;
public final IProblemFactory problemFactory;
public final CompilerOptions options;
/* When temporarily switching policies, store here the original root policy (for temporary resume). */
private IErrorHandlingPolicy rootPolicy;
protected boolean suppressTagging = false;
/*
* 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 ProblemSeverities.Error; // by default all problems are errors
}
public CategorizedProblem createProblem(
char[] fileName,
int problemId,
String[] problemArguments,
String[] messageArguments,
int severity,
int problemStartPosition,
int problemEndPosition,
int lineNumber,
int columnNumber) {
return this.problemFactory.createProblem(
fileName,
problemId,
problemArguments,
messageArguments,
severity,
problemStartPosition,
problemEndPosition,
lineNumber,
columnNumber);
}
public CategorizedProblem createProblem(
char[] fileName,
int problemId,
String[] problemArguments,
int elaborationId,
String[] messageArguments,
int severity,
int problemStartPosition,
int problemEndPosition,
int lineNumber,
int columnNumber) {
return this.problemFactory.createProblem(
fileName,
problemId,
problemArguments,
elaborationId,
messageArguments,
severity,
problemStartPosition,
problemEndPosition,
lineNumber,
columnNumber);
}
public void handle(
int problemId,
String[] problemArguments,
int elaborationId,
String[] messageArguments,
int severity,
int problemStartPosition,
int problemEndPosition,
ReferenceContext referenceContext,
CompilationResult unitResult) {
if (severity == ProblemSeverities.Ignore)
return;
boolean mandatory = (severity & (ProblemSeverities.Error | ProblemSeverities.Optional)) == ProblemSeverities.Error;
if ((severity & ProblemSeverities.InternalError) == 0 && this.policy.ignoreAllErrors()) {
// Error is not to be exposed, but clients may need still notification as to whether there are silently-ignored-errors.
// if no reference context, we need to abort from the current compilation process
if (referenceContext == null) {
if ((severity & ProblemSeverities.Error) != 0) { // non reportable error is fatal
CategorizedProblem problem = this.createProblem(null, problemId, problemArguments, elaborationId, messageArguments, severity, 0, 0, 0, 0);
throw new AbortCompilation(null, problem);
} else {
return; // ignore non reportable warning
}
}
if (mandatory)
referenceContext.tagAsHavingIgnoredMandatoryErrors(problemId);
return;
}
if ((severity & ProblemSeverities.Optional) != 0 && problemId != IProblem.Task && !this.options.ignoreSourceFolderWarningOption) {
ICompilationUnit cu = unitResult.getCompilationUnit();
try{
if (cu != null && cu.ignoreOptionalProblems())
return;
// workaround for illegal implementation of ICompilationUnit, see https://bugs.eclipse.org/372351
} catch (AbstractMethodError ex) {
// continue
}
}
// if no reference context, we need to abort from the current compilation process
if (referenceContext == null) {
if ((severity & ProblemSeverities.Error) != 0) { // non reportable error is fatal
CategorizedProblem problem = this.createProblem(null, problemId, problemArguments, elaborationId, messageArguments, severity, 0, 0, 0, 0);
throw new AbortCompilation(null, problem);
} else {
return; // ignore non reportable warning
}
}
int[] lineEnds;
int lineNumber = problemStartPosition >= 0
? Util.getLineNumber(problemStartPosition, lineEnds = unitResult.getLineSeparatorPositions(), 0, lineEnds.length-1)
: 0;
int columnNumber = problemStartPosition >= 0
? Util.searchColumnNumber(unitResult.getLineSeparatorPositions(), lineNumber, problemStartPosition)
: 0;
CategorizedProblem problem =
this.createProblem(
unitResult.getFileName(),
problemId,
problemArguments,
elaborationId,
messageArguments,
severity,
problemStartPosition,
problemEndPosition,
lineNumber,
columnNumber);
if (problem == null) return; // problem couldn't be created, ignore
switch (severity & ProblemSeverities.Error) {
case ProblemSeverities.Error :
record(problem, unitResult, referenceContext, mandatory);
if ((severity & ProblemSeverities.Fatal) != 0) {
// don't abort or tag as error if the error is suppressed
if (!referenceContext.hasErrors() && !mandatory && this.options.suppressOptionalErrors) {
CompilationUnitDeclaration unitDecl = referenceContext.getCompilationUnitDeclaration();
if (unitDecl != null && unitDecl.isSuppressed(problem)) {
return;
}
}
if (!this.suppressTagging || this.options.treatOptionalErrorAsFatal) {
referenceContext.tagAsHavingErrors();
}
// should abort ?
int abortLevel;
if ((abortLevel = this.policy.stopOnFirstError() ? ProblemSeverities.AbortCompilation : severity & ProblemSeverities.Abort) != 0) {
referenceContext.abort(abortLevel, problem);
}
}
break;
case ProblemSeverities.Warning :
record(problem, unitResult, referenceContext, false);
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,
0, // no message elaboration
messageArguments,
computeSeverity(problemId), // severity inferred using the ID
problemStartPosition,
problemEndPosition,
referenceContext,
unitResult);
}
public void record(CategorizedProblem problem, CompilationResult unitResult, ReferenceContext referenceContext, boolean mandatoryError) {
unitResult.record(problem, referenceContext, mandatoryError);
}
/** @return old policy. */
public IErrorHandlingPolicy switchErrorHandlingPolicy(IErrorHandlingPolicy newPolicy) {
if (this.rootPolicy == null)
this.rootPolicy = this.policy;
IErrorHandlingPolicy presentPolicy = this.policy;
this.policy = newPolicy;
return presentPolicy;
}
/**
* Temporarily suspend a temporary error handling policy.
* @return old policy.
*/
public IErrorHandlingPolicy suspendTempErrorHandlingPolicy() {
IErrorHandlingPolicy presentPolicy = this.policy;
if (this.rootPolicy != null)
this.policy = this.rootPolicy;
return presentPolicy;
}
/**
* Resume from a corresponding {@link #suspendTempErrorHandlingPolicy()}.
* @param previousPolicy the result value of the matching suspend call
*/
public void resumeTempErrorHandlingPolicy(IErrorHandlingPolicy previousPolicy) {
this.policy = previousPolicy;
}
}