blob: a32c4de02e3a851e65bacaf5ed3b783e9637559c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.text;
import org.eclipse.jface.text.Position;
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
import java.util.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.source.*;
import org.eclipse.pde.internal.ui.editor.context.XMLDocumentSetupParticpant;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.spelling.*;
/**
* Reconcile strategy used for spell checking XML documents.
*
*/
public class XMLReconcilingStrategy extends SpellingReconcileStrategy {
/**
* Spelling problem collector.
*/
private class SpellingProblemCollector implements ISpellingProblemCollector {
/** Annotation model. */
private IAnnotationModel fAnnotationModel;
/** Annotations to add. */
private Map<SpellingAnnotation, Position> fAddAnnotations;
/** Lock object for modifying the annotations. */
private Object fLockObject;
/**
* Initializes this collector with the given annotation model.
*
* @param annotationModel the annotation model
*/
public SpellingProblemCollector(IAnnotationModel annotationModel) {
Assert.isLegal(annotationModel != null);
fAnnotationModel = annotationModel;
if (fAnnotationModel instanceof ISynchronizable)
fLockObject = ((ISynchronizable) fAnnotationModel).getLockObject();
else
fLockObject = fAnnotationModel;
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept(org.eclipse.ui.texteditor.spelling.SpellingProblem)
*/
@Override
public void accept(SpellingProblem problem) {
fAddAnnotations.put(new SpellingAnnotation(problem), new Position(problem.getOffset(), problem.getLength()));
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#beginCollecting()
*/
@Override
public void beginCollecting() {
fAddAnnotations = new HashMap<>();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#endCollecting()
*/
@Override
public void endCollecting() {
synchronized (fLockObject) {
for (Iterator<SpellingAnnotation> iter = fAddAnnotations.keySet().iterator(); iter.hasNext();) {
Annotation annotation = iter.next();
fAnnotationModel.addAnnotation(annotation, fAddAnnotations.get(annotation));
}
deleteNonstringSpellingAnnotations(fAddAnnotations.keySet().iterator());
}
fAddAnnotations = null;
}
}
public XMLReconcilingStrategy(ISourceViewer viewer) {
super(viewer, EditorsUI.getSpellingService());
}
@Override
public void reconcile(IRegion region) {
deleteAllAnnotations(region);
super.reconcile(region);
}
/**
* Deletes all the spelling annotations located inside the area marked by <code>region</code>
*/
private void deleteAllAnnotations(IRegion region) {
IAnnotationModel model = getAnnotationModel();
if (model == null)
return;
Iterator<?> iter = model.getAnnotationIterator();
while (iter.hasNext()) {
Annotation annotation = (Annotation) iter.next();
if (annotation instanceof SpellingAnnotation) {
SpellingAnnotation spellingAnnotation = (SpellingAnnotation) annotation;
Position position = model.getPosition(spellingAnnotation);
if (position.overlapsWith(region.getOffset(), region.getLength())) {
model.removeAnnotation(spellingAnnotation);
}
}
}
}
/**
* Deletes the spelling annotations marked for XML Tags
*/
private void deleteNonstringSpellingAnnotations(Iterator<SpellingAnnotation> iter) {
if (!(getDocument() instanceof IDocumentExtension3)) { //can not proceed otherwise
return;
}
IDocumentExtension3 document = (IDocumentExtension3) getDocument();
IDocumentPartitioner docPartitioner = document.getDocumentPartitioner(XMLStringPartitionScanner.XML_STRING);
IDocumentPartitioner pdeXMLPartitioner = document.getDocumentPartitioner(XMLDocumentSetupParticpant.XML_PARTITIONING);
IAnnotationModel model = getAnnotationModel();
while (iter.hasNext()) {
Object annotation = iter.next();
if (annotation instanceof SpellingAnnotation) {
SpellingAnnotation spellingAnnotation = (SpellingAnnotation) annotation;
Position position = model.getPosition(spellingAnnotation);
String docContentType = docPartitioner.getContentType(position.getOffset());
String pdeXMLContentType = pdeXMLPartitioner.getContentType(position.getOffset());
if ((!XMLStringPartitionScanner.XML_STRING.equalsIgnoreCase(docContentType) && !XMLStringPartitionScanner.CUSTOM_TAG.equalsIgnoreCase(docContentType)) // delete the annotation if the marked position was not selected by XML_STRING document partitioner
|| (XMLStringPartitionScanner.CUSTOM_TAG.equalsIgnoreCase(docContentType)) && XMLPartitionScanner.XML_TAG.equalsIgnoreCase(pdeXMLContentType)) { // also delete the annotations that are positioned at special XML Tags
model.removeAnnotation(spellingAnnotation);
}
}
}
}
@Override
protected ISpellingProblemCollector createSpellingProblemCollector() {
IAnnotationModel model = getAnnotationModel();
if (model == null)
return null;
return new SpellingProblemCollector(model);
}
}