/******************************************************************************* * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ 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; } }