blob: 769d0c0fca7b293571ad8a7af12872c9ecdf2b7f [file] [log] [blame]
/*******************************************************************************
* 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.compiler.problem;
import java.util.Arrays;
import org.eclipse.dltk.compiler.util.Messages;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
public class DefaultProblem extends CategorizedProblem {
private static int hashCode(Object[] array) {
final int prime = 31;
if (array == null)
return 0;
int result = 1;
for (int index = 0; index < array.length; index++) {
result = prime * result
+ (array[index] == null ? 0 : array[index].hashCode());
}
return result;
}
private String fileName;
private IProblemIdentifier id;
private int startPosition, endPosition, line, column;
private ProblemSeverity severity;
private String[] arguments;
private String message;
public static final String MARKER_TYPE_PREFIX = "org.eclipse.dltk"; //$NON-NLS-1$
public static final String MARKER_TYPE_PROBLEM = "org.eclipse.dltk.core.problem"; //$NON-NLS-1$
public static final String MARKER_TYPE_TASK = "org.eclipse.dltk.core.task"; //$NON-NLS-1$
public static final Object[] EMPTY_VALUES = {};
public DefaultProblem(String originatingFileName, String message,
IProblemIdentifier id, String[] stringArguments,
ProblemSeverity severity, int startPosition, int endPosition,
int line, int column) {
this.fileName = originatingFileName;
this.message = message;
this.id = id;
this.arguments = stringArguments;
this.severity = severity;
this.startPosition = startPosition;
this.endPosition = endPosition;
this.line = line;
this.column = column;
}
@Deprecated
public DefaultProblem(String originatingFileName, String message, int id,
String[] stringArguments, ProblemSeverity severity,
int startPosition, int endPosition, int line) {
this(originatingFileName, message, DefaultProblemIdentifier.decode(id),
stringArguments, severity, startPosition, endPosition, line, 0);
}
@Deprecated
public DefaultProblem(String message, int id, String[] stringArguments,
ProblemSeverity severity, int startPosition, int endPosition,
int line) {
this(NONAME, message, DefaultProblemIdentifier.decode(id),
stringArguments, severity, startPosition, endPosition, line, 0);
}
public DefaultProblem(String message, IProblemIdentifier id,
String[] stringArguments, ProblemSeverity severity,
int startPosition, int endPosition, int line) {
this(NONAME, message, id, stringArguments, severity, startPosition,
endPosition, line, 0);
}
private static final String NONAME = ""; //$NON-NLS-1$
public String errorReportSource(char[] unitSource) {
return errorReportSource(unitSource, 0);
}
public String errorReportSource(char[] unitSource, int tagBits) {
// extra from the source the inaccurate token
// and "highlight" it using some underneath ^^^^^
// put some context around too.
// this code assumes that the font used in the console is fixed size
// sanity .....
if ((this.startPosition > this.endPosition)
|| ((this.startPosition < 0) && (this.endPosition < 0))
|| unitSource.length == 0)
return Messages.problem_noSourceInformation;
StringBuffer errorBuffer = new StringBuffer();
if (DLTKCore.DEBUG) {
System.err.println("TODO: Add correct code here. DefaultProblem"); //$NON-NLS-1$
}
// if ((tagBits & Main.Logger.EMACS) == 0) {
// errorBuffer.append(' ').append(Messages.bind(Messages.problem_atLine,
// String.valueOf(this.line)));
// errorBuffer.append(Util.LINE_SEPARATOR);
// }
errorBuffer.append('\t');
char c;
final char SPACE = '\u0020';
final char MARK = '^';
final char TAB = '\t';
// the next code tries to underline the token.....
// it assumes (for a good display) that token source does not
// contain any \r \n. This is false on statements !
// (the code still works but the display is not optimal !)
// expand to line limits
int length = unitSource.length, begin, end;
for (begin = this.startPosition >= length ? length - 1
: this.startPosition; begin > 0; begin--) {
if ((c = unitSource[begin - 1]) == '\n' || c == '\r')
break;
}
for (end = this.endPosition >= length ? length - 1 : this.endPosition; end + 1 < length; end++) {
if ((c = unitSource[end + 1]) == '\r' || c == '\n')
break;
}
// trim left and right spaces/tabs
while ((c = unitSource[begin]) == ' ' || c == '\t')
begin++;
while ((c = unitSource[end]) == ' ' || c == '\t')
end--;
// copy source
errorBuffer.append(unitSource, begin, end - begin + 1);
errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
// compute underline
for (int i = begin; i < this.startPosition; i++) {
errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
}
for (int i = this.startPosition; i <= (this.endPosition >= length ? length - 1
: this.endPosition); i++) {
errorBuffer.append(MARK);
}
return errorBuffer.toString();
}
/**
* Answer back the original arguments recorded into the problem.
*
* @return java.lang.String[]
*/
@Override
public String[] getArguments() {
return this.arguments;
}
/**
* @see org.eclipse.dltk.core.compiler.CategorizedProblem#getCategoryID()
*/
@Override
public int getCategoryID() {
// return ProblemReporter.getProblemCategory(this.severity, this.id);
if (DLTKCore.DEBUG) {
System.err
.println("TODO: DefaultProblem getCategoryID always return 0. Fix it."); //$NON-NLS-1$
}
return 0;
}
/**
* Answer the type of problem.
*
* @see org.eclipse.dltk.core.compiler.IProblem#getID()
* @return int
*/
@Override
public IProblemIdentifier getID() {
return this.id;
}
/**
* Answers a readable name for the category which this problem belongs to,
* or null if none could be found. FOR TESTING PURPOSE
*
* @return java.lang.String
*/
public String getInternalCategoryMessage() {
switch (getCategoryID()) {
case CAT_UNSPECIFIED:
return "unspecified"; //$NON-NLS-1$
case CAT_BUILDPATH:
return "buildpath"; //$NON-NLS-1$
case CAT_SYNTAX:
return "syntax"; //$NON-NLS-1$
case CAT_IMPORT:
return "import"; //$NON-NLS-1$
case CAT_TYPE:
return "type"; //$NON-NLS-1$
case CAT_MEMBER:
return "member"; //$NON-NLS-1$
case CAT_INTERNAL:
return "internal"; //$NON-NLS-1$
case CAT_CODE_STYLE:
return "code style"; //$NON-NLS-1$
case CAT_POTENTIAL_PROGRAMMING_PROBLEM:
return "potential programming problem"; //$NON-NLS-1$
case CAT_NAME_SHADOWING_CONFLICT:
return "name shadowing conflict"; //$NON-NLS-1$
case CAT_DEPRECATION:
return "deprecation"; //$NON-NLS-1$
case CAT_UNNECESSARY_CODE:
return "unnecessary code"; //$NON-NLS-1$
case CAT_UNCHECKED_RAW:
return "unchecked/raw"; //$NON-NLS-1$
case CAT_NLS:
return "nls"; //$NON-NLS-1$
case CAT_RESTRICTION:
return "restriction"; //$NON-NLS-1$
}
return null;
}
/**
* Returns the marker type associated to this problem.
*
* @see org.eclipse.dltk.core.compiler.CategorizedProblem#getMarkerType()
*/
@Override
public String getMarkerType() {
return isTask() ? MARKER_TYPE_TASK : MARKER_TYPE_PROBLEM;
}
/**
* @since 3.0
*/
@Override
public boolean isTask() {
return this.id == IProblem.Task;
}
/**
* Answer a localized, human-readable message string which describes the
* problem.
*
* @return java.lang.String
*/
@Override
public String getMessage() {
return this.message;
}
public int getColumn() {
return this.column;
}
/**
* Answer the file name in which the problem was found.
*
* @return String
*/
@Override
public String getOriginatingFileName() {
return this.fileName;
}
/**
* Answer the end position of the problem (inclusive), or -1 if unknown.
*
* @return int
*/
@Override
public int getSourceEnd() {
return this.endPosition;
}
/**
* Answer the line number in source where the problem begins.
*
* @return int
*/
@Override
public int getSourceLineNumber() {
return this.line;
}
/**
* Answer the start position of the problem (inclusive), or -1 if unknown.
*
* @return int
*/
@Override
public int getSourceStart() {
return this.startPosition;
}
@Override
public ProblemSeverity getSeverity() {
return severity;
}
@Override
public void setSeverity(ProblemSeverity severity) {
this.severity = severity;
}
/*
* Helper method: checks the severity to see if the Error bit is set.
*
* @return boolean
*/
@Override
public boolean isError() {
return this.severity == ProblemSeverity.ERROR;
}
/*
* Helper method: checks the severity to see if the Error bit is not set.
*
* @return boolean
*/
@Override
public boolean isWarning() {
return this.severity == ProblemSeverity.WARNING;
}
public void setOriginatingFileName(String fileName) {
this.fileName = fileName;
}
/**
* Set the end position of the problem (inclusive), or -1 if unknown.
*
* Used for shifting problem positions.
*
* @param sourceEnd
* the new value of the sourceEnd of the receiver
*/
@Override
public void setSourceEnd(int sourceEnd) {
this.endPosition = sourceEnd;
}
/**
* Set the line number in source where the problem begins.
*
* @param lineNumber
* the new value of the line number of the receiver
*/
@Override
public void setSourceLineNumber(int lineNumber) {
this.line = lineNumber;
}
/**
* Set the start position of the problem (inclusive), or -1 if unknown.
*
* Used for shifting problem positions.
*
* @param sourceStart
* the new value of the source start position of the receiver
*/
@Override
public void setSourceStart(int sourceStart) {
this.startPosition = sourceStart;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer();
sb.append("Pb"); //$NON-NLS-1$
if (this.id != null) {
sb.append('#');
sb.append(this.id.name());
}
sb.append(' ');
sb.append(line);
sb.append('[');
sb.append(startPosition);
sb.append(".."); //$NON-NLS-1$
sb.append(endPosition);
sb.append(']');
sb.append(':');
if (this.message != null) {
sb.append(this.message);
} else {
if (this.arguments != null) {
for (int i = 0; i < this.arguments.length; i++) {
sb.append(' ');
sb.append(this.arguments[i]);
}
}
}
return sb.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + DefaultProblem.hashCode(arguments);
result = prime * result + column;
result = prime * result + endPosition;
result = prime * result
+ ((fileName == null) ? 0 : fileName.hashCode());
result = prime * result + (id == null ? 0 : id.hashCode());
result = prime * result + line;
result = prime * result + ((message == null) ? 0 : message.hashCode());
result = prime * result + severity.hashCode();
result = prime * result + startPosition;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final DefaultProblem other = (DefaultProblem) obj;
if (!Arrays.equals(arguments, other.arguments))
return false;
if (column != other.column)
return false;
if (endPosition != other.endPosition)
return false;
if (fileName == null) {
if (other.fileName != null)
return false;
} else if (!fileName.equals(other.fileName))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (line != other.line)
return false;
if (message == null) {
if (other.message != null)
return false;
} else if (!message.equals(other.message))
return false;
if (severity != other.severity)
return false;
if (startPosition != other.startPosition)
return false;
return true;
}
}