/*=============================================================================# # Copyright (c) 2008-2016 Stephan Wahlbrink (WalWare.de) 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 # # Contributors: # IBM Corporation - concepts in JDT # Stephan Wahlbrink - initial API in StatET #=============================================================================*/ package de.walware.ecommons.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 de.walware.ecommons.ltk.IProblem; import de.walware.ecommons.ltk.IProblemRequestor; /** * 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 ProblemRequestor implements IProblemRequestor { protected final List<IProblem> fReportedProblems = new ArrayList<>(); protected final boolean fHandleTemporaryProblems; private int fState = 1; public ProblemRequestor() { fHandleTemporaryProblems = isHandlingTemporaryProblems(); } @Override public void acceptProblems(final IProblem problem) { if (fHandleTemporaryProblems) { fReportedProblems.add(problem); } } @Override public void acceptProblems(final String modelTypeId, final List<IProblem> problems) { if (fHandleTemporaryProblems) { fReportedProblems.addAll(problems); } } @Override public void finish() { if (fState < 0) { throw new IllegalStateException("Already finished"); } fState = -1; reportProblems(fReportedProblems); } } private final AtomicInteger fReportingCounter = new AtomicInteger(); private final List<SourceProblemAnnotation> fProblemAnnotations = new ArrayList<>(); // private ReverseMap fReverseMap= new ReverseMap(); // private List fPreviouslyOverlaid= null; // private List fCurrentlyOverlaid= 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 IProblemRequestor createProblemRequestor() { fReportingCounter.incrementAndGet(); return doCreateProblemRequestor(); } protected IProblemRequestor doCreateProblemRequestor() { return new ProblemRequestor(); } public void clearProblems(final String category) { synchronized (getLockObject()) { if (fProblemAnnotations.size() > 0) { if (category == null) { removeAnnotations(fProblemAnnotations, true, true); fProblemAnnotations.clear(); } else { final Iterator<SourceProblemAnnotation> iter = fProblemAnnotations.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<IProblem> reportedProblems) { boolean reportedProblemsChanged = false; synchronized (getLockObject()) { if (fReportingCounter.decrementAndGet() != 0) { return; } // fPreviouslyOverlaid = fCurrentlyOverlaid; // fCurrentlyOverlaid = new ArrayList(); if (fProblemAnnotations.size() > 0) { reportedProblemsChanged = true; removeAnnotations(fProblemAnnotations, false, true); fProblemAnnotations.clear(); } if (reportedProblems != null && reportedProblems.size() > 0) { for (final IProblem 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); fProblemAnnotations.add(annotation); reportedProblemsChanged = true; } } catch (final BadLocationException x) { // ignore invalid position } } } } // removeMarkerOverlays(isCanceled); // fPreviouslyOverlaid= 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); // fPreviouslyOverlaid.remove(annotation); // fCurrentlyOverlaid.add(annotation); // } // } else { // } // } // // private void removeMarkerOverlays(boolean isCanceled) { // if (isCanceled) { // fCurrentlyOverlaid.addAll(fPreviouslyOverlaid); // } else if (fPreviouslyOverlaid != null) { // Iterator e= fPreviouslyOverlaid.iterator(); // while (e.hasNext()) { // JavaMarkerAnnotation annotation= (JavaMarkerAnnotation) e.next(); // annotation.setOverlay(null); // } // } // } protected Position createPosition(final IProblem problem) { final int start = problem.getSourceStartOffset(); final int end = problem.getSourceStopOffset(); if (start < 0 && end < 0) { assert (start >= 0 && end >= 0); } return new Position(start, end-start); } protected SourceProblemAnnotation createAnnotation(final IProblem problem) { return null; } // @Override // protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException { // super.addAnnotation(annotation, position, fireModelChanged); // // synchronized (getLockObject()) { // Object cached = fReverseMap.get(position); // if (cached == null) // fReverseMap.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); // fReverseMap.put(position, list); // } // } // } // // @Override // protected void removeAllAnnotations(boolean fireModelChanged) { // super.removeAllAnnotations(fireModelChanged); // synchronized (getLockObject()) { // fReverseMap.clear(); // } // } // // @Override // protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) { // Position position = getPosition(annotation); // synchronized (getLockObject()) { // Object cached= fReverseMap.get(position); // if (cached instanceof List) { // List list= (List) cached; // list.remove(annotation); // if (list.size() == 1) { // fReverseMap.put(position, list.get(0)); // list.clear(); // } // } else if (cached instanceof Annotation) { // fReverseMap.remove(position); // } // } // super.removeAnnotation(annotation, fireModelChanged); // } }