blob: b49b9ce9c03e609327c649210197072a0a5289b7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.internal.ui.text.spelling;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.core.IProblemRequestor;
import org.eclipse.dltk.ui.text.spelling.SpellCheckDelegate;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.ui.texteditor.spelling.SpellingService;
/**
* Reconcile strategy for spell checking comments.
*
* @since 4.0
*/
public class ScriptSpellingReconcileStrategy
implements IReconcilingStrategy, IReconcilingStrategyExtension {
/**
* Spelling problem collector that forwards {@link SpellingProblem}s as
* {@link IProblem}s to the {@link IProblemRequestor}.
*/
private class SpellingProblemCollector
implements ISpellingProblemCollector {
SpellingProblemCollector() {
}
@Override
public void accept(SpellingProblem problem) {
final IProblemRequestor requestor = fRequestor;
if (requestor != null) {
try {
final IDocument document = getDocument();
int line = document.getLineOfOffset(problem.getOffset())
+ 1;
String word = document.get(problem.getOffset(),
problem.getLength());
// boolean dictionaryMatch= false;
// boolean sentenceStart= false;
// if (problem instanceof JavaSpellingProblem) {
// dictionaryMatch=
// ((JavaSpellingProblem)problem).isDictionaryMatch();
// sentenceStart= ((JavaSpellingProblem)
// problem).isSentenceStart();
// }
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81514
IEditorInput editorInput = fEditor.getEditorInput();
if (editorInput != null) {
ScriptSpellingProblem iProblem = new ScriptSpellingProblem(
problem.getOffset(),
problem.getOffset() + problem.getLength(), line,
problem.getMessage(), word,
false /* dictionaryMatch */,
false /* sentenceStart */, document,
editorInput.getName(), problem);
requestor.acceptProblem(iProblem);
}
} catch (BadLocationException x) {
// drop this SpellingProblem
}
}
}
@Override
public void beginCollecting() {
if (fRequestor != null)
fRequestor.beginReporting();
}
@Override
public void endCollecting() {
if (fRequestor != null)
fRequestor.endReporting();
}
}
private final SpellingService fSpellingService;
/** The text editor to operate on. */
protected final ITextEditor fEditor;
/** The problem requester. */
protected IProblemRequestor fRequestor;
private final String fPartitioning;
/** The spelling context containing the Java source content type. */
private final SpellingContext fSpellingContext;
protected SpellCheckDelegate fCheckDelegate;
/**
* Creates a new comment reconcile strategy.
*
* @param editor
* the text editor to operate on
* @param partitioning
*/
public ScriptSpellingReconcileStrategy(ITextEditor editor,
String partitioning, IContentType contentType,
SpellCheckDelegate checkDelegate) {
fSpellingService = EditorsUI.getSpellingService();
fEditor = editor;
fPartitioning = partitioning;
fSpellingContext = new SpellingContext();
fSpellingContext.setContentType(contentType);
fCheckDelegate = checkDelegate;
}
@Override
public void initialReconcile() {
reconcile(new Region(0, fDocument.getLength()));
}
@Override
public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
try {
IRegion startLineInfo = fDocument
.getLineInformationOfOffset(subRegion.getOffset());
IRegion endLineInfo = fDocument
.getLineInformationOfOffset(subRegion.getOffset()
+ Math.max(0, subRegion.getLength() - 1));
if (startLineInfo.getOffset() == endLineInfo.getOffset())
subRegion = startLineInfo;
else
subRegion = new Region(startLineInfo.getOffset(),
endLineInfo.getOffset()
+ Math.max(0, endLineInfo.getLength() - 1)
- startLineInfo.getOffset());
} catch (BadLocationException e) {
subRegion = new Region(0, fDocument.getLength());
}
reconcile(subRegion);
}
@Override
public void reconcile(IRegion region) {
if (fRequestor != null && isSpellingEnabled()) {
fRequestor.beginReporting();
try {
ITypedRegion[] partitions = TextUtilities.computePartitioning(
fDocument, fPartitioning, region.getOffset(),
region.getLength(), false);
List<IRegion> lst = new ArrayList<>(partitions.length);
for (int index = 0; index < partitions.length; index++) {
if (fProgressMonitor != null
&& fProgressMonitor.isCanceled())
return;
// if (listener.isProblemsThresholdReached())
// return;
final ITypedRegion partition = partitions[index];
// if (isIgnoringJavaStrings
// && type.equals(IJavaPartitions.JAVA_STRING))
// continue;
final IRegion[] regions = fCheckDelegate
.computeRegions(partition);
if (regions != null) {
Collections.addAll(lst, regions);
}
}
if (lst.size() > 0) {
fSpellingService.check(fDocument,
lst.toArray(new IRegion[lst.size()]),
fSpellingContext, fSpellingProblemCollector,
fProgressMonitor);
}
} catch (BadLocationException e) {
// ignore
} finally {
fRequestor.endReporting();
}
}
}
private boolean isSpellingEnabled() {
return EditorsUI.getPreferenceStore()
.getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED);
}
@Override
public void setDocument(IDocument document) {
fDocument = document;
fSpellingProblemCollector = new SpellingProblemCollector();
updateProblemRequester();
}
/**
* Update the problem requester based on the current editor
*/
private void updateProblemRequester() {
IAnnotationModel model = getAnnotationModel();
fRequestor = (model instanceof IProblemRequestor)
? (IProblemRequestor) model
: null;
}
private IAnnotationModel getAnnotationModel() {
final IDocumentProvider documentProvider = fEditor
.getDocumentProvider();
if (documentProvider == null)
return null;
return documentProvider.getAnnotationModel(fEditor.getEditorInput());
}
/** The document to operate on. */
private IDocument fDocument;
/** The progress monitor. */
private IProgressMonitor fProgressMonitor;
private ISpellingProblemCollector fSpellingProblemCollector;
/**
* Returns the document which is spell checked.
*
* @return the document
*/
protected final IDocument getDocument() {
return fDocument;
}
@Override
public final void setProgressMonitor(IProgressMonitor monitor) {
fProgressMonitor = monitor;
}
}