| /******************************************************************************* |
| * 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; |
| } |
| |
| } |