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.IPHPPartitions;
21 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
22 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
23 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
24 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEvent;
25 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellEventListener;
26 import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.jface.preference.IPreferenceStore;
30 import org.eclipse.jface.text.BadLocationException;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IRegion;
33 import org.eclipse.jface.text.ITypedRegion;
34 import org.eclipse.jface.text.TextUtilities;
35 import org.eclipse.jface.text.reconciler.DirtyRegion;
36 import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
37 import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
38 import org.eclipse.jface.text.source.IAnnotationModel;
39 import org.eclipse.ui.texteditor.ITextEditor;
42 * Reconcile strategy to spell-check comments.
46 public class SpellReconcileStrategy implements IReconcilingStrategy, 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 */
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 org.eclipse.jdt.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.getLineInformationOfOffset(fStart);
96 prefix= fDocument.get(line.getOffset(), fStart - line.getOffset());
97 postfix= fDocument.get(fEnd + 1, line.getOffset() + line.getLength() - fEnd);
99 } catch (BadLocationException exception) {
102 return new String[] { fWord, prefix, postfix, fSentence ? Boolean.toString(true) : Boolean.toString(false), fMatch ? Boolean.toString(true) : Boolean.toString(false)};
106 * @see org.eclipse.jdt.core.compiler.IProblem#getID()
113 * @see org.eclipse.jdt.core.compiler.IProblem#getMessage()
115 public String getMessage() {
117 if (fSentence && fMatch)
118 return MessageFormat.format(PHPUIMessages.getString("Spelling.error.case.label"), new String[] { fWord }); //$NON-NLS-1$
120 return MessageFormat.format(PHPUIMessages.getString("Spelling.error.label"), new String[] { fWord }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
124 * @see org.eclipse.jdt.core.compiler.IProblem#getOriginatingFileName()
126 public char[] getOriginatingFileName() {
127 return fEditor.getEditorInput().getName().toCharArray();
131 * @see org.eclipse.jdt.core.compiler.IProblem#getSourceEnd()
133 public final int getSourceEnd() {
138 * @see org.eclipse.jdt.core.compiler.IProblem#getSourceLineNumber()
140 public final int getSourceLineNumber() {
145 * @see org.eclipse.jdt.core.compiler.IProblem#getSourceStart()
147 public final int getSourceStart() {
152 * Was the problem word found in the dictionary?
154 * @return <code>true</code> iff the word was found, <code>false</code>
157 public final boolean isDictionaryMatch() {
162 * @see org.eclipse.jdt.core.compiler.IProblem#isError()
164 public final boolean isError() {
169 * Does the problem word start a new sentence?
171 * @return <code>true</code> iff it starts a new sentence, <code>false</code>
174 public final boolean isSentenceStart() {
179 * @see org.eclipse.jdt.core.compiler.IProblem#isWarning()
181 public final boolean isWarning() {
186 * Sets whether the problem word was found in the dictionary.
189 * <code>true</code> iff the word was found, <code>false</code>
192 public final void setDictionaryMatch(final boolean match) {
197 * Sets whether the problem word starts a new sentence.
200 * <code>true</code> iff the word starts a new sentence,
201 * <code>false</code> otherwise.
203 public final void setSentenceStart(final boolean sentence) {
208 * @see org.eclipse.jdt.core.compiler.IProblem#setSourceEnd(int)
210 public final void setSourceEnd(final int end) {
215 * @see org.eclipse.jdt.core.compiler.IProblem#setSourceLineNumber(int)
217 public final void setSourceLineNumber(final int line) {
222 * @see org.eclipse.jdt.core.compiler.IProblem#setSourceStart(int)
224 public final void setSourceStart(final int start) {
229 /** The document to operate on */
230 private IDocument fDocument= null;
232 /** The text editor to operate on */
233 private final ITextEditor fEditor;
235 /** The current locale */
236 private Locale fLocale= SpellCheckEngine.getDefaultLocale();
238 /** The partitioning of the document */
239 private final String fPartitioning;
241 /** The preference store to use */
242 private final IPreferenceStore fPreferences;
244 /** The problem requestor */
245 private IProblemRequestor fRequestor;
248 * Creates a new comment reconcile strategy.
251 * The text editor to operate on
252 * @param partitioning
253 * The partitioning of the document
255 * The preference store to get the preferences from
257 public SpellReconcileStrategy(final ITextEditor editor, final String partitioning, final IPreferenceStore store) {
259 fPartitioning= partitioning;
262 updateProblemRequestor();
266 * Returns the current locale of the spell checking preferences.
268 * @return The current locale of the spell checking preferences
270 public Locale getLocale() {
272 final String locale= fPreferences.getString(ISpellCheckPreferenceKeys.SPELLING_LOCALE);
273 if (locale.equals(fLocale.toString()))
276 if (locale.length() >= 5)
277 return new Locale(locale.substring(0, 2), locale.substring(3, 5));
279 return SpellCheckEngine.getDefaultLocale();
283 * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent)
285 public void handle(final ISpellEvent event) {
287 if (fRequestor != null) {
289 final SpellProblem problem= new SpellProblem(event.getWord());
291 problem.setSourceStart(event.getBegin());
292 problem.setSourceEnd(event.getEnd());
293 problem.setSentenceStart(event.isStart());
294 problem.setDictionaryMatch(event.isMatch());
297 problem.setSourceLineNumber(fDocument.getLineOfOffset(event.getBegin()) + 1);
298 } catch (BadLocationException x) {
302 fRequestor.acceptProblem(problem);
307 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
309 public void initialReconcile() {
313 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,org.eclipse.jface.text.IRegion)
315 public void reconcile(final DirtyRegion dirtyRegion, final IRegion subRegion) {
316 reconcile(subRegion);
320 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
322 public void reconcile(final IRegion region) {
324 if (fPreferences.getBoolean(ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING) && fRequestor != null) {
328 fRequestor.beginReporting();
330 ITypedRegion partition= null;
331 final ITypedRegion[] partitions= TextUtilities.computePartitioning(fDocument, fPartitioning, 0, fDocument.getLength(), false);
333 final Locale locale= getLocale();
334 final ISpellCheckEngine engine= SpellCheckEngine.getInstance();
336 final ISpellChecker checker= engine.createSpellChecker(locale, fPreferences);
337 if (checker != null) {
339 checker.addListener(this);
341 for (int index= 0; index < partitions.length; index++) {
342 partition= partitions[index];
343 if (!partition.getType().equals(IDocument.DEFAULT_CONTENT_TYPE) &&
344 !partition.getType().equals(PHPDocumentPartitioner.PHP_SCRIPT_CODE))
345 checker.execute(new SpellCheckIterator(fDocument, partition, locale));
349 checker.removeListener(this);
352 } catch (BadLocationException exception) {
355 fRequestor.endReporting();
361 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
363 public final void setDocument(final IDocument document) {
366 updateProblemRequestor();
370 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
372 public final void setProgressMonitor(final IProgressMonitor monitor) {
377 * Update the problem requestor based on the current editor
381 private void updateProblemRequestor() {
382 final IAnnotationModel model= fEditor.getDocumentProvider().getAnnotationModel(fEditor.getEditorInput());
383 fRequestor= (model instanceof IProblemRequestor) ? (IProblemRequestor) model : null;