blob: b98c6abf381916b5795549c3452f46d9bbf96529 [file] [log] [blame]
package org.eclipse.jdt.internal.core.builder.impl;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.internal.core.builder.*;
import org.eclipse.jdt.core.*;
import java.util.*;
/**
* An <code>IProblemReporter</code> that reports problems using the <code>IMarker</code> API.
* It keeps the problems backed in a ProblemTable as well, since the marker manager only
* maintains problems for the last built state.
* In particular, the test suite requires that problems be retrieved for previously built states,
* and for currently built states (batch and incremental builds of the same workspace).
*/
public class MarkerProblemReporter implements IProblemReporter {
protected IProject fProject;
protected ProblemTable fProblemTable = new ProblemTable();
private IDevelopmentContext dc;
/**
* Creates a new MarkerProblemReporter that is not initialized.
* Used only during deserialization.
*/
public MarkerProblemReporter() {
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public IProblemReporter copy() {
/* The copy still reports to the same marker manager, since there's only one,
* but the backing problem table is copied. */
MarkerProblemReporter copy = new MarkerProblemReporter(fProject, this.dc);
copy.fProblemTable = (ProblemTable) fProblemTable.copy();
return copy;
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public Enumeration getAllProblems() {
return fProblemTable.getAllProblems();
}
/**
* Returns the extra flags for the given marker.
*/
protected int getFlags(IMarker marker) throws CoreException {
if (!marker.exists()) return 0;
Integer flags = (Integer) marker.getAttribute(IJavaModelMarker.FLAGS);
return flags == null ? 0 : flags.intValue();
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public Enumeration getImageProblems() {
return fProblemTable.getImageProblems();
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public Enumeration getProblemKeys() {
return fProblemTable.getProblemKeys();
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public Enumeration getProblems(Object sourceID) {
return fProblemTable.getProblems(sourceID);
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public Vector getProblemVector(Object sourceID) {
return fProblemTable.getProblemVector(sourceID);
}
/**
* Returns the resource for the given source ID.
* Returns null if the source ID is not a SourceEntry or resource,
* or if the resource could not be found.
*/
protected IResource getResource(Object sourceID) {
if (sourceID instanceof IResource) {
return (IResource) sourceID;
}
if (!(sourceID instanceof SourceEntry))
return null;
SourceEntry entry = (SourceEntry) sourceID;
IPath path = entry.getPath();
if (path.isAbsolute()) {
if (fProject.getFullPath().isPrefixOf(path)) {
return fProject.getWorkspace().getRoot().getFile(path);
}
} else {
return fProject.getFile(path);
}
return null;
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public boolean hasProblems(Object sourceID) {
return fProblemTable.hasProblems(sourceID);
}
/**
* Creates a marker from the given problem detail and add it to the resource.
* The marker is as follows:
* - its type is T_PROBLEM
* - its plugin ID is the JavaBuilder's plugin ID
* - its message is the problem's message
* - its priority reflects the severity of the problem
* - its range is the problem's range
* - it has an extra attribute "ID" which holds the problem's id
*/
protected void markerFromProblemDetail(IResource resource, IProblemDetail problem) throws CoreException {
IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
marker.setAttribute(IMarker.MESSAGE, problem.getMessage());
int sev = problem.getSeverity();
marker.setAttribute(IMarker.SEVERITY , ((sev & IProblemDetail.S_ERROR) != 0 ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING));
if ((sev & ProblemDetailImpl.S_SYNTAX_ERROR) != 0) {
setFlags(marker, ProblemDetailImpl.S_SYNTAX_ERROR);
}
marker.setAttribute("ID"/*nonNLS*/, new Integer(problem.getID()));
int start = problem.getStartPos();
marker.setAttribute(IMarker.CHAR_START, new Integer(start));
marker.setAttribute(IMarker.CHAR_END, new Integer(problem.getEndPos() + 1));
marker.setAttribute(IMarker.LINE_NUMBER, new Integer(problem.getLineNumber()));
// compute a user-friendly location
IJavaElement element = JavaCore.create(resource);
if (element instanceof ICompilationUnit){ // try to find a finer grain element
ICompilationUnit unit = (ICompilationUnit) element;
IJavaElement fragment = unit.getElementAt(start);
if (fragment != null) element = fragment;
}
String location = null;
if (element instanceof org.eclipse.jdt.internal.core.JavaElement){
location = ((org.eclipse.jdt.internal.core.JavaElement)element).readableName();
}
if (location != null) marker.setAttribute(IMarker.LOCATION, location);
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public void putProblem(Object sourceID, IProblemDetail problem) {
/* Delegate first to the backing problem table. */
fProblemTable.putProblem(sourceID, problem);
/* Now update the markers. */
IResource resource = getResource(sourceID);
if (resource != null) {
try {
markerFromProblemDetail(resource, problem);
} catch (CoreException e) {
throw ((JavaDevelopmentContextImpl)this.dc).internalException(e);
}
}
}
/**
* Remove problem markers for the given element. If removeSyntaxErrors is true, remove only syntax errors,
* otherwise remove only non-syntax errors.
*/
protected void removeMarkers(Object sourceID, boolean removeSyntaxErrors) {
IResource resource = getResource(sourceID);
if (resource != null && resource.exists()) {
try {
IMarker[] markers = resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
if (markers.length > 0) {
Vector toRemove = new Vector(markers.length);
for (int i = 0; i < markers.length; i++) {
IMarker marker = markers[i];
try {
boolean isSyntaxError = (getFlags(marker) & ProblemDetailImpl.S_SYNTAX_ERROR) != 0;
if (isSyntaxError == removeSyntaxErrors) {
toRemove.addElement(marker);
}
} catch(CoreException e){ // marker state cannot be accessed - ignore it
}
}
if (toRemove.size() > 0) {
IMarker[] markersToRemove = new IMarker[toRemove.size()];
toRemove.copyInto(markersToRemove);
resource.getWorkspace().deleteMarkers(markersToRemove);
}
}
} catch (CoreException e) { // silently absorb CoreException during marker deletion
}
}
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public void removeNonSyntaxErrors(Object sourceID) {
/* Delegate first to the backing problem table. */
fProblemTable.removeNonSyntaxErrors(sourceID);
removeMarkers(sourceID, false);
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public void removeProblems(Object sourceID) {
/* Delegate first to the backing problem table. */
fProblemTable.removeProblems(sourceID);
/* Now update the markers. */
IResource resource = getResource(sourceID);
if (resource != null) {
try {
// See PR 1G2NPUH
// If the resource doesn't exist, we don't want to try to remove markers for it.
// Simply ignore. This test is done to prevent from having an exception.
if (resource.exists())
resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
} catch (CoreException e) {
throw ((JavaDevelopmentContextImpl)this.dc).internalException(e);
}
}
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public void removeSyntaxErrors(Object sourceID) {
/* Delegate first to the backing problem table. */
fProblemTable.removeSyntaxErrors(sourceID);
removeMarkers(sourceID, true);
}
/**
* Sets the extra flags for the given marker.
*/
protected void setFlags(IMarker marker, int flags) throws CoreException {
// Don't take space if no extra flags.
marker.setAttribute(IJavaModelMarker.FLAGS, flags == 0 ? null : new Integer(flags));
}
/**
* Creates a new MarkerProblemReporter that reports problems as markers
* against the given project.
*/
public MarkerProblemReporter(IProject project, IDevelopmentContext dc) {
initialize(project, dc);
}
/**
* @see org.eclipse.jdt.internal.core.builder.IProblemReporter
*/
public void initialize(IProject project, IDevelopmentContext dc) {
this.fProject = project;
this.dc = dc;
}
}