blob: e2e5733114ba253459476b79b40d92e68d2a03fa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
* IBM - Refactor phase and severity as types for localization
*******************************************************************************/
package org.eclipse.ocl.lpg;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.ocl.internal.l10n.OCLMessages;
/**
* A <code>ProblemHandler</code> handles problems detected during the various lexical
* syntactic, semantic analysis and validation phases of source text processing.
*
* <code>setParser</code> should be invoked once the source text is available, then
* <code>handleProblem</code> for each problem and finally <code>flush</code> to send
* any accumulated problems to an appropriate recipient such as an error log or
* problem marker view.
*
* See <code>AbstractProblemHandler</code> for a default implementation of the per
* processing phase convenience methods and <code>StringProblemHandler</code> for
* a complete handler that just accumulates all problem reports as a string.
*/
public interface ProblemHandler {
String ERROR_MESSAGES[] = {
/* LEX_ERROR_CODE */ OCLMessages.OCLParseErrorCodes_LEX_ERROR,
/* ERROR_CODE */ OCLMessages.OCLParseErrorCodes_ERROR,
/* BEFORE_CODE */ OCLMessages.OCLParseErrorCodes_BEFORE,
/* INSERTION_CODE */ OCLMessages.OCLParseErrorCodes_INSERTION,
/* INVALID_CODE */ OCLMessages.OCLParseErrorCodes_INVALID,
/* SUBSTITUTION_CODE, SECONDARY_CODE */ OCLMessages.OCLParseErrorCodes_SUBSTITUTION_SECONDARY,
/* DELETION_CODE */ OCLMessages.OCLParseErrorCodes_DELETION,
/* MERGE_CODE */ OCLMessages.OCLParseErrorCodes_MERGE,
/* MISPLACED_CODE */ OCLMessages.OCLParseErrorCodes_MISPLACED,
/* SCOPE_CODE */ OCLMessages.OCLParseErrorCodes_SCOPE,
/* EOF_CODE */ OCLMessages.OCLParseErrorCodes_EOF,
/* INVALID_TOKEN_CODE */ OCLMessages.OCLParseErrorCodes_INVALID_TOKEN
};
/**
* Standard processing phases for problem messages. This class may be
* extended by custom problem handlers to define additional phases in
* custom processes.
*
* @author Christian W. Damus
*
* @since 1.2
*/
class Phase implements Comparable<Phase> {
/** Identifies problems found in the tokenizing (lexing) phase. */
public static Phase LEXER = new Phase(OCLMessages.Phase_Lexer);
/** Identifies problems found in the concrete syntax parsing phase. */
public static Phase PARSER = new Phase(OCLMessages.Phase_Parser);
/** Identifies problems found in the abstract syntax parsing phase. */
public static Phase ANALYZER = new Phase(OCLMessages.Phase_Analyzer);
/** Identifies problems found in the abstract syntax validation phase. */
public static Phase VALIDATOR = new Phase(OCLMessages.Phase_Validator);
/** Identifies problems found in a utility method (not really a parsing phase). */
public static Phase UTILITY = new Phase(OCLMessages.Phase_Utility);
/** Identifies problems found in un-parsing an OCL expression or constraint. */
public static Phase UNPARSER = new Phase(OCLMessages.Phase_Unparser);
private final String localizedName;
/**
* Creates a new phase instance with a localized name for display in
* error messages.
*
* @param lname the localized name of the phase
*/
protected Phase(String lname) {
localizedName = lname;
}
/**
* Phases sort according to their names.
*/
public final int compareTo(Phase o) {
return localizedName.compareTo(o.localizedName);
}
/**
* My hash code is my localized name's hash code.
*/
@Override
public final int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((localizedName == null) ? 0
: localizedName.hashCode());
return result;
}
/**
* I am equal to any <tt>Phase</tt> that has the same localized name
* as I.
*/
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Phase)) {
return false;
}
Phase other = (Phase) obj;
if (localizedName == null) {
if (other.localizedName != null) {
return false;
}
} else if (!localizedName.equals(other.localizedName)) {
return false;
}
return true;
}
@Override
public String toString() {
return localizedName;
}
}
/**
* Standard problem severities. The values are defined in increasing
* order of their severity.
*
* @author Christian W. Damus
*
* @since 1.2
*/
enum Severity {
/**
* Severity constant indicating absence of any problem.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#OK} and Eclipse <tt>IStatus.OK</tt>.
*/
OK(OCLMessages.Severity_OK, Diagnostic.OK) {
@Override
public boolean isOK() {
return true;
}},
/**
* Severity constant indicating an informational message
* that, really, is not a problem but a hint or suggestion.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#INFO} and Eclipse <tt>IStatus.INFO</tt>.
*/
INFO(OCLMessages.Severity_Info, Diagnostic.INFO),
/**
* Severity constant indicating a warning problem.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#WARNING} and Eclipse <tt>IStatus.WARNING</tt>.
*/
WARNING(OCLMessages.Severity_Warning, Diagnostic.WARNING),
/**
* Severity constant indicating an error problem that does not
* prevent the parser from proceeding, but which does indicate
* an ill-formed construct.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#ERROR} and Eclipse <tt>IStatus.ERROR</tt>.
*/
ERROR(OCLMessages.Severity_Error, Diagnostic.ERROR),
/**
* Severity constant indicating an error problem that prevents
* the parser from continuing to process the remainder of the
* input.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#ERROR} and Eclipse <tt>IStatus.ERROR</tt>,
* because these frameworks do not distinguish between fatal
* and non-fatal conditions.
*/
FATAL(OCLMessages.Severity_Fatal_Error, Diagnostic.ERROR),
/**
* Severity constant indicating a deliberate cancellation of the
* parsing operation by the user.
* Corresponds to the EMF {@link Diagnostic} severity
* {@link Diagnostic#CANCEL} and Eclipse <tt>IStatus.CANCEL</tt>.
* Cancellation in both of these frameworks, and in OCL, does
* not actually indicate an error condition despite its having
* the highest value. However, an operation that was canceled
* is incomplete and any results produced are necessarily invalid
* as in the case of {@link #FATAL} errors.
*/
CANCEL(OCLMessages.Severity_Cancel, Diagnostic.CANCEL);
private final int diagnosticSeverity;
private final String localizedName;
Severity(String lname, int sev) {
localizedName = lname;
diagnosticSeverity = sev;
}
public int getDiagnosticSeverity() {
return diagnosticSeverity;
}
/**
* Am I the "OK" severity?
*
* @return whether I am OK
*
* @see #OK
*/
public boolean isOK() {
return false;
}
@Override
public String toString() {
return localizedName;
}
}
/**
* Define the syntactic parser from which source tokens and text may be obtained.
* @param parser
*/
void setParser(AbstractParser parser);
/**
* Queries the parser from which I obtain source tokens and text.
* @return my parser
*/
AbstractParser getParser();
/**
* Handle a problem of problemSeverity that has arisen during processingPhase and which
* is explained by problemMessage optionally clarified, if non-null, by processingContext,
* and if non-negative by the startOffset and endOffset character indexes in the parsing stream.
*
* All other problem handling messages should redirect to this method.
*
* @param problemSeverity text describing the problem severity (e.g. <code>errorSeverity</code>)
* @param processingPhase optional text describing the processing phase (e.g. <code>analyzerProblem</code>)
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void handleProblem(Severity problemSeverity, Phase processingPhase, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Convenience method typically invoking <code>handleProblem</code>
* with a <code>analyzerProblem</code> processing phase.
* @param problemSeverity text describing the problem severity
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void analyzerProblem(Severity problemSeverity, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Convenience method typically invoking <code>handleProblem</code>
* with a <code>lexerProblem</code> processing phase.
* @param problemSeverity text describing the problem severity
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void lexerProblem(Severity problemSeverity, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Convenience method typically invoking <code>handleProblem</code>
* with a <code>parserProblem</code> processing phase.
* @param problemSeverity text describing the problem severity
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void parserProblem(Severity problemSeverity, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Convenience method typically invoking <code>handleProblem</code>
* with a <code>utilityProblem</code> processing phase.
* @param problemSeverity text describing the problem severity
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void utilityProblem(Severity problemSeverity, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Convenience method typically invoking <code>handleProblem</code>
* with a <code>validatorProblem</code> processing phase.
* @param problemSeverity text describing the problem severity
* @param problemMessage message describing the problem
* @param processingContext optional message describing the reporting context (e.g. <code>"PathNameCS"</code>)
* @param startOffset (inclusive) index of first source character influencing the problem, -ve if unknown
* @param endOffset (exclusive) index of last source character influencing the problem, -ve if unknown
*/
void validatorProblem(Severity problemSeverity, String problemMessage,
String processingContext, int startOffset, int endOffset);
/**
* Sets the line offset for reporting errors.
* E.g,. if an error occurred at line 2, but the offset was
* set to -1, then line 1 will be reported.
*
* @param offset
*/
void setErrorReportLineOffset(int offset);
/**
* Queries the line offset for reporting errors.
* E.g,. if an error occurred at line 2, but the offset was
* set to -1, then line 1 will be reported.
*
* @return the line offset
*/
int getErrorReportLineOffset();
/**
* Notifies me that parsing is about to begin, from which I may receive
* problems. I should initialize myself accordingly, if necessary.
*/
void beginParse();
/**
* Notifies me that parsing has completed, and I will get no further
* problems in this session. I may clean up accordingly, if necessary.
*/
void endParse();
/**
* Notifies me that validation is about to begin, from which I may receive
* problems. I should initialize myself accordingly, if necessary.
*/
void beginValidation();
/**
* Notifies me that validation has completed, and I will get no further
* problems in this session. I may clean up accordingly, if necessary.
*/
void endValidation();
/**
* Flush all problems to their recipient.
*
* This method allows handlers to batch up error reports into a single composite
* report or transaction.
*
* @param monitor an optional EMF monitor for reporting progress. May be
* <code>null</code> if not needed by the caller
*/
void flush(Monitor monitor);
}