1 /*****************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *****************************************************************************/
12 package net.sourceforge.phpdt.internal.ui.text.spelling;
14 import java.text.MessageFormat;
15 import java.util.Locale;
17 import net.sourceforge.phpdt.core.IProblemRequestor;
18 import net.sourceforge.phpdt.core.compiler.IProblem;
19 import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
20 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
21 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
22 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
23 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent;
24 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEventListener;
25 import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
27 import org.eclipse.core.runtime.IProgressMonitor;
28 import org.eclipse.jface.preference.IPreferenceStore;
29 import org.eclipse.jface.text.BadLocationException;
30 import org.eclipse.jface.text.IDocument;
31 import org.eclipse.jface.text.IRegion;
32 import org.eclipse.jface.text.ITypedRegion;
33 import org.eclipse.jface.text.TextUtilities;
34 import org.eclipse.jface.text.reconciler.DirtyRegion;
35 import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
36 import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
37 import org.eclipse.jface.text.source.IAnnotationModel;
38 import org.eclipse.ui.texteditor.ITextEditor;
41 * Reconcile strategy to spell-check comments.
45 public class SpellReconcileStrategy implements IReconcilingStrategy,
46 IReconcilingStrategyExtension, ISpellEventListener {
49 * Spelling problem to be accepted by problem requestors.
51 public class SpellProblem implements IProblem {
53 /** The id of the problem */
54 public static final int Spelling = 0x80000000;
56 /** The end offset of the problem */
59 /** The line number of the problem */
60 private int fLine = 1;
62 /** Was the word found in the dictionary? */
63 private boolean fMatch;
65 /** Does the word start a new sentence? */
66 private boolean fSentence = false;
68 /** The start offset of the problem */
69 private int fStart = 0;
71 /** The word which caused the problem */
72 private final String fWord;
75 * Creates a new spelling problem
78 * The word which caused the problem
80 protected SpellProblem(final String word) {
85 * @see net.sourceforge.phpdt.core.compiler.IProblem#getArguments()
87 public String[] getArguments() {
89 String prefix = ""; //$NON-NLS-1$
90 String postfix = ""; //$NON-NLS-1$
94 final IRegion line = fDocument
95 .getLineInformationOfOffset(fStart);
97 prefix = fDocument.get(line.getOffset(), fStart
99 postfix = fDocument.get(fEnd + 1, line.getOffset()
100 + line.getLength() - fEnd);
102 } catch (BadLocationException exception) {
105 return new String[] {
109 fSentence ? Boolean.toString(true) : Boolean
111 fMatch ? Boolean.toString(true) : Boolean.toString(false) };
115 * @see net.sourceforge.phpdt.core.compiler.IProblem#getID()
122 * @see net.sourceforge.phpdt.core.compiler.IProblem#getMessage()
124 public String getMessage() {
126 if (fSentence && fMatch)
130 .getString("Spelling.error.case.label"), new String[] { fWord }); //$NON-NLS-1$
132 return MessageFormat.format(PHPUIMessages
133 .getString("Spelling.error.label"), new String[] { fWord }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
137 * @see net.sourceforge.phpdt.core.compiler.IProblem#getOriginatingFileName()
139 public char[] getOriginatingFileName() {
140 return fEditor.getEditorInput().getName().toCharArray();
144 * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceEnd()
146 public final int getSourceEnd() {
151 * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceLineNumber()
153 public final int getSourceLineNumber() {
158 * @see net.sourceforge.phpdt.core.compiler.IProblem#getSourceStart()
160 public final int getSourceStart() {
165 * Was the problem word found in the dictionary?
167 * @return <code>true</code> iff the word was found,
168 * <code>false</code> otherwise
170 public final boolean isDictionaryMatch() {
175 * @see net.sourceforge.phpdt.core.compiler.IProblem#isError()
177 public final boolean isError() {
182 * Does the problem word start a new sentence?
184 * @return <code>true</code> iff it starts a new sentence,
185 * <code>false</code> otherwise
187 public final boolean isSentenceStart() {
192 * @see net.sourceforge.phpdt.core.compiler.IProblem#isWarning()
194 public final boolean isWarning() {
199 * Sets whether the problem word was found in the dictionary.
202 * <code>true</code> iff the word was found,
203 * <code>false</code> otherwise
205 public final void setDictionaryMatch(final boolean match) {
210 * Sets whether the problem word starts a new sentence.
213 * <code>true</code> iff the word starts a new sentence,
214 * <code>false</code> otherwise.
216 public final void setSentenceStart(final boolean sentence) {
217 fSentence = sentence;
221 * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceEnd(int)
223 public final void setSourceEnd(final int end) {
228 * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceLineNumber(int)
230 public final void setSourceLineNumber(final int line) {
235 * @see net.sourceforge.phpdt.core.compiler.IProblem#setSourceStart(int)
237 public final void setSourceStart(final int start) {
242 /** The document to operate on */
243 private IDocument fDocument = null;
245 /** The text editor to operate on */
246 private final ITextEditor fEditor;
248 /** The current locale */
249 private Locale fLocale = SpellCheckEngine.getDefaultLocale();
251 /** The partitioning of the document */
252 private final String fPartitioning;
254 /** The preference store to use */
255 private final IPreferenceStore fPreferences;
257 /** The problem requestor */
258 private IProblemRequestor fRequestor;
261 * Creates a new comment reconcile strategy.
264 * The text editor to operate on
265 * @param partitioning
266 * The partitioning of the document
268 * The preference store to get the preferences from
270 public SpellReconcileStrategy(final ITextEditor editor,
271 final String partitioning, final IPreferenceStore store) {
273 fPartitioning = partitioning;
274 fPreferences = store;
276 updateProblemRequestor();
280 * Returns the current locale of the spell checking preferences.
282 * @return The current locale of the spell checking preferences
284 public Locale getLocale() {
286 final String locale = fPreferences
287 .getString(ISpellCheckPreferenceKeys.SPELLING_LOCALE);
288 if (locale.equals(fLocale.toString()))
291 if (locale.length() >= 5)
292 return new Locale(locale.substring(0, 2), locale.substring(3, 5));
294 return SpellCheckEngine.getDefaultLocale();
298 * @see net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent)
300 public void handle(final ISpellEvent event) {
302 if (fRequestor != null) {
304 final SpellProblem problem = new SpellProblem(event.getWord());
306 problem.setSourceStart(event.getBegin());
307 problem.setSourceEnd(event.getEnd());
308 problem.setSentenceStart(event.isStart());
309 problem.setDictionaryMatch(event.isMatch());
312 problem.setSourceLineNumber(fDocument.getLineOfOffset(event
314 } catch (BadLocationException x) {
318 fRequestor.acceptProblem(problem);
323 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
325 public void initialReconcile() {
329 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,org.eclipse.jface.text.IRegion)
331 public void reconcile(final DirtyRegion dirtyRegion, final IRegion subRegion) {
332 reconcile(subRegion);
336 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
338 public void reconcile(final IRegion region) {
341 .getBoolean(ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING)
342 && fRequestor != null) {
346 fRequestor.beginReporting();
348 ITypedRegion partition = null;
349 final ITypedRegion[] partitions = TextUtilities
350 .computePartitioning(fDocument, fPartitioning, 0,
351 fDocument.getLength(), false);
353 final Locale locale = getLocale();
354 final ISpellCheckEngine engine = SpellCheckEngine.getInstance();
356 final ISpellChecker checker = engine.createSpellChecker(locale,
358 if (checker != null) {
360 checker.addListener(this);
362 for (int index = 0; index < partitions.length; index++) {
363 partition = partitions[index];
364 if (!partition.getType().equals(
365 IDocument.DEFAULT_CONTENT_TYPE)
369 PHPDocumentPartitioner.PHP_SCRIPT_CODE))
370 checker.execute(new SpellCheckIterator(
371 fDocument, partition, locale));
375 checker.removeListener(this);
378 } catch (BadLocationException exception) {
381 fRequestor.endReporting();
387 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
389 public final void setDocument(final IDocument document) {
390 fDocument = document;
392 updateProblemRequestor();
396 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
398 public final void setProgressMonitor(final IProgressMonitor monitor) {
403 * Update the problem requestor based on the current editor
407 private void updateProblemRequestor() {
408 final IAnnotationModel model = fEditor.getDocumentProvider()
409 .getAnnotationModel(fEditor.getEditorInput());
410 fRequestor = (model instanceof IProblemRequestor) ? (IProblemRequestor) model