blob: 2fde916765b71c570e34edf949ee0758061dc9e4 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2020 IBM Corporation 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.
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# IBM Corporation - org.eclipse.jdt: initial API and implementation
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ltk.ui.sourceediting;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Position;
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
import org.eclipse.statet.ltk.issues.core.Problem;
import org.eclipse.statet.ltk.issues.core.ProblemRequestor;
/**
* Abstract annotation model dealing with marker annotations and temporary problems.
* Also acts as problem requester for its source unit.
*/
public abstract class SourceAnnotationModel extends ResourceMarkerAnnotationModel {
protected class SourceAnnotationProblemRequestor implements ProblemRequestor {
protected final List<Problem> reportedProblems= new ArrayList<>();
protected final boolean handleTemporaryProblems;
private int state= 1;
public SourceAnnotationProblemRequestor() {
this.handleTemporaryProblems= isHandlingTemporaryProblems();
}
@Override
public void acceptProblems(final Problem problem) {
if (this.handleTemporaryProblems) {
this.reportedProblems.add(problem);
}
}
@Override
public void acceptProblems(final String modelTypeId, final List<Problem> problems) {
if (this.handleTemporaryProblems) {
this.reportedProblems.addAll(problems);
}
}
@Override
public void finish() {
if (this.state < 0) {
throw new IllegalStateException("Already finished");
}
this.state= -1;
reportProblems(this.reportedProblems);
}
}
private final AtomicInteger reportingCounter= new AtomicInteger();
private final List<SourceProblemAnnotation> problemAnnotations= new ArrayList<>();
// private ReverseMap reverseMap= new ReverseMap();
// private List previouslyOverlaid= null;
// private List currentlyOverlaid= new ArrayList();
public SourceAnnotationModel(final IResource resource) {
super(resource);
}
protected abstract boolean isHandlingTemporaryProblems();
// @Override
// protected MarkerAnnotation createMarkerAnnotation(IMarker marker) {
// if (JavaMarkerAnnotation.isJavaAnnotation(marker))
// return new JavaMarkerAnnotation(marker);
// return super.createMarkerAnnotation(marker);
// }
// @Override
// protected AnnotationModelEvent createAnnotationModelEvent() {
// return new CompilationUnitAnnotationModelEvent(this, getResource());
// }
public final ProblemRequestor createProblemRequestor() {
this.reportingCounter.incrementAndGet();
return doCreateProblemRequestor();
}
protected ProblemRequestor doCreateProblemRequestor() {
return new SourceAnnotationProblemRequestor();
}
public void clearProblems(final String category) {
synchronized (getLockObject()) {
if (this.problemAnnotations.size() > 0) {
if (category == null) {
removeAnnotations(this.problemAnnotations, true, true);
this.problemAnnotations.clear();
}
else {
final Iterator<SourceProblemAnnotation> iter= this.problemAnnotations.iterator();
List<SourceProblemAnnotation> toRemove= null;
while (iter.hasNext()) {
final SourceProblemAnnotation annotation= iter.next();
if (annotation.getProblem().getCategoryId() == category) {
iter.remove();
if (toRemove == null) {
toRemove= new ArrayList<>();
}
toRemove.add(annotation);
}
}
if (toRemove != null) {
removeAnnotations(toRemove, true, true);
}
}
}
}
}
private void reportProblems(final List<Problem> reportedProblems) {
boolean reportedProblemsChanged= false;
synchronized (getLockObject()) {
if (this.reportingCounter.decrementAndGet() != 0) {
return;
}
// this.previouslyOverlaid= this.currentlyOverlaid;
// this.currentlyOverlaid= new ArrayList();
if (this.problemAnnotations.size() > 0) {
reportedProblemsChanged= true;
removeAnnotations(this.problemAnnotations, false, true);
this.problemAnnotations.clear();
}
if (reportedProblems != null && reportedProblems.size() > 0) {
for (final Problem problem : reportedProblems) {
final Position position= createPosition(problem);
if (position != null) {
try {
final SourceProblemAnnotation annotation= createAnnotation(problem);
// overlayMarkers(position, annotation);
if (annotation != null) {
addAnnotation(annotation, position, false);
this.problemAnnotations.add(annotation);
reportedProblemsChanged= true;
}
} catch (final BadLocationException x) {
// ignore invalid position
}
}
}
}
// removeMarkerOverlays(isCanceled);
// this.previouslyOverlaid= null;
}
if (reportedProblemsChanged) {
fireModelChanged();
}
}
// private void overlayMarkers(Position position, ProblemAnnotation problemAnnotation) {
// Object value= getAnnotations(position);
// if (value instanceof List) {
// List list= (List) value;
// for (Iterator e= list.iterator(); e.hasNext();)
// setOverlay(e.next(), problemAnnotation);
// } else {
// setOverlay(value, problemAnnotation);
// }
// }
//
// private void setOverlay(Object value, ProblemAnnotation problemAnnotation) {
// if (value instanceof JavaMarkerAnnotation) {
// JavaMarkerAnnotation annotation= (JavaMarkerAnnotation) value;
// if (annotation.isProblem()) {
// annotation.setOverlay(problemAnnotation);
// this.previouslyOverlaid.remove(annotation);
// this.currentlyOverlaid.add(annotation);
// }
// } else {
// }
// }
//
// private void removeMarkerOverlays(boolean isCanceled) {
// if (isCanceled) {
// this.currentlyOverlaid.addAll(this.previouslyOverlaid);
// } else if (this.previouslyOverlaid != null) {
// Iterator e= this.previouslyOverlaid.iterator();
// while (e.hasNext()) {
// JavaMarkerAnnotation annotation= (JavaMarkerAnnotation) e.next();
// annotation.setOverlay(null);
// }
// }
// }
protected Position createPosition(final Problem problem) {
final int start= problem.getSourceStartOffset();
final int end= problem.getSourceEndOffset();
if (start < 0 && end < 0) {
assert (start >= 0 && end >= 0);
}
return new Position(start, end-start);
}
protected SourceProblemAnnotation createAnnotation(final Problem problem) {
return null;
}
// @Override
// protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException {
// super.addAnnotation(annotation, position, fireModelChanged);
//
// synchronized (getLockObject()) {
// Object cached= this.reverseMap.get(position);
// if (cached == null)
// this.reverseMap.put(position, annotation);
// else if (cached instanceof List) {
// List list= (List) cached;
// list.add(annotation);
// } else if (cached instanceof Annotation) {
// List list= new ArrayList(2);
// list.add(cached);
// list.add(annotation);
// this.reverseMap.put(position, list);
// }
// }
// }
//
// @Override
// protected void removeAllAnnotations(boolean fireModelChanged) {
// super.removeAllAnnotations(fireModelChanged);
// synchronized (getLockObject()) {
// this.reverseMap.clear();
// }
// }
//
// @Override
// protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) {
// Position position= getPosition(annotation);
// synchronized (getLockObject()) {
// Object cached= this.reverseMap.get(position);
// if (cached instanceof List) {
// List list= (List) cached;
// list.remove(annotation);
// if (list.size() == 1) {
// this.reverseMap.put(position, list.get(0));
// list.clear();
// }
// } else if (cached instanceof Annotation) {
// this.reverseMap.remove(position);
// }
// }
// super.removeAnnotation(annotation, fireModelChanged);
// }
}