| /***************************************************************************** |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *****************************************************************************/ |
| |
| package org.eclipse.jdt.internal.ui.text.spelling; |
| |
| import java.text.MessageFormat; |
| import java.util.Locale; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| |
| import org.eclipse.jface.preference.IPreferenceStore; |
| |
| 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.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.texteditor.ITextEditor; |
| |
| import org.eclipse.jdt.core.IProblemRequestor; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| |
| import org.eclipse.jdt.internal.ui.JavaUIMessages; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEventListener; |
| |
| /** |
| * Reconcile strategy to spell-check comments. |
| * |
| * @since 3.0 |
| */ |
| public class SpellReconcileStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension, ISpellEventListener { |
| |
| /** |
| * Spelling problem to be accepted by problem requestors. |
| */ |
| public class SpellProblem implements IProblem { |
| |
| /** The id of the problem */ |
| public static final int Spelling= 0x80000000; |
| |
| /** The end offset of the problem */ |
| private int fEnd= 0; |
| |
| /** The line number of the problem */ |
| private int fLine= 1; |
| |
| /** Was the word found in the dictionary? */ |
| private boolean fMatch; |
| |
| /** Does the word start a new sentence? */ |
| private boolean fSentence= false; |
| |
| /** The start offset of the problem */ |
| private int fStart= 0; |
| |
| /** The word which caused the problem */ |
| private final String fWord; |
| |
| /** |
| * Creates a new spelling problem |
| * |
| * @param word |
| * The word which caused the problem |
| */ |
| protected SpellProblem(final String word) { |
| fWord= word; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getArguments() |
| */ |
| public String[] getArguments() { |
| |
| String prefix= ""; //$NON-NLS-1$ |
| String postfix= ""; //$NON-NLS-1$ |
| |
| try { |
| |
| final IRegion line= fDocument.getLineInformationOfOffset(fStart); |
| |
| prefix= fDocument.get(line.getOffset(), fStart - line.getOffset()); |
| postfix= fDocument.get(fEnd + 1, line.getOffset() + line.getLength() - fEnd); |
| |
| } catch (BadLocationException exception) { |
| // Do nothing |
| } |
| return new String[] { fWord, prefix, postfix, fSentence ? Boolean.toString(true) : Boolean.toString(false), fMatch ? Boolean.toString(true) : Boolean.toString(false)}; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getID() |
| */ |
| public int getID() { |
| return Spelling; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getMessage() |
| */ |
| public String getMessage() { |
| |
| if (fSentence && fMatch) |
| return MessageFormat.format(JavaUIMessages.getString("Spelling.error.case.label"), new String[] { fWord }); //$NON-NLS-1$ |
| |
| return MessageFormat.format(JavaUIMessages.getString("Spelling.error.label"), new String[] { fWord }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getOriginatingFileName() |
| */ |
| public char[] getOriginatingFileName() { |
| return fEditor.getEditorInput().getName().toCharArray(); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getSourceEnd() |
| */ |
| public final int getSourceEnd() { |
| return fEnd; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getSourceLineNumber() |
| */ |
| public final int getSourceLineNumber() { |
| return fLine; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#getSourceStart() |
| */ |
| public final int getSourceStart() { |
| return fStart; |
| } |
| |
| /** |
| * Was the problem word found in the dictionary? |
| * |
| * @return <code>true</code> iff the word was found, <code>false</code> |
| * otherwise |
| */ |
| public final boolean isDictionaryMatch() { |
| return fMatch; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#isError() |
| */ |
| public final boolean isError() { |
| return false; |
| } |
| |
| /** |
| * Does the problem word start a new sentence? |
| * |
| * @return <code>true</code> iff it starts a new sentence, <code>false</code> |
| * otherwise |
| */ |
| public final boolean isSentenceStart() { |
| return fSentence; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#isWarning() |
| */ |
| public final boolean isWarning() { |
| return true; |
| } |
| |
| /** |
| * Sets whether the problem word was found in the dictionary. |
| * |
| * @param match |
| * <code>true</code> iff the word was found, <code>false</code> |
| * otherwise |
| */ |
| public final void setDictionaryMatch(final boolean match) { |
| fMatch= match; |
| } |
| |
| /** |
| * Sets whether the problem word starts a new sentence. |
| * |
| * @param sentence |
| * <code>true</code> iff the word starts a new sentence, |
| * <code>false</code> otherwise. |
| */ |
| public final void setSentenceStart(final boolean sentence) { |
| fSentence= sentence; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#setSourceEnd(int) |
| */ |
| public final void setSourceEnd(final int end) { |
| fEnd= end; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#setSourceLineNumber(int) |
| */ |
| public final void setSourceLineNumber(final int line) { |
| fLine= line; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.core.compiler.IProblem#setSourceStart(int) |
| */ |
| public final void setSourceStart(final int start) { |
| fStart= start; |
| } |
| } |
| |
| /** The document to operate on. */ |
| private IDocument fDocument= null; |
| |
| /** The text editor to operate on. */ |
| private final ITextEditor fEditor; |
| |
| /** The current locale. */ |
| private Locale fLocale= SpellCheckEngine.getDefaultLocale(); |
| |
| /** The partitioning of the document. */ |
| private final String fPartitioning; |
| |
| /** The preference store to use. */ |
| private final IPreferenceStore fPreferences; |
| |
| /** The problem requestor. */ |
| private IProblemRequestor fRequestor; |
| |
| /** The progress monitor. */ |
| private IProgressMonitor fProgressMonitor; |
| |
| |
| /** |
| * Creates a new comment reconcile strategy. |
| * |
| * @param editor |
| * The text editor to operate on |
| * @param partitioning |
| * The partitioning of the document |
| * @param store |
| * The preference store to get the preferences from |
| */ |
| public SpellReconcileStrategy(final ITextEditor editor, final String partitioning, final IPreferenceStore store) { |
| fEditor= editor; |
| fPartitioning= partitioning; |
| fPreferences= store; |
| |
| updateProblemRequestor(); |
| } |
| |
| /** |
| * Returns the current locale of the spell checking preferences. |
| * |
| * @return The current locale of the spell checking preferences |
| */ |
| public Locale getLocale() { |
| |
| final String locale= fPreferences.getString(ISpellCheckPreferenceKeys.SPELLING_LOCALE); |
| if (locale.equals(fLocale.toString())) |
| return fLocale; |
| |
| if (locale.length() >= 5) |
| return new Locale(locale.substring(0, 2), locale.substring(3, 5)); |
| |
| return SpellCheckEngine.getDefaultLocale(); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent) |
| */ |
| public void handle(final ISpellEvent event) { |
| |
| if (fRequestor != null) { |
| |
| final SpellProblem problem= new SpellProblem(event.getWord()); |
| |
| problem.setSourceStart(event.getBegin()); |
| problem.setSourceEnd(event.getEnd()); |
| problem.setSentenceStart(event.isStart()); |
| problem.setDictionaryMatch(event.isMatch()); |
| |
| try { |
| problem.setSourceLineNumber(fDocument.getLineOfOffset(event.getBegin()) + 1); |
| } catch (BadLocationException x) { |
| // Do nothing |
| } |
| |
| fRequestor.acceptProblem(problem); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile() |
| */ |
| public void initialReconcile() { |
| reconcile(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,org.eclipse.jface.text.IRegion) |
| */ |
| public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) { |
| reconcile(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion) |
| */ |
| public void reconcile(IRegion region) { |
| reconcile(); |
| } |
| |
| private void reconcile() { |
| |
| if (fPreferences.getBoolean(ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING) && fRequestor != null) { |
| |
| try { |
| |
| fRequestor.beginReporting(); |
| |
| ITypedRegion partition= null; |
| final ITypedRegion[] partitions= TextUtilities.computePartitioning(fDocument, fPartitioning, 0, fDocument.getLength(), false); |
| |
| final Locale locale= getLocale(); |
| final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); |
| |
| final ISpellChecker checker= engine.createSpellChecker(locale, fPreferences); |
| if (checker != null) { |
| try { |
| checker.addListener(this); |
| |
| for (int index= 0; index < partitions.length; index++) { |
| if (fProgressMonitor != null && fProgressMonitor.isCanceled()) |
| return; |
| |
| partition= partitions[index]; |
| if (!partition.getType().equals(IDocument.DEFAULT_CONTENT_TYPE)) |
| checker.execute(new SpellCheckIterator(fDocument, partition, locale)); |
| } |
| |
| } finally { |
| checker.removeListener(this); |
| } |
| } |
| } catch (BadLocationException exception) { |
| // Do nothing |
| } finally { |
| fRequestor.endReporting(); |
| } |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument) |
| */ |
| public final void setDocument(final IDocument document) { |
| fDocument= document; |
| |
| updateProblemRequestor(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public final void setProgressMonitor(final IProgressMonitor monitor) { |
| fProgressMonitor= monitor; |
| } |
| |
| /** |
| * Update the problem requestor based on the current editor |
| * |
| * @since 3.0 |
| */ |
| private void updateProblemRequestor() { |
| final IAnnotationModel model= fEditor.getDocumentProvider().getAnnotationModel(fEditor.getEditorInput()); |
| fRequestor= (model instanceof IProblemRequestor) ? (IProblemRequestor) model : null; |
| } |
| } |