// Copyright (c) 2006 by Leif Frenzel <himself@leiffrenzel.de> // All rights reserved. package net.sf.eclipsefp.haskell.ui.internal.editors.cabal; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescription; import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionLoader; import org.eclipse.jface.text.AbstractDocument; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.reconciler.DirtyRegion; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy; /** * reconciler for Cabal * * @author JP Moresmau * @author Leif Frenzel */ class CabalReconcilingStrategy extends SpellingReconcileStrategy { private final CabalFormEditor editor; private final CabalFoldingStructureProvider foldingStructureProvider; CabalReconcilingStrategy( final CabalFormEditor editor,final ISourceViewer sourceViewer ) { super(sourceViewer,EditorsUI.getSpellingService()); this.editor = editor; foldingStructureProvider = new CabalFoldingStructureProvider( editor ); } // interface methods of IReconcilingStrategy //////////////////////////////////////////// @Override public void reconcile( final IRegion region ) { AbstractDocument document = (AbstractDocument) getDocument(); IAnnotationModel model = getAnnotationModel(); if (region.getOffset() == 0 && region.getLength() == document.getLength()) { //reconciling whole document super.reconcile(region); } else { //partial reconciliation //preserve spelling annotations first @SuppressWarnings("unchecked") Iterator<Annotation> iter = model.getAnnotationIterator(); Map<Annotation,Position> spellingErrors = new HashMap<>(); while (iter.hasNext()) { Annotation annotation = iter.next(); if (annotation instanceof SpellingAnnotation) { SpellingAnnotation spellingAnnotation = (SpellingAnnotation) annotation; Position position = model.getPosition(spellingAnnotation); spellingErrors.put(spellingAnnotation, position); } } //reconcile super.reconcile(region); //restore annotations model = getAnnotationModel(); iter = spellingErrors.keySet().iterator(); while (iter.hasNext()) { Annotation annotation = iter.next(); model.addAnnotation(annotation, spellingErrors.get(annotation)); } } reconcile(); } @Override public void reconcile( final DirtyRegion dirtyRegion, final IRegion subRegion ) { super.reconcile( dirtyRegion, subRegion ); reconcile(); } @Override public void setDocument( final IDocument document ) { super.setDocument( document ); foldingStructureProvider.setDocument( document ); } // interface methods of IReconcilingStrategyExtension ///////////////////////////////////////////////////// @Override public void initialReconcile() { reconcile(); } // helping methods ////////////////// private void reconcile() { String content = getDocument().get(); final PackageDescription pd = PackageDescriptionLoader.load( content ); if (editor!=null){ Display.getDefault().asyncExec( new Runnable() { @Override public void run() { editor.setPackageDescription( pd ); } } ); foldingStructureProvider.updateFoldingRegions( pd ); } } }