blob: 5ee7c8600e01e315bfbe5fe68f1eb1e7826a5219 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.core.sourcemodel;
import static org.eclipse.statet.ltk.ast.core.AstNode.NA_OFFSET;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_NUMBER_EXP_DIGIT_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_NUMBER_HEX_DIGIT_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_NUMBER_HEX_FLOAT_EXP_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_NUMBER_INT_WITH_DEC_POINT;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_NUMBER_NON_INT_WITH_L;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_HEX_DIGIT_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_UNEXPECTED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_UNKOWN;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS123_SYNTAX_TEXT_NULLCHAR;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS12_SYNTAX_TEXT_INVALID;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS12_SYNTAX_TOKEN_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS12_SYNTAX_TOKEN_UNEXPECTED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS12_SYNTAX_TOKEN_UNKNOWN;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_CC_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_CONDITION_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_CONDITION_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_ELEMENTNAME_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_AFTER_OP_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_AS_ARGVALUE_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_AS_BODY_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_AS_CONDITION_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_AS_FORSEQ_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_BEFORE_OP_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_EXPR_IN_GROUP_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_FCALL_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_FDEF_ARGS_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_FDEF_ARGS_NOT_CLOSED;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_IF_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_IN_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_OPERATOR_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS2_SYNTAX_SYMBOL_MISSING;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUSFLAG_SUBSEQUENT;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS_MASK_12;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS_MASK_123;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS_MASK_3;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS_OK;
import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS_RUNTIME_ERROR;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.statet.jcommons.text.core.TextLineInformation;
import org.eclipse.statet.ecommons.runtime.core.util.MessageBuilder;
import org.eclipse.statet.internal.r.core.RCorePlugin;
import org.eclipse.statet.ltk.ast.core.StatusDetail;
import org.eclipse.statet.ltk.core.SourceContent;
import org.eclipse.statet.ltk.issues.core.BasicProblem;
import org.eclipse.statet.ltk.issues.core.Problem;
import org.eclipse.statet.ltk.issues.core.ProblemRequestor;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnit;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.core.model.IRSourceUnit;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.r.core.rsource.IRSourceConstants;
import org.eclipse.statet.r.core.rsource.ast.Arithmetic;
import org.eclipse.statet.r.core.rsource.ast.Assignment;
import org.eclipse.statet.r.core.rsource.ast.Block;
import org.eclipse.statet.r.core.rsource.ast.CForLoop;
import org.eclipse.statet.r.core.rsource.ast.CIfElse;
import org.eclipse.statet.r.core.rsource.ast.CLoopCommand;
import org.eclipse.statet.r.core.rsource.ast.CRepeatLoop;
import org.eclipse.statet.r.core.rsource.ast.CWhileLoop;
import org.eclipse.statet.r.core.rsource.ast.Dummy;
import org.eclipse.statet.r.core.rsource.ast.FCall;
import org.eclipse.statet.r.core.rsource.ast.FDef;
import org.eclipse.statet.r.core.rsource.ast.Group;
import org.eclipse.statet.r.core.rsource.ast.Help;
import org.eclipse.statet.r.core.rsource.ast.Logical;
import org.eclipse.statet.r.core.rsource.ast.Model;
import org.eclipse.statet.r.core.rsource.ast.NSGet;
import org.eclipse.statet.r.core.rsource.ast.NodeType;
import org.eclipse.statet.r.core.rsource.ast.NullConst;
import org.eclipse.statet.r.core.rsource.ast.NumberConst;
import org.eclipse.statet.r.core.rsource.ast.Power;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;
import org.eclipse.statet.r.core.rsource.ast.RAstVisitor;
import org.eclipse.statet.r.core.rsource.ast.Relational;
import org.eclipse.statet.r.core.rsource.ast.Seq;
import org.eclipse.statet.r.core.rsource.ast.Sign;
import org.eclipse.statet.r.core.rsource.ast.SourceComponent;
import org.eclipse.statet.r.core.rsource.ast.Special;
import org.eclipse.statet.r.core.rsource.ast.StringConst;
import org.eclipse.statet.r.core.rsource.ast.SubIndexed;
import org.eclipse.statet.r.core.rsource.ast.SubNamed;
import org.eclipse.statet.r.core.rsource.ast.Symbol;
/**
* Reports syntax problems in AST to {@link ProblemRequestor} of source units
*/
public class SyntaxProblemReporter extends RAstVisitor {
private static final int BUFFER_SIZE= 100;
private static final int FULL_TEXT_LIMIT= 100;
private static final int START_TEXT_LIMIT= 25;
private static final int MASK= 0x00ffffff;
private final boolean reportSubsequent= false;
private ISourceUnit sourceUnit;
private SourceContent sourceContent;
private String currentText;
private ProblemRequestor currentRequestor;
private final StringBuilder tmpBuilder= new StringBuilder();
private final MessageBuilder messageBuilder= new MessageBuilder();
private final List<Problem> problemBuffer= new ArrayList<>(BUFFER_SIZE);
// private int maxOffset;
public SyntaxProblemReporter() {
}
public void run(final IRSourceUnit su, final SourceContent content,
final RAstNode node, final ProblemRequestor problemRequestor) {
try {
this.sourceUnit= su;
this.sourceContent= content;
this.currentText= content.getText();
// this.currentDoc= su.getDocument(null);
// this.maxOffset= this.currentDoc.getLength();
this.currentRequestor= problemRequestor;
node.acceptInR(this);
if (this.problemBuffer.size() > 0) {
this.currentRequestor.acceptProblems(RModel.R_TYPE_ID, this.problemBuffer);
}
}
catch (final OperationCanceledException e) {}
catch (final InvocationTargetException e) {}
finally {
this.problemBuffer.clear();
this.sourceUnit= null;
// this.currentDoc= null;
this.currentRequestor= null;
}
}
private boolean requiredCheck(final int code) {
return code != STATUS_OK &&
(this.reportSubsequent || ((code & STATUSFLAG_SUBSEQUENT) == 0));
}
protected final void addProblem(final int severity, final int code, final String message,
int startOffset, int endOffset) {
if (startOffset < this.sourceContent.getStartOffset()) {
startOffset= this.sourceContent.getStartOffset();
}
if (endOffset < startOffset) {
endOffset= startOffset;
}
else if (endOffset > this.sourceContent.getEndOffset()) {
endOffset= this.sourceContent.getEndOffset();
}
this.problemBuffer.add(new BasicProblem(RModel.R_TYPE_ID, severity, code, message,
startOffset, endOffset ));
if (this.problemBuffer.size() >= BUFFER_SIZE) {
this.currentRequestor.acceptProblems(RModel.R_TYPE_ID, this.problemBuffer);
this.problemBuffer.clear();
}
}
protected final StringBuilder getStringBuilder() {
this.tmpBuilder.setLength(0);
return this.tmpBuilder;
}
protected String getStartText(final RAstNode node, final int offset)
throws BadLocationException {
final String text= node.getText();
if (text != null) {
if (text.length() > START_TEXT_LIMIT) {
final StringBuilder sb= getStringBuilder();
sb.append(text, 0, START_TEXT_LIMIT);
sb.append('…');
return sb.toString();
}
else {
return text;
}
}
else {
if (node.getLength() - offset > START_TEXT_LIMIT) {
final StringBuilder sb= getStringBuilder();
sb.append(this.sourceContent.getText(),
node.getStartOffset() + offset, node.getStartOffset() + offset + START_TEXT_LIMIT);
sb.append('…');
return sb.toString();
}
else {
return this.sourceContent.getText().substring(
node.getStartOffset() + offset, node.getEndOffset() + offset );
}
}
}
protected String getDetailText(final RAstNode node, final int offset, final StatusDetail detail)
throws BadLocationException {
final String text= node.getText();
if (text != null) {
final int begin= detail.getStartOffset() - node.getStartOffset() - offset;
return text.substring(begin, begin + detail.getLength());
}
else {
return this.sourceContent.getText().substring(
detail.getStartOffset(), detail.getEndOffset() );
}
}
private void handleCommonCodes(final RAstNode node, final int code)
throws BadLocationException, InvocationTargetException {
STATUS: switch (code & STATUS_MASK_12) {
case STATUS_RUNTIME_ERROR:
throw new InvocationTargetException(new CoreException(
new Status(IStatus.ERROR, RCore.BUNDLE_ID, -1,
"Error occurred when parsing source code. Please submit a bug report with a code snippet.", //$NON-NLS-1$
null)));
case STATUS12_SYNTAX_TOKEN_UNEXPECTED:
addProblem(Problem.SEVERITY_ERROR, code,
this.messageBuilder.bind(ProblemMessages.Syntax_TokenUnexpected_message, getFullText(node)),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
default:
handleUnknownCodes(node);
break STATUS;
}
}
protected void handleUnknownCodes(final RAstNode node) {
final int code= (node.getStatusCode() & MASK);
final StringBuilder sb= new StringBuilder();
sb.append("Unhandled/Unknown code of R AST node:"); //$NON-NLS-1$
sb.append('\n');
sb.append(" Code: 0x").append(Integer.toHexString(code)); //$NON-NLS-1$
sb.append('\n');
sb.append(" Node: ").append(node);
sb.append(" (").append(node.getStartOffset()).append(", ").append(node.getLength()).append(')'); //$NON-NLS-1$ //$NON-NLS-2$
sb.append('\n');
if (this.sourceContent != null) {
final TextLineInformation lines= this.sourceContent.getLines();
final int line= lines.getLineOfOffset(node.getStartOffset());
sb.append(" Line ").append((line + 1)).append(" (offset )").append(lines.getStartOffset(line)); //$NON-NLS-1$ //$NON-NLS-2$
sb.append('\n');
final int firstLine= Math.max(0, line - 2);
final int lastLine= Math.min(lines.getNumberOfLines() - 1, lines.getLineOfOffset(line) + 2);
sb.append(" Source (line ").append((firstLine + 1)).append('-').append((lastLine)).append("): \n"); //$NON-NLS-1$ //$NON-NLS-2$
sb.append(this.currentText.substring(lines.getStartOffset(firstLine),
lines.getStartOffset(lastLine) ));
}
RCorePlugin.log(new Status(IStatus.WARNING, RCore.BUNDLE_ID, sb.toString()));
}
@Override
public void visit(final SourceComponent node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & IRSourceConstants.STATUS_MASK_2)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Block node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_CC_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_BlockNotClosed_message,
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Group node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_CC_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_GroupNotClosed_message,
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final CIfElse node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_IF_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_IfOfElseMissing_message,
node.getStartOffset(), node.getStartOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_CONDITION_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionMissing_If_message,
node.getStartOffset() + 1, node.getStartOffset() + 3 );
break STATUS;
case STATUS2_SYNTAX_CONDITION_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionNotClosed_If_message,
node.getCondChild().getEndOffset() - 1, node.getCondChild().getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final CForLoop node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_CONDITION_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionMissing_For_message,
node.getStartOffset() + 2, node.getStartOffset() + 4 );
break STATUS;
case STATUS2_SYNTAX_CONDITION_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionNotClosed_For_message,
node.getCondChild().getEndOffset() - 1, node.getCondChild().getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_IN_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_InOfForConditionMissing_message,
node.getVarChild().getEndOffset() - 1, node.getVarChild().getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final CRepeatLoop node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final CWhileLoop node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_CONDITION_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionMissing_While_message,
node.getStartOffset() + 4, node.getStartOffset() + 6 );
break;
case STATUS2_SYNTAX_CONDITION_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ConditionNotClosed_While_message,
node.getCondChild().getEndOffset() - 1, node.getCondChild().getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final CLoopCommand node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FCall node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_FCALL_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_FcallArgsNotClosed_message,
node.getArgsChild().getEndOffset() - 1, node.getArgsChild().getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FCall.Args node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FCall.Arg node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FDef node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_FDEF_ARGS_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_FdefArgsMissing_message,
node.getStartOffset() + 7, node.getStartOffset() + 9 );
break STATUS;
case STATUS2_SYNTAX_FDEF_ARGS_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_FdefArgsNotClosed_message,
node.getArgsChild().getEndOffset() - 1, node.getArgsChild().getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FDef.Args node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final FDef.Arg node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Assignment node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Model node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Relational node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
if ((code & STATUS_MASK_123) == (IRSourceConstants.STATUS123_SYNTAX_SEQREL_UNEXPECTED)) {
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_TokenUnexpected_SeqRel_message,
node.getOperator(0).text ),
node.getStartOffset(), node.getEndOffset() );
}
else {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Logical node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Arithmetic node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Power node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Seq node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Special node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS12_SYNTAX_TOKEN_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_SpecialNotClosed_message,
getStartText(node, 1) ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Sign node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final SubIndexed node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case IRSourceConstants.STATUS2_SYNTAX_SUBINDEXED_NOT_CLOSED:
if (node.getNodeType() == NodeType.SUB_INDEXED_S) {
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_SubindexedNotClosed_S_message,
getStartText(node, 0) ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
}
else if (node.getSublistCloseOffset() != NA_OFFSET) {
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_SubindexedNotClosed_Done_message,
getStartText(node, 0) ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
}
else {
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_SubindexedNotClosed_Dboth_message,
getStartText(node, 0) ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
}
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final SubIndexed.Args node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final SubIndexed.Arg node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final SubNamed node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final NSGet node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
private void handleTextInvalid(final RAstNode node, final int code) throws BadLocationException {
final StatusDetail detail= StatusDetail.getStatusDetail(node);
switch ((code & STATUS_MASK_123)) {
case STATUS123_SYNTAX_TEXT_NULLCHAR:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_Text_NullCharNotAllowed_message,
detail.getStartOffset(), detail.getEndOffset() );
return;
case STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_HEX_DIGIT_MISSING:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Text_EscapeSeqHexDigitMissing_message,
detail.getText() ),
detail.getStartOffset(), detail.getEndOffset() );
return;
case STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Text_EscapeSeqNotClosed_message,
detail.getText() ),
detail.getStartOffset(), detail.getEndOffset() );
return;
case STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_UNEXPECTED:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Text_QuotedSymbol_EscapeSeqUnexpected_message,
detail.getText() ),
detail.getStartOffset(), detail.getEndOffset() );
return;
case STATUS123_SYNTAX_TEXT_ESCAPE_SEQ_UNKOWN:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Text_EscapeSeqUnknown_message,
detail.getText() ),
detail.getStartOffset(), detail.getEndOffset() );
return;
default:
handleUnknownCodes(node);
return;
}
}
@Override
public void visit(final StringConst node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS12_SYNTAX_TOKEN_NOT_CLOSED:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_StringNotClosed_message,
getStartText(node, 1), node.getOperator(0).text ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS12_SYNTAX_TEXT_INVALID:
handleTextInvalid(node, code);
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
}
@Override
public void visit(final NumberConst node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_123)) {
case STATUS123_SYNTAX_NUMBER_HEX_DIGIT_MISSING:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Number_HexDigitMissing_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
case STATUS123_SYNTAX_NUMBER_HEX_FLOAT_EXP_MISSING:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Number_HexFloatExpMissing_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
case STATUS123_SYNTAX_NUMBER_EXP_DIGIT_MISSING:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Number_ExpDigitMissing_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
case STATUS123_SYNTAX_NUMBER_NON_INT_WITH_L:
addProblem(Problem.SEVERITY_WARNING, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Number_NonIntWithLLiteral_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
case STATUS123_SYNTAX_NUMBER_INT_WITH_DEC_POINT:
addProblem(Problem.SEVERITY_WARNING, code, this.messageBuilder.bind(
ProblemMessages.Syntax_Number_IntWithDecPoint_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
}
@Override
public void visit(final NullConst node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break STATUS;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Symbol node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS2_SYNTAX_SYMBOL_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_SymbolMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_ELEMENTNAME_MISSING:
// this can be a status for string too, but never used there
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ElementnameMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS12_SYNTAX_TOKEN_NOT_CLOSED:
// assert(node.getOperator(0) == RTerminal.SYMBOL_G)
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_QuotedSymbolNotClosed_message,
getStartText(node, 1) ),
node.getEndOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS12_SYNTAX_TEXT_INVALID:
// assert(node.getOperator(0) == RTerminal.SYMBOL_G)
handleTextInvalid(node, code);
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
}
@Override
public void visit(final Help node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
// STATUS: switch ((code & STATUS_MASK_12)) {
// default:
handleCommonCodes(node, code);
// break;
// }
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
@Override
public void visit(final Dummy node) throws InvocationTargetException {
final int code= (node.getStatusCode() & MASK);
if (requiredCheck(code)) {
try {
STATUS: switch ((code & STATUS_MASK_12)) {
case STATUS12_SYNTAX_TOKEN_UNKNOWN:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_TokenUnknown_message,
getFullText(node) ),
node.getStartOffset(), node.getEndOffset() );
break STATUS;
case STATUS2_SYNTAX_EXPR_BEFORE_OP_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ExprBeforeOpMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_EXPR_AFTER_OP_MISSING:
addProblem(Problem.SEVERITY_ERROR, code, this.messageBuilder.bind(
ProblemMessages.Syntax_ExprAfterOpMissing_message,
getFullText(node) ),
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
// case STATUS2_SYNTAX_EXPR_AS_REF_MISSING:
// addProblem(Problem.ERROR, code,
// ProblemMessages.,
// node.getStartOffset() - 1, node.getEndOffset() + 1);
// break;
case STATUS2_SYNTAX_EXPR_AS_CONDITION_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ExprAsConditionMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_EXPR_AS_FORSEQ_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ExprAsForSequenceMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_EXPR_AS_BODY_MISSING:
{
final String message;
STATUS3: switch (code & IRSourceConstants.STATUS_MASK_3) {
case IRSourceConstants.STATUS3_IF:
message= ProblemMessages.Syntax_ExprAsThenBodyMissing_message;
break STATUS3;
case IRSourceConstants.STATUS3_ELSE:
message= ProblemMessages.Syntax_ExprAsElseBodyMissing_message;
break STATUS3;
case IRSourceConstants.STATUS3_FOR:
case IRSourceConstants.STATUS3_WHILE:
case IRSourceConstants.STATUS3_REPEAT:
message= ProblemMessages.Syntax_ExprAsLoopBodyMissing_message;
break STATUS3;
case IRSourceConstants.STATUS3_FDEF:
message= ProblemMessages.Syntax_ExprAsFdefBodyMissing_message;
break STATUS3;
default:
handleUnknownCodes(node);
break STATUS;
}
if (node.getLength() > 0) {
addProblem(Problem.SEVERITY_ERROR, code, message,
node.getStartOffset(), node.getEndOffset() );
}
else {
addProblem(Problem.SEVERITY_ERROR, code, message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
}
break STATUS;
}
case STATUS2_SYNTAX_EXPR_IN_GROUP_MISSING:
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ExprInGroupMissing_message,
node.getStartOffset() - 1, node.getEndOffset() + 1 );
break STATUS;
case STATUS2_SYNTAX_EXPR_AS_ARGVALUE_MISSING:
if ((code & STATUS_MASK_3) == IRSourceConstants.STATUS3_FDEF) {
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_ExprAsFdefArgDefaultMissing_message,
node.getStartOffset() - 1, node.getEndOffset() );
}
else {
handleUnknownCodes(node);
}
break STATUS;
case STATUS2_SYNTAX_OPERATOR_MISSING:
if (node.getChildCount() == 2) {
addProblem(Problem.SEVERITY_ERROR, code,
ProblemMessages.Syntax_OperatorMissing_message,
node.getChild(0).getEndOffset() - 1, node.getChild(1).getStartOffset() + 1 );
}
else {
handleUnknownCodes(node);
}
break STATUS;
default:
handleCommonCodes(node, code);
break STATUS;
}
}
catch (final BadLocationException e) {
throw new InvocationTargetException(e);
}
}
node.acceptInRChildren(this);
}
protected String getFullText(final RAstNode node) throws BadLocationException {
final String text= node.getText();
if (text != null) {
if (text.length() > FULL_TEXT_LIMIT) {
return text.substring(0, FULL_TEXT_LIMIT) + '…';
}
else {
return text;
}
}
else {
if (node.getLength() > FULL_TEXT_LIMIT) {
return this.currentText.substring(node.getStartOffset(),
node.getStartOffset() + FULL_TEXT_LIMIT ) + '…';
}
else {
return this.currentText.substring(node.getStartOffset(), node.getEndOffset());
}
}
}
}