### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.text.tests Index: src/org/eclipse/jdt/text/tests/spelling/SpellCheckEngineTestCase.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/spelling/SpellCheckEngineTestCase.java,v retrieving revision 1.10 diff -u -r1.10 SpellCheckEngineTestCase.java --- src/org/eclipse/jdt/text/tests/spelling/SpellCheckEngineTestCase.java 31 Dec 2008 21:14:07 -0000 1.10 +++ src/org/eclipse/jdt/text/tests/spelling/SpellCheckEngineTestCase.java 15 Dec 2010 05:46:17 -0000 @@ -22,14 +22,16 @@ import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.internal.texteditor.spelling.engine.AbstractSpellDictionary; +import org.eclipse.ui.internal.texteditor.spelling.engine.DefaultPhoneticDistanceAlgorithm; + +import org.eclipse.ui.texteditor.spelling.correction.RankedWordProposal; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckEngine; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + import org.eclipse.jdt.ui.PreferenceConstants; -import org.eclipse.jdt.internal.ui.text.spelling.SpellCheckEngine; -import org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary; -import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultPhoneticDistanceAlgorithm; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.RankedWordProposal; public class SpellCheckEngineTestCase extends TestCase { #P org.eclipse.jdt.ui Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/META-INF/MANIFEST.MF,v retrieving revision 1.85 diff -u -r1.85 MANIFEST.MF --- META-INF/MANIFEST.MF 29 Jul 2010 11:19:35 -0000 1.85 +++ META-INF/MANIFEST.MF 15 Dec 2010 05:46:19 -0000 @@ -42,7 +42,7 @@ org.eclipse.jdt.internal.corext.refactoring.util;x-internal:=true, org.eclipse.jdt.internal.corext.template.java;x-internal:=true, org.eclipse.jdt.internal.corext.util;x-friends:="org.eclipse.jdt.junit", - org.eclipse.jdt.internal.ui;x-friends:="org.eclipse.jdt.junit, org.eclipse.jdt.apt.ui", + org.eclipse.jdt.internal.ui;x-friends:="org.eclipse.jdt.junit,org.eclipse.jdt.apt.ui", org.eclipse.jdt.internal.ui.actions;x-friends:="org.eclipse.jdt.junit", org.eclipse.jdt.internal.ui.browsing;x-internal:=true, org.eclipse.jdt.internal.ui.callhierarchy;x-internal:=true, @@ -86,13 +86,12 @@ org.eclipse.jdt.internal.ui.text.java.hover;x-internal:=true, org.eclipse.jdt.internal.ui.text.javadoc;x-internal:=true, org.eclipse.jdt.internal.ui.text.spelling;x-internal:=true, - org.eclipse.jdt.internal.ui.text.spelling.engine;x-internal:=true, org.eclipse.jdt.internal.ui.text.template.contentassist;x-internal:=true, org.eclipse.jdt.internal.ui.text.template.preferences;x-internal:=true, org.eclipse.jdt.internal.ui.typehierarchy;x-internal:=true, - org.eclipse.jdt.internal.ui.util;x-friends:="org.eclipse.jdt.junit, org.eclipse.jdt.apt.ui", + org.eclipse.jdt.internal.ui.util;x-friends:="org.eclipse.jdt.junit,org.eclipse.jdt.apt.ui", org.eclipse.jdt.internal.ui.viewsupport;x-friends:="org.eclipse.jdt.junit", - org.eclipse.jdt.internal.ui.wizards;x-friends:="org.eclipse.jdt.junit, org.eclipse.jdt.apt.ui", + org.eclipse.jdt.internal.ui.wizards;x-friends:="org.eclipse.jdt.junit,org.eclipse.jdt.apt.ui", org.eclipse.jdt.internal.ui.wizards.buildpaths;x-internal:=true, org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage;x-internal:=true, org.eclipse.jdt.internal.ui.wizards.dialogfields;x-friends:="org.eclipse.jdt.apt.ui", Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/plugin.xml,v retrieving revision 1.846 diff -u -r1.846 plugin.xml --- plugin.xml 6 Dec 2010 07:02:24 -0000 1.846 +++ plugin.xml 15 Dec 2010 05:46:19 -0000 @@ -185,14 +185,15 @@ class="org.eclipse.jdt.internal.ui.text.correction.QuickFixProcessor" id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor"> - - + --> @@ -5600,10 +5601,22 @@ + label="Java spelling engine" + class="org.eclipse.jdt.internal.ui.text.spelling.JavaSpellingEngine" + default="false" + id="org.eclipse.jdt.internal.ui.text.spelling.JavaSpellingEngine" + contentType="org.eclipse.jdt.core.javaSource"> + + + + + Index: ui/org/eclipse/jdt/internal/ui/JavaPlugin.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPlugin.java,v retrieving revision 1.225 diff -u -r1.225 JavaPlugin.java --- ui/org/eclipse/jdt/internal/ui/JavaPlugin.java 25 Feb 2010 07:30:03 -0000 1.225 +++ ui/org/eclipse/jdt/internal/ui/JavaPlugin.java 15 Dec 2010 05:46:19 -0000 @@ -61,6 +61,7 @@ import org.eclipse.ui.texteditor.ChainedPreferenceStore; import org.eclipse.ui.texteditor.ConfigurationElementSorter; import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry; @@ -101,7 +102,6 @@ import org.eclipse.jdt.internal.ui.text.folding.JavaFoldingStructureProviderRegistry; import org.eclipse.jdt.internal.ui.text.java.ContentAssistHistory; import org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor; -import org.eclipse.jdt.internal.ui.text.spelling.SpellCheckEngine; import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry; import org.eclipse.jdt.internal.ui.viewsupport.ImagesOnFileSystemRegistry; import org.eclipse.jdt.internal.ui.viewsupport.ProblemMarkerManager; Index: ui/org/eclipse/jdt/internal/ui/preferences/SpellingConfigurationBlock.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/SpellingConfigurationBlock.java,v retrieving revision 1.44 diff -u -r1.44 SpellingConfigurationBlock.java --- ui/org/eclipse/jdt/internal/ui/preferences/SpellingConfigurationBlock.java 18 Mar 2009 11:20:10 -0000 1.44 +++ ui/org/eclipse/jdt/internal/ui/preferences/SpellingConfigurationBlock.java 15 Dec 2010 05:46:19 -0000 @@ -52,6 +52,8 @@ import org.eclipse.ui.ide.dialogs.EncodingFieldEditor; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + import org.eclipse.debug.ui.StringVariableSelectionDialog; import org.eclipse.jdt.internal.corext.util.Messages; @@ -61,7 +63,6 @@ import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; import org.eclipse.jdt.internal.ui.dialogs.StatusUtil; -import org.eclipse.jdt.internal.ui.text.spelling.SpellCheckEngine; import org.eclipse.jdt.internal.ui.util.SWTUtil; import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener; Index: ui/org/eclipse/jdt/internal/ui/propertiesfileeditor/PropertiesCorrectionProcessor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/propertiesfileeditor/PropertiesCorrectionProcessor.java,v retrieving revision 1.1 diff -u -r1.1 PropertiesCorrectionProcessor.java --- ui/org/eclipse/jdt/internal/ui/propertiesfileeditor/PropertiesCorrectionProcessor.java 6 Dec 2010 16:04:51 -0000 1.1 +++ ui/org/eclipse/jdt/internal/ui/propertiesfileeditor/PropertiesCorrectionProcessor.java 15 Dec 2010 05:46:19 -0000 @@ -28,7 +28,7 @@ import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.TextInvocationContext; -import org.eclipse.ui.texteditor.spelling.SpellingCorrectionProcessor; +import org.eclipse.ui.texteditor.spelling.correction.SpellingCorrectionProcessor; import org.eclipse.ltk.core.refactoring.NullChange; @@ -48,7 +48,7 @@ private String fErrorMessage; - private SpellingCorrectionProcessor fSpellingCorrectionProcessor; + private org.eclipse.ui.texteditor.spelling.correction.SpellingCorrectionProcessor fSpellingCorrectionProcessor; private ICompletionProposal[] fPreComputedProposals; Index: ui/org/eclipse/jdt/internal/ui/text/spelling/AddWordProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/AddWordProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/AddWordProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/AddWordProposal.java 15 Dec 2009 13:03:38 -0000 1.16 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,174 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Shell; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialogWithToggle; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; - -import org.eclipse.ui.dialogs.PreferencesUtil; - -import org.eclipse.ui.texteditor.spelling.SpellingProblem; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.PreferenceConstants; -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; - -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.JavaPluginImages; -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.ISpellChecker; - -/** - * Proposal to add the unknown word to the dictionaries. - * - * @since 3.0 - */ -public class AddWordProposal implements IJavaCompletionProposal { - - private static final String PREF_KEY_DO_NOT_ASK= "do_not_ask_to_install_user_dictionary"; //$NON-NLS-1$ - - /** The invocation context */ - private final IQuickAssistInvocationContext fContext; - - /** The word to add */ - private final String fWord; - - - /** - * Creates a new add word proposal - * - * @param word - * The word to add - * @param context - * The invocation context - */ - public AddWordProposal(final String word, final IQuickAssistInvocationContext context) { - fContext= context; - fWord= word; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) - */ - public final void apply(final IDocument document) { - - final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); - final ISpellChecker checker= engine.getSpellChecker(); - - if (checker == null) - return; - - if (!checker.acceptsWords()) { - final Shell shell; - if (fContext != null && fContext.getSourceViewer() != null) - shell= fContext.getSourceViewer().getTextWidget().getShell(); - else - shell= JavaPlugin.getActiveWorkbenchShell(); - - if (!canAskToConfigure() || !askUserToConfigureUserDictionary(shell)) - return; - - String[] preferencePageIds= new String[] { "org.eclipse.ui.editors.preferencePages.Spelling" }; //$NON-NLS-1$ - PreferencesUtil.createPreferenceDialogOn(shell, preferencePageIds[0], preferencePageIds, null).open(); - } - - if (checker.acceptsWords()) { - checker.addWord(fWord); - if (fContext != null && fContext.getSourceViewer() != null) - SpellingProblem.removeAll(fContext.getSourceViewer(), fWord); - } - } - - /** - * Asks the user whether he wants to configure a user dictionary. - * - * @param shell the shell - * @return true if the user wants to configure the user dictionary - * @since 3.3 - */ - private boolean askUserToConfigureUserDictionary(Shell shell) { - MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openYesNoQuestion( - shell, - JavaUIMessages.Spelling_add_askToConfigure_title, - JavaUIMessages.Spelling_add_askToConfigure_question, - JavaUIMessages.Spelling_add_askToConfigure_ignoreMessage, - false, - null, - null); - - PreferenceConstants.getPreferenceStore().setValue(PREF_KEY_DO_NOT_ASK, toggleDialog.getToggleState()); - - return toggleDialog.getReturnCode() == IDialogConstants.YES_ID; - } - - /** - * Tells whether this proposal can ask to - * configure a user dictionary. - * - * @return true if it can ask the user - */ - static boolean canAskToConfigure() { - return !PreferenceConstants.getPreferenceStore().getBoolean(PREF_KEY_DO_NOT_ASK); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() - */ - public String getAdditionalProposalInfo() { - return Messages.format(JavaUIMessages.Spelling_add_info, new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord)}); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() - */ - public final IContextInformation getContextInformation() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return Messages.format(JavaUIMessages.Spelling_add_label, new String[] { fWord }); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() - */ - public Image getImage() { - return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD); - } - - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() - */ - public int getRelevance() { - return Integer.MIN_VALUE; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) - */ - public final Point getSelection(final IDocument document) { - return new Point(fContext.getOffset(), fContext.getLength()); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/ChangeCaseProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/ChangeCaseProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/ChangeCaseProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/ChangeCaseProposal.java 15 Dec 2009 13:03:38 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.Locale; - -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; - -import org.eclipse.jdt.internal.ui.JavaUIMessages; - -/** - * Proposal to change the letter case of a word. - * - * @since 3.0 - */ -public class ChangeCaseProposal extends WordCorrectionProposal { - - /** - * Creates a new change case proposal. - * - * @param arguments The problem arguments associated with the spelling problem - * @param offset The offset in the document where to apply the proposal - * @param length The length in the document to apply the proposal - * @param context The invocation context for this proposal - * @param locale The locale to use for the case change - */ - public ChangeCaseProposal(final String[] arguments, final int offset, final int length, final IQuickAssistInvocationContext context, final Locale locale) { - super(Character.isLowerCase(arguments[0].charAt(0)) ? Character.toUpperCase(arguments[0].charAt(0)) + arguments[0].substring(1) : arguments[0], arguments, offset, length, context, Integer.MAX_VALUE); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return JavaUIMessages.Spelling_case_label; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/DefaultSpellingEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/DefaultSpellingEngine.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/DefaultSpellingEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/DefaultSpellingEngine.java 17 Nov 2006 11:49:06 -0000 1.9 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,95 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.content.IContentTypeManager; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; - -import org.eclipse.ui.texteditor.spelling.ISpellingEngine; -import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; -import org.eclipse.ui.texteditor.spelling.SpellingContext; - -import org.eclipse.jdt.core.JavaCore; - -/** - * Default spelling engine. - *

- * Internally this spelling engine uses a different spelling engine depending on - * the {@linkplain IContentType content type}. Currently this engine supports - * the text, Java and Java properties file content types. - *

- * - * @since 3.1 - */ -public class DefaultSpellingEngine implements ISpellingEngine { - - /** Text content type */ - private static final IContentType TEXT_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT); - - /** Java source content type */ - private static final IContentType JAVA_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE); - - /** Java properties content type */ - private static final IContentType PROPERTIES_CONTENT_TYPE= Platform.getContentTypeManager().getContentType("org.eclipse.jdt.core.javaProperties"); //$NON-NLS-1$ - - /** Available spelling engines by content type */ - private Map fEngines= new HashMap(); - - /** - * Initialize concrete engines. - */ - public DefaultSpellingEngine() { - if (JAVA_CONTENT_TYPE != null) - fEngines.put(JAVA_CONTENT_TYPE, new JavaSpellingEngine()); - if (PROPERTIES_CONTENT_TYPE != null) - fEngines.put(PROPERTIES_CONTENT_TYPE, new PropertiesFileSpellingEngine()); - if (TEXT_CONTENT_TYPE != null) - fEngines.put(TEXT_CONTENT_TYPE, new TextSpellingEngine()); - } - - /* - * @see org.eclipse.ui.texteditor.spelling.ISpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.ui.texteditor.spelling.SpellingContext, org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector, org.eclipse.core.runtime.IProgressMonitor) - */ - public void check(IDocument document, IRegion[] regions, SpellingContext context, ISpellingProblemCollector collector, IProgressMonitor monitor) { - ISpellingEngine engine= getEngine(context.getContentType()); - if (engine == null) - engine= getEngine(TEXT_CONTENT_TYPE); - if (engine != null) - engine.check(document, regions, context, collector, monitor); - } - - /** - * Returns a spelling engine for the given content type or - * null if none could be found. - * - * @param contentType the content type - * @return a spelling engine for the given content type or - * null if none could be found - */ - private ISpellingEngine getEngine(IContentType contentType) { - if (contentType == null) - return null; - - if (fEngines.containsKey(contentType)) - return (ISpellingEngine) fEngines.get(contentType); - - return getEngine(contentType.getBaseType()); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/DisableSpellCheckingProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/DisableSpellCheckingProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/DisableSpellCheckingProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/DisableSpellCheckingProposal.java 15 Dec 2009 13:03:38 -0000 1.4 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,99 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import org.eclipse.jface.preference.IPreferenceStore; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; - -import org.eclipse.ui.texteditor.spelling.SpellingService; - -import org.eclipse.ui.editors.text.EditorsUI; - -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; - -import org.eclipse.jdt.internal.ui.JavaPluginImages; -import org.eclipse.jdt.internal.ui.JavaUIMessages; - - -/** - * Proposal to disable spell checking. - * - * @since 3.3 - */ -public class DisableSpellCheckingProposal implements IJavaCompletionProposal { - - /** The invocation context */ - private IQuickAssistInvocationContext fContext; - - /** - * Creates a new proposal. - * - * @param context the invocation context - */ - public DisableSpellCheckingProposal(IQuickAssistInvocationContext context) { - fContext= context; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) - */ - public final void apply(final IDocument document) { - IPreferenceStore store= EditorsUI.getPreferenceStore(); - store.setValue(SpellingService.PREFERENCE_SPELLING_ENABLED, false); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() - */ - public String getAdditionalProposalInfo() { - return JavaUIMessages.Spelling_disable_info; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() - */ - public final IContextInformation getContextInformation() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return JavaUIMessages.Spelling_disable_label; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() - */ - public Image getImage() { - return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE); - } - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() - */ - public final int getRelevance() { - return Integer.MIN_VALUE + 1; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) - */ - public final Point getSelection(final IDocument document) { - return new Point(fContext.getOffset(), fContext.getLength()); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/HtmlTagDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/HtmlTagDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/HtmlTagDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/HtmlTagDictionary.java 31 Dec 2008 21:13:29 -0000 1.11 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,67 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.net.URL; - -import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; -import org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary; - -/** - * Dictionary for html tags. - * - * @since 3.0 - */ -public class HtmlTagDictionary extends AbstractSpellDictionary { - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName() - */ - protected final URL getURL() { - return null; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) - */ - public boolean isCorrect(final String word) { - - if (word.charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX) - return super.isCorrect(word); - - return false; - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL) - */ - protected synchronized boolean load(final URL url) { - - unload(); - - for (int index= 0; index < IHtmlTagConstants.HTML_GENERAL_TAGS.length; index++) { - - hashWord(IHtmlTagConstants.HTML_TAG_PREFIX + IHtmlTagConstants.HTML_GENERAL_TAGS[index] + IHtmlTagConstants.HTML_TAG_POSTFIX); - hashWord(IHtmlTagConstants.HTML_CLOSE_PREFIX + IHtmlTagConstants.HTML_GENERAL_TAGS[index] + IHtmlTagConstants.HTML_TAG_POSTFIX); - } - return true; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#stripNonLetters(java.lang.String) - * @since 3.3 - */ - protected String stripNonLetters(String word) { - return word; - } - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaDocTagDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaDocTagDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/JavaDocTagDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/JavaDocTagDictionary.java 11 Sep 2008 11:59:51 -0000 1.10 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,70 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.net.URL; - -import org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary; - - -/** - * Dictionary for Javadoc tags. - * - * @since 3.0 - */ -public class JavaDocTagDictionary extends AbstractSpellDictionary implements IJavaDocTagConstants { - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName() - */ - protected final URL getURL() { - return null; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) - */ - public boolean isCorrect(final String word) { - - if (word.charAt(0) == JAVADOC_TAG_PREFIX) - return super.isCorrect(word); - - return false; - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL) - */ - protected synchronized boolean load(final URL url) { - - unload(); - - for (int index= 0; index < JAVADOC_LINK_TAGS.length; index++) - hashWord(JAVADOC_LINK_TAGS[index]); - - for (int index= 0; index < JAVADOC_ROOT_TAGS.length; index++) - hashWord(JAVADOC_ROOT_TAGS[index]); - - for (int index= 0; index < JAVADOC_PARAM_TAGS.length; index++) - hashWord(JAVADOC_PARAM_TAGS[index]); - - return true; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#stripNonLetters(java.lang.String) - * @since 3.3 - */ - protected String stripNonLetters(String word) { - return word; - } - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingEngine.java,v retrieving revision 1.14 diff -u -r1.14 JavaSpellingEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingEngine.java 15 Jan 2010 12:20:21 -0000 1.14 +++ ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingEngine.java 15 Dec 2010 05:46:19 -0000 @@ -19,12 +19,15 @@ import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextUtilities; + import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; +import org.eclipse.ui.texteditor.spelling.SpellCheckIterator; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellingEngine; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.ui.text.IJavaPartitions; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; /** Index: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingProblem.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingProblem.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingProblem.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingProblem.java 15 Dec 2009 13:03:37 -0000 1.19 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,239 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.eclipse.core.runtime.Assert; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; -import org.eclipse.jface.text.source.TextInvocationContext; - -import org.eclipse.ui.texteditor.spelling.SpellingProblem; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.PreferenceConstants; -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; - -import org.eclipse.jdt.internal.ui.JavaUIMessages; -import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -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.RankedWordProposal; - -/** - * A {@link SpellingProblem} that adapts a {@link ISpellEvent}. - *

- * TODO: remove {@link ISpellEvent} notification mechanism - *

- */ -public class JavaSpellingProblem extends SpellingProblem { - - /** Spell event */ - private ISpellEvent fSpellEvent; - - /** - * The associated document. - * - * @since 3.3 - */ - private IDocument fDocument; - - /** - * Initialize with the given spell event. - * - * @param spellEvent the spell event - * @param document the document - */ - public JavaSpellingProblem(ISpellEvent spellEvent, IDocument document) { - Assert.isLegal(document != null); - Assert.isLegal(spellEvent != null); - fSpellEvent= spellEvent; - fDocument= document; - } - - /* - * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getOffset() - */ - public int getOffset() { - return fSpellEvent.getBegin(); - } - - /* - * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getLength() - */ - public int getLength() { - return fSpellEvent.getEnd() - fSpellEvent.getBegin() + 1; - } - - /* - * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getMessage() - */ - public String getMessage() { - if (isSentenceStart() && isDictionaryMatch()) - return Messages.format(JavaUIMessages.Spelling_error_case_label, new String[] { fSpellEvent.getWord() }); - - return Messages.format(JavaUIMessages.Spelling_error_label, new String[] { fSpellEvent.getWord() }); - } - - /* - * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getProposals() - */ - public ICompletionProposal[] getProposals() { - return getProposals(null); - } - - /* - * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getProposals(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext) - * @since 3.4 - */ - public ICompletionProposal[] getProposals(IQuickAssistInvocationContext context) { - String[] arguments= getArguments(); - if (arguments == null) - return new ICompletionProposal[0]; - - if (arguments[0].indexOf('&') != -1 && isIgnoringAmpersand()) - return new ICompletionProposal[0]; // no proposals for now - - final int threshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD); - int size= 0; - List proposals= null; - - RankedWordProposal proposal= null; - IJavaCompletionProposal[] result= null; - int index= 0; - - boolean fixed= false; - boolean match= false; - boolean sentence= false; - - final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); - final ISpellChecker checker= engine.getSpellChecker(); - - if (checker != null) { - - if (context == null) - context= new TextInvocationContext(null, getOffset(), getLength()); - else - context= new TextInvocationContext(context.getSourceViewer(), getOffset(), getLength()); - - // FIXME: this is a pretty ugly hack - fixed= arguments[0].charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX - || arguments[0].charAt(0) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX; - - if ((sentence && match) && !fixed) - result= new IJavaCompletionProposal[] { new ChangeCaseProposal( - arguments, getOffset(), getLength(), context, engine - .getLocale()) }; - else { - - proposals= new ArrayList(checker.getProposals(arguments[0], - sentence)); - size= proposals.size(); - - if (threshold > 0 && size > threshold) { - - Collections.sort(proposals); - proposals= proposals - .subList(size - threshold - 1, size - 1); - size= proposals.size(); - } - - boolean extendable= !fixed ? (checker.acceptsWords() || AddWordProposal.canAskToConfigure()) : false; - result= new IJavaCompletionProposal[size + (extendable ? 3 : 2)]; - - for (index= 0; index < size; index++) { - - proposal= (RankedWordProposal) proposals.get(index); - result[index]= new WordCorrectionProposal(proposal - .getText(), arguments, getOffset(), getLength(), - context, proposal.getRank()); - } - - if (extendable) - result[index++]= new AddWordProposal(arguments[0], context); - - result[index++]= new WordIgnoreProposal(arguments[0], context); - result[index++]= new DisableSpellCheckingProposal(context); - } - } - - return result; - } - - private boolean isIgnoringAmpersand() { - return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SPELLING_IGNORE_AMPERSAND_IN_PROPERTIES); - } - - public String[] getArguments() { - - String prefix= ""; //$NON-NLS-1$ - String postfix= ""; //$NON-NLS-1$ - String word; - try { - word= fDocument.get(getOffset(), getLength()); - } catch (BadLocationException e) { - return null; - } - - try { - - IRegion line= fDocument.getLineInformationOfOffset(getOffset()); - prefix= fDocument.get(line.getOffset(), getOffset() - line.getOffset()); - int postfixStart= getOffset() + getLength(); - postfix= fDocument.get(postfixStart, line.getOffset() + line.getLength() - postfixStart); - - } catch (BadLocationException exception) { - // Do nothing - } - return new String[] { - word, - prefix, - postfix, - isSentenceStart() ? Boolean.toString(true) : Boolean - .toString(false), - isDictionaryMatch() ? Boolean.toString(true) : Boolean - .toString(false) }; - } - - /** - * Returns true iff the corresponding word was found in the dictionary. - *

- * NOTE: to be removed, see {@link #getProposals()} - *

- * - * @return true iff the corresponding word was found in the dictionary - */ - public boolean isDictionaryMatch() { - return fSpellEvent.isMatch(); - } - - /** - * Returns true iff the corresponding word starts a sentence. - *

- * NOTE: to be removed, see {@link #getProposals()} - *

- * - * @return true iff the corresponding word starts a sentence - */ - public boolean isSentenceStart() { - return fSpellEvent.isStart(); - } - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingReconcileStrategy.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingReconcileStrategy.java,v retrieving revision 1.19 diff -u -r1.19 JavaSpellingReconcileStrategy.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingReconcileStrategy.java 19 Feb 2010 10:38:00 -0000 1.19 +++ ui/org/eclipse/jdt/internal/ui/text/spelling/JavaSpellingReconcileStrategy.java 15 Dec 2010 05:46:19 -0000 @@ -27,6 +27,7 @@ import org.eclipse.ui.texteditor.spelling.SpellingProblem; import org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy; import org.eclipse.ui.texteditor.spelling.SpellingService; +import org.eclipse.ui.texteditor.spelling.TextSpellingProblem; import org.eclipse.ui.editors.text.EditorsUI; @@ -60,9 +61,9 @@ String word= getDocument().get(problem.getOffset(), problem.getLength()); boolean dictionaryMatch= false; boolean sentenceStart= false; - if (problem instanceof JavaSpellingProblem) { - dictionaryMatch= ((JavaSpellingProblem)problem).isDictionaryMatch(); - sentenceStart= ((JavaSpellingProblem) problem).isSentenceStart(); + if (problem instanceof TextSpellingProblem) { + dictionaryMatch= ((TextSpellingProblem)problem).isDictionaryMatch(); + sentenceStart= ((TextSpellingProblem)problem).isSentenceStart(); } // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81514 IEditorInput editorInput= fEditor.getEditorInput(); Index: ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellCheckIterator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellCheckIterator.java,v retrieving revision 1.4 diff -u -r1.4 PropertiesFileSpellCheckIterator.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellCheckIterator.java 31 Dec 2008 21:13:29 -0000 1.4 +++ ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellCheckIterator.java 15 Dec 2010 05:46:19 -0000 @@ -17,6 +17,8 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; +import org.eclipse.ui.texteditor.spelling.SpellCheckIterator; + /** * Iterator to spell check Java properties files Index: ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellingEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellingEngine.java,v retrieving revision 1.13 diff -u -r1.13 PropertiesFileSpellingEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellingEngine.java 15 Jan 2010 12:20:21 -0000 1.13 +++ ui/org/eclipse/jdt/internal/ui/text/spelling/PropertiesFileSpellingEngine.java 15 Dec 2010 05:46:19 -0000 @@ -26,13 +26,16 @@ import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.TypedRegion; + import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; +import org.eclipse.ui.texteditor.spelling.SpellCheckIterator; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellingEngine; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; /** * Properties file spelling engine Index: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckEngine.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckEngine.java 30 Aug 2010 14:34:07 -0000 1.30 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,502 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.eclipse.core.variables.IStringVariableManager; -import org.eclipse.core.variables.VariablesPlugin; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.FileLocator; - -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.util.IPropertyChangeListener; -import org.eclipse.jface.util.PropertyChangeEvent; - -import org.eclipse.ui.texteditor.spelling.SpellingService; - -import org.eclipse.ui.editors.text.EditorsUI; - -import org.eclipse.jdt.ui.PreferenceConstants; - -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultSpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary; -import org.eclipse.jdt.internal.ui.text.spelling.engine.LocaleSensitiveSpellDictionary; -import org.eclipse.jdt.internal.ui.text.spelling.engine.PersistentSpellDictionary; - - -/** - * Spell check engine for Java source spell checking. - * - * @since 3.0 - */ -public class SpellCheckEngine implements ISpellCheckEngine, IPropertyChangeListener { - - /** The dictionary location */ - public static final String DICTIONARY_LOCATION= "dictionaries/"; //$NON-NLS-1$ - - /** The singleton engine instance */ - private static ISpellCheckEngine fgEngine= null; - - /** - * Caches the locales of installed dictionaries. - * - * @since 3.3 - */ - private static Set fgLocalesWithInstalledDictionaries; - - /** - * Returns the locales for which this - * spell check engine has dictionaries in certain location. - * - * @param location dictionaries location - * @return The available locales for this engine - */ - private static Set getLocalesWithInstalledDictionaries(URL location) { - String[] fileNames; - try { - URL url= FileLocator.toFileURL(location); - File file= new File(url.getFile()); - if (!file.isDirectory()) - return Collections.EMPTY_SET; - fileNames= file.list(); - if (fileNames == null) - return Collections.EMPTY_SET; - } catch (IOException ex) { - JavaPlugin.log(ex); - return Collections.EMPTY_SET; - } - - Set localesWithInstalledDictionaries= new HashSet(); - int fileNameCount= fileNames.length; - for (int i= 0; i < fileNameCount; i++) { - String fileName= fileNames[i]; - int localeEnd= fileName.indexOf(".dictionary"); //$NON-NLS-1$ - if (localeEnd > 1) { - String localeName= fileName.substring(0, localeEnd); - int languageEnd=localeName.indexOf('_'); - if (languageEnd == -1) - localesWithInstalledDictionaries.add(new Locale(localeName)); - else if (languageEnd == 2 && localeName.length() == 5) - localesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3))); - else if (localeName.length() > 6 && localeName.charAt(5) == '_') - localesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3, 5), localeName.substring(6))); - } - } - - return localesWithInstalledDictionaries; - } - - - /** - * Returns the locales for which this - * spell check engine has dictionaries. - * - * @return The available locales for this engine - */ - public static Set getLocalesWithInstalledDictionaries() { - if (fgLocalesWithInstalledDictionaries != null) - return fgLocalesWithInstalledDictionaries; - - Enumeration locations; - try { - locations= getDictionaryLocations(); - if (locations == null) - return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET; - } catch (IOException ex) { - JavaPlugin.log(ex); - return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET; - } - - fgLocalesWithInstalledDictionaries= new HashSet(); - - while (locations.hasMoreElements()) { - URL location= (URL) locations.nextElement(); - Set locales= getLocalesWithInstalledDictionaries(location); - fgLocalesWithInstalledDictionaries.addAll(locales); - } - - return fgLocalesWithInstalledDictionaries; - } - - /** - * Returns the default locale for this engine. - * - * @return The default locale - */ - public static Locale getDefaultLocale() { - return Locale.getDefault(); - } - - /** - * Returns the dictionary closest to the given locale. - * - * @param locale the locale - * @return the dictionary or null if none is suitable - * @since 3.3 - */ - public ISpellDictionary findDictionary(Locale locale) { - ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(locale); - if (dictionary != null) - return dictionary; - - // Try same language - String language= locale.getLanguage(); - Iterator iter= fLocaleDictionaries.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry= (Entry)iter.next(); - Locale dictLocale= (Locale)entry.getKey(); - if (dictLocale.getLanguage().equals(language)) - return (ISpellDictionary)entry.getValue(); - } - - return null; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#findDictionary(java.util.Locale) - * @since 3.3 - */ - public static Locale findClosestLocale(Locale locale) { - if (locale == null || locale.toString().length() == 0) - return locale; - - if (getLocalesWithInstalledDictionaries().contains(locale)) - return locale; - - // Try same language - String language= locale.getLanguage(); - Iterator iter= getLocalesWithInstalledDictionaries().iterator(); - while (iter.hasNext()) { - Locale dictLocale= (Locale)iter.next(); - if (dictLocale.getLanguage().equals(language)) - return dictLocale; - } - - // Try whether American English is present - Locale defaultLocale= Locale.US; - if (getLocalesWithInstalledDictionaries().contains(defaultLocale)) - return defaultLocale; - - return null; - } - - /** - * Returns the enumeration of URLs for the dictionary locations where - * the Platform dictionaries are located. - *

- * This is in org.eclipse.jdt.ui/dictionaries/ - * which can also be populated via fragments. - *

- * - * @throws IOException if there is an I/O error - * @return The dictionary locations, or null iff the locations are not known - */ - public static Enumeration getDictionaryLocations() throws IOException { - final JavaPlugin plugin= JavaPlugin.getDefault(); - if (plugin != null) - return plugin.getBundle().getResources("/" + DICTIONARY_LOCATION); //$NON-NLS-1$ - return null; - } - - /** - * Returns the singleton instance of the spell check engine. - * - * @return The singleton instance of the spell check engine - */ - public static synchronized final ISpellCheckEngine getInstance() { - - if (fgEngine == null) - fgEngine= new SpellCheckEngine(); - - return fgEngine; - } - - /** - * Shuts down the singleton instance of the spell check engine. - */ - public static synchronized final void shutdownInstance() { - if (fgEngine != null) { - fgEngine.shutdown(); - fgEngine= null; - } - } - - /** The registered locale insensitive dictionaries */ - private Set fGlobalDictionaries= new HashSet(); - - /** The spell checker for fLocale */ - private ISpellChecker fChecker= null; - - /** The registered locale sensitive dictionaries */ - private Map fLocaleDictionaries= new HashMap(); - - /** The user dictionary */ - private ISpellDictionary fUserDictionary= null; - - /** - * Creates a new spell check manager. - */ - private SpellCheckEngine() { - - fGlobalDictionaries.add(new TaskTagDictionary()); - fGlobalDictionaries.add(new HtmlTagDictionary()); - fGlobalDictionaries.add(new JavaDocTagDictionary()); - - try { - - Locale locale= null; - final Enumeration locations= getDictionaryLocations(); - - while (locations != null && locations.hasMoreElements()) { - URL location= (URL)locations.nextElement(); - - for (final Iterator iterator= getLocalesWithInstalledDictionaries(location).iterator(); iterator.hasNext();) { - - locale= (Locale)iterator.next(); - fLocaleDictionaries.put(locale, new LocaleSensitiveSpellDictionary(locale, location)); - } - } - - } catch (IOException exception) { - // Do nothing - } - - JavaPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); - EditorsUI.getPreferenceStore().addPropertyChangeListener(this); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#getSpellChecker() - */ - public synchronized final ISpellChecker getSpellChecker() throws IllegalStateException { - if (fGlobalDictionaries == null) - throw new IllegalStateException("spell checker has been shut down"); //$NON-NLS-1$ - - IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); - Locale locale= getCurrentLocale(store); - if (fUserDictionary == null && "".equals(locale.toString())) //$NON-NLS-1$ - return null; - - if (fChecker != null && fChecker.getLocale().equals(locale)) - return fChecker; - - resetSpellChecker(); - - fChecker= new DefaultSpellChecker(store, locale); - resetUserDictionary(); - - for (Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { - ISpellDictionary dictionary= (ISpellDictionary)iterator.next(); - fChecker.addDictionary(dictionary); - } - - ISpellDictionary dictionary= findDictionary(fChecker.getLocale()); - if (dictionary != null) - fChecker.addDictionary(dictionary); - - return fChecker; - } - - /** - * Returns the current locale of the spelling preferences. - * - * @param store the preference store - * @return The current locale of the spelling preferences - */ - private Locale getCurrentLocale(IPreferenceStore store) { - return convertToLocale(store.getString(PreferenceConstants.SPELLING_LOCALE)); - } - - public static Locale convertToLocale(String locale) { - Locale defaultLocale= SpellCheckEngine.getDefaultLocale(); - if (locale.equals(defaultLocale.toString())) - return defaultLocale; - - int length= locale.length(); - if (length >= 5) - return new Locale(locale.substring(0, 2), locale.substring(3, 5)); - - if (length == 2 && locale.indexOf('_') == -1) - return new Locale(locale); - - if (length == 3 && locale.charAt(0) == '_') - return new Locale("", locale.substring(1)); //$NON-NLS-1$ - - return new Locale(""); //$NON-NLS-1$ - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale() - */ - public synchronized final Locale getLocale() { - if (fChecker == null) - return null; - - return fChecker.getLocale(); - } - - /* - * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) - */ - public final void propertyChange(final PropertyChangeEvent event) { - if (event.getProperty().equals(PreferenceConstants.SPELLING_LOCALE)) { - resetSpellChecker(); - return; - } - - if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY)) { - resetUserDictionary(); - return; - } - - if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING)) { - resetUserDictionary(); - return; - } - - if (event.getProperty().equals(SpellingService.PREFERENCE_SPELLING_ENABLED) && !EditorsUI.getPreferenceStore().getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED)) { - if (this == fgEngine) - SpellCheckEngine.shutdownInstance(); - else - shutdown(); - } - } - - /** - * Resets the current checker's user dictionary. - */ - private synchronized void resetUserDictionary() { - if (fChecker == null) - return; - - // Update user dictionary - if (fUserDictionary != null) { - fChecker.removeDictionary(fUserDictionary); - fUserDictionary.unload(); - fUserDictionary= null; - } - - IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); - String filePath= store.getString(PreferenceConstants.SPELLING_USER_DICTIONARY); - - VariablesPlugin variablesPlugin= VariablesPlugin.getDefault(); - if (variablesPlugin == null) - return; - - IStringVariableManager variableManager= variablesPlugin.getStringVariableManager(); - try { - filePath= variableManager.performStringSubstitution(filePath); - } catch (CoreException e) { - JavaPlugin.log(e); - return; - } - if (filePath.length() > 0) { - try { - File file= new File(filePath); - if (!file.exists() && !file.createNewFile()) - return; - - final URL url= new URL("file", null, filePath); //$NON-NLS-1$ - InputStream stream= url.openStream(); - if (stream != null) { - try { - fUserDictionary= new PersistentSpellDictionary(url); - fChecker.addDictionary(fUserDictionary); - } finally { - stream.close(); - } - } - } catch (MalformedURLException exception) { - // Do nothing - } catch (IOException exception) { - // Do nothing - } - } - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary) - */ - public synchronized final void registerGlobalDictionary(final ISpellDictionary dictionary) { - fGlobalDictionaries.add(dictionary); - resetSpellChecker(); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale, org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary) - */ - public synchronized final void registerDictionary(final Locale locale, final ISpellDictionary dictionary) { - fLocaleDictionaries.put(locale, dictionary); - resetSpellChecker(); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#unload() - */ - public synchronized final void shutdown() { - - JavaPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); - EditorsUI.getPreferenceStore().removePropertyChangeListener(this); - - ISpellDictionary dictionary= null; - for (final Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { - dictionary= (ISpellDictionary)iterator.next(); - dictionary.unload(); - } - fGlobalDictionaries= null; - - for (final Iterator iterator= fLocaleDictionaries.values().iterator(); iterator.hasNext();) { - dictionary= (ISpellDictionary)iterator.next(); - dictionary.unload(); - } - fLocaleDictionaries= null; - - fUserDictionary= null; - fChecker= null; - } - - private synchronized void resetSpellChecker() { - if (fChecker != null) { - ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(fChecker.getLocale()); - if (dictionary != null) - dictionary.unload(); - } - fChecker= null; - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary) - */ - public synchronized final void unregisterDictionary(final ISpellDictionary dictionary) { - fGlobalDictionaries.remove(dictionary); - fLocaleDictionaries.values().remove(dictionary); - dictionary.unload(); - resetSpellChecker(); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckIterator.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckIterator.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckIterator.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/SpellCheckIterator.java 6 Jan 2010 13:50:48 -0000 1.18 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,428 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.LinkedList; -import java.util.Locale; - -import com.ibm.icu.text.BreakIterator; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.TextUtilities; - -import org.eclipse.jdt.internal.corext.refactoring.nls.NLSElement; - -import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; -import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultSpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckIterator; - - -/** - * Iterator to spell check javadoc comment regions. - * - * @since 3.0 - */ -public class SpellCheckIterator implements ISpellCheckIterator { - - /** - * The token that denotes whitespace. - * - * @since 3.6 - */ - private static final int WHITE_SPACE_TOKEN= -1; - - /** The content of the region */ - protected final String fContent; - - /** The line delimiter */ - private final String fDelimiter; - - /** The last token */ - protected String fLastToken= null; - - /** The next break */ - protected int fNext= 1; - - /** The offset of the region */ - protected final int fOffset; - - /** The predecessor break */ - private int fPredecessor; - - /** The previous break */ - protected int fPrevious= 0; - - /** The sentence breaks */ - private final LinkedList fSentenceBreaks= new LinkedList(); - - /** Does the current word start a sentence? */ - private boolean fStartsSentence= false; - - /** The successor break */ - protected int fSuccessor; - - /** The word iterator */ - private final BreakIterator fWordIterator; - - private boolean fIsIgnoringSingleLetters; - - /** - * Creates a new spell check iterator. - * - * @param document the document containing the specified partition - * @param region the region to spell check - * @param locale the locale to use for spell checking - */ - public SpellCheckIterator(IDocument document, IRegion region, Locale locale) { - this(document, region, locale, BreakIterator.getWordInstance(locale)); - } - - /** - * Creates a new spell check iterator. - * - * @param document the document containing the specified partition - * @param region the region to spell check - * @param locale the locale to use for spell checking - * @param breakIterator the break-iterator - */ - public SpellCheckIterator(IDocument document, IRegion region, Locale locale, BreakIterator breakIterator) { - fOffset= region.getOffset(); - fWordIterator= breakIterator; - fDelimiter= TextUtilities.getDefaultLineDelimiter(document); - - String content; - try { - - content= document.get(region.getOffset(), region.getLength()); - if (content.startsWith(NLSElement.TAG_PREFIX)) - content= ""; //$NON-NLS-1$ - - } catch (Exception exception) { - content= ""; //$NON-NLS-1$ - } - fContent= content; - - fWordIterator.setText(content); - fPredecessor= fWordIterator.first(); - fSuccessor= fWordIterator.next(); - - final BreakIterator iterator= BreakIterator.getSentenceInstance(locale); - iterator.setText(content); - - int offset= iterator.current(); - while (offset != BreakIterator.DONE) { - - fSentenceBreaks.add(new Integer(offset)); - offset= iterator.next(); - } - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckIterator#setIgnoreSingleLetters(boolean) - * @since 3.3 - */ - public void setIgnoreSingleLetters(boolean state) { - fIsIgnoringSingleLetters= state; - } - - /* - * @see org.eclipse.spelling.done.ISpellCheckIterator#getBegin() - */ - public final int getBegin() { - return fPrevious + fOffset; - } - - /* - * @see org.eclipse.spelling.done.ISpellCheckIterator#getEnd() - */ - public final int getEnd() { - return fNext + fOffset - 1; - } - - /* - * @see java.util.Iterator#hasNext() - */ - public final boolean hasNext() { - return fSuccessor != BreakIterator.DONE; - } - - /** - * Does the specified token consist of at least one letter and digits - * only? - * - * @param begin the begin index - * @param end the end index - * @return true iff the token consists of digits and at - * least one letter only, false otherwise - */ - protected final boolean isAlphaNumeric(final int begin, final int end) { - - char character= 0; - - boolean letter= false; - for (int index= begin; index < end; index++) { - - character= fContent.charAt(index); - if (Character.isLetter(character)) - letter= true; - - if (!Character.isLetterOrDigit(character)) - return false; - } - return letter; - } - - /** - * Checks the last token against the given tags? - * - * @param tags the tags to check - * @return true iff the last token is in the given array - */ - protected final boolean isToken(final String[] tags) { - return isToken(fLastToken, tags); - } - - /** - * Checks the given token against the given tags? - * - * @param token the token to check - * @param tags the tags to check - * @return true iff the last token is in the given array - * @since 3.3 - */ - protected final boolean isToken(final String token, final String[] tags) { - - if (token != null) { - - for (int index= 0; index < tags.length; index++) { - - if (token.equals(tags[index])) - return true; - } - } - return false; - } - - /** - * Is the current token a single letter token surrounded by - * non-whitespace characters? - * - * @param begin the begin index - * @return true iff the token is a single letter token, - * false otherwise - */ - protected final boolean isSingleLetter(final int begin) { - if (!Character.isLetter(fContent.charAt(begin))) - return false; - - if (begin > 0 && !Character.isWhitespace(fContent.charAt(begin - 1))) - return false; - - if (begin < fContent.length() - 1 && !Character.isWhitespace(fContent.charAt(begin + 1))) - return false; - - return true; - } - - /** - * Does the specified token look like an URL? - * - * @param begin the begin index - * @return true iff this token look like an URL, - * false otherwise - */ - protected final boolean isUrlToken(final int begin) { - - for (int index= 0; index < DefaultSpellChecker.URL_PREFIXES.length; index++) { - - if (fContent.startsWith(DefaultSpellChecker.URL_PREFIXES[index], begin)) - return true; - } - return false; - } - - /** - * Does the specified token consist of whitespace only? - * - * @param begin the begin index - * @param end the end index - * @return true iff the token consists of whitespace - * only, false otherwise - */ - protected final boolean isWhitespace(final int begin, final int end) { - - for (int index= begin; index < end; index++) { - - if (!Character.isWhitespace(fContent.charAt(index))) - return false; - } - return true; - } - - /* - * @see java.util.Iterator#next() - */ - public Object next() { - - String token= nextToken(); - while (token == null && fSuccessor != BreakIterator.DONE) - token= nextToken(); - - fLastToken= token; - - return token; - } - - /** - * Advances the end index to the next word break. - */ - protected final void nextBreak() { - - fNext= fSuccessor; - fPredecessor= fSuccessor; - - fSuccessor= fWordIterator.next(); - } - - /** - * Returns the next sentence break. - * - * @return the next sentence break - */ - protected final int nextSentence() { - return ((Integer) fSentenceBreaks.getFirst()).intValue(); - } - - /** - * Determines the next token to be spell checked. - * - * @return the next token to be spell checked, or null - * iff the next token is not a candidate for spell checking. - */ - protected String nextToken() { - - String token= null; - - fPrevious= fPredecessor; - fStartsSentence= false; - - nextBreak(); - - boolean update= false; - if (fNext - fPrevious > 0) { - - if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX) { - - nextBreak(); - if (Character.isLetter(fContent.charAt(fPrevious + 1))) { - update= true; - token= fContent.substring(fPrevious, fNext); - } else - fPredecessor= fNext; - - } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_TAG_PREFIX && (Character.isLetter(fContent.charAt(fNext)) || fContent.charAt(fNext) == '/')) { - - if (fContent.startsWith(IHtmlTagConstants.HTML_CLOSE_PREFIX, fPrevious)) - nextBreak(); - - nextBreak(); - - if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_TAG_POSTFIX) { - - nextBreak(); - if (fSuccessor != BreakIterator.DONE) { - update= true; - token= fContent.substring(fPrevious, fNext); - } - } - } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_ENTITY_START && (Character.isLetter(fContent.charAt(fNext)))) { - nextBreak(); - if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_ENTITY_END) { - nextBreak(); - if (isToken(fContent.substring(fPrevious, fNext), IHtmlTagConstants.HTML_ENTITY_CODES)) { - skipTokens(fPrevious, IHtmlTagConstants.HTML_ENTITY_END); - update= true; - } else - token= fContent.substring(fPrevious, fNext); - } else - token= fContent.substring(fPrevious, fNext); - - update= true; - } else if (!isWhitespace(fPrevious, fNext) && isAlphaNumeric(fPrevious, fNext)) { - - if (isUrlToken(fPrevious)) - skipTokens(fPrevious, WHITE_SPACE_TOKEN); - else if (isToken(IJavaDocTagConstants.JAVADOC_PARAM_TAGS)) - fLastToken= null; - else if (isToken(IJavaDocTagConstants.JAVADOC_REFERENCE_TAGS)) { - fLastToken= null; - skipTokens(fPrevious, fDelimiter.charAt(0)); - } else if (fNext - fPrevious > 1 || isSingleLetter(fPrevious) && !fIsIgnoringSingleLetters) - token= fContent.substring(fPrevious, fNext); - - update= true; - } - } - - if (update && fSentenceBreaks.size() > 0) { - - if (fPrevious >= nextSentence()) { - - while (fSentenceBreaks.size() > 0 && fPrevious >= nextSentence()) - fSentenceBreaks.removeFirst(); - - fStartsSentence= (fLastToken == null) || (token != null); - } - } - return token; - } - - /* - * @see java.util.Iterator#remove() - */ - public final void remove() { - throw new UnsupportedOperationException(); - } - - /** - * Skip the tokens until the stop character is reached. - * - * @param begin the begin index - * @param stop the stop character - */ - protected final void skipTokens(final int begin, final int stop) { - final boolean isStoppingOnWhiteSpace= stop == WHITE_SPACE_TOKEN; - int end= begin; - while (end < fContent.length()) { - char ch= fContent.charAt(end); - if (ch == stop || isStoppingOnWhiteSpace && Character.isWhitespace(ch)) - break; - end++; - } - - if (end < fContent.length()) { - - fNext= end; - fPredecessor= fNext; - - fSuccessor= fWordIterator.following(fNext); - } else - fSuccessor= BreakIterator.DONE; - } - - /* - * @see org.eclipse.spelling.done.ISpellCheckIterator#startsSentence() - */ - public final boolean startsSentence() { - return fStartsSentence; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellingEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/SpellingEngine.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/SpellingEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/SpellingEngine.java 31 Dec 2008 21:13:29 -0000 1.13 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.core.runtime.IProgressMonitor; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; - -import org.eclipse.ui.texteditor.spelling.ISpellingEngine; -import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; -import org.eclipse.ui.texteditor.spelling.SpellingContext; - -import org.eclipse.jdt.ui.PreferenceConstants; - -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -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; - - -/** - * Internal abstract spelling engine, subclasses provide a content-type specific implementation. - * - * @since 3.1 - */ -public abstract class SpellingEngine implements ISpellingEngine { - - /** - * {@link ISpellEvent}listener that forwards events as - * {@link org.eclipse.ui.texteditor.spelling.SpellingProblem}. - */ - protected static class SpellEventListener implements ISpellEventListener { - - /** Spelling problem collector */ - private ISpellingProblemCollector fCollector; - - /** - * The document. - * @since 3.3 - */ - private IDocument fDocument; - - private int fProblemsThreshold; - private int fProblemCount; - - /** - * Initialize with the given spelling problem collector. - * - * @param collector the spelling problem collector - * @param document the document - */ - public SpellEventListener(ISpellingProblemCollector collector, IDocument document) { - fCollector= collector; - fDocument= document; - fProblemsThreshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent) - */ - public void handle(ISpellEvent event) { - if (isProblemsThresholdReached()) - return; - fProblemCount++; - fCollector.accept(new JavaSpellingProblem(event, fDocument)); - } - - boolean isProblemsThresholdReached() { - return fProblemCount >= fProblemsThreshold; - } - } - - /* - * @see org.eclipse.ui.texteditor.spelling.ISpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.ui.texteditor.spelling.SpellingContext, org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector, org.eclipse.core.runtime.IProgressMonitor) - */ - public void check(IDocument document, IRegion[] regions, SpellingContext context, ISpellingProblemCollector collector, IProgressMonitor monitor) { - if (collector != null) { - final ISpellCheckEngine spellingEngine= SpellCheckEngine.getInstance(); - ISpellChecker checker= spellingEngine.getSpellChecker(); - if (checker != null) - check(document, regions, checker, collector, monitor); - } - } - - /** - * Spell checks the given document regions with the given arguments. - * - * @param document the document - * @param regions the regions - * @param checker the spell checker - * @param collector the spelling problem collector - * @param monitor the progress monitor, can be null - */ - protected abstract void check(IDocument document, IRegion[] regions, ISpellChecker checker, ISpellingProblemCollector collector, IProgressMonitor monitor); - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/TaskTagDictionary.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/spelling/TaskTagDictionary.java,v retrieving revision 1.11 diff -u -r1.11 TaskTagDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/TaskTagDictionary.java 31 Dec 2008 21:13:29 -0000 1.11 +++ ui/org/eclipse/jdt/internal/ui/text/spelling/TaskTagDictionary.java 15 Dec 2010 05:46:19 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,9 +18,11 @@ import org.eclipse.core.runtime.Preferences.IPropertyChangeListener; import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; +import org.eclipse.ui.texteditor.spelling.engine.AbstractSpellDictionary; + + import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary; /** * Dictionary for task tags. Index: ui/org/eclipse/jdt/internal/ui/text/spelling/TextSpellingEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/TextSpellingEngine.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/TextSpellingEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/TextSpellingEngine.java 21 Apr 2008 10:04:50 -0000 1.9 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.core.runtime.IProgressMonitor; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; - -import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; - -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; - -/** - * Text spelling engine - * - * @since 3.1 - */ -public class TextSpellingEngine extends SpellingEngine { - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.SpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker, org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector, org.eclipse.core.runtime.IProgressMonitor) - */ - protected void check(IDocument document, IRegion[] regions, ISpellChecker checker, ISpellingProblemCollector collector, IProgressMonitor monitor) { - SpellEventListener listener= new SpellEventListener(collector, document); - for (int i= 0; i < regions.length; i++) { - if (monitor != null && monitor.isCanceled()) - return; - if (listener.isProblemsThresholdReached()) - return; - checker.execute(listener, new SpellCheckIterator(document, regions[i], checker.getLocale())); - } - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/WordCompletionProposalComputer.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/WordCompletionProposalComputer.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/WordCompletionProposalComputer.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/WordCompletionProposalComputer.java 31 Dec 2008 21:13:29 -0000 1.9 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,139 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.core.runtime.IProgressMonitor; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; - -import org.eclipse.jdt.ui.PreferenceConstants; -import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer; - -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.JavaPluginImages; -import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.RankedWordProposal; - -/** - * Content assist processor to complete words. - * Note: This is currently not supported because the spelling engine - * cannot return word proposals but only correction proposals. - *

- * If we enable this again we must register the computer in plugin.xml: - *

- * 
- *

- * - * @since 3.0 - */ -public final class WordCompletionProposalComputer implements IJavaCompletionProposalComputer { - - /** The prefix rank shift */ - private static final int PREFIX_RANK_SHIFT= 500; - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor) - */ - public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) { - if (contributes()) { - try { - IDocument document= context.getDocument(); - final int offset= context.getInvocationOffset(); - - final IRegion region= document.getLineInformationOfOffset(offset); - final String content= document.get(region.getOffset(), region.getLength()); - - int index= offset - region.getOffset() - 1; - while (index >= 0 && Character.isLetter(content.charAt(index))) - index--; - - final int start= region.getOffset() + index + 1; - final String candidate= content.substring(index + 1, offset - region.getOffset()); - - if (candidate.length() > 0) { - - final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); - final ISpellChecker checker= engine.getSpellChecker(); - - if (checker != null) { - - final List proposals= new ArrayList(checker.getProposals(candidate, Character.isUpperCase(candidate.charAt(0)))); - final List result= new ArrayList(proposals.size()); - - for (Iterator it= proposals.iterator(); it.hasNext();) { - RankedWordProposal word= (RankedWordProposal) it.next(); - String text= word.getText(); - if (text.startsWith(candidate)) - word.setRank(word.getRank() + PREFIX_RANK_SHIFT); - - result.add(new JavaCompletionProposal(text, start, candidate.length(), JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME), text, word.getRank()) { - /* - * @see org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent) - */ - public boolean validate(IDocument doc, int validate_offset, DocumentEvent event) { - return offset == validate_offset; - } - }); - } - - return result; - } - } - } catch (BadLocationException exception) { - // log & ignore - JavaPlugin.log(exception); - } - } - return Collections.EMPTY_LIST; - } - - private boolean contributes() { - return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor) - */ - public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) { - return Collections.EMPTY_LIST; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#getErrorMessage() - */ - public String getErrorMessage() { - return null; // no error message available - } - - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer#sessionStarted() - */ - public void sessionStarted() { - } - - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer#sessionEnded() - */ - public void sessionEnded() { - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/WordCorrectionProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/WordCorrectionProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/WordCorrectionProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/WordCorrectionProposal.java 15 Dec 2009 13:03:38 -0000 1.12 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,178 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; - -import org.eclipse.jdt.internal.ui.JavaPluginImages; -import org.eclipse.jdt.internal.ui.JavaUIMessages; -import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; - -/** - * Proposal to correct the incorrectly spelled word. - * - * @since 3.0 - */ -public class WordCorrectionProposal implements IJavaCompletionProposal { - - /** - * Returns the html representation of the specified string. - * - * @param string - * The string to return the html representation for - * @return The html representation for the string - */ - public static String getHtmlRepresentation(final String string) { - - final int length= string.length(); - final StringBuffer buffer= new StringBuffer(string); - - for (int offset= length - 1; offset >= 0; offset--) { - - for (int index= 0; index < IHtmlTagConstants.HTML_ENTITY_CHARACTERS.length; index++) { - - if (string.charAt(offset) == IHtmlTagConstants.HTML_ENTITY_CHARACTERS[index]) { - - buffer.replace(offset, offset + 1, String.valueOf(IHtmlTagConstants.HTML_ENTITY_CODES[index])); - break; - } - } - } - return buffer.toString(); - } - - /** The invocation context */ - private final IQuickAssistInvocationContext fContext; - - /** The length in the document */ - private final int fLength; - - /** The line where to apply the correction */ - private final String fLine; - - /** The offset in the document */ - private final int fOffset; - - /** The relevance of this proposal */ - private final int fRelevance; - - /** The word to complete */ - private final String fWord; - - /** - * Creates a new word correction proposal. - * - * @param word the corrected word - * @param arguments the problem arguments associated with the spelling problem - * @param offset the offset in the document where to apply the proposal - * @param length the lenght in the document to apply the proposal - * @param context the invocation context for this proposal - * @param relevance the relevance of this proposal - */ - public WordCorrectionProposal(final String word, final String[] arguments, final int offset, final int length, final IQuickAssistInvocationContext context, final int relevance) { - - fWord= Character.isUpperCase(arguments[0].charAt(0)) ? Character.toUpperCase(word.charAt(0)) + word.substring(1) : word; - - fOffset= offset; - fLength= length; - fContext= context; - fRelevance= relevance; - - final StringBuffer buffer= new StringBuffer(80); - - buffer.append("...
"); //$NON-NLS-1$ - buffer.append(getHtmlRepresentation(arguments[1])); - buffer.append(""); //$NON-NLS-1$ - buffer.append(getHtmlRepresentation(fWord)); - buffer.append(""); //$NON-NLS-1$ - buffer.append(getHtmlRepresentation(arguments[2])); - buffer.append("
..."); //$NON-NLS-1$ - - fLine= buffer.toString(); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) - */ - public final void apply(final IDocument document) { - try { - document.replace(fOffset, fLength, fWord); - } catch (BadLocationException exception) { - // Do nothing - } - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() - */ - public String getAdditionalProposalInfo() { - return fLine; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() - */ - public final IContextInformation getContextInformation() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return Messages.format(JavaUIMessages.Spelling_correct_label, new String[] { fWord }); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() - */ - public Image getImage() { - return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME); - } - - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() - */ - public final int getRelevance() { - return fRelevance; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) - */ - public final Point getSelection(final IDocument document) { - - int offset= fContext.getOffset(); - int length= fContext.getLength(); - - final int delta= fWord.length() - fLength; - if (offset <= fOffset && offset + length >= fOffset) - length += delta; - else if (offset > fOffset && offset + length > fOffset + fLength) { - offset += delta; - length -= delta; - } else - length += delta; - - return new Point(offset, length); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/WordIgnoreProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/WordIgnoreProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/WordIgnoreProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/WordIgnoreProposal.java 15 Dec 2009 13:03:37 -0000 1.13 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,115 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; -import org.eclipse.jface.text.source.ISourceViewer; - -import org.eclipse.ui.texteditor.spelling.SpellingProblem; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; - -import org.eclipse.jdt.internal.ui.JavaPluginImages; -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.ISpellChecker; - -/** - * Proposal to ignore the word during the current editing session. - * - * @since 3.0 - */ -public class WordIgnoreProposal implements IJavaCompletionProposal { - - /** The invocation context */ - private IQuickAssistInvocationContext fContext; - - /** The word to ignore */ - private String fWord; - - /** - * Creates a new spell ignore proposal. - * - * @param word - * The word to ignore - * @param context - * The invocation context - */ - public WordIgnoreProposal(final String word, final IQuickAssistInvocationContext context) { - fWord= word; - fContext= context; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) - */ - public final void apply(final IDocument document) { - - final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); - final ISpellChecker checker= engine.getSpellChecker(); - - if (checker != null) { - checker.ignoreWord(fWord); - ISourceViewer sourceViewer= fContext.getSourceViewer(); - if (sourceViewer != null) - SpellingProblem.removeAll(sourceViewer, fWord); - } - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() - */ - public String getAdditionalProposalInfo() { - return Messages.format(JavaUIMessages.Spelling_ignore_info, new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord)}); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() - */ - public final IContextInformation getContextInformation() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return Messages.format(JavaUIMessages.Spelling_ignore_label, new String[] { fWord }); - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() - */ - public Image getImage() { - return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE); - } - /* - * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() - */ - public final int getRelevance() { - return Integer.MIN_VALUE + 1; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) - */ - public final Point getSelection(final IDocument document) { - return new Point(fContext.getOffset(), fContext.getLength()); - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/WordQuickFixProcessor.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/WordQuickFixProcessor.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/WordQuickFixProcessor.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/WordQuickFixProcessor.java 15 Dec 2009 13:03:38 -0000 1.14 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,134 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.eclipse.core.runtime.CoreException; - -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.TextInvocationContext; - -import org.eclipse.jdt.core.ICompilationUnit; - -import org.eclipse.jdt.ui.PreferenceConstants; -import org.eclipse.jdt.ui.text.java.IInvocationContext; -import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; -import org.eclipse.jdt.ui.text.java.IProblemLocation; -import org.eclipse.jdt.ui.text.java.IQuickFixProcessor; - -import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; -import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; -import org.eclipse.jdt.internal.ui.text.spelling.engine.RankedWordProposal; - -/** - * Quick fix processor for incorrectly spelled words. - * - * @since 3.0 - */ -public class WordQuickFixProcessor implements IQuickFixProcessor { - - /** - * Creates a new word quick fix processor. - */ - public WordQuickFixProcessor() { - // For extension point - } - - /* - * @see org.eclipse.jdt.ui.text.java.IQuickFixProcessor#getCorrections(org.eclipse.jdt.ui.text.java.IInvocationContext,org.eclipse.jdt.ui.text.java.IProblemLocation[]) - */ - public IJavaCompletionProposal[] getCorrections(IInvocationContext invocationContext, IProblemLocation[] locations) throws CoreException { - - final int threshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD); - - int size= 0; - List proposals= null; - String[] arguments= null; - - IProblemLocation location= null; - RankedWordProposal proposal= null; - IJavaCompletionProposal[] result= null; - - boolean fixed= false; - boolean match= false; - boolean sentence= false; - - final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); - final ISpellChecker checker= engine.getSpellChecker(); - - if (checker != null) { - - for (int index= 0; index < locations.length; index++) { - location= locations[index]; - - ISourceViewer sourceViewer= null; - if (invocationContext instanceof IQuickAssistInvocationContext) - sourceViewer= ((IQuickAssistInvocationContext)invocationContext).getSourceViewer(); - IQuickAssistInvocationContext context= new TextInvocationContext(sourceViewer, location.getOffset(), location.getLength()); - - if (location.getProblemId() == JavaSpellingReconcileStrategy.SPELLING_PROBLEM_ID) { - - arguments= location.getProblemArguments(); - if (arguments != null && arguments.length > 4) { - - sentence= Boolean.valueOf(arguments[3]).booleanValue(); - match= Boolean.valueOf(arguments[4]).booleanValue(); - fixed= arguments[0].charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX || arguments[0].charAt(0) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX; - - if ((sentence && match) && !fixed) - result= new IJavaCompletionProposal[] { new ChangeCaseProposal(arguments, location.getOffset(), location.getLength(), context, engine.getLocale())}; - else { - - proposals= new ArrayList(checker.getProposals(arguments[0], sentence)); - size= proposals.size(); - - if (threshold > 0 && size > threshold) { - - Collections.sort(proposals); - proposals= proposals.subList(size - threshold - 1, size - 1); - size= proposals.size(); - } - - boolean extendable= !fixed ? (checker.acceptsWords() || AddWordProposal.canAskToConfigure()) : false; - result= new IJavaCompletionProposal[size + (extendable ? 3 : 2)]; - - for (index= 0; index < size; index++) { - - proposal= (RankedWordProposal)proposals.get(index); - result[index]= new WordCorrectionProposal(proposal.getText(), arguments, location.getOffset(), location.getLength(), context, proposal.getRank()); - } - - if (extendable) - result[index++]= new AddWordProposal(arguments[0], context); - - result[index++]= new WordIgnoreProposal(arguments[0], context); - result[index++]= new DisableSpellCheckingProposal(context); - } - break; - } - } - } - } - return result; - } - - /* - * @see org.eclipse.jdt.ui.text.java.IQuickFixProcessor#hasCorrections(org.eclipse.jdt.core.ICompilationUnit,int) - */ - public final boolean hasCorrections(ICompilationUnit unit, int id) { - return id == JavaSpellingReconcileStrategy.SPELLING_PROBLEM_ID; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/AbstractSpellDictionary.java 19 Feb 2010 10:38:00 -0000 1.29 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,745 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.MalformedInputException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; - -import org.eclipse.core.resources.ResourcesPlugin; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.JavaUI; -import org.eclipse.jdt.ui.PreferenceConstants; - -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.JavaUIMessages; -import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; - - -/** - * Partial implementation of a spell dictionary. - * - * @since 3.0 - */ -public abstract class AbstractSpellDictionary implements ISpellDictionary { - - /** - * Byte array wrapper - * @since 3.6 - */ - private static class ByteArrayWrapper { - - private static int hashCode(byte[] array) { - int prime= 31; - if (array == null) - return 0; - int result= 1; - for (int index= 0; index < array.length; index++) { - result= prime * result + array[index]; - } - return result; - } - - private byte[] byteArray; - - public ByteArrayWrapper(byte[] byteArray) { - this.byteArray= byteArray; - } - public int hashCode() { - final int prime= 31; - int result= 1; - result= prime * result + ByteArrayWrapper.hashCode(byteArray); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof ByteArrayWrapper)) - return false; - ByteArrayWrapper other= (ByteArrayWrapper)obj; - if (!Arrays.equals(byteArray, other.byteArray)) - return false; - return true; - } - } - - - /** - * Canonical name for UTF-8 encoding - * @since 3.6 - */ - private static final String UTF_8= "UTF-8"; //$NON-NLS-1$ - - /** The bucket capacity */ - protected static final int BUCKET_CAPACITY= 4; - - /** The word buffer capacity */ - protected static final int BUFFER_CAPACITY= 32; - - /** The distance threshold */ - protected static final int DISTANCE_THRESHOLD= 160; - - /** - * The hash load factor - * @since 3.6 - */ - protected static final float LOAD_FACTOR= 0.85f; - - /** The phonetic distance algorithm */ - private IPhoneticDistanceAlgorithm fDistanceAlgorithm= new DefaultPhoneticDistanceAlgorithm(); - - /** The mapping from phonetic hashes to word lists */ - private final Map fHashBuckets= new HashMap(getInitialSize(), LOAD_FACTOR); - - /** The phonetic hash provider */ - private IPhoneticHashProvider fHashProvider= new DefaultPhoneticHashProvider(); - - /** Is the dictionary already loaded? */ - private boolean fLoaded= false; - /** - * Must the dictionary be loaded? - * @since 3.2 - */ - private boolean fMustLoad= true; - - /** - * Tells whether to strip non-letters at word boundaries. - * @since 3.3 - */ - boolean fIsStrippingNonLetters= true; - - /** - * Returns the initial size of dictionary. - * - * @return The initial size of dictionary. - * @since 3.6 - */ - protected int getInitialSize() { - return 32; - } - - /** - * Returns all candidates with the same phonetic hash. - * - * @param hash - * The hash to retrieve the candidates of - * @return Array of candidates for the phonetic hash - */ - protected final Object getCandidates(final String hash) { - ByteArrayWrapper hashBytes; - try { - hashBytes= new ByteArrayWrapper(hash.getBytes(UTF_8)); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return null; - } - return fHashBuckets.get(hashBytes); - } - - /** - * Returns all candidates that have a phonetic hash within a bounded - * distance to the specified word. - * - * @param word - * The word to find the nearest matches for - * @param sentence - * true iff the proposals start a new sentence, - * false otherwise - * @param hashs - * Array of close hashes to find the matches - * @return Set of ranked words with bounded distance to the specified word - */ - protected final Set getCandidates(final String word, final boolean sentence, final ArrayList hashs) { - - int distance= 0; - String hash= null; - - final StringBuffer buffer= new StringBuffer(BUFFER_CAPACITY); - final HashSet result= new HashSet(BUCKET_CAPACITY * hashs.size()); - - for (int index= 0; index < hashs.size(); index++) { - - hash= (String)hashs.get(index); - - final Object candidates= getCandidates(hash); - if (candidates == null) - continue; - else if (candidates instanceof byte[]) { - String candidate; - try { - candidate= new String((byte[])candidates, UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return result; - } - distance= fDistanceAlgorithm.getDistance(word, candidate); - if (distance < DISTANCE_THRESHOLD) { - buffer.setLength(0); - buffer.append(candidate); - if (sentence) - buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); - result.add(new RankedWordProposal(buffer.toString(), -distance)); - } - continue; - } - - final ArrayList candidateList= (ArrayList)candidates; - int candidateSize= Math.min(500, candidateList.size()); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=195357 - for (int offset= 0; offset < candidateSize; offset++) { - - String candidate; - try { - candidate= new String((byte[])candidateList.get(offset), UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return result; - } - distance= fDistanceAlgorithm.getDistance(word, candidate); - - if (distance < DISTANCE_THRESHOLD) { - - buffer.setLength(0); - buffer.append(candidate); - - if (sentence) - buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); - - result.add(new RankedWordProposal(buffer.toString(), -distance)); - } - } - } - return result; - } - - /** - * Returns all approximations that have a phonetic hash with smallest - * possible distance to the specified word. - * - * @param word - * The word to find the nearest matches for - * @param sentence - * true iff the proposals start a new sentence, - * false otherwise - * @param result - * Set of ranked words with smallest possible distance to the - * specified word - */ - protected final void getCandidates(final String word, final boolean sentence, final Set result) { - - int distance= 0; - int minimum= Integer.MAX_VALUE; - - StringBuffer buffer= new StringBuffer(BUFFER_CAPACITY); - - final Object candidates= getCandidates(fHashProvider.getHash(word)); - if (candidates == null) - return; - else if (candidates instanceof byte[]) { - String candidate; - try { - candidate= new String((byte[])candidates, UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return; - } - distance= fDistanceAlgorithm.getDistance(word, candidate); - buffer.append(candidate); - if (sentence) - buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); - result.add(new RankedWordProposal(buffer.toString(), -distance)); - return; - } - - final ArrayList candidateList= (ArrayList)candidates; - final ArrayList matches= new ArrayList(candidateList.size()); - - for (int index= 0; index < candidateList.size(); index++) { - String candidate; - try { - candidate= new String((byte[])candidateList.get(index), UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return; - } - distance= fDistanceAlgorithm.getDistance(word, candidate); - - if (distance <= minimum) { - - if (distance < minimum) - matches.clear(); - - buffer.setLength(0); - buffer.append(candidate); - - if (sentence) - buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); - - matches.add(new RankedWordProposal(buffer.toString(), -distance)); - minimum= distance; - } - } - - result.addAll(matches); - } - - /** - * Tells whether this dictionary is empty. - * - * @return true if this dictionary is empty - * @since 3.3 - */ - protected boolean isEmpty() { - return fHashBuckets.size() == 0; - } - - /** - * Returns the used phonetic distance algorithm. - * - * @return The phonetic distance algorithm - */ - protected final IPhoneticDistanceAlgorithm getDistanceAlgorithm() { - return fDistanceAlgorithm; - } - - /** - * Returns the used phonetic hash provider. - * - * @return The phonetic hash provider - */ - protected final IPhoneticHashProvider getHashProvider() { - return fHashProvider; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#getProposals(java.lang.String,boolean) - */ - public Set getProposals(final String word, final boolean sentence) { - - try { - - if (!fLoaded) { - synchronized (this) { - fLoaded= load(getURL()); - if (fLoaded) - compact(); - } - } - - } catch (MalformedURLException exception) { - // Do nothing - } - - final String hash= fHashProvider.getHash(word); - final char[] mutators= fHashProvider.getMutators(); - - final ArrayList neighborhood= new ArrayList((word.length() + 1) * (mutators.length + 2)); - neighborhood.add(hash); - - final Set candidates= getCandidates(word, sentence, neighborhood); - neighborhood.clear(); - - char previous= 0; - char next= 0; - - char[] characters= word.toCharArray(); - for (int index= 0; index < word.length() - 1; index++) { - - next= characters[index]; - previous= characters[index + 1]; - - characters[index]= previous; - characters[index + 1]= next; - - neighborhood.add(fHashProvider.getHash(new String(characters))); - - characters[index]= next; - characters[index + 1]= previous; - } - - final String sentinel= word + " "; //$NON-NLS-1$ - - characters= sentinel.toCharArray(); - int offset= characters.length - 1; - - while (true) { - - for (int index= 0; index < mutators.length; index++) { - - characters[offset]= mutators[index]; - neighborhood.add(fHashProvider.getHash(new String(characters))); - } - - if (offset == 0) - break; - - characters[offset]= characters[offset - 1]; - --offset; - } - - char mutated= 0; - characters= word.toCharArray(); - - for (int index= 0; index < word.length(); index++) { - - mutated= characters[index]; - for (int mutator= 0; mutator < mutators.length; mutator++) { - - characters[index]= mutators[mutator]; - neighborhood.add(fHashProvider.getHash(new String(characters))); - } - characters[index]= mutated; - } - - characters= word.toCharArray(); - final char[] deleted= new char[characters.length - 1]; - - for (int index= 0; index < deleted.length; index++) - deleted[index]= characters[index]; - - next= characters[characters.length - 1]; - offset= deleted.length; - - while (true) { - - neighborhood.add(fHashProvider.getHash(new String(characters))); - if (offset == 0) - break; - - previous= next; - next= deleted[offset - 1]; - - deleted[offset - 1]= previous; - --offset; - } - - neighborhood.remove(hash); - final Set matches= getCandidates(word, sentence, neighborhood); - - if (matches.size() == 0 && candidates.size() == 0) - getCandidates(word, sentence, candidates); - - candidates.addAll(matches); - - return candidates; - } - - /** - * Returns the URL of the dictionary word list. - * - * @throws MalformedURLException - * if the URL could not be retrieved - * @return The URL of the dictionary word list - */ - protected abstract URL getURL() throws MalformedURLException; - - /** - * Hashes the word into the dictionary. - * - * @param word - * The word to hash in the dictionary - */ - protected final void hashWord(final String word) { - - final String hash= fHashProvider.getHash(word); - ByteArrayWrapper hashBytes; - byte[] wordBytes; - try { - hashBytes= new ByteArrayWrapper(hash.getBytes(UTF_8)); - wordBytes= word.getBytes(UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return; - } - - Object bucket= fHashBuckets.get(hashBytes); - - if (bucket == null) { - fHashBuckets.put(hashBytes, wordBytes); - } else if (bucket instanceof ArrayList) { - ((ArrayList)bucket).add(wordBytes); - } else { - ArrayList list= new ArrayList(BUCKET_CAPACITY); - list.add(bucket); - list.add(wordBytes); - fHashBuckets.put(hashBytes, list); - } - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) - */ - public boolean isCorrect(String word) { - word= stripNonLetters(word); - try { - - if (!fLoaded) { - synchronized (this) { - fLoaded= load(getURL()); - if (fLoaded) - compact(); - } - } - - } catch (MalformedURLException exception) { - // Do nothing - } - - final Object candidates= getCandidates(fHashProvider.getHash(word)); - if (candidates == null) - return false; - else if (candidates instanceof byte[]) { - String candidate; - try { - candidate= new String((byte[])candidates, UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return false; - } - if (candidate.equals(word) || candidate.equals(word.toLowerCase())) - return true; - return false; - } - final ArrayList candidateList= (ArrayList)candidates; - byte[] wordBytes; - byte[] lowercaseWordBytes; - try { - wordBytes= word.getBytes(UTF_8); - lowercaseWordBytes= word.toLowerCase().getBytes(UTF_8); - } catch (UnsupportedEncodingException e) { - JavaPlugin.log(e); - return false; - } - for (int index= 0; index < candidateList.size(); index++) { - byte[] candidate= (byte[])candidateList.get(index); - if (Arrays.equals(candidate, wordBytes) || Arrays.equals(candidate, lowercaseWordBytes)) { - return true; - } - } - return false; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#setStripNonLetters(boolean) - * @since 3.3 - */ - public void setStripNonLetters(boolean state) { - fIsStrippingNonLetters= state; - } - - /** - * Strips non-letter characters from the given word. - *

- * This will only happen if the corresponding preference is enabled. - *

- * - * @param word the word to strip - * @return the stripped word - * @since 3.3 - */ - protected String stripNonLetters(String word) { - if (!fIsStrippingNonLetters) - return word; - - int i= 0; - int j= word.length() - 1; - while (i <= j && !Character.isLetter(word.charAt(i))) - i++; - if (i > j) - return ""; //$NON-NLS-1$ - - while (j > i && !Character.isLetter(word.charAt(j))) - j--; - - return word.substring(i, j+1); - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#isLoaded() - */ - public synchronized final boolean isLoaded() { - return fLoaded || fHashBuckets.size() > 0; - } - - /** - * Loads a dictionary word list from disk. - * - * @param url - * The URL of the word list to load - * @return true iff the word list could be loaded, false - * otherwise - */ - protected synchronized boolean load(final URL url) { - if (!fMustLoad) - return fLoaded; - - if (url != null) { - InputStream stream= null; - int line= 0; - try { - stream= url.openStream(); - if (stream != null) { - String word= null; - - // Setup a reader with a decoder in order to read over malformed input if needed. - CharsetDecoder decoder= Charset.forName(getEncoding()).newDecoder(); - decoder.onMalformedInput(CodingErrorAction.REPORT); - decoder.onUnmappableCharacter(CodingErrorAction.REPORT); - final BufferedReader reader= new BufferedReader(new InputStreamReader(stream, decoder)); - - boolean doRead= true; - while (doRead) { - try { - word= reader.readLine(); - } catch (MalformedInputException ex) { - // Tell the decoder to replace malformed input in order to read the line. - decoder.onMalformedInput(CodingErrorAction.REPLACE); - decoder.reset(); - word= reader.readLine(); - decoder.onMalformedInput(CodingErrorAction.REPORT); - - String message= Messages.format(JavaUIMessages.AbstractSpellingDictionary_encodingError, new String[] { word, decoder.replacement(), BasicElementLabels.getURLPart(url.toString()) }); - IStatus status= new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.OK, message, ex); - JavaPlugin.log(status); - - doRead= word != null; - continue; - } - doRead= word != null; - if (doRead) - hashWord(word); - } - return true; - } - } catch (FileNotFoundException ex) { - String urlString= url.toString(); - String lowercaseUrlString= urlString.toLowerCase(); - if (urlString.equals(lowercaseUrlString)) - JavaPlugin.log(ex); - else - try { - return load(new URL(lowercaseUrlString)); - } catch (MalformedURLException e) { - JavaPlugin.log(e); - } - } catch (IOException exception) { - if (line > 0) { - String message= Messages.format(JavaUIMessages.AbstractSpellingDictionary_encodingError, new Object[] { new Integer(line), BasicElementLabels.getURLPart(url.toString()) }); - IStatus status= new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.OK, message, exception); - JavaPlugin.log(status); - } else - JavaPlugin.log(exception); - } finally { - fMustLoad= false; - try { - if (stream != null) - stream.close(); - } catch (IOException x) { - } - } - } - return false; - } - - /** - * Compacts the dictionary. - * - * @since 3.3. - */ - private void compact() { - Iterator iter= fHashBuckets.values().iterator(); - while (iter.hasNext()) { - Object element= iter.next(); - if (element instanceof ArrayList) - ((ArrayList)element).trimToSize(); - } - } - - /** - * Sets the phonetic distance algorithm to use. - * - * @param algorithm - * The phonetic distance algorithm - */ - protected final void setDistanceAlgorithm(final IPhoneticDistanceAlgorithm algorithm) { - fDistanceAlgorithm= algorithm; - } - - /** - * Sets the phonetic hash provider to use. - * - * @param provider - * The phonetic hash provider - */ - protected final void setHashProvider(final IPhoneticHashProvider provider) { - fHashProvider= provider; - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#unload() - */ - public synchronized void unload() { - fLoaded= false; - fMustLoad= true; - fHashBuckets.clear(); - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#acceptsWords() - */ - public boolean acceptsWords() { - return false; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String) - */ - public void addWord(final String word) { - // Do nothing - } - - /** - * Returns the encoding of this dictionary. - * - * @return the encoding of this dictionary - * @since 3.3 - */ - protected String getEncoding() { - String encoding= JavaPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING); - if (encoding == null || encoding.length() == 0) - encoding= ResourcesPlugin.getEncoding(); - return encoding; - } - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticDistanceAlgorithm.java 29 May 2007 18:41:37 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,103 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -/** - * Default phonetic distance algorithm for English words. - *

- * This algorithm implements the Levenshtein text edit distance. - *

- * - * @since 3.0 - */ -public final class DefaultPhoneticDistanceAlgorithm implements IPhoneticDistanceAlgorithm { - - /** The change case cost */ - public static final int COST_CASE= 10; - - /** The insert character cost */ - public static final int COST_INSERT= 95; - - /** The remove character cost */ - public static final int COST_REMOVE= 95; - - /** The substitute characters cost */ - public static final int COST_SUBSTITUTE= 100; - - /** The swap characters cost */ - public static final int COST_SWAP= 90; - - /* - * @see org.eclipse.spelling.done.IPhoneticDistanceAlgorithm#getDistance(java.lang.String,java.lang.String) - */ - public final int getDistance(final String from, final String to) { - - final char[] first= (" " + from).toCharArray(); //$NON-NLS-1$ - final char[] second= (" " + to).toCharArray(); //$NON-NLS-1$ - - final int rows= first.length; - final int columns= second.length; - - final int[][] metric= new int[rows][columns]; - for (int column= 1; column < columns; column++) - metric[0][column]= metric[0][column - 1] + COST_REMOVE; - - for (int row= 1; row < rows; row++) - metric[row][0]= metric[row - 1][0] + COST_INSERT; - - char source, target; - - int swap= Integer.MAX_VALUE; - int change= Integer.MAX_VALUE; - - int minimum, diagonal, insert, remove; - for (int row= 1; row < rows; row++) { - - source= first[row]; - for (int column= 1; column < columns; column++) { - - target= second[column]; - diagonal= metric[row - 1][column - 1]; - - if (source == target) { - metric[row][column]= diagonal; - continue; - } - - change= Integer.MAX_VALUE; - if (Character.toLowerCase(source) == Character.toLowerCase(target)) - change= COST_CASE + diagonal; - - swap= Integer.MAX_VALUE; - if (row != 1 && column != 1 && source == second[column - 1] && first[row - 1] == target) - swap= COST_SWAP + metric[row - 2][column - 2]; - - minimum= COST_SUBSTITUTE + diagonal; - if (swap < minimum) - minimum= swap; - - remove= metric[row][column - 1]; - if (COST_REMOVE + remove < minimum) - minimum= COST_REMOVE + remove; - - insert= metric[row - 1][column]; - if (COST_INSERT + insert < minimum) - minimum= COST_INSERT + insert; - if (change < minimum) - minimum= change; - - metric[row][column]= minimum; - } - } - return metric[rows - 1][columns - 1]; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultPhoneticHashProvider.java 17 Jun 2005 15:51:53 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,683 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -/** - * Default phonetic hash provider for english languages. - *

- * This algorithm uses an adapted version double metaphone algorithm by - * Lawrence Philips. - *

- * - * @since 3.0 - */ -public final class DefaultPhoneticHashProvider implements IPhoneticHashProvider { - - private static final String[] meta01= { "ACH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta02= { "BACHER", "MACHER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta03= { "CAESAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta04= { "CHIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta05= { "CH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta06= { "CHAE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta07= { "HARAC", "HARIS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta08= { "HOR", "HYM", "HIA", "HEM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - private static final String[] meta09= { "CHORE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta10= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta11= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta12= { "ORCHES", "ARCHIT", "ORCHID", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta13= { "T", "S", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta14= { "A", "O", "U", "E", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - private static final String[] meta15= { "L", "R", "N", "M", "B", "H", "F", "V", "W", " ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ - private static final String[] meta16= { "MC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta17= { "CZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta18= { "WICZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta19= { "CIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta20= { "CC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta21= { "I", "E", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta22= { "HU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta23= { "UCCEE", "UCCES", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta24= { "CK", "CG", "CQ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta25= { "CI", "CE", "CY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta26= { "GN", "KN", "PN", "WR", "PS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ - private static final String[] meta27= { " C", " Q", " G", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta28= { "C", "K", "Q", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta29= { "CE", "CI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta30= { "DG", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta31= { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta32= { "DT", "DD", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta33= { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta34= { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta35= { "B", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta36= { "C", "G", "L", "R", "T", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ - private static final String[] meta37= { "EY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta38= { "LI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta39= { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ - private static final String[] meta40= { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta41= { "DANGER", "RANGER", "MANGER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta42= { "E", "I", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta43= { "RGY", "OGY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta44= { "E", "I", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta45= { "AGGI", "OGGI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta46= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta47= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta48= { "ET", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta49= { "C", "X", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta50= { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta51= { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta52= { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta53= { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta54= { "L", "T", "K", "S", "N", "M", "B", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ - private static final String[] meta55= { "S", "K", "L", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta56= { "ILLO", "ILLA", "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta57= { "AS", "OS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta58= { "A", "O", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta59= { "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta60= { "UMB", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta61= { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta62= { "P", "B", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta63= { "IE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta64= { "ME", "MA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta65= { "ISL", "YSL", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta66= { "SUGAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta67= { "SH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta68= { "HEIM", "HOEK", "HOLM", "HOLZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - private static final String[] meta69= { "SIO", "SIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta70= { "SIAN", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta71= { "M", "N", "L", "W", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - private static final String[] meta72= { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta73= { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta74= { "SC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta75= { "OO", "ER", "EN", "UY", "ED", "EM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ - private static final String[] meta76= { "ER", "EN", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta77= { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String[] meta78= { "AI", "OI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta79= { "S", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta80= { "TION", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta81= { "TIA", "TCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta82= { "TH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta83= { "TTH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta84= { "OM", "AM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta85= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta86= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta87= { "T", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta88= { "WR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta89= { "WH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta90= { "EWSKI", "EWSKY", "OWSKI", "OWSKY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - private static final String[] meta91= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String[] meta92= { "WICZ", "WITZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta93= { "IAU", "EAU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta94= { "AU", "OU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final String[] meta95= { "W", "K", "CZ", "WITZ" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - - /** The mutator characters */ - private static final char[] MUTATOR_CHARACTERS= { 'A', 'B', 'X', 'S', 'K', 'J', 'T', 'F', 'H', 'L', 'M', 'N', 'P', 'R', '0' }; - - /** The vowel characters */ - private static final char[] VOWEL_CHARACTERS= new char[] { 'A', 'E', 'I', 'O', 'U', 'Y' }; - - /** - * Test whether the specified string contains one of the candidates in the - * list. - * - * @param candidates - * Array of candidates to check - * @param token - * The token to check for occurrences of the candidates - * @param offset - * The offset where to begin checking in the string - * @param length - * The length of the range in the string to check - * @return true iff the string contains one of the - * candidates, false otherwise. - */ - protected static final boolean hasOneOf(final String[] candidates, final char[] token, final int offset, final int length) { - - if (offset < 0 || offset >= token.length || candidates.length == 0) - return false; - - final String checkable= new String(token, offset, length); - for (int index= 0; index < candidates.length; index++) { - - if (candidates[index].equals(checkable)) - return true; - } - return false; - } - - /** - * Test whether the specified token contains one of the candidates in the - * list. - * - * @param candidates - * Array of candidates to check - * @param token - * The token to check for occurrences of the candidates - * @return true iff the string contains one of the - * candidates, false otherwise. - */ - protected static final boolean hasOneOf(final String[] candidates, final String token) { - - for (int index= 0; index < candidates.length; index++) { - - if (token.indexOf(candidates[index]) >= 0) - return true; - } - return false; - } - - /** - * Tests whether the specified token contains a vowel at the specified - * offset. - * - * @param token - * The token to check for a vowel - * @param offset - * The offset where to begin checking in the token - * @param length - * The length of the range in the token to check - * @return true iff the token contains a vowel, false - * otherwise. - */ - protected static final boolean hasVowel(final char[] token, final int offset, final int length) { - - if (offset >= 0 && offset < length) { - - final char character= token[offset]; - for (int index= 0; index < VOWEL_CHARACTERS.length; index++) { - - if (VOWEL_CHARACTERS[index] == character) - return true; - } - } - return false; - } - - /* - * @see org.eclipse.spelling.done.IPhoneticHasher#getHash(java.lang.String) - */ - public final String getHash(final String word) { - - final String input= word.toUpperCase() + " "; //$NON-NLS-1$ - final char[] hashable= input.toCharArray(); - - final boolean has95= hasOneOf(meta95, input); - final StringBuffer buffer= new StringBuffer(hashable.length); - - int offset= 0; - if (hasOneOf(meta26, hashable, 0, 2)) - offset += 1; - - if (hashable[0] == 'X') { - buffer.append('S'); - offset += 1; - } - - while (offset < hashable.length) { - - switch (hashable[offset]) { - case 'A' : - case 'E' : - case 'I' : - case 'O' : - case 'U' : - case 'Y' : - if (offset == 0) - buffer.append('A'); - offset += 1; - break; - case 'B' : - buffer.append('P'); - if (hashable[offset + 1] == 'B') - offset += 2; - else - offset += 1; - break; - case 'C' : - if ((offset > 1) && !hasVowel(hashable, offset - 2, hashable.length) && hasOneOf(meta01, hashable, (offset - 1), 3) && (hashable[offset + 2] != 'I') && (hashable[offset + 2] != 'E') || hasOneOf(meta02, hashable, (offset - 2), 6)) { - buffer.append('K'); - offset += 2; - break; - } - if ((offset == 0) && hasOneOf(meta03, hashable, offset, 6)) { - buffer.append('S'); - offset += 2; - break; - } - if (hasOneOf(meta04, hashable, offset, 4)) { - buffer.append('K'); - offset += 2; - break; - } - if (hasOneOf(meta05, hashable, offset, 2)) { - if ((offset > 0) && hasOneOf(meta06, hashable, offset, 4)) { - buffer.append('K'); - offset += 2; - break; - } - if ((offset == 0) && hasOneOf(meta07, hashable, (offset + 1), 5) || hasOneOf(meta08, hashable, offset + 1, 3) && !hasOneOf(meta09, hashable, 0, 5)) { - buffer.append('K'); - offset += 2; - break; - } - if (hasOneOf(meta10, hashable, 0, 4) || hasOneOf(meta11, hashable, 0, 3) || hasOneOf(meta12, hashable, offset - 2, 6) || hasOneOf(meta13, hashable, offset + 2, 1) || (hasOneOf(meta14, hashable, offset - 1, 1) || (offset == 0)) && hasOneOf(meta15, hashable, offset + 2, 1)) { - buffer.append('K'); - } else { - if (offset > 0) { - if (hasOneOf(meta16, hashable, 0, 2)) - buffer.append('K'); - else - buffer.append('X'); - } else { - buffer.append('X'); - } - } - offset += 2; - break; - } - if (hasOneOf(meta17, hashable, offset, 2) && !hasOneOf(meta18, hashable, offset, 4)) { - buffer.append('S'); - offset += 2; - break; - } - if (hasOneOf(meta19, hashable, offset, 2)) { - buffer.append('X'); - offset += 2; - break; - } - if (hasOneOf(meta20, hashable, offset, 2) && !((offset == 1) && hashable[0] == 'M')) { - if (hasOneOf(meta21, hashable, offset + 2, 1) && !hasOneOf(meta22, hashable, offset + 2, 2)) { - if (((offset == 1) && (hashable[offset - 1] == 'A')) || hasOneOf(meta23, hashable, (offset - 1), 5)) - buffer.append("KS"); //$NON-NLS-1$ - else - buffer.append('X'); - offset += 3; - break; - } else { - buffer.append('K'); - offset += 2; - break; - } - } - if (hasOneOf(meta24, hashable, offset, 2)) { - buffer.append('K'); - offset += 2; - break; - } else if (hasOneOf(meta25, hashable, offset, 2)) { - buffer.append('S'); - offset += 2; - break; - } - buffer.append('K'); - if (hasOneOf(meta27, hashable, offset + 1, 2)) - offset += 3; - else if (hasOneOf(meta28, hashable, offset + 1, 1) && !hasOneOf(meta29, hashable, offset + 1, 2)) - offset += 2; - else - offset += 1; - break; - case '\u00C7' : - buffer.append('S'); - offset += 1; - break; - case 'D' : - if (hasOneOf(meta30, hashable, offset, 2)) { - if (hasOneOf(meta31, hashable, offset + 2, 1)) { - buffer.append('J'); - offset += 3; - break; - } else { - buffer.append("TK"); //$NON-NLS-1$ - offset += 2; - break; - } - } - buffer.append('T'); - if (hasOneOf(meta32, hashable, offset, 2)) { - offset += 2; - } else { - offset += 1; - } - break; - case 'F' : - if (hashable[offset + 1] == 'F') - offset += 2; - else - offset += 1; - buffer.append('F'); - break; - case 'G' : - if (hashable[offset + 1] == 'H') { - if ((offset > 0) && !hasVowel(hashable, offset - 1, hashable.length)) { - buffer.append('K'); - offset += 2; - break; - } - if (offset < 3) { - if (offset == 0) { - if (hashable[offset + 2] == 'I') - buffer.append('J'); - else - buffer.append('K'); - offset += 2; - break; - } - } - if ((offset > 1) && hasOneOf(meta33, hashable, offset - 2, 1) || ((offset > 2) && hasOneOf(meta34, hashable, offset - 3, 1)) || ((offset > 3) && hasOneOf(meta35, hashable, offset - 4, 1))) { - offset += 2; - break; - } else { - if ((offset > 2) && (hashable[offset - 1] == 'U') && hasOneOf(meta36, hashable, offset - 3, 1)) { - buffer.append('F'); - } else { - if ((offset > 0) && (hashable[offset - 1] != 'I')) - buffer.append('K'); - } - offset += 2; - break; - } - } - if (hashable[offset + 1] == 'N') { - if ((offset == 1) && hasVowel(hashable, 0, hashable.length) && !has95) { - buffer.append("KN"); //$NON-NLS-1$ - } else { - if (!hasOneOf(meta37, hashable, offset + 2, 2) && (hashable[offset + 1] != 'Y') && !has95) { - buffer.append("N"); //$NON-NLS-1$ - } else { - buffer.append("KN"); //$NON-NLS-1$ - } - } - offset += 2; - break; - } - if (hasOneOf(meta38, hashable, offset + 1, 2) && !has95) { - buffer.append("KL"); //$NON-NLS-1$ - offset += 2; - break; - } - if ((offset == 0) && ((hashable[offset + 1] == 'Y') || hasOneOf(meta39, hashable, offset + 1, 2))) { - buffer.append('K'); - offset += 2; - break; - } - if ((hasOneOf(meta40, hashable, offset + 1, 2) || (hashable[offset + 1] == 'Y')) && !hasOneOf(meta41, hashable, 0, 6) && !hasOneOf(meta42, hashable, offset - 1, 1) && !hasOneOf(meta43, hashable, offset - 1, 3)) { - buffer.append('K'); - offset += 2; - break; - } - if (hasOneOf(meta44, hashable, offset + 1, 1) || hasOneOf(meta45, hashable, offset - 1, 4)) { - if (hasOneOf(meta46, hashable, 0, 4) || hasOneOf(meta47, hashable, 0, 3) || hasOneOf(meta48, hashable, offset + 1, 2)) { - buffer.append('K'); - } else { - buffer.append('J'); - } - offset += 2; - break; - } - if (hashable[offset + 1] == 'G') - offset += 2; - else - offset += 1; - buffer.append('K'); - break; - case 'H' : - if (((offset == 0) || hasVowel(hashable, offset - 1, hashable.length)) && hasVowel(hashable, offset + 1, hashable.length)) { - buffer.append('H'); - offset += 2; - } else { - offset += 1; - } - break; - case 'J' : - if (hasOneOf(meta50, hashable, offset, 4) || hasOneOf(meta51, hashable, 0, 4)) { - if ((offset == 0) && (hashable[offset + 4] == ' ') || hasOneOf(meta52, hashable, 0, 4)) { - buffer.append('H'); - } else { - buffer.append('J'); - } - offset += 1; - break; - } - if ((offset == 0) && !hasOneOf(meta53, hashable, offset, 4)) { - buffer.append('J'); - } else { - if (hasVowel(hashable, offset - 1, hashable.length) && !has95 && ((hashable[offset + 1] == 'A') || hashable[offset + 1] == 'O')) { - buffer.append('J'); - } else { - if (offset == (hashable.length - 1)) { - buffer.append('J'); - } else { - if (!hasOneOf(meta54, hashable, offset + 1, 1) && !hasOneOf(meta55, hashable, offset - 1, 1)) { - buffer.append('J'); - } - } - } - } - if (hashable[offset + 1] == 'J') - offset += 2; - else - offset += 1; - break; - case 'K' : - if (hashable[offset + 1] == 'K') - offset += 2; - else - offset += 1; - buffer.append('K'); - break; - case 'L' : - if (hashable[offset + 1] == 'L') { - if (((offset == (hashable.length - 3)) && hasOneOf(meta56, hashable, offset - 1, 4)) || ((hasOneOf(meta57, hashable, (hashable.length - 1) - 1, 2) || hasOneOf(meta58, hashable, hashable.length - 1, 1)) && hasOneOf(meta59, hashable, offset - 1, 4))) { - buffer.append('L'); - offset += 2; - break; - } - offset += 2; - } else - offset += 1; - buffer.append('L'); - break; - case 'M' : - if ((hasOneOf(meta60, hashable, offset - 1, 3) && (((offset + 1) == (hashable.length - 1)) || hasOneOf(meta61, hashable, offset + 2, 2))) || (hashable[offset + 1] == 'M')) - offset += 2; - else - offset += 1; - buffer.append('M'); - break; - case 'N' : - if (hashable[offset + 1] == 'N') - offset += 2; - else - offset += 1; - buffer.append('N'); - break; - case '\u00D1' : - offset += 1; - buffer.append('N'); - break; - case 'P' : - if (hashable[offset + 1] == 'N') { - buffer.append('F'); - offset += 2; - break; - } - if (hasOneOf(meta62, hashable, offset + 1, 1)) - offset += 2; - else - offset += 1; - buffer.append('P'); - break; - case 'Q' : - if (hashable[offset + 1] == 'Q') - offset += 2; - else - offset += 1; - buffer.append('K'); - break; - case 'R' : - if (!((offset == (hashable.length - 1)) && !has95 && hasOneOf(meta63, hashable, offset - 2, 2) && !hasOneOf(meta64, hashable, offset - 4, 2))) - buffer.append('R'); - if (hashable[offset + 1] == 'R') - offset += 2; - else - offset += 1; - break; - case 'S' : - if (hasOneOf(meta65, hashable, offset - 1, 3)) { - offset += 1; - break; - } - if ((offset == 0) && hasOneOf(meta66, hashable, offset, 5)) { - buffer.append('X'); - offset += 1; - break; - } - if (hasOneOf(meta67, hashable, offset, 2)) { - if (hasOneOf(meta68, hashable, offset + 1, 4)) - buffer.append('S'); - else - buffer.append('X'); - offset += 2; - break; - } - if (hasOneOf(meta69, hashable, offset, 3) || hasOneOf(meta70, hashable, offset, 4)) { - buffer.append('S'); - offset += 3; - break; - } - if (((offset == 0) && hasOneOf(meta71, hashable, offset + 1, 1)) || hasOneOf(meta72, hashable, offset + 1, 1)) { - buffer.append('S'); - if (hasOneOf(meta73, hashable, offset + 1, 1)) - offset += 2; - else - offset += 1; - break; - } - if (hasOneOf(meta74, hashable, offset, 2)) { - if (hashable[offset + 2] == 'H') - if (hasOneOf(meta75, hashable, offset + 3, 2)) { - if (hasOneOf(meta76, hashable, offset + 3, 2)) { - buffer.append("X"); //$NON-NLS-1$ - } else { - buffer.append("SK"); //$NON-NLS-1$ - } - offset += 3; - break; - } else { - buffer.append('X'); - offset += 3; - break; - } - if (hasOneOf(meta77, hashable, offset + 2, 1)) { - buffer.append('S'); - offset += 3; - break; - } - buffer.append("SK"); //$NON-NLS-1$ - offset += 3; - break; - } - if (!((offset == (hashable.length - 1)) && hasOneOf(meta78, hashable, offset - 2, 2))) - buffer.append('S'); - if (hasOneOf(meta79, hashable, offset + 1, 1)) - offset += 2; - else - offset += 1; - break; - case 'T' : - if (hasOneOf(meta80, hashable, offset, 4)) { - buffer.append('X'); - offset += 3; - break; - } - if (hasOneOf(meta81, hashable, offset, 3)) { - buffer.append('X'); - offset += 3; - break; - } - if (hasOneOf(meta82, hashable, offset, 2) || hasOneOf(meta83, hashable, offset, 3)) { - if (hasOneOf(meta84, hashable, (offset + 2), 2) || hasOneOf(meta85, hashable, 0, 4) || hasOneOf(meta86, hashable, 0, 3)) { - buffer.append('T'); - } else { - buffer.append('0'); - } - offset += 2; - break; - } - if (hasOneOf(meta87, hashable, offset + 1, 1)) { - offset += 2; - } else - offset += 1; - buffer.append('T'); - break; - case 'V' : - if (hashable[offset + 1] == 'V') - offset += 2; - else - offset += 1; - buffer.append('F'); - break; - case 'W' : - if (hasOneOf(meta88, hashable, offset, 2)) { - buffer.append('R'); - offset += 2; - break; - } - if ((offset == 0) && (hasVowel(hashable, offset + 1, hashable.length) || hasOneOf(meta89, hashable, offset, 2))) { - buffer.append('A'); - } - if (((offset == (hashable.length - 1)) && hasVowel(hashable, offset - 1, hashable.length)) || hasOneOf(meta90, hashable, offset - 1, 5) || hasOneOf(meta91, hashable, 0, 3)) { - buffer.append('F'); - offset += 1; - break; - } - if (hasOneOf(meta92, hashable, offset, 4)) { - buffer.append("TS"); //$NON-NLS-1$ - offset += 4; - break; - } - offset += 1; - break; - case 'X' : - if (!((offset == (hashable.length - 1)) && (hasOneOf(meta93, hashable, offset - 3, 3) || hasOneOf(meta94, hashable, offset - 2, 2)))) - buffer.append("KS"); //$NON-NLS-1$ - if (hasOneOf(meta49, hashable, offset + 1, 1)) - offset += 2; - else - offset += 1; - break; - case 'Z' : - if (hashable[offset + 1] == 'H') { - buffer.append('J'); - offset += 2; - break; - } else { - buffer.append('S'); - } - if (hashable[offset + 1] == 'Z') - offset += 2; - else - offset += 1; - break; - default : - offset += 1; - } - } - return buffer.toString(); - } - - /* - * @see org.eclipse.spelling.done.IPhoneticHasher#getMutators() - */ - public final char[] getMutators() { - return MUTATOR_CHARACTERS; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/DefaultSpellChecker.java 11 Sep 2008 11:59:37 -0000 1.16 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,344 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Set; - -import org.eclipse.core.runtime.Assert; - -import org.eclipse.jface.preference.IPreferenceStore; - -import org.eclipse.jdt.ui.PreferenceConstants; - - -/** - * Default spell checker for standard text. - * - * @since 3.0 - */ -public class DefaultSpellChecker implements ISpellChecker { - - /** Array of URL prefixes */ - public static final String[] URL_PREFIXES= new String[] { "http://", "https://", "www.", "ftp://", "ftps://", "news://", "mailto://" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ - - /** - * Does this word contain digits? - * - * @param word the word to check - * @return true iff this word contains digits, false> otherwise - */ - protected static boolean isDigits(final String word) { - - for (int index= 0; index < word.length(); index++) { - - if (Character.isDigit(word.charAt(index))) - return true; - } - return false; - } - - /** - * Does this word contain mixed-case letters? - * - * @param word - * The word to check - * @param sentence - * true iff the specified word starts a new - * sentence, false otherwise - * @return true iff the contains mixed-case letters, false - * otherwise - */ - protected static boolean isMixedCase(final String word, final boolean sentence) { - - final int length= word.length(); - boolean upper= Character.isUpperCase(word.charAt(0)); - - if (sentence && upper && (length > 1)) - upper= Character.isUpperCase(word.charAt(1)); - - if (upper) { - - for (int index= length - 1; index > 0; index--) { - if (Character.isLowerCase(word.charAt(index))) - return true; - } - } else { - - for (int index= length - 1; index > 0; index--) { - if (Character.isUpperCase(word.charAt(index))) - return true; - } - } - return false; - } - - /** - * Does this word contain upper-case letters only? - * - * @param word - * The word to check - * @return true iff this word only contains upper-case - * letters, false otherwise - */ - protected static boolean isUpperCase(final String word) { - - for (int index= word.length() - 1; index >= 0; index--) { - - if (Character.isLowerCase(word.charAt(index))) - return false; - } - return true; - } - - /** - * Does this word look like an URL? - * - * @param word - * The word to check - * @return true iff this word looks like an URL, false - * otherwise - */ - protected static boolean isUrl(final String word) { - - for (int index= 0; index < URL_PREFIXES.length; index++) { - - if (word.startsWith(URL_PREFIXES[index])) - return true; - } - return false; - } - - /** - * The dictionaries to use for spell checking. Synchronized to avoid - * concurrent modifications. - */ - private final Set fDictionaries= Collections.synchronizedSet(new HashSet()); - - /** - * The words to be ignored. Synchronized to avoid concurrent modifications. - */ - private final Set fIgnored= Collections.synchronizedSet(new HashSet()); - - /** - * The preference store. Assumes the IPreferenceStore - * implementation is thread safe. - */ - private final IPreferenceStore fPreferences; - - /** - * The locale of this checker. - * @since 3.3 - */ - private Locale fLocale; - - /** - * Creates a new default spell checker. - * - * @param store the preference store for this spell checker - * @param locale the locale - */ - public DefaultSpellChecker(IPreferenceStore store, Locale locale) { - Assert.isLegal(store != null); - Assert.isLegal(locale != null); - - fPreferences= store; - fLocale= locale; - } - - /* - * @see org.eclipse.spelling.done.ISpellChecker#addDictionary(org.eclipse.spelling.done.ISpellDictionary) - */ - public final void addDictionary(final ISpellDictionary dictionary) { - // synchronizing is necessary as this is a write access - fDictionaries.add(dictionary); - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellChecker#acceptsWords() - */ - public boolean acceptsWords() { - // synchronizing might not be needed here since acceptWords is - // a read-only access and only called in the same thread as - // the modifying methods add/checkWord (?) - Set copy; - synchronized (fDictionaries) { - copy= new HashSet(fDictionaries); - } - - ISpellDictionary dictionary= null; - for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { - - dictionary= (ISpellDictionary)iterator.next(); - if (dictionary.acceptsWords()) - return true; - } - return false; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#addWord(java.lang.String) - */ - public void addWord(final String word) { - // synchronizing is necessary as this is a write access - Set copy; - synchronized (fDictionaries) { - copy= new HashSet(fDictionaries); - } - - final String addable= word.toLowerCase(); - for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { - ISpellDictionary dictionary= (ISpellDictionary)iterator.next(); - if (dictionary.acceptsWords()) - dictionary.addWord(addable); - } - - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellChecker#checkWord(java.lang.String) - */ - public final void checkWord(final String word) { - // synchronizing is necessary as this is a write access - fIgnored.remove(word.toLowerCase()); - } - - /* - * @see org.eclipse.spelling.done.ISpellChecker#execute(org.eclipse.spelling.ISpellCheckTokenizer) - */ - public void execute(final ISpellEventListener listener, final ISpellCheckIterator iterator) { - - final boolean ignoreDigits= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_DIGITS); - final boolean ignoreMixed= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_MIXED); - final boolean ignoreSentence= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_SENTENCE); - final boolean ignoreUpper= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_UPPER); - final boolean ignoreURLS= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_URLS); - final boolean ignoreNonLetters= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS); - final boolean ignoreSingleLetters= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS); - final int problemsThreshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD); - - iterator.setIgnoreSingleLetters(ignoreSingleLetters); - - Iterator iter= fDictionaries.iterator(); - while (iter.hasNext()) - ((ISpellDictionary)iter.next()).setStripNonLetters(ignoreNonLetters); - - String word= null; - boolean starts= false; - int problemCount= 0; - - while (problemCount <= problemsThreshold && iterator.hasNext()) { - - word= (String)iterator.next(); - if (word != null) { - - // synchronizing is necessary as this is called inside the reconciler - if (!fIgnored.contains(word)) { - - starts= iterator.startsSentence(); - if (!isCorrect(word)) { - - boolean isMixed= isMixedCase(word, true); - boolean isUpper= isUpperCase(word); - boolean isDigits= isDigits(word); - boolean isURL= isUrl(word); - - if ( !ignoreMixed && isMixed || !ignoreUpper && isUpper || !ignoreDigits && isDigits || !ignoreURLS && isURL || !(isMixed || isUpper || isDigits || isURL)) { - listener.handle(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), starts, false)); - problemCount++; - } - - } else { - - if (!ignoreSentence && starts && Character.isLowerCase(word.charAt(0))) { - listener.handle(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), true, true)); - problemCount++; - } - } - } - } - } - } - - /* - * @see org.eclipse.spelling.done.ISpellChecker#getProposals(java.lang.String,boolean) - */ - public Set getProposals(final String word, final boolean sentence) { - - // synchronizing might not be needed here since getProposals is - // a read-only access and only called in the same thread as - // the modifing methods add/removeDictionary (?) - Set copy; - synchronized (fDictionaries) { - copy= new HashSet(fDictionaries); - } - - ISpellDictionary dictionary= null; - final HashSet proposals= new HashSet(); - - for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { - - dictionary= (ISpellDictionary)iterator.next(); - proposals.addAll(dictionary.getProposals(word, sentence)); - } - return proposals; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#ignoreWord(java.lang.String) - */ - public final void ignoreWord(final String word) { - // synchronizing is necessary as this is a write access - fIgnored.add(word.toLowerCase()); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#isCorrect(java.lang.String) - */ - public final boolean isCorrect(final String word) { - // synchronizing is necessary as this is called from execute - Set copy; - synchronized (fDictionaries) { - copy= new HashSet(fDictionaries); - } - - if (fIgnored.contains(word.toLowerCase())) - return true; - - ISpellDictionary dictionary= null; - for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { - - dictionary= (ISpellDictionary)iterator.next(); - if (dictionary.isCorrect(word)) - return true; - } - return false; - } - - /* - * @see org.eclipse.spelling.done.ISpellChecker#removeDictionary(org.eclipse.spelling.done.ISpellDictionary) - */ - public final void removeDictionary(final ISpellDictionary dictionary) { - // synchronizing is necessary as this is a write access - fDictionaries.remove(dictionary); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#getLocale() - * @since 3.3 - */ - public Locale getLocale() { - return fLocale; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticDistanceAlgorithm.java 17 Jun 2005 15:51:53 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -/** - * Interface of algorithms to compute the phonetic distance between two words. - * - * @since 3.0 - */ -public interface IPhoneticDistanceAlgorithm { - - /** - * Returns the non-negative phonetic distance between two words - * - * @param from - * The first word - * @param to - * The second word - * @return The non-negative phonetic distance between the words. - */ - public int getDistance(String from, String to); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/IPhoneticHashProvider.java 17 Jun 2005 15:51:53 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -/** - * Interface of hashers to compute the phonetic hash for a word. - * - * @since 3.0 - */ -public interface IPhoneticHashProvider { - - /** - * Returns the phonetic hash for the word. - * - * @param word - * The word to get the phonetic hash for - * @return The phonetic hash for the word - */ - public String getHash(String word); - - /** - * Returns an array of characters to compute possible mutations. - * - * @return Array of possible mutator characters - */ - public char[] getMutators(); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckEngine.java 31 Dec 2008 21:13:23 -0000 1.10 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Locale; - -import org.eclipse.jdt.ui.PreferenceConstants; - -/** - * Interface for a spell check engine. - *

- * This engine can be configured with multiple - * dictionaries. - *

- * - * @since 3.0 - */ -public interface ISpellCheckEngine { - - /** - * Returns a spell checker configured with the global - * dictionaries and the locale dictionary that correspond to the current - * {@linkplain PreferenceConstants#SPELLING_LOCALE locale preference}. - *

- * Note: Changes to the spelling engine dictionaries - * are not propagated to this spell checker.

- * - * @return a configured instance of the spell checker or null if none - * @throws IllegalStateException if called after being shut down - */ - ISpellChecker getSpellChecker() throws IllegalStateException; - - /** - * Returns the locale of the current spell check engine. - * - * @return the locale of the current spell check engine - */ - Locale getLocale(); - - /** - * Registers a global dictionary. - * - * @param dictionary the global dictionary to register - */ - void registerGlobalDictionary(ISpellDictionary dictionary); - - /** - * Registers a dictionary tuned for the specified locale with this engine. - * - * @param locale - * The locale to register the dictionary with - * @param dictionary - * The dictionary to register - */ - void registerDictionary(Locale locale, ISpellDictionary dictionary); - - /** - * Shuts down this spell check engine and its associated components. - *

- * Further calls to this engine result in exceptions. - *

- */ - void shutdown(); - - /** - * Unregisters a dictionary previously registered either by a call to - * registerDictionary(Locale,ISpellDictionary) or registerDictionary(ISpellDictionary). - *

- * If the dictionary was not registered before, nothing happens.

- * - * @param dictionary the dictionary to unregister - */ - void unregisterDictionary(ISpellDictionary dictionary); - -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellCheckIterator.java 31 Dec 2008 21:13:23 -0000 1.10 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Iterator; - -/** - * Interface for iterators used for spell checking. - * - * @since 3.0 - */ -public interface ISpellCheckIterator extends Iterator { - - /** - * Returns the begin index (inclusive) of the current word. - * - * @return The begin index of the current word - */ - public int getBegin(); - - /** - * Returns the end index (exclusive) of the current word. - * - * @return The end index of the current word - */ - public int getEnd(); - - /** - * Does the current word start a new sentence? - * - * @return true iff the current word starts a new sentence, false otherwise - */ - public boolean startsSentence(); - - /** - * Tells whether to ignore single letters - * from being checked. - * - * @since 3.3 - * @param state true if single letters should be ignored - */ - public void setIgnoreSingleLetters(boolean state); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellChecker.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellChecker.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellChecker.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellChecker.java 11 Sep 2008 11:59:37 -0000 1.12 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Locale; -import java.util.Set; - -/** - * Interface for spell checkers. - * - * @since 3.0 - */ -public interface ISpellChecker { - - /** - * Adds a dictionary to the list of active dictionaries. - * - * @param dictionary - * The dictionary to add - */ - void addDictionary(ISpellDictionary dictionary); - - /** - * Returns whether this spell checker accepts word additions. - * - * @return true if word additions are accepted, false otherwise - */ - boolean acceptsWords(); - - /** - * Adds the specified word to the set of correct words. - * - * @param word - * The word to add to the set of correct words - */ - void addWord(String word); - - /** - * Checks the specified word until calling ignoreWord(String). - * - * @param word - * The word to check - */ - void checkWord(String word); - - /** - * Checks the spelling with the spell check iterator. Implementations must - * be thread safe as this may be called inside a reconciler thread. - * - * @param listener the spell event listener - * @param iterator the iterator to use for spell checking - */ - void execute(ISpellEventListener listener, ISpellCheckIterator iterator); - - /** - * Returns the ranked proposals for a word. - * - * @param word - * The word to retrieve the proposals for - * @param sentence - * true iff the proposals should start a - * sentence, false otherwise - * @return Set of ranked proposals for the word - */ - Set getProposals(String word, boolean sentence); - - /** - * Ignores the specified word until calling checkWord(String). - * - * @param word - * The word to ignore - */ - void ignoreWord(String word); - - /** - * Is the specified word correctly spelled? Implementations must be thread - * safe as this may be called from within a reconciler thread. - * - * @param word - * The word to check its spelling - * @return true iff the word is correctly spelled, false - * otherwise - */ - boolean isCorrect(String word); - - /** - * Remove a dictionary from the list of active dictionaries. - * - * @param dictionary - * The dictionary to remove - */ - void removeDictionary(ISpellDictionary dictionary); - - /** - * Returns the current locale of the spell check engine. - * - * @return The current locale of the engine - * @since 3.3 - */ - Locale getLocale(); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellDictionary.java 31 Dec 2008 21:13:23 -0000 1.11 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,77 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Set; - -/** - * Interface of dictionaries to use for spell checking. - * - * @since 3.0 - */ -public interface ISpellDictionary { - - /** - * Returns whether this dictionary accepts new words. - * - * @return true if this dictionary accepts new words, false otherwise - */ - public boolean acceptsWords(); - - /** - * Externalizes the specified word. - * - * @param word - * The word to externalize in the dictionary - */ - public void addWord(String word); - - /** - * Returns the ranked word proposals for an incorrectly spelled word. - * - * @param word - * The word to retrieve the proposals for - * @param sentence - * true iff the proposals start a new sentence, - * false otherwise - * @return Array of ranked word proposals - */ - public Set getProposals(String word, boolean sentence); - - /** - * Is the specified word correctly spelled? - * - * @param word the word to spell check - * @return true iff this word is correctly spelled, false otherwise - */ - public boolean isCorrect(String word); - - /** - * Is the dictionary loaded? - * - * @return true iff it is loaded, false otherwise - */ - public boolean isLoaded(); - - /** - * Empties the dictionary. - */ - public void unload(); - - /** - * Tells whether to strip non-letters from word boundaries. - * - * @param state true if non-letters should be stripped - * @since 3.3 - */ - public void setStripNonLetters(boolean state); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEvent.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEvent.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEvent.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEvent.java 31 Dec 2008 21:13:23 -0000 1.9 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,64 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Set; - -/** - * Event fired by spell checkers. - * - * @since 3.0 - */ -public interface ISpellEvent { - - /** - * Returns the begin index of the incorrectly spelled word. - * - * @return The begin index of the word - */ - public int getBegin(); - - /** - * Returns the end index of the incorrectly spelled word. - * - * @return The end index of the word - */ - public int getEnd(); - - /** - * Returns the proposals for the incorrectly spelled word. - * - * @return Array of proposals for the word - */ - public Set getProposals(); - - /** - * Returns the incorrectly spelled word. - * - * @return The incorrect word - */ - public String getWord(); - - /** - * Was the incorrectly spelled word found in the dictionary? - * - * @return true iff the word was found, false otherwise - */ - public boolean isMatch(); - - /** - * Does the incorrectly spelled word start a new sentence? - * - * @return true iff the word starts a new sentence, false otherwise - */ - public boolean isStart(); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEventListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEventListener.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEventListener.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/ISpellEventListener.java 17 Jun 2005 15:51:53 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - - -/** - * Interface for spell event listeners. - * - * @since 3.0 - */ -public interface ISpellEventListener { - - /** - * Handles a spell event. - * - * @param event - * Event to handle - */ - public void handle(ISpellEvent event); -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/LocaleSensitiveSpellDictionary.java 15 Jan 2010 10:44:30 -0000 1.10 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,67 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Locale; - - -/** - * Platform wide read-only locale sensitive dictionary for spell checking. - * - * @since 3.0 - */ -public class LocaleSensitiveSpellDictionary extends AbstractSpellDictionary { - - /** The locale of this dictionary */ - private final Locale fLocale; - - /** The location of the dictionaries */ - private final URL fLocation; - - /** - * Creates a new locale sensitive spell dictionary. - * - * @param locale - * The locale for this dictionary - * @param location - * The location of the locale sensitive dictionaries - */ - public LocaleSensitiveSpellDictionary(final Locale locale, final URL location) { - fLocation= location; - fLocale= locale; - } - - /** - * Returns the locale of this dictionary. - * - * @return The locale of this dictionary - */ - public final Locale getLocale() { - return fLocale; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL() - */ - protected final URL getURL() throws MalformedURLException { - return new URL(fLocation, fLocale.toString() + ".dictionary"); //$NON-NLS-1$ - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getInitialSize() - * @since 3.6 - */ - protected int getInitialSize() { - return 32 * 1024; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/PersistentSpellDictionary.java 11 Sep 2008 11:59:37 -0000 1.10 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,97 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * Benjamin Muskalla - [spell checking][implementation] PersistentSpellDictionary closes wrong stream - https://bugs.eclipse.org/bugs/show_bug.cgi?id=236421 - *******************************************************************************/ -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -import org.eclipse.jdt.internal.ui.JavaPlugin; - - -/** - * Persistent modifiable word-list based dictionary. - * - * @since 3.0 - */ -public class PersistentSpellDictionary extends AbstractSpellDictionary { - - /** The word list location */ - private final URL fLocation; - - /** - * Creates a new persistent spell dictionary. - * - * @param url the URL of the word list for this dictionary - */ - public PersistentSpellDictionary(final URL url) { - fLocation= url; - } - - /* - * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#acceptsWords() - */ - public boolean acceptsWords() { - return true; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String) - */ - public void addWord(final String word) { - if (isCorrect(word)) - return; - - FileOutputStream fileStream= null; - try { - Charset charset= Charset.forName(getEncoding()); - ByteBuffer byteBuffer= charset.encode(word + "\n"); //$NON-NLS-1$ - int size= byteBuffer.limit(); - final byte[] byteArray; - if (byteBuffer.hasArray()) - byteArray= byteBuffer.array(); - else { - byteArray= new byte[size]; - byteBuffer.get(byteArray); - } - - fileStream= new FileOutputStream(fLocation.getPath(), true); - - // Encoding UTF-16 charset writes a BOM. In which case we need to cut it away if the file isn't empty - int bomCutSize= 0; - if (!isEmpty() && "UTF-16".equals(charset.name())) //$NON-NLS-1$ - bomCutSize= 2; - - fileStream.write(byteArray, bomCutSize, size - bomCutSize); - } catch (IOException exception) { - JavaPlugin.log(exception); - return; - } finally { - try { - if (fileStream != null) - fileStream.close(); - } catch (IOException e) { - } - } - - hashWord(word); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL() - */ - protected final URL getURL() { - return fLocation; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/RankedWordProposal.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/RankedWordProposal.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/RankedWordProposal.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/RankedWordProposal.java 17 Jun 2005 15:51:53 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -/** - * Ranked word proposal for quick fix and content assist. - * - * @since 3.0 - */ -public class RankedWordProposal implements Comparable { - - /** The word rank */ - private int fRank; - - /** The word text */ - private final String fText; - - /** - * Creates a new ranked word proposal. - * - * @param text - * The text of this proposal - * @param rank - * The rank of this proposal - */ - public RankedWordProposal(final String text, final int rank) { - fText= text; - fRank= rank; - } - - /* - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - public final int compareTo(Object object) { - - final RankedWordProposal word= (RankedWordProposal)object; - final int rank= word.getRank(); - - if (fRank < rank) - return -1; - - if (fRank > rank) - return 1; - - return 0; - } - - /* - * @see java.lang.Object#equals(java.lang.Object) - */ - public final boolean equals(Object object) { - - if (object instanceof RankedWordProposal) - return object.hashCode() == hashCode(); - - return false; - } - - /** - * Returns the rank of the word - * - * @return The rank of the word - */ - public final int getRank() { - return fRank; - } - - /** - * Returns the text of this word. - * - * @return The text of this word - */ - public final String getText() { - return fText; - } - - /* - * @see java.lang.Object#hashCode() - */ - public final int hashCode() { - return fText.hashCode(); - } - - /** - * Sets the rank of the word. - * - * @param rank - * The rank to set - */ - public final void setRank(final int rank) { - fRank= rank; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/SpellEvent.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/SpellEvent.java diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/SpellEvent.java --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/SpellEvent.java 31 Dec 2008 21:13:23 -0000 1.8 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.jdt.internal.ui.text.spelling.engine; - -import java.util.Set; - -/** - * Spell event fired for words detected by a spell check iterator. - * - * @since 3.0 - */ -public class SpellEvent implements ISpellEvent { - - /** The begin index of the word in the spell checkable medium */ - private final int fBegin; - - /** The spell checker that causes the event */ - private final ISpellChecker fChecker; - - /** The end index of the word in the spell checkable medium */ - private final int fEnd; - - /** Was the word found in the dictionary? */ - private final boolean fMatch; - - /** Does the word start a new sentence? */ - private final boolean fSentence; - - /** The word that causes the spell event */ - private final String fWord; - - /** - * Creates a new spell event. - * - * @param checker - * The spell checker that causes the event - * @param word - * The word that causes the event - * @param begin - * The begin index of the word in the spell checkable medium - * @param end - * The end index of the word in the spell checkable medium - * @param sentence - * true iff the word starts a new sentence, - * false otherwise - * @param match - * true iff the word was found in the dictionary, - * false otherwise - */ - protected SpellEvent(final ISpellChecker checker, final String word, final int begin, final int end, final boolean sentence, final boolean match) { - fChecker= checker; - fEnd= end; - fBegin= begin; - fWord= word; - fSentence= sentence; - fMatch= match; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getBegin() - */ - public final int getBegin() { - return fBegin; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getEnd() - */ - public final int getEnd() { - return fEnd; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getProposals() - */ - public final Set getProposals() { - return fChecker.getProposals(fWord, fSentence); - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getWord() - */ - public final String getWord() { - return fWord; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#isMatch() - */ - public final boolean isMatch() { - return fMatch; - } - - /* - * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#isStart() - */ - public final boolean isStart() { - return fSentence; - } -} Index: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/package.html =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/text/spelling/engine/package.html diff -N ui/org/eclipse/jdt/internal/ui/text/spelling/engine/package.html --- ui/org/eclipse/jdt/internal/ui/text/spelling/engine/package.html 9 Feb 2004 03:20:10 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,84 +0,0 @@ - - - - - - - Package-level Javadoc - - -Provides the core functionality for spell-checking documents -

-Package Specification

-This package provides the interfaces for the notions of dictionary, edit distance, phonetic hash, -spell event and spell-check iterator. For most of these interfaces a default implementation -for english languages is provided. These implementations can be reused in custom dictionaries or -spell-check iterators, or replaced by more specialized algorithms for a particular group of languages. -

-Spell Check Engine

-The central point to access the spell-checker functionality is the interface ISpellCheckEngine. -Implementations of this interface provide support for life-cycle management, registering and unregistering -dictionaries, changing the locale of the engine and creating a spell-checker for a specific language. -

-The following steps are needed to obtain a spell-checker for a specific language: -

    -
  • Create an instance of ISpellCheckEngine. In this package, no default implementation is provided, -since the management of the dictionary registering and loading is application dependent. Usually, instances -of ISpellCheckEngine are implemented as singletons.
  • -
  • Create the appropriate dictionaries that should be used during the spell-check process. All dictionaries that -can be registered with ISpellCheckEngine must implement the interface ISpellCheckDictionary. -For this interface, an abstract implementation is provided in the class AbstractSpellDictionary. -Depending on the language of the words contained in this dictionary, custom algorithms for the phonetic hash - (IPhoneticHashProvider) and the edit distance (IPhoneticDistanceAlgorithm) should be implemented - and registered with the dictionary.
  • -
  • Instances of spell-checkers can now be created by calling createSpellChecker(Locale), where the locale - denotes the language that the spell-checker should use while executing.
  • -
-When requesting a new spell-checker with a different locale via createSpellChecker(Locale), the spell-checker is -reconfigured with the new dictionaries. More concretely, the old dictionary is unregistered and a new one registered for the -desired locale is associated with the spell-checker. If no such dictionary is available, no spell-checker is returned and -the locale of the engine is reset to its default locale. -

-Dictionaries

-Dictionaries are the data structures to hold word lists for a particular language. All implementations of dictionaries must -implement the interface ISpellDictionary. It provides support for life-cycle management as well as the facility to query -words from the list, add words to the list and get correction proposals for incorrectly spelt words. -

-This package provides a default implementation of a dictionary (AbstractSpellDictionary) that uses algorithms -convenient for english languages.
-Every dictionary needs two kinds of algorithms to be plugged in: -

    -
  • An edit distance algorithm: Edit distance algorithms implement the interface IPhoneticDistanceAlgorithm. The algorithm -is used to determine the similarity between two words. This package provides a default implementation for languages using the latin alphabet (DefaultPhoneticDistanceAlgorithm). -The default algorithm uses the Levenshtein text edit distance.
  • -
  • A hash algorithm: Phonetic hash providers implement the interface IPhoneticHashProvider. The purpose of -phonetic hashes is to have a representation of words which allows comparing it to other, similar words. This package provides a default -implementation which is convenient for slavic and english languages. It uses the double metaphone algorithm by published -Lawrence Philips.
  • -
-By plugging in custom implementations of one or both of these algorithms the abstract implementation AbstractSpellDictionary can -be customized to specified languages and alphabets. -

-Spell Check Iterators

-Instances of ISpellChecker are usually language-, locale- and medium independent implementations and therefore need an input provider. The -interface ISpellCheckIterator serves this purpose by abstracting the tokenizing of text media to a simple iteration. The actual spell-check process -is launched by calling ISpellChecker#execute(ISpellCheckIterator). This method uses the indicated spell-check iterator to determine the -words that are to be spell-checked. This package provides no default implementation of a spell-check iterator. -

-Event Handling

-To communicate the results of a spell-check pass, spell-checkers fire spell events that inform listeners about the status -of a particular word being spell-checked. Instances that are interested in receiving spell events must implement -the interface ISpellEventListener and register with the spell-checker before the spell-check process starts.

-A spell event contains the following information: -

    -
  • The word being spell-checked
  • -
  • The begin index of the current word in the text medium
  • -
  • The end index in the text medium
  • -
  • A flag whether this word was found in one of the registered dictionaries
  • -
  • A flag that indicates whether this word starts a new sentence
  • -
  • The set of proposals if the word was not correctly spelt. This information is lazily computed.
  • -
-Spell event listeners are free to handle the events in any way. However, listeners are not allowed to block during -the event handling unless the spell-checking process happens in another thread. - - Index: ui/org/eclipse/jdt/ui/PreferenceConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/PreferenceConstants.java,v retrieving revision 1.257 diff -u -r1.257 PreferenceConstants.java --- ui/org/eclipse/jdt/ui/PreferenceConstants.java 5 Nov 2010 05:49:58 -0000 1.257 +++ ui/org/eclipse/jdt/ui/PreferenceConstants.java 15 Dec 2010 05:46:19 -0000 @@ -34,6 +34,7 @@ import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; @@ -52,7 +53,6 @@ import org.eclipse.jdt.internal.ui.preferences.formatter.FormatterProfileManager; import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry; import org.eclipse.jdt.internal.ui.text.java.ProposalSorterRegistry; -import org.eclipse.jdt.internal.ui.text.spelling.SpellCheckEngine; /** #P org.eclipse.jdt.ui.tests Index: leaks/org/eclipse/jdt/ui/tests/leaks/JavaLeakTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui.tests/leaks/org/eclipse/jdt/ui/tests/leaks/JavaLeakTest.java,v retrieving revision 1.29 diff -u -r1.29 JavaLeakTest.java --- leaks/org/eclipse/jdt/ui/tests/leaks/JavaLeakTest.java 15 Aug 2010 19:36:25 -0000 1.29 +++ leaks/org/eclipse/jdt/ui/tests/leaks/JavaLeakTest.java 15 Dec 2010 05:46:24 -0000 @@ -45,6 +45,7 @@ import org.eclipse.ui.texteditor.AbstractTextEditor; import org.eclipse.ui.texteditor.ChainedPreferenceStore; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextEditor; @@ -62,7 +63,6 @@ import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileEditor; -import org.eclipse.jdt.internal.ui.text.spelling.SpellCheckEngine; import org.eclipse.jdt.internal.ui.wizards.JavaProjectWizard; import org.eclipse.jdt.internal.ui.wizards.NewClassCreationWizard; import org.eclipse.jdt.internal.ui.wizards.NewInterfaceCreationWizard; #P org.eclipse.ui.editors Index: .settings/.api_filters =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.editors/.settings/.api_filters,v retrieving revision 1.3 diff -u -r1.3 .api_filters --- .settings/.api_filters 15 Dec 2008 10:02:20 -0000 1.3 +++ .settings/.api_filters 15 Dec 2010 05:46:26 -0000 @@ -1,5 +1,13 @@ - + + + + + + + + + @@ -8,12 +16,11 @@ - - - + - - + + + Index: src/org/eclipse/ui/editors/text/TextSourceViewerConfiguration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.editors/src/org/eclipse/ui/editors/text/TextSourceViewerConfiguration.java,v retrieving revision 1.49 diff -u -r1.49 TextSourceViewerConfiguration.java --- src/org/eclipse/ui/editors/text/TextSourceViewerConfiguration.java 10 Nov 2010 15:37:24 -0000 1.49 +++ src/org/eclipse/ui/editors/text/TextSourceViewerConfiguration.java 15 Dec 2010 05:46:26 -0000 @@ -54,9 +54,9 @@ import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.HyperlinkDetectorRegistry; -import org.eclipse.ui.texteditor.spelling.SpellingCorrectionProcessor; import org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy; import org.eclipse.ui.texteditor.spelling.SpellingService; +import org.eclipse.ui.texteditor.spelling.correction.SpellingCorrectionProcessor; /** #P org.eclipse.ui.workbench.texteditor Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF,v retrieving revision 1.35 diff -u -r1.35 MANIFEST.MF --- META-INF/MANIFEST.MF 29 Jul 2010 11:19:34 -0000 1.35 +++ META-INF/MANIFEST.MF 15 Dec 2010 05:46:30 -0000 @@ -9,22 +9,27 @@ Bundle-Localization: plugin Export-Package: org.eclipse.ui.contentassist, - org.eclipse.ui.internal.texteditor; texteditor="split"; mandatory:="texteditor"; x-friends:="org.eclipse.ui.editors", + org.eclipse.ui.internal.texteditor;texteditor=split;mandatory:=texteditor;x-friends:="org.eclipse.ui.editors", org.eclipse.ui.internal.texteditor.quickdiff;x-internal:=true, org.eclipse.ui.internal.texteditor.quickdiff.compare.equivalence;x-internal:=true, org.eclipse.ui.internal.texteditor.rulers;x-internal:=true, org.eclipse.ui.internal.texteditor.spelling;x-internal:=true, - org.eclipse.ui.texteditor; texteditor="split"; mandatory:="texteditor", + org.eclipse.ui.internal.texteditor.spelling.engine;x-internal:=true, + org.eclipse.ui.texteditor;texteditor=split;mandatory:=texteditor, org.eclipse.ui.texteditor.link, org.eclipse.ui.texteditor.quickdiff, org.eclipse.ui.texteditor.rulers, org.eclipse.ui.texteditor.spelling, + org.eclipse.ui.texteditor.spelling.correction, + org.eclipse.ui.texteditor.spelling.engine, org.eclipse.ui.texteditor.templates Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", org.eclipse.compare.core;bundle-version="[3.5.0,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.4.100,4.0.0)", org.eclipse.jface.text;bundle-version="[3.7.0,4.0.0)", - org.eclipse.ui;bundle-version="[3.5.0,4.0.0)" + org.eclipse.ui;bundle-version="[3.5.0,4.0.0)", + org.eclipse.core.resources;bundle-version="3.6.100", + org.eclipse.core.variables;bundle-version="3.2.400" Bundle-RequiredExecutionEnvironment: J2SE-1.4 Import-Package: com.ibm.icu.text Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/plugin.xml,v retrieving revision 1.97 diff -u -r1.97 plugin.xml --- plugin.xml 29 Jul 2010 09:52:56 -0000 1.97 +++ plugin.xml 15 Dec 2010 05:46:30 -0000 @@ -1182,4 +1182,14 @@
+ + + + + Index: schema/spellingEngine.exsd =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/schema/spellingEngine.exsd,v retrieving revision 1.6 diff -u -r1.6 spellingEngine.exsd --- schema/spellingEngine.exsd 30 Jan 2007 13:14:19 -0000 1.6 +++ schema/spellingEngine.exsd 15 Dec 2010 05:46:30 -0000 @@ -1,6 +1,6 @@ - + @@ -11,6 +11,11 @@ + + + + + @@ -79,6 +84,13 @@ + + + + + + + @@ -130,14 +142,6 @@ - - - - - - - - Index: src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java,v retrieving revision 1.22 diff -u -r1.22 TextEditorPlugin.java --- src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java 22 Oct 2008 11:05:00 -0000 1.22 +++ src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java 15 Dec 2010 05:46:30 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,7 +19,9 @@ import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IRegistryChangeEvent; import org.eclipse.core.runtime.IRegistryChangeListener; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IAction; @@ -197,4 +199,20 @@ public SpellingEngineRegistry getSpellingEngineRegistry() { return fSpellingEngineRegistry; } + + public static String getPluginId() { + return PLUGIN_ID; + } + + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + public static void logErrorMessage(String message) { + log(new Status(IStatus.ERROR, getPluginId(), message, null)); + } + + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getPluginId(), "Internal Error", e)); + } } Index: src/org/eclipse/ui/internal/texteditor/spelling/IProblemLocation.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/IProblemLocation.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/IProblemLocation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/IProblemLocation.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling; + + + +/** + * Problem information for quick fix and quick assist processors. + *

+ * Note: this interface is not intended to be implemented. + *

+ * + * @since 3.0 + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +/* + * TODO: copied from JDT and slightly modified, could probably remain here as the text editor should also have a notion of problem location + * + */ +public interface IProblemLocation { + + /** + * Returns the start offset of the problem. + * + * @return the start offset of the problem + */ + int getOffset(); + + /** + * Returns the length of the problem. + * + * @return the length of the problem + */ + int getLength(); + + /** + * Returns the marker type of this problem. + * + * @return The marker type of the problem. + * @since 3.2 + */ + String getMarkerType(); + + /** + * Returns the id of problem. Note that problem ids are defined per problem marker type. + * See {@link org.eclipse.jdt.core.compiler.IProblem} for id definitions for problems of type + * org.eclipse.jdt.core.problem and org.eclipse.jdt.core.task. + * + * @return The id of the problem. + */ + int getProblemId(); + + /** + * Returns the original arguments recorded into the problem. + * + * @return String[] Returns the problem arguments. + */ + String[] getProblemArguments(); + + /** + * Returns if the problem has error severity. + * + * @return true if the problem has error severity + */ + boolean isError(); +} Index: src/org/eclipse/ui/internal/texteditor/spelling/ISpellingCompletionProposalComputer.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/ISpellingCompletionProposalComputer.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/ISpellingCompletionProposalComputer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/ISpellingCompletionProposalComputer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling; + +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Computes completions and context information displayed by the Java editor content assistant. + * Contributions to the org.eclipse.jdt.ui.javaCompletionProposalComputer extension point + * must implement this interface. + * + * @since 3.2 + */ + +/* + * TODO: Apparently this is not supported. See Javadoc of WordCompletionProposalComputer + */ +public interface ISpellingCompletionProposalComputer { + /** + * Informs the computer that a content assist session has started. This call will always be + * followed by a {@link #sessionEnded()} call, but not necessarily by calls to + * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals} + * or + * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}. + */ + void sessionStarted(); + + /** + * Returns a list of completion proposals valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of completion proposals (element type: {@link ICompletionProposal}) + */ + //List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns context information objects valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of context information objects (element type: {@link IContextInformation}) + */ + //List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns the reason why this computer was unable to produce any completion proposals or + * context information. + * + * @return an error message or null if no error occurred + */ + String getErrorMessage(); + + /** + * Informs the computer that a content assist session has ended. This call will always be after + * any calls to + * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals} + * and + * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}. + */ + void sessionEnded(); +} Index: src/org/eclipse/ui/internal/texteditor/spelling/Messages.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/Messages.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/Messages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/Messages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling; + +import com.ibm.icu.text.MessageFormat; + +/** + * Helper class to format message strings. + * + * @since 3.1 + */ +public class Messages { + + public static String format(String message, Object object) { + return MessageFormat.format(message, new Object[] { object}); + } + + public static String format(String message, Object[] objects) { + return MessageFormat.format(message, objects); + } + + private Messages() { + // Not for instantiation + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/NoCompletionsProposal.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/NoCompletionsProposal.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/NoCompletionsProposal.java --- src/org/eclipse/ui/internal/texteditor/spelling/NoCompletionsProposal.java 31 Dec 2008 21:13:47 -0000 1.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.ui.internal.texteditor.spelling; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.contentassist.IContextInformation; - -/** - * Proposal telling that there are no proposals available. - *

- * Applying this proposal does nothing. - *

- * - * @since 3.3 - */ -public final class NoCompletionsProposal implements ICompletionProposal { - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) - */ - public void apply(IDocument document) { - // do nothing - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() - */ - public String getAdditionalProposalInfo() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() - */ - public IContextInformation getContextInformation() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() - */ - public String getDisplayString() { - return SpellingMessages.NoCompletionsProposal_displayString; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() - */ - public Image getImage() { - return null; - } - - /* - * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) - */ - public Point getSelection(IDocument document) { - return null; - } - -} Index: src/org/eclipse/ui/internal/texteditor/spelling/SpellingEngineRegistry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/spelling/SpellingEngineRegistry.java,v retrieving revision 1.8 diff -u -r1.8 SpellingEngineRegistry.java --- src/org/eclipse/ui/internal/texteditor/spelling/SpellingEngineRegistry.java 16 Sep 2009 14:18:16 -0000 1.8 +++ src/org/eclipse/ui/internal/texteditor/spelling/SpellingEngineRegistry.java 15 Dec 2010 05:46:33 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,12 +12,15 @@ package org.eclipse.ui.internal.texteditor.spelling; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.ui.internal.texteditor.TextEditorPlugin; @@ -64,6 +67,36 @@ } /** + * Returns the descriptor with the given contentType or null if none could be + * found. + * + * @param contentType the content type + * + * @return the descriptor with the given content type or null + */ + public SpellingEngineDescriptor getDescriptor(IContentType contentType) { + ensureExtensionsLoaded(); + Collection descriptors= fDescriptorsMap.values(); // TODO: better way ? + + for (Iterator iterator= descriptors.iterator(); iterator.hasNext();) { + SpellingEngineDescriptor descriptor= (SpellingEngineDescriptor)iterator.next(); + if (descriptor.getContentType() == null) { //'all content type' + return descriptor; + } + } + + // there is no 'all content type' engine + for (Iterator iterator= descriptors.iterator(); iterator.hasNext();) { + SpellingEngineDescriptor descriptor= (SpellingEngineDescriptor)iterator.next(); + IContentType descriptorContentType= Platform.getContentTypeManager().getContentType(descriptor.getContentType()); + if (descriptorContentType != null && descriptorContentType.equals(contentType)) { + return descriptor; + } + } + return null; + } + + /** * Returns the default descriptor. * * @return the default descriptor Index: src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.java,v retrieving revision 1.8 diff -u -r1.8 SpellingMessages.java --- src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.java 31 Dec 2008 21:13:47 -0000 1.8 +++ src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.java 15 Dec 2010 05:46:33 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,20 +17,33 @@ * * @since 3.1 */ -final class SpellingMessages extends NLS { +public final class SpellingMessages extends NLS { private static final String BUNDLE_NAME= SpellingMessages.class.getName(); private SpellingMessages() { // Do not instantiate } - + + static { + NLS.initializeMessages(BUNDLE_NAME, SpellingMessages.class); + } public static String EmptySpellingPreferenceBlock_emptyCaption; public static String NoCompletionsProposal_displayString; - - static { - NLS.initializeMessages(BUNDLE_NAME, SpellingMessages.class); - } + public static String Spelling_error_label; + public static String Spelling_correct_label; + public static String Spelling_add_info; + public static String Spelling_add_label; + public static String Spelling_add_askToConfigure_title; + public static String Spelling_add_askToConfigure_question; + public static String Spelling_add_askToConfigure_ignoreMessage; + public static String Spelling_ignore_info; + public static String Spelling_ignore_label; + public static String Spelling_disable_label; + public static String Spelling_disable_info; + public static String Spelling_case_label; + public static String Spelling_error_case_label; + public static String AbstractSpellingDictionary_encodingError; } Index: src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.properties,v retrieving revision 1.7 diff -u -r1.7 SpellingMessages.properties --- src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.properties 31 Dec 2008 21:13:47 -0000 1.7 +++ src/org/eclipse/ui/internal/texteditor/spelling/SpellingMessages.properties 15 Dec 2010 05:46:33 -0000 @@ -12,3 +12,19 @@ EmptySpellingPreferenceBlock_emptyCaption= NoCompletionsProposal_displayString= No suggestions available + +Spelling_error_label=The word ''{0}'' is not correctly spelled +Spelling_correct_label=Change to ''{0}'' +Spelling_add_info=Adds the word ''{0}'' to the dictionary +Spelling_add_label=Add ''{0}'' to dictionary +Spelling_add_askToConfigure_title=Missing User Dictionary +Spelling_add_askToConfigure_question=A user dictionary is needed to add words.\nDo you want to configure it now?\n +Spelling_add_askToConfigure_ignoreMessage= &Do not show 'Add word' proposals if user dictionary is missing +Spelling_ignore_info=Ignores ''{0}'' during the current session +Spelling_ignore_label=Ignore ''{0}'' during the current session +Spelling_case_label=Change to upper case +Spelling_disable_label=Disable spell checking +Spelling_disable_info=Disables spell checking. +Spelling_error_case_label= The word ''{0}'' should have an initial upper case letter +AbstractSpellingDictionary_encodingError= Could not read: ''{0}'', where the bad characters are replaced by ''{1}''. Check the encoding of the spelling dictionary ({2}). + Index: src/org/eclipse/ui/internal/texteditor/spelling/TextSpellingEngine.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/TextSpellingEngine.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/TextSpellingEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/TextSpellingEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; + +import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; +import org.eclipse.ui.texteditor.spelling.SpellCheckIterator; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellingEngine; + +/** + * Text spelling engine + * + * @since 3.1 + */ +public class TextSpellingEngine extends SpellingEngine { + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.SpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker, org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector, org.eclipse.core.runtime.IProgressMonitor) + */ + protected void check(IDocument document, IRegion[] regions, ISpellChecker checker, ISpellingProblemCollector collector, IProgressMonitor monitor) { + SpellEventListener listener= new SpellEventListener(collector, document); + for (int i= 0; i < regions.length; i++) { + if (monitor != null && monitor.isCanceled()) + return; + //TODO : Commented to get it working + /*if (listener.isProblemsThresholdReached()) + return;*/ + checker.execute(listener, new SpellCheckIterator(document, regions[i], checker.getLocale())); + } + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/WordCompletionProposalComputer.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/WordCompletionProposalComputer.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/WordCompletionProposalComputer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/WordCompletionProposalComputer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling; + + +/** + * Content assist processor to complete words. + * Note: This is currently not supported because the spelling engine + * cannot return word proposals but only correction proposals. + *

+ * If we enable this again we must register the computer in plugin.xml: + *

+ * 
+ *

+ * + * @since 3.0 + */ +/* + * TODO: the Javadoc says that this is not supported?? What is word completion then Alt+/. Anyway leave it for now + */ + + + +/*public final class WordCompletionProposalComputer implements IJavaCompletionProposalComputer { + + *//** The prefix rank shift */ +/* +private static final int PREFIX_RANK_SHIFT= 500; + + +* @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor) + +public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) { +if (contributes()) { +try { +IDocument document= context.getDocument(); +final int offset= context.getInvocationOffset(); + +final IRegion region= document.getLineInformationOfOffset(offset); +final String content= document.get(region.getOffset(), region.getLength()); + +int index= offset - region.getOffset() - 1; +while (index >= 0 && Character.isLetter(content.charAt(index))) +index--; + +final int start= region.getOffset() + index + 1; +final String candidate= content.substring(index + 1, offset - region.getOffset()); + +if (candidate.length() > 0) { + +final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); +final ISpellChecker checker= engine.getSpellChecker(); + +if (checker != null) { + +final List proposals= new ArrayList(checker.getProposals(candidate, Character.isUpperCase(candidate.charAt(0)))); +final List result= new ArrayList(proposals.size()); + +for (Iterator it= proposals.iterator(); it.hasNext();) { +RankedWordProposal word= (RankedWordProposal) it.next(); +String text= word.getText(); +if (text.startsWith(candidate)) +word.setRank(word.getRank() + PREFIX_RANK_SHIFT); + +result.add(new JavaCompletionProposal(text, start, candidate.length(), JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME), text, word.getRank()) { + +* @see org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent) + +public boolean validate(IDocument doc, int validate_offset, DocumentEvent event) { +return offset == validate_offset; +} +}); +} + +return result; +} +} +} catch (BadLocationException exception) { +// log & ignore +TextEditorPlugin.log(exception); +} +} +return Collections.EMPTY_LIST; +} + +private boolean contributes() { +return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST); +} + + +* @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor) + +public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) { +return Collections.EMPTY_LIST; +} + + +* @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#getErrorMessage() + +public String getErrorMessage() { +return null; // no error message available +} + + +* @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer#sessionStarted() + +public void sessionStarted() { +} + + +* @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer#sessionEnded() + +public void sessionEnded() { +} +} +*/ \ No newline at end of file Index: src/org/eclipse/ui/internal/texteditor/spelling/WordQuickFixProcessor.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/WordQuickFixProcessor.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/WordQuickFixProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/WordQuickFixProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; +import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.TextInvocationContext; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; +import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; +import org.eclipse.ui.texteditor.spelling.correction.AddWordProposal; +import org.eclipse.ui.texteditor.spelling.correction.ChangeCaseProposal; +import org.eclipse.ui.texteditor.spelling.correction.DisableSpellCheckingProposal; +import org.eclipse.ui.texteditor.spelling.correction.IHtmlTagConstants; +import org.eclipse.ui.texteditor.spelling.correction.IJavaDocTagConstants; +import org.eclipse.ui.texteditor.spelling.correction.ISpellingCompletionProposal; +import org.eclipse.ui.texteditor.spelling.correction.RankedWordProposal; +import org.eclipse.ui.texteditor.spelling.correction.WordCorrectionProposal; +import org.eclipse.ui.texteditor.spelling.correction.WordIgnoreProposal; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckEngine; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + +/** + * Quick fix processor for incorrectly spelled words. + * + * @since 3.0 + */ +public class WordQuickFixProcessor implements IQuickAssistProcessor { + + //TODO: copied from JavaSpellingReconcileStrategy, will most definitely not work as it would need to be hooked in other places as well + public static final int SPELLING_PROBLEM_ID= 0x80000000; + + /** + * Creates a new word quick fix processor. + */ + public WordQuickFixProcessor() { + // For extension point + } + + /* + * @see org.eclipse.jdt.ui.text.java.IQuickFixProcessor#getCorrections(org.eclipse.jdt.ui.text.java.IInvocationContext,org.eclipse.jdt.ui.text.java.IProblemLocation[]) + */ + private ISpellingCompletionProposal[] getCorrections(IQuickAssistInvocationContext invocationContext, IProblemLocation[] locations) throws CoreException { + + final int threshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD); + + int size= 0; + List proposals= null; + String[] arguments= null; + + IProblemLocation location= null; + RankedWordProposal proposal= null; + ISpellingCompletionProposal[] result= null; + + boolean fixed= false; + boolean match= false; + boolean sentence= false; + + final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); + final ISpellChecker checker= engine.getSpellChecker(); + + if (checker != null) { + + for (int index= 0; index < locations.length; index++) { + location= locations[index]; + + ISourceViewer sourceViewer= null; + if (invocationContext != null) + sourceViewer= invocationContext.getSourceViewer(); + IQuickAssistInvocationContext context= new TextInvocationContext(sourceViewer, location.getOffset(), location.getLength()); + + if (location.getProblemId() == SPELLING_PROBLEM_ID) { + + arguments= location.getProblemArguments(); + if (arguments != null && arguments.length > 4) { + + sentence= Boolean.valueOf(arguments[3]).booleanValue(); + match= Boolean.valueOf(arguments[4]).booleanValue(); + fixed= arguments[0].charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX || arguments[0].charAt(0) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX; + + if ((sentence && match) && !fixed) + result= new ISpellingCompletionProposal[] { new ChangeCaseProposal(arguments, location.getOffset(), location.getLength(), context, engine.getLocale()) }; + else { + + proposals= new ArrayList(checker.getProposals(arguments[0], sentence)); + size= proposals.size(); + + if (threshold > 0 && size > threshold) { + + Collections.sort(proposals); + proposals= proposals.subList(size - threshold - 1, size - 1); + size= proposals.size(); + } + + boolean extendable= !fixed ? (checker.acceptsWords() || AddWordProposal.canAskToConfigure()) : false; + result= new ISpellingCompletionProposal[size + (extendable ? 3 : 2)]; + + for (index= 0; index < size; index++) { + + proposal= (RankedWordProposal)proposals.get(index); + result[index]= new WordCorrectionProposal(proposal.getText(), arguments, location.getOffset(), location.getLength(), context, proposal.getRank()); + } + + if (extendable) + result[index++]= new AddWordProposal(arguments[0], context); + + result[index++]= new WordIgnoreProposal(arguments[0], context); + result[index++]= new DisableSpellCheckingProposal(context); + } + break; + } + } + } + } + return result; + } + + public String getErrorMessage() { + // TODO Auto-generated method stub + return null; + } + + public boolean canFix(Annotation annotation) { + return annotation != null && SpellingAnnotation.TYPE.equals(annotation.getType()); + } + + public boolean canAssist(IQuickAssistInvocationContext invocationContext) { + return false; + } + + public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) { + try { + return getCorrections(invocationContext, null); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticDistanceAlgorithm.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticDistanceAlgorithm.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticDistanceAlgorithm.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticDistanceAlgorithm.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling.engine; + +/** + * Default phonetic distance algorithm for English words. + *

+ * This algorithm implements the Levenshtein text edit distance. + *

+ * + * @since 3.0 + */ +public final class DefaultPhoneticDistanceAlgorithm implements IPhoneticDistanceAlgorithm { + + /** The change case cost */ + public static final int COST_CASE= 10; + + /** The insert character cost */ + public static final int COST_INSERT= 95; + + /** The remove character cost */ + public static final int COST_REMOVE= 95; + + /** The substitute characters cost */ + public static final int COST_SUBSTITUTE= 100; + + /** The swap characters cost */ + public static final int COST_SWAP= 90; + + /* + * @see org.eclipse.spelling.done.IPhoneticDistanceAlgorithm#getDistance(java.lang.String,java.lang.String) + */ + public final int getDistance(final String from, final String to) { + + final char[] first= (" " + from).toCharArray(); //$NON-NLS-1$ + final char[] second= (" " + to).toCharArray(); //$NON-NLS-1$ + + final int rows= first.length; + final int columns= second.length; + + final int[][] metric= new int[rows][columns]; + for (int column= 1; column < columns; column++) + metric[0][column]= metric[0][column - 1] + COST_REMOVE; + + for (int row= 1; row < rows; row++) + metric[row][0]= metric[row - 1][0] + COST_INSERT; + + char source, target; + + int swap= Integer.MAX_VALUE; + int change= Integer.MAX_VALUE; + + int minimum, diagonal, insert, remove; + for (int row= 1; row < rows; row++) { + + source= first[row]; + for (int column= 1; column < columns; column++) { + + target= second[column]; + diagonal= metric[row - 1][column - 1]; + + if (source == target) { + metric[row][column]= diagonal; + continue; + } + + change= Integer.MAX_VALUE; + if (Character.toLowerCase(source) == Character.toLowerCase(target)) + change= COST_CASE + diagonal; + + swap= Integer.MAX_VALUE; + if (row != 1 && column != 1 && source == second[column - 1] && first[row - 1] == target) + swap= COST_SWAP + metric[row - 2][column - 2]; + + minimum= COST_SUBSTITUTE + diagonal; + if (swap < minimum) + minimum= swap; + + remove= metric[row][column - 1]; + if (COST_REMOVE + remove < minimum) + minimum= COST_REMOVE + remove; + + insert= metric[row - 1][column]; + if (COST_INSERT + insert < minimum) + minimum= COST_INSERT + insert; + if (change < minimum) + minimum= change; + + metric[row][column]= minimum; + } + } + return metric[rows - 1][columns - 1]; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticHashProvider.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticHashProvider.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticHashProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultPhoneticHashProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,683 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling.engine; + +/** + * Default phonetic hash provider for english languages. + *

+ * This algorithm uses an adapted version double metaphone algorithm by + * Lawrence Philips. + *

+ * + * @since 3.0 + */ +public final class DefaultPhoneticHashProvider implements IPhoneticHashProvider { + + private static final String[] meta01= { "ACH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta02= { "BACHER", "MACHER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta03= { "CAESAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta04= { "CHIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta05= { "CH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta06= { "CHAE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta07= { "HARAC", "HARIS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta08= { "HOR", "HYM", "HIA", "HEM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final String[] meta09= { "CHORE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta10= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta11= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta12= { "ORCHES", "ARCHIT", "ORCHID", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta13= { "T", "S", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta14= { "A", "O", "U", "E", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final String[] meta15= { "L", "R", "N", "M", "B", "H", "F", "V", "W", " ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ + private static final String[] meta16= { "MC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta17= { "CZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta18= { "WICZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta19= { "CIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta20= { "CC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta21= { "I", "E", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta22= { "HU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta23= { "UCCEE", "UCCES", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta24= { "CK", "CG", "CQ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta25= { "CI", "CE", "CY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta26= { "GN", "KN", "PN", "WR", "PS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + private static final String[] meta27= { " C", " Q", " G", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta28= { "C", "K", "Q", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta29= { "CE", "CI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta30= { "DG", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta31= { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta32= { "DT", "DD", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta33= { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta34= { "B", "H", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta35= { "B", "H", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta36= { "C", "G", "L", "R", "T", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + private static final String[] meta37= { "EY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta38= { "LI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta39= { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ + private static final String[] meta40= { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta41= { "DANGER", "RANGER", "MANGER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta42= { "E", "I", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta43= { "RGY", "OGY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta44= { "E", "I", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta45= { "AGGI", "OGGI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta46= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta47= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta48= { "ET", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta49= { "C", "X", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta50= { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta51= { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta52= { "SAN ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta53= { "JOSE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta54= { "L", "T", "K", "S", "N", "M", "B", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ + private static final String[] meta55= { "S", "K", "L", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta56= { "ILLO", "ILLA", "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta57= { "AS", "OS", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta58= { "A", "O", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta59= { "ALLE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta60= { "UMB", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta61= { "ER", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta62= { "P", "B", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta63= { "IE", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta64= { "ME", "MA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta65= { "ISL", "YSL", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta66= { "SUGAR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta67= { "SH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta68= { "HEIM", "HOEK", "HOLM", "HOLZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final String[] meta69= { "SIO", "SIA", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta70= { "SIAN", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta71= { "M", "N", "L", "W", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final String[] meta72= { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta73= { "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta74= { "SC", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta75= { "OO", "ER", "EN", "UY", "ED", "EM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + private static final String[] meta76= { "ER", "EN", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta77= { "I", "E", "Y", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private static final String[] meta78= { "AI", "OI", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta79= { "S", "Z", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta80= { "TION", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta81= { "TIA", "TCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta82= { "TH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta83= { "TTH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta84= { "OM", "AM", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta85= { "VAN ", "VON ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta86= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta87= { "T", "D", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta88= { "WR", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta89= { "WH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta90= { "EWSKI", "EWSKY", "OWSKI", "OWSKY", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final String[] meta91= { "SCH", "" }; //$NON-NLS-1$ //$NON-NLS-2$ + private static final String[] meta92= { "WICZ", "WITZ", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta93= { "IAU", "EAU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta94= { "AU", "OU", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String[] meta95= { "W", "K", "CZ", "WITZ" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + /** The mutator characters */ + private static final char[] MUTATOR_CHARACTERS= { 'A', 'B', 'X', 'S', 'K', 'J', 'T', 'F', 'H', 'L', 'M', 'N', 'P', 'R', '0' }; + + /** The vowel characters */ + private static final char[] VOWEL_CHARACTERS= new char[] { 'A', 'E', 'I', 'O', 'U', 'Y' }; + + /** + * Test whether the specified string contains one of the candidates in the + * list. + * + * @param candidates + * Array of candidates to check + * @param token + * The token to check for occurrences of the candidates + * @param offset + * The offset where to begin checking in the string + * @param length + * The length of the range in the string to check + * @return true iff the string contains one of the + * candidates, false otherwise. + */ + protected static final boolean hasOneOf(final String[] candidates, final char[] token, final int offset, final int length) { + + if (offset < 0 || offset >= token.length || candidates.length == 0) + return false; + + final String checkable= new String(token, offset, length); + for (int index= 0; index < candidates.length; index++) { + + if (candidates[index].equals(checkable)) + return true; + } + return false; + } + + /** + * Test whether the specified token contains one of the candidates in the + * list. + * + * @param candidates + * Array of candidates to check + * @param token + * The token to check for occurrences of the candidates + * @return true iff the string contains one of the + * candidates, false otherwise. + */ + protected static final boolean hasOneOf(final String[] candidates, final String token) { + + for (int index= 0; index < candidates.length; index++) { + + if (token.indexOf(candidates[index]) >= 0) + return true; + } + return false; + } + + /** + * Tests whether the specified token contains a vowel at the specified + * offset. + * + * @param token + * The token to check for a vowel + * @param offset + * The offset where to begin checking in the token + * @param length + * The length of the range in the token to check + * @return true iff the token contains a vowel, false + * otherwise. + */ + protected static final boolean hasVowel(final char[] token, final int offset, final int length) { + + if (offset >= 0 && offset < length) { + + final char character= token[offset]; + for (int index= 0; index < VOWEL_CHARACTERS.length; index++) { + + if (VOWEL_CHARACTERS[index] == character) + return true; + } + } + return false; + } + + /* + * @see org.eclipse.spelling.done.IPhoneticHasher#getHash(java.lang.String) + */ + public final String getHash(final String word) { + + final String input= word.toUpperCase() + " "; //$NON-NLS-1$ + final char[] hashable= input.toCharArray(); + + final boolean has95= hasOneOf(meta95, input); + final StringBuffer buffer= new StringBuffer(hashable.length); + + int offset= 0; + if (hasOneOf(meta26, hashable, 0, 2)) + offset += 1; + + if (hashable[0] == 'X') { + buffer.append('S'); + offset += 1; + } + + while (offset < hashable.length) { + + switch (hashable[offset]) { + case 'A' : + case 'E' : + case 'I' : + case 'O' : + case 'U' : + case 'Y' : + if (offset == 0) + buffer.append('A'); + offset += 1; + break; + case 'B' : + buffer.append('P'); + if (hashable[offset + 1] == 'B') + offset += 2; + else + offset += 1; + break; + case 'C' : + if ((offset > 1) && !hasVowel(hashable, offset - 2, hashable.length) && hasOneOf(meta01, hashable, (offset - 1), 3) && (hashable[offset + 2] != 'I') && (hashable[offset + 2] != 'E') || hasOneOf(meta02, hashable, (offset - 2), 6)) { + buffer.append('K'); + offset += 2; + break; + } + if ((offset == 0) && hasOneOf(meta03, hashable, offset, 6)) { + buffer.append('S'); + offset += 2; + break; + } + if (hasOneOf(meta04, hashable, offset, 4)) { + buffer.append('K'); + offset += 2; + break; + } + if (hasOneOf(meta05, hashable, offset, 2)) { + if ((offset > 0) && hasOneOf(meta06, hashable, offset, 4)) { + buffer.append('K'); + offset += 2; + break; + } + if ((offset == 0) && hasOneOf(meta07, hashable, (offset + 1), 5) || hasOneOf(meta08, hashable, offset + 1, 3) && !hasOneOf(meta09, hashable, 0, 5)) { + buffer.append('K'); + offset += 2; + break; + } + if (hasOneOf(meta10, hashable, 0, 4) || hasOneOf(meta11, hashable, 0, 3) || hasOneOf(meta12, hashable, offset - 2, 6) || hasOneOf(meta13, hashable, offset + 2, 1) || (hasOneOf(meta14, hashable, offset - 1, 1) || (offset == 0)) && hasOneOf(meta15, hashable, offset + 2, 1)) { + buffer.append('K'); + } else { + if (offset > 0) { + if (hasOneOf(meta16, hashable, 0, 2)) + buffer.append('K'); + else + buffer.append('X'); + } else { + buffer.append('X'); + } + } + offset += 2; + break; + } + if (hasOneOf(meta17, hashable, offset, 2) && !hasOneOf(meta18, hashable, offset, 4)) { + buffer.append('S'); + offset += 2; + break; + } + if (hasOneOf(meta19, hashable, offset, 2)) { + buffer.append('X'); + offset += 2; + break; + } + if (hasOneOf(meta20, hashable, offset, 2) && !((offset == 1) && hashable[0] == 'M')) { + if (hasOneOf(meta21, hashable, offset + 2, 1) && !hasOneOf(meta22, hashable, offset + 2, 2)) { + if (((offset == 1) && (hashable[offset - 1] == 'A')) || hasOneOf(meta23, hashable, (offset - 1), 5)) + buffer.append("KS"); //$NON-NLS-1$ + else + buffer.append('X'); + offset += 3; + break; + } else { + buffer.append('K'); + offset += 2; + break; + } + } + if (hasOneOf(meta24, hashable, offset, 2)) { + buffer.append('K'); + offset += 2; + break; + } else if (hasOneOf(meta25, hashable, offset, 2)) { + buffer.append('S'); + offset += 2; + break; + } + buffer.append('K'); + if (hasOneOf(meta27, hashable, offset + 1, 2)) + offset += 3; + else if (hasOneOf(meta28, hashable, offset + 1, 1) && !hasOneOf(meta29, hashable, offset + 1, 2)) + offset += 2; + else + offset += 1; + break; + case '\u00C7' : + buffer.append('S'); + offset += 1; + break; + case 'D' : + if (hasOneOf(meta30, hashable, offset, 2)) { + if (hasOneOf(meta31, hashable, offset + 2, 1)) { + buffer.append('J'); + offset += 3; + break; + } else { + buffer.append("TK"); //$NON-NLS-1$ + offset += 2; + break; + } + } + buffer.append('T'); + if (hasOneOf(meta32, hashable, offset, 2)) { + offset += 2; + } else { + offset += 1; + } + break; + case 'F' : + if (hashable[offset + 1] == 'F') + offset += 2; + else + offset += 1; + buffer.append('F'); + break; + case 'G' : + if (hashable[offset + 1] == 'H') { + if ((offset > 0) && !hasVowel(hashable, offset - 1, hashable.length)) { + buffer.append('K'); + offset += 2; + break; + } + if (offset < 3) { + if (offset == 0) { + if (hashable[offset + 2] == 'I') + buffer.append('J'); + else + buffer.append('K'); + offset += 2; + break; + } + } + if ((offset > 1) && hasOneOf(meta33, hashable, offset - 2, 1) || ((offset > 2) && hasOneOf(meta34, hashable, offset - 3, 1)) || ((offset > 3) && hasOneOf(meta35, hashable, offset - 4, 1))) { + offset += 2; + break; + } else { + if ((offset > 2) && (hashable[offset - 1] == 'U') && hasOneOf(meta36, hashable, offset - 3, 1)) { + buffer.append('F'); + } else { + if ((offset > 0) && (hashable[offset - 1] != 'I')) + buffer.append('K'); + } + offset += 2; + break; + } + } + if (hashable[offset + 1] == 'N') { + if ((offset == 1) && hasVowel(hashable, 0, hashable.length) && !has95) { + buffer.append("KN"); //$NON-NLS-1$ + } else { + if (!hasOneOf(meta37, hashable, offset + 2, 2) && (hashable[offset + 1] != 'Y') && !has95) { + buffer.append("N"); //$NON-NLS-1$ + } else { + buffer.append("KN"); //$NON-NLS-1$ + } + } + offset += 2; + break; + } + if (hasOneOf(meta38, hashable, offset + 1, 2) && !has95) { + buffer.append("KL"); //$NON-NLS-1$ + offset += 2; + break; + } + if ((offset == 0) && ((hashable[offset + 1] == 'Y') || hasOneOf(meta39, hashable, offset + 1, 2))) { + buffer.append('K'); + offset += 2; + break; + } + if ((hasOneOf(meta40, hashable, offset + 1, 2) || (hashable[offset + 1] == 'Y')) && !hasOneOf(meta41, hashable, 0, 6) && !hasOneOf(meta42, hashable, offset - 1, 1) && !hasOneOf(meta43, hashable, offset - 1, 3)) { + buffer.append('K'); + offset += 2; + break; + } + if (hasOneOf(meta44, hashable, offset + 1, 1) || hasOneOf(meta45, hashable, offset - 1, 4)) { + if (hasOneOf(meta46, hashable, 0, 4) || hasOneOf(meta47, hashable, 0, 3) || hasOneOf(meta48, hashable, offset + 1, 2)) { + buffer.append('K'); + } else { + buffer.append('J'); + } + offset += 2; + break; + } + if (hashable[offset + 1] == 'G') + offset += 2; + else + offset += 1; + buffer.append('K'); + break; + case 'H' : + if (((offset == 0) || hasVowel(hashable, offset - 1, hashable.length)) && hasVowel(hashable, offset + 1, hashable.length)) { + buffer.append('H'); + offset += 2; + } else { + offset += 1; + } + break; + case 'J' : + if (hasOneOf(meta50, hashable, offset, 4) || hasOneOf(meta51, hashable, 0, 4)) { + if ((offset == 0) && (hashable[offset + 4] == ' ') || hasOneOf(meta52, hashable, 0, 4)) { + buffer.append('H'); + } else { + buffer.append('J'); + } + offset += 1; + break; + } + if ((offset == 0) && !hasOneOf(meta53, hashable, offset, 4)) { + buffer.append('J'); + } else { + if (hasVowel(hashable, offset - 1, hashable.length) && !has95 && ((hashable[offset + 1] == 'A') || hashable[offset + 1] == 'O')) { + buffer.append('J'); + } else { + if (offset == (hashable.length - 1)) { + buffer.append('J'); + } else { + if (!hasOneOf(meta54, hashable, offset + 1, 1) && !hasOneOf(meta55, hashable, offset - 1, 1)) { + buffer.append('J'); + } + } + } + } + if (hashable[offset + 1] == 'J') + offset += 2; + else + offset += 1; + break; + case 'K' : + if (hashable[offset + 1] == 'K') + offset += 2; + else + offset += 1; + buffer.append('K'); + break; + case 'L' : + if (hashable[offset + 1] == 'L') { + if (((offset == (hashable.length - 3)) && hasOneOf(meta56, hashable, offset - 1, 4)) || ((hasOneOf(meta57, hashable, (hashable.length - 1) - 1, 2) || hasOneOf(meta58, hashable, hashable.length - 1, 1)) && hasOneOf(meta59, hashable, offset - 1, 4))) { + buffer.append('L'); + offset += 2; + break; + } + offset += 2; + } else + offset += 1; + buffer.append('L'); + break; + case 'M' : + if ((hasOneOf(meta60, hashable, offset - 1, 3) && (((offset + 1) == (hashable.length - 1)) || hasOneOf(meta61, hashable, offset + 2, 2))) || (hashable[offset + 1] == 'M')) + offset += 2; + else + offset += 1; + buffer.append('M'); + break; + case 'N' : + if (hashable[offset + 1] == 'N') + offset += 2; + else + offset += 1; + buffer.append('N'); + break; + case '\u00D1' : + offset += 1; + buffer.append('N'); + break; + case 'P' : + if (hashable[offset + 1] == 'N') { + buffer.append('F'); + offset += 2; + break; + } + if (hasOneOf(meta62, hashable, offset + 1, 1)) + offset += 2; + else + offset += 1; + buffer.append('P'); + break; + case 'Q' : + if (hashable[offset + 1] == 'Q') + offset += 2; + else + offset += 1; + buffer.append('K'); + break; + case 'R' : + if (!((offset == (hashable.length - 1)) && !has95 && hasOneOf(meta63, hashable, offset - 2, 2) && !hasOneOf(meta64, hashable, offset - 4, 2))) + buffer.append('R'); + if (hashable[offset + 1] == 'R') + offset += 2; + else + offset += 1; + break; + case 'S' : + if (hasOneOf(meta65, hashable, offset - 1, 3)) { + offset += 1; + break; + } + if ((offset == 0) && hasOneOf(meta66, hashable, offset, 5)) { + buffer.append('X'); + offset += 1; + break; + } + if (hasOneOf(meta67, hashable, offset, 2)) { + if (hasOneOf(meta68, hashable, offset + 1, 4)) + buffer.append('S'); + else + buffer.append('X'); + offset += 2; + break; + } + if (hasOneOf(meta69, hashable, offset, 3) || hasOneOf(meta70, hashable, offset, 4)) { + buffer.append('S'); + offset += 3; + break; + } + if (((offset == 0) && hasOneOf(meta71, hashable, offset + 1, 1)) || hasOneOf(meta72, hashable, offset + 1, 1)) { + buffer.append('S'); + if (hasOneOf(meta73, hashable, offset + 1, 1)) + offset += 2; + else + offset += 1; + break; + } + if (hasOneOf(meta74, hashable, offset, 2)) { + if (hashable[offset + 2] == 'H') + if (hasOneOf(meta75, hashable, offset + 3, 2)) { + if (hasOneOf(meta76, hashable, offset + 3, 2)) { + buffer.append("X"); //$NON-NLS-1$ + } else { + buffer.append("SK"); //$NON-NLS-1$ + } + offset += 3; + break; + } else { + buffer.append('X'); + offset += 3; + break; + } + if (hasOneOf(meta77, hashable, offset + 2, 1)) { + buffer.append('S'); + offset += 3; + break; + } + buffer.append("SK"); //$NON-NLS-1$ + offset += 3; + break; + } + if (!((offset == (hashable.length - 1)) && hasOneOf(meta78, hashable, offset - 2, 2))) + buffer.append('S'); + if (hasOneOf(meta79, hashable, offset + 1, 1)) + offset += 2; + else + offset += 1; + break; + case 'T' : + if (hasOneOf(meta80, hashable, offset, 4)) { + buffer.append('X'); + offset += 3; + break; + } + if (hasOneOf(meta81, hashable, offset, 3)) { + buffer.append('X'); + offset += 3; + break; + } + if (hasOneOf(meta82, hashable, offset, 2) || hasOneOf(meta83, hashable, offset, 3)) { + if (hasOneOf(meta84, hashable, (offset + 2), 2) || hasOneOf(meta85, hashable, 0, 4) || hasOneOf(meta86, hashable, 0, 3)) { + buffer.append('T'); + } else { + buffer.append('0'); + } + offset += 2; + break; + } + if (hasOneOf(meta87, hashable, offset + 1, 1)) { + offset += 2; + } else + offset += 1; + buffer.append('T'); + break; + case 'V' : + if (hashable[offset + 1] == 'V') + offset += 2; + else + offset += 1; + buffer.append('F'); + break; + case 'W' : + if (hasOneOf(meta88, hashable, offset, 2)) { + buffer.append('R'); + offset += 2; + break; + } + if ((offset == 0) && (hasVowel(hashable, offset + 1, hashable.length) || hasOneOf(meta89, hashable, offset, 2))) { + buffer.append('A'); + } + if (((offset == (hashable.length - 1)) && hasVowel(hashable, offset - 1, hashable.length)) || hasOneOf(meta90, hashable, offset - 1, 5) || hasOneOf(meta91, hashable, 0, 3)) { + buffer.append('F'); + offset += 1; + break; + } + if (hasOneOf(meta92, hashable, offset, 4)) { + buffer.append("TS"); //$NON-NLS-1$ + offset += 4; + break; + } + offset += 1; + break; + case 'X' : + if (!((offset == (hashable.length - 1)) && (hasOneOf(meta93, hashable, offset - 3, 3) || hasOneOf(meta94, hashable, offset - 2, 2)))) + buffer.append("KS"); //$NON-NLS-1$ + if (hasOneOf(meta49, hashable, offset + 1, 1)) + offset += 2; + else + offset += 1; + break; + case 'Z' : + if (hashable[offset + 1] == 'H') { + buffer.append('J'); + offset += 2; + break; + } else { + buffer.append('S'); + } + if (hashable[offset + 1] == 'Z') + offset += 2; + else + offset += 1; + break; + default : + offset += 1; + } + } + return buffer.toString(); + } + + /* + * @see org.eclipse.spelling.done.IPhoneticHasher#getMutators() + */ + public final char[] getMutators() { + return MUTATOR_CHARACTERS; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultSpellChecker.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultSpellChecker.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultSpellChecker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/DefaultSpellChecker.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,349 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling.engine; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckIterator; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.ISpellDictionary; +import org.eclipse.ui.texteditor.spelling.engine.ISpellEventListener; + + +/** + * Default spell checker for standard text. + * + * @since 3.0 + */ +public class DefaultSpellChecker implements ISpellChecker { + + /** Array of URL prefixes */ + public static final String[] URL_PREFIXES= new String[] { "http://", "https://", "www.", "ftp://", "ftps://", "news://", "mailto://" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + + /** + * Does this word contain digits? + * + * @param word the word to check + * @return true iff this word contains digits, false> otherwise + */ + protected static boolean isDigits(final String word) { + + for (int index= 0; index < word.length(); index++) { + + if (Character.isDigit(word.charAt(index))) + return true; + } + return false; + } + + /** + * Does this word contain mixed-case letters? + * + * @param word + * The word to check + * @param sentence + * true iff the specified word starts a new + * sentence, false otherwise + * @return true iff the contains mixed-case letters, false + * otherwise + */ + protected static boolean isMixedCase(final String word, final boolean sentence) { + + final int length= word.length(); + boolean upper= Character.isUpperCase(word.charAt(0)); + + if (sentence && upper && (length > 1)) + upper= Character.isUpperCase(word.charAt(1)); + + if (upper) { + + for (int index= length - 1; index > 0; index--) { + if (Character.isLowerCase(word.charAt(index))) + return true; + } + } else { + + for (int index= length - 1; index > 0; index--) { + if (Character.isUpperCase(word.charAt(index))) + return true; + } + } + return false; + } + + /** + * Does this word contain upper-case letters only? + * + * @param word + * The word to check + * @return true iff this word only contains upper-case + * letters, false otherwise + */ + protected static boolean isUpperCase(final String word) { + + for (int index= word.length() - 1; index >= 0; index--) { + + if (Character.isLowerCase(word.charAt(index))) + return false; + } + return true; + } + + /** + * Does this word look like an URL? + * + * @param word + * The word to check + * @return true iff this word looks like an URL, false + * otherwise + */ + protected static boolean isUrl(final String word) { + + for (int index= 0; index < URL_PREFIXES.length; index++) { + + if (word.startsWith(URL_PREFIXES[index])) + return true; + } + return false; + } + + /** + * The dictionaries to use for spell checking. Synchronized to avoid + * concurrent modifications. + */ + private final Set fDictionaries= Collections.synchronizedSet(new HashSet()); + + /** + * The words to be ignored. Synchronized to avoid concurrent modifications. + */ + private final Set fIgnored= Collections.synchronizedSet(new HashSet()); + + /** + * The preference store. Assumes the IPreferenceStore + * implementation is thread safe. + */ + private final IPreferenceStore fPreferences; + + /** + * The locale of this checker. + * @since 3.3 + */ + private Locale fLocale; + + /** + * Creates a new default spell checker. + * + * @param store the preference store for this spell checker + * @param locale the locale + */ + public DefaultSpellChecker(IPreferenceStore store, Locale locale) { + Assert.isLegal(store != null); + Assert.isLegal(locale != null); + + fPreferences= store; + fLocale= locale; + } + + /* + * @see org.eclipse.spelling.done.ISpellChecker#addDictionary(org.eclipse.spelling.done.ISpellDictionary) + */ + public final void addDictionary(final ISpellDictionary dictionary) { + // synchronizing is necessary as this is a write access + fDictionaries.add(dictionary); + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellChecker#acceptsWords() + */ + public boolean acceptsWords() { + // synchronizing might not be needed here since acceptWords is + // a read-only access and only called in the same thread as + // the modifying methods add/checkWord (?) + Set copy; + synchronized (fDictionaries) { + copy= new HashSet(fDictionaries); + } + + ISpellDictionary dictionary= null; + for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { + + dictionary= (ISpellDictionary)iterator.next(); + if (dictionary.acceptsWords()) + return true; + } + return false; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#addWord(java.lang.String) + */ + public void addWord(final String word) { + // synchronizing is necessary as this is a write access + Set copy; + synchronized (fDictionaries) { + copy= new HashSet(fDictionaries); + } + + final String addable= word.toLowerCase(); + for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { + ISpellDictionary dictionary= (ISpellDictionary)iterator.next(); + if (dictionary.acceptsWords()) + dictionary.addWord(addable); + } + + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellChecker#checkWord(java.lang.String) + */ + public final void checkWord(final String word) { + // synchronizing is necessary as this is a write access + fIgnored.remove(word.toLowerCase()); + } + + /* + * @see org.eclipse.spelling.done.ISpellChecker#execute(org.eclipse.spelling.ISpellCheckTokenizer) + */ + public void execute(final ISpellEventListener listener, final ISpellCheckIterator iterator) { + + final boolean ignoreDigits= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_DIGITS); + final boolean ignoreMixed= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_MIXED); + final boolean ignoreSentence= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_SENTENCE); + final boolean ignoreUpper= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_UPPER); + final boolean ignoreURLS= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_URLS); + final boolean ignoreNonLetters= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS); + final boolean ignoreSingleLetters= fPreferences.getBoolean(PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS); + final int problemsThreshold= 100;//TODO: assigned to 100 for testing, remove later // PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD); + + iterator.setIgnoreSingleLetters(ignoreSingleLetters); + + Iterator iter= fDictionaries.iterator(); + while (iter.hasNext()) + ((ISpellDictionary)iter.next()).setStripNonLetters(ignoreNonLetters); + + String word= null; + boolean starts= false; + int problemCount= 0; + + while (problemCount <= problemsThreshold && iterator.hasNext()) { + + word= (String)iterator.next(); + if (word != null) { + + // synchronizing is necessary as this is called inside the reconciler + if (!fIgnored.contains(word)) { + + starts= iterator.startsSentence(); + if (!isCorrect(word)) { + + boolean isMixed= isMixedCase(word, true); + boolean isUpper= isUpperCase(word); + boolean isDigits= isDigits(word); + boolean isURL= isUrl(word); + + if ( !ignoreMixed && isMixed || !ignoreUpper && isUpper || !ignoreDigits && isDigits || !ignoreURLS && isURL || !(isMixed || isUpper || isDigits || isURL)) { + listener.handle(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), starts, false)); + problemCount++; + } + + } else { + + //TODO: code commented for testing + /*if (!ignoreSentence && starts && Character.isLowerCase(word.charAt(0))) { + listener.handle(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), true, true)); + problemCount++; + }*/ + } + } + } + } + } + + /* + * @see org.eclipse.spelling.done.ISpellChecker#getProposals(java.lang.String,boolean) + */ + public Set getProposals(final String word, final boolean sentence) { + + // synchronizing might not be needed here since getProposals is + // a read-only access and only called in the same thread as + // the modifing methods add/removeDictionary (?) + Set copy; + synchronized (fDictionaries) { + copy= new HashSet(fDictionaries); + } + + ISpellDictionary dictionary= null; + final HashSet proposals= new HashSet(); + + for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { + + dictionary= (ISpellDictionary)iterator.next(); + proposals.addAll(dictionary.getProposals(word, sentence)); + } + return proposals; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#ignoreWord(java.lang.String) + */ + public final void ignoreWord(final String word) { + // synchronizing is necessary as this is a write access + fIgnored.add(word.toLowerCase()); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#isCorrect(java.lang.String) + */ + public final boolean isCorrect(final String word) { + // synchronizing is necessary as this is called from execute + Set copy; + synchronized (fDictionaries) { + copy= new HashSet(fDictionaries); + } + + if (fIgnored.contains(word.toLowerCase())) + return true; + + ISpellDictionary dictionary= null; + for (final Iterator iterator= copy.iterator(); iterator.hasNext();) { + + dictionary= (ISpellDictionary)iterator.next(); + if (dictionary.isCorrect(word)) + return true; + } + return false; + } + + /* + * @see org.eclipse.spelling.done.ISpellChecker#removeDictionary(org.eclipse.spelling.done.ISpellDictionary) + */ + public final void removeDictionary(final ISpellDictionary dictionary) { + // synchronizing is necessary as this is a write access + fDictionaries.remove(dictionary); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker#getLocale() + * @since 3.3 + */ + public Locale getLocale() { + return fLocale; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticDistanceAlgorithm.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticDistanceAlgorithm.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticDistanceAlgorithm.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticDistanceAlgorithm.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling.engine; + +/** + * Interface of algorithms to compute the phonetic distance between two words. + * + * @since 3.0 + */ +public interface IPhoneticDistanceAlgorithm { + + /** + * Returns the non-negative phonetic distance between two words + * + * @param from + * The first word + * @param to + * The second word + * @return The non-negative phonetic distance between the words. + */ + public int getDistance(String from, String to); +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticHashProvider.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticHashProvider.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticHashProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/IPhoneticHashProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling.engine; + +/** + * Interface of hashers to compute the phonetic hash for a word. + * + * @since 3.0 + */ +public interface IPhoneticHashProvider { + + /** + * Returns the phonetic hash for the word. + * + * @param word + * The word to get the phonetic hash for + * @return The phonetic hash for the word + */ + public String getHash(String word); + + /** + * Returns an array of characters to compute possible mutations. + * + * @return Array of possible mutator characters + */ + public char[] getMutators(); +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/LocaleSensitiveSpellDictionary.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/LocaleSensitiveSpellDictionary.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/LocaleSensitiveSpellDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/LocaleSensitiveSpellDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling.engine; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Locale; + +import org.eclipse.ui.texteditor.spelling.engine.AbstractSpellDictionary; + + +/** + * Platform wide read-only locale sensitive dictionary for spell checking. + * + * @since 3.0 + */ +public class LocaleSensitiveSpellDictionary extends AbstractSpellDictionary { + + /** The locale of this dictionary */ + private final Locale fLocale; + + /** The location of the dictionaries */ + private final URL fLocation; + + /** + * Creates a new locale sensitive spell dictionary. + * + * @param locale + * The locale for this dictionary + * @param location + * The location of the locale sensitive dictionaries + */ + public LocaleSensitiveSpellDictionary(final Locale locale, final URL location) { + fLocation= location; + fLocale= locale; + } + + /** + * Returns the locale of this dictionary. + * + * @return The locale of this dictionary + */ + public final Locale getLocale() { + return fLocale; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL() + */ + protected final URL getURL() throws MalformedURLException { + return new URL(fLocation, fLocale.toString() + ".dictionary"); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getInitialSize() + * @since 3.6 + */ + protected int getInitialSize() { + return 32 * 1024; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/PersistentSpellDictionary.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/PersistentSpellDictionary.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/PersistentSpellDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/PersistentSpellDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Benjamin Muskalla - [spell checking][implementation] PersistentSpellDictionary closes wrong stream - https://bugs.eclipse.org/bugs/show_bug.cgi?id=236421 + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.spelling.engine; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + +import org.eclipse.ui.texteditor.spelling.engine.AbstractSpellDictionary; + + +/** + * Persistent modifiable word-list based dictionary. + * + * @since 3.0 + */ +public class PersistentSpellDictionary extends AbstractSpellDictionary { + + /** The word list location */ + private final URL fLocation; + + /** + * Creates a new persistent spell dictionary. + * + * @param url the URL of the word list for this dictionary + */ + public PersistentSpellDictionary(final URL url) { + fLocation= url; + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#acceptsWords() + */ + public boolean acceptsWords() { + return true; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String) + */ + public void addWord(final String word) { + if (isCorrect(word)) + return; + + FileOutputStream fileStream= null; + try { + Charset charset= Charset.forName(getEncoding()); + ByteBuffer byteBuffer= charset.encode(word + "\n"); //$NON-NLS-1$ + int size= byteBuffer.limit(); + final byte[] byteArray; + if (byteBuffer.hasArray()) + byteArray= byteBuffer.array(); + else { + byteArray= new byte[size]; + byteBuffer.get(byteArray); + } + + fileStream= new FileOutputStream(fLocation.getPath(), true); + + // Encoding UTF-16 charset writes a BOM. In which case we need to cut it away if the file isn't empty + int bomCutSize= 0; + if (!isEmpty() && "UTF-16".equals(charset.name())) //$NON-NLS-1$ + bomCutSize= 2; + + fileStream.write(byteArray, bomCutSize, size - bomCutSize); + } catch (IOException exception) { + TextEditorPlugin.log(exception); + return; + } finally { + try { + if (fileStream != null) + fileStream.close(); + } catch (IOException e) { + } + } + + hashWord(word); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL() + */ + protected final URL getURL() { + return fLocation; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/SpellEvent.java =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/SpellEvent.java diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/SpellEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/SpellEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.texteditor.spelling.engine; + +import java.util.Set; + +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.ISpellEvent; + +/** + * Spell event fired for words detected by a spell check iterator. + * + * @since 3.0 + */ +public class SpellEvent implements ISpellEvent { + + /** The begin index of the word in the spell checkable medium */ + private final int fBegin; + + /** The spell checker that causes the event */ + private final ISpellChecker fChecker; + + /** The end index of the word in the spell checkable medium */ + private final int fEnd; + + /** Was the word found in the dictionary? */ + private final boolean fMatch; + + /** Does the word start a new sentence? */ + private final boolean fSentence; + + /** The word that causes the spell event */ + private final String fWord; + + /** + * Creates a new spell event. + * + * @param checker + * The spell checker that causes the event + * @param word + * The word that causes the event + * @param begin + * The begin index of the word in the spell checkable medium + * @param end + * The end index of the word in the spell checkable medium + * @param sentence + * true iff the word starts a new sentence, + * false otherwise + * @param match + * true iff the word was found in the dictionary, + * false otherwise + */ + protected SpellEvent(final ISpellChecker checker, final String word, final int begin, final int end, final boolean sentence, final boolean match) { + fChecker= checker; + fEnd= end; + fBegin= begin; + fWord= word; + fSentence= sentence; + fMatch= match; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getBegin() + */ + public final int getBegin() { + return fBegin; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getEnd() + */ + public final int getEnd() { + return fEnd; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getProposals() + */ + public final Set getProposals() { + return fChecker.getProposals(fWord, fSentence); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#getWord() + */ + public final String getWord() { + return fWord; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#isMatch() + */ + public final boolean isMatch() { + return fMatch; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent#isStart() + */ + public final boolean isStart() { + return fSentence; + } +} Index: src/org/eclipse/ui/internal/texteditor/spelling/engine/package.html =================================================================== RCS file: src/org/eclipse/ui/internal/texteditor/spelling/engine/package.html diff -N src/org/eclipse/ui/internal/texteditor/spelling/engine/package.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/texteditor/spelling/engine/package.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,84 @@ + + + + + + + Package-level Javadoc + + +Provides the core functionality for spell-checking documents +

+Package Specification

+This package provides the interfaces for the notions of dictionary, edit distance, phonetic hash, +spell event and spell-check iterator. For most of these interfaces a default implementation +for english languages is provided. These implementations can be reused in custom dictionaries or +spell-check iterators, or replaced by more specialized algorithms for a particular group of languages. +

+Spell Check Engine

+The central point to access the spell-checker functionality is the interface ISpellCheckEngine. +Implementations of this interface provide support for life-cycle management, registering and unregistering +dictionaries, changing the locale of the engine and creating a spell-checker for a specific language. +

+The following steps are needed to obtain a spell-checker for a specific language: +

    +
  • Create an instance of ISpellCheckEngine. In this package, no default implementation is provided, +since the management of the dictionary registering and loading is application dependent. Usually, instances +of ISpellCheckEngine are implemented as singletons.
  • +
  • Create the appropriate dictionaries that should be used during the spell-check process. All dictionaries that +can be registered with ISpellCheckEngine must implement the interface ISpellCheckDictionary. +For this interface, an abstract implementation is provided in the class AbstractSpellDictionary. +Depending on the language of the words contained in this dictionary, custom algorithms for the phonetic hash + (IPhoneticHashProvider) and the edit distance (IPhoneticDistanceAlgorithm) should be implemented + and registered with the dictionary.
  • +
  • Instances of spell-checkers can now be created by calling createSpellChecker(Locale), where the locale + denotes the language that the spell-checker should use while executing.
  • +
+When requesting a new spell-checker with a different locale via createSpellChecker(Locale), the spell-checker is +reconfigured with the new dictionaries. More concretely, the old dictionary is unregistered and a new one registered for the +desired locale is associated with the spell-checker. If no such dictionary is available, no spell-checker is returned and +the locale of the engine is reset to its default locale. +

+Dictionaries

+Dictionaries are the data structures to hold word lists for a particular language. All implementations of dictionaries must +implement the interface ISpellDictionary. It provides support for life-cycle management as well as the facility to query +words from the list, add words to the list and get correction proposals for incorrectly spelt words. +

+This package provides a default implementation of a dictionary (AbstractSpellDictionary) that uses algorithms +convenient for english languages.
+Every dictionary needs two kinds of algorithms to be plugged in: +

    +
  • An edit distance algorithm: Edit distance algorithms implement the interface IPhoneticDistanceAlgorithm. The algorithm +is used to determine the similarity between two words. This package provides a default implementation for languages using the latin alphabet (DefaultPhoneticDistanceAlgorithm). +The default algorithm uses the Levenshtein text edit distance.
  • +
  • A hash algorithm: Phonetic hash providers implement the interface IPhoneticHashProvider. The purpose of +phonetic hashes is to have a representation of words which allows comparing it to other, similar words. This package provides a default +implementation which is convenient for slavic and english languages. It uses the double metaphone algorithm by published +Lawrence Philips.
  • +
+By plugging in custom implementations of one or both of these algorithms the abstract implementation AbstractSpellDictionary can +be customized to specified languages and alphabets. +

+Spell Check Iterators

+Instances of ISpellChecker are usually language-, locale- and medium independent implementations and therefore need an input provider. The +interface ISpellCheckIterator serves this purpose by abstracting the tokenizing of text media to a simple iteration. The actual spell-check process +is launched by calling ISpellChecker#execute(ISpellCheckIterator). This method uses the indicated spell-check iterator to determine the +words that are to be spell-checked. This package provides no default implementation of a spell-check iterator. +

+Event Handling

+To communicate the results of a spell-check pass, spell-checkers fire spell events that inform listeners about the status +of a particular word being spell-checked. Instances that are interested in receiving spell events must implement +the interface ISpellEventListener and register with the spell-checker before the spell-check process starts.

+A spell event contains the following information: +

    +
  • The word being spell-checked
  • +
  • The begin index of the current word in the text medium
  • +
  • The end index in the text medium
  • +
  • A flag whether this word was found in one of the registered dictionaries
  • +
  • A flag that indicates whether this word starts a new sentence
  • +
  • The set of proposals if the word was not correctly spelt. This information is lazily computed.
  • +
+Spell event listeners are free to handle the events in any way. However, listeners are not allowed to block during +the event handling unless the spell-checking process happens in another thread. + + Index: src/org/eclipse/ui/texteditor/spelling/ISpellingEngine.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/ISpellingEngine.java diff -N src/org/eclipse/ui/texteditor/spelling/ISpellingEngine.java --- src/org/eclipse/ui/texteditor/spelling/ISpellingEngine.java 17 Jun 2005 15:48:42 -0000 1.6 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.ui.texteditor.spelling; - -import org.eclipse.core.runtime.IProgressMonitor; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; - -/** - * A spelling engine that can be contributed to the - * org.eclipse.ui.workbench.texteditor.spellingEngine extension - * point. The SpellingContext provides information about the - * content type to be checked. In general a spelling engine should at least - * support the text {@link org.eclipse.core.runtime.content.IContentType content type}. - *

- * This interface is intended to be implemented by clients. - *

- * - * @since 3.1 - */ -public interface ISpellingEngine { - - /** - * Checks the given regions in the given document. Reports all found - * spelling problems to the collector. - * - * @param document the document to check - * @param regions the regions to check - * @param context the context - * @param collector the problem collector - * @param monitor the progress monitor, can be null - */ - public void check(IDocument document, IRegion[] regions, SpellingContext context, ISpellingProblemCollector collector, IProgressMonitor monitor); -} Index: src/org/eclipse/ui/texteditor/spelling/PreferenceConstants.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/PreferenceConstants.java diff -N src/org/eclipse/ui/texteditor/spelling/PreferenceConstants.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/PreferenceConstants.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,431 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Guven Demir - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514 + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling; + +import java.util.Locale; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.InstanceScope; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; + +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + + +/** + * Preference constants used in the JDT-UI preference store. Clients should only read the + * JDT-UI preference store using these values. Clients are not allowed to modify the + * preference store programmatically. + *

+ * This class it is not intended to be instantiated or subclassed by clients. + *

+ * + * @since 2.0 + * + * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. + */ +public class PreferenceConstants { + + private PreferenceConstants() { + } + + /** + * A named preference that controls which completion proposal categories have been excluded from + * the default proposal list. + *

+ * Value is of type String, a "\0"-separated list of identifiers. + *

+ * + * @see #getExcludedCompletionProposalCategories() + * @see #setExcludedCompletionProposalCategories(String[]) + * @since 3.2 + */ + public static final String CODEASSIST_EXCLUDED_CATEGORIES= "content_assist_disabled_computers"; //$NON-NLS-1$ + + + /** + * A named preference that controls return type rendering of methods in the UI. + *

+ * Value is of type Boolean: if true return types + * are rendered + *

+ */ + public static final String APPEARANCE_METHOD_RETURNTYPE= "org.eclipse.jdt.ui.methodreturntype";//$NON-NLS-1$ + + /** + * A named preference that controls type parameter rendering of methods in the UI. + *

+ * Value is of type Boolean: if true return types + * are rendered + *

+ * @since 3.1 + */ + public static final String APPEARANCE_METHOD_TYPEPARAMETERS= "org.eclipse.jdt.ui.methodtypeparametesr";//$NON-NLS-1$ + + /** + * A named preference that controls if override indicators are rendered in the UI. + *

+ * Value is of type Boolean: if true override + * indicators are rendered + *

+ * @deprecated Override Indicator is now controlled on the platform's decorator preference page + */ + public static final String APPEARANCE_OVERRIDE_INDICATOR= "org.eclipse.jdt.ui.overrideindicator";//$NON-NLS-1$ + + /** + * A named preference that controls if quick assist light bulbs are shown. + *

+ * Value is of type Boolean: if true light bulbs are shown + * for quick assists. + *

+ * + * @since 3.0 + */ + public static final String EDITOR_QUICKASSIST_LIGHTBULB="org.eclipse.jdt.quickassist.lightbulb"; //$NON-NLS-1$ + + + + /** + * A named preference that holds a list of possible JRE libraries used by the New Java Project wizard. A library + * consists of a description and an arbitrary number of IClasspathEntrys, that will represent the + * JRE on the new project's class path. + *

+ * Value is of type String: a semicolon separated list of encoded JRE libraries. + * NEWPROJECT_JRELIBRARY_INDEX defines the currently used library. Clients + * should use the method encodeJRELibrary to encode a JRE library into a string + * and the methods decodeJRELibraryDescription(String) and + * decodeJRELibraryClasspathEntries(String) to decode the description and the array + * of class path entries from an encoded string. + *

+ * + * @see #NEWPROJECT_JRELIBRARY_INDEX + * @see #encodeJRELibrary(String, IClasspathEntry[]) + * @see #decodeJRELibraryDescription(String) + * @see #decodeJRELibraryClasspathEntries(String) + */ + public static final String NEWPROJECT_JRELIBRARY_LIST= "org.eclipse.jdt.ui.wizards.jre.list"; //$NON-NLS-1$ + + /** + * A named preferences that specifies the current active JRE library. + *

+ * Value is of type Integer: an index into the list of possible JRE libraries. + *

+ * + * @see #NEWPROJECT_JRELIBRARY_LIST + */ + public static final String NEWPROJECT_JRELIBRARY_INDEX= "org.eclipse.jdt.ui.wizards.jre.index"; //$NON-NLS-1$ + + /** + * A named preference that controls whether Java comments should be + * spell checked. + *

+ * Value is of type Boolean. + *

+ * + * @deprecated since 3.1, use {@link org.eclipse.ui.texteditor.spelling.SpellingService#PREFERENCE_SPELLING_ENABLED} + * and {@link org.eclipse.ui.texteditor.spelling.SpellingService#PREFERENCE_SPELLING_ENGINE} + * @since 3.0 + */ + public final static String SPELLING_CHECK_SPELLING= "spelling_check_spelling"; //$NON-NLS-1$ + + /** + * A named preference that controls whether words containing digits should + * be skipped during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_IGNORE_DIGITS= "spelling_ignore_digits"; //$NON-NLS-1$ + + /** + * A named preference that controls whether mixed case words should be + * skipped during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_IGNORE_MIXED= "spelling_ignore_mixed"; //$NON-NLS-1$ + + /** + * A named preference that controls whether sentence capitalization should + * be ignored during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_IGNORE_SENTENCE= "spelling_ignore_sentence"; //$NON-NLS-1$ + + /** + * A named preference that controls whether upper case words should be + * skipped during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_IGNORE_UPPER= "spelling_ignore_upper"; //$NON-NLS-1$ + + /** + * A named preference that controls whether URLs should be ignored during + * spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_IGNORE_URLS= "spelling_ignore_urls"; //$NON-NLS-1$ + + /** + * A named preference that controls whether single letters + * should be ignored during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.3 + */ + public final static String SPELLING_IGNORE_SINGLE_LETTERS= "spelling_ignore_single_letters"; //$NON-NLS-1$ + + /** + * A named preference that controls whether '&' in + * Java properties files are ignored. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.3 + */ + public final static String SPELLING_IGNORE_AMPERSAND_IN_PROPERTIES= "spelling_ignore_ampersand_in_properties"; //$NON-NLS-1$ + + /** + * A named preference that controls whether non-letters at word boundaries + * should be ignored during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.3 + */ + public final static String SPELLING_IGNORE_NON_LETTERS= "spelling_ignore_non_letters"; //$NON-NLS-1$ + + /** + * A named preference that controls whether Java strings + * should be ignored during spell checking. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.4 + */ + public static final String SPELLING_IGNORE_JAVA_STRINGS= "spelling_ignore_java_strings"; //$NON-NLS-1$; + + /** + * A named preference that controls the locale used for spell checking. + *

+ * Value is of type String. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_LOCALE= "spelling_locale"; //$NON-NLS-1$ + + /** + * A named preference that controls the number of proposals offered during + * spell checking. + *

+ * Value is of type Integer. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_PROPOSAL_THRESHOLD= "spelling_proposal_threshold"; //$NON-NLS-1$ + + /** + * A named preference that controls the maximum number of problems reported during spell checking. + *

+ * Value is of type Integer. + *

+ * + * @since 3.4 + */ + public final static String SPELLING_PROBLEMS_THRESHOLD= "spelling_problems_threshold"; //$NON-NLS-1$ + + /** + * A named preference that specifies the workspace user dictionary. + *

+ * Value is of type Integer. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_USER_DICTIONARY= "spelling_user_dictionary"; //$NON-NLS-1$ + + /** + * A named preference that specifies encoding of the workspace user dictionary. + *

+ * Value is of type String. + *

+ * + * @since 3.3 + */ + public final static String SPELLING_USER_DICTIONARY_ENCODING= "spelling_user_dictionary_encoding"; //$NON-NLS-1$ + + /** + * A named preference that specifies whether spelling dictionaries are available to content assist. + * + * Note: This is currently not supported because the spelling engine + * cannot return word proposals but only correction proposals. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public final static String SPELLING_ENABLE_CONTENTASSIST= "spelling_enable_contentassist"; //$NON-NLS-1$ + + + + + //---------- Properties File Editor ---------- + + /** + * Initializes the given preference store with the default values. + * + * @param store the preference store to be initialized + * + * @since 2.1 + */ + public static void initializeDefaultValues(IPreferenceStore store) { + + // spell checking + store.setDefault(PreferenceConstants.SPELLING_LOCALE, "en_US"); //$NON-NLS-1$ + String isInitializedKey= "spelling_locale_initialized"; //$NON-NLS-1$ + if (!store.getBoolean(isInitializedKey)) { + store.setValue(isInitializedKey, true); + Locale locale= SpellCheckEngine.getDefaultLocale(); + locale= SpellCheckEngine.findClosestLocale(locale); + if (locale != null) + store.setValue(PreferenceConstants.SPELLING_LOCALE, locale.toString()); + } + store.setDefault(PreferenceConstants.SPELLING_IGNORE_DIGITS, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_MIXED, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_SENTENCE, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_UPPER, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_URLS, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_AMPERSAND_IN_PROPERTIES, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS, true); + store.setDefault(PreferenceConstants.SPELLING_IGNORE_JAVA_STRINGS, true); + store.setDefault(PreferenceConstants.SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$ + + // Note: For backwards compatibility we must use the property and not the workspace default + store.setDefault(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING, System.getProperty("file.encoding")); //$NON-NLS-1$ + + store.setDefault(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD, 20); + store.setDefault(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD, 100); + /* + * XXX: This is currently disabled because the spelling engine + * cannot return word proposals but only correction proposals. + */ + store.setToDefault(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST); + } + + /** + * Returns the JDT-UI preference store. + * + * @return the JDT-UI preference store + */ + public static IPreferenceStore getPreferenceStore() { + return TextEditorPlugin.getDefault().getPreferenceStore(); + } + + /** + * Returns the completion proposal categories which + * are excluded from the default proposal list. + * + * @return an array with the IDs of the excluded categories + * @see #CODEASSIST_EXCLUDED_CATEGORIES + * @since 3.4 + */ + public static String[] getExcludedCompletionProposalCategories() { + String encodedPreference= getPreference(CODEASSIST_EXCLUDED_CATEGORIES, null); + StringTokenizer tokenizer= new StringTokenizer(encodedPreference, "\0"); //$NON-NLS-1$ + String[] result= new String[tokenizer.countTokens()]; + for (int i= 0; i < result.length; i++) + result[i]= tokenizer.nextToken(); + return result; + } + + /** + * Sets the completion proposal categories which are excluded from the + * default proposal list and reloads the registry. + * + * @param categories the array with the IDs of the excluded categories + * @see #CODEASSIST_EXCLUDED_CATEGORIES + * @since 3.4 + */ + public static void setExcludedCompletionProposalCategories(String[] categories) { + Assert.isLegal(categories != null); + StringBuffer buf= new StringBuffer(50 * categories.length); + for (int i= 0; i < categories.length; i++) { + buf.append(categories[i]); + buf.append('\0'); + } + getPreferenceStore().setValue(CODEASSIST_EXCLUDED_CATEGORIES, buf.toString()); + //TODO: what to do with this ? + //CompletionProposalComputerRegistry.getDefault().reload(); + } + + /** + * Returns the value for the given key in the given context. + * @param key The preference key + * @param project The current context or null if no context is available and the + * workspace setting should be taken. Note that passing null should + * be avoided. + * @return Returns the current value for the string. + * @since 3.1 + */ + + //TODO: it was : public static String getPreference(String key, IJavaProject project) { + // does it affect anything? + public static String getPreference(String key, IProject project) { + String val; + if (project != null) { + val= new ProjectScope(project.getProject()).getNode(TextEditorPlugin.PLUGIN_ID).get(key, null); + if (val != null) { + return val; + } + } + val= new InstanceScope().getNode(TextEditorPlugin.PLUGIN_ID).get(key, null); + if (val != null) { + return val; + } + return new DefaultScope().getNode(TextEditorPlugin.PLUGIN_ID).get(key, null); + } +} + Index: src/org/eclipse/ui/texteditor/spelling/SpellCheckIterator.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/SpellCheckIterator.java diff -N src/org/eclipse/ui/texteditor/spelling/SpellCheckIterator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/SpellCheckIterator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,433 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling; + +import java.util.LinkedList; +import java.util.Locale; + +import com.ibm.icu.text.BreakIterator; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.TextUtilities; + +import org.eclipse.ui.internal.texteditor.spelling.engine.DefaultSpellChecker; + +import org.eclipse.ui.texteditor.spelling.correction.IHtmlTagConstants; +import org.eclipse.ui.texteditor.spelling.correction.IJavaDocTagConstants; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckIterator; + + +/** + * Iterator to spell check javadoc comment regions. + * + * @since 3.0 + */ +/* + * Ha! this does more than javadoc + */ +public class SpellCheckIterator implements ISpellCheckIterator { + + /** + * The token that denotes whitespace. + * + * @since 3.6 + */ + private static final int WHITE_SPACE_TOKEN= -1; + + /** The content of the region */ + protected final String fContent; + + /** The line delimiter */ + private final String fDelimiter; + + /** The last token */ + protected String fLastToken= null; + + /** The next break */ + protected int fNext= 1; + + /** The offset of the region */ + protected final int fOffset; + + /** The predecessor break */ + private int fPredecessor; + + /** The previous break */ + protected int fPrevious= 0; + + /** The sentence breaks */ + private final LinkedList fSentenceBreaks= new LinkedList(); + + /** Does the current word start a sentence? */ + private boolean fStartsSentence= false; + + /** The successor break */ + protected int fSuccessor; + + /** The word iterator */ + private final BreakIterator fWordIterator; + + private boolean fIsIgnoringSingleLetters; + + /** + * Creates a new spell check iterator. + * + * @param document the document containing the specified partition + * @param region the region to spell check + * @param locale the locale to use for spell checking + */ + public SpellCheckIterator(IDocument document, IRegion region, Locale locale) { + this(document, region, locale, BreakIterator.getWordInstance(locale)); + } + + /** + * Creates a new spell check iterator. + * + * @param document the document containing the specified partition + * @param region the region to spell check + * @param locale the locale to use for spell checking + * @param breakIterator the break-iterator + */ + public SpellCheckIterator(IDocument document, IRegion region, Locale locale, BreakIterator breakIterator) { + fOffset= region.getOffset(); + fWordIterator= breakIterator; + fDelimiter= TextUtilities.getDefaultLineDelimiter(document); + + String content; + try { + + content= document.get(region.getOffset(), region.getLength()); + //TODO: Fix this + //if (content.startsWith(NLSElement.TAG_PREFIX)) + if (content.startsWith("//$NON-NLS-")) //$NON-NLS-1$ + content= ""; //$NON-NLS-1$ + + } catch (Exception exception) { + content= ""; //$NON-NLS-1$ + } + fContent= content; + + fWordIterator.setText(content); + fPredecessor= fWordIterator.first(); + fSuccessor= fWordIterator.next(); + + final BreakIterator iterator= BreakIterator.getSentenceInstance(locale); + iterator.setText(content); + + int offset= iterator.current(); + while (offset != BreakIterator.DONE) { + + fSentenceBreaks.add(new Integer(offset)); + offset= iterator.next(); + } + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckIterator#setIgnoreSingleLetters(boolean) + * @since 3.3 + */ + public void setIgnoreSingleLetters(boolean state) { + fIsIgnoringSingleLetters= state; + } + + /* + * @see org.eclipse.spelling.done.ISpellCheckIterator#getBegin() + */ + public final int getBegin() { + return fPrevious + fOffset; + } + + /* + * @see org.eclipse.spelling.done.ISpellCheckIterator#getEnd() + */ + public final int getEnd() { + return fNext + fOffset - 1; + } + + /* + * @see java.util.Iterator#hasNext() + */ + public final boolean hasNext() { + return fSuccessor != BreakIterator.DONE; + } + + /** + * Does the specified token consist of at least one letter and digits + * only? + * + * @param begin the begin index + * @param end the end index + * @return true iff the token consists of digits and at + * least one letter only, false otherwise + */ + protected final boolean isAlphaNumeric(final int begin, final int end) { + + char character= 0; + + boolean letter= false; + for (int index= begin; index < end; index++) { + + character= fContent.charAt(index); + if (Character.isLetter(character)) + letter= true; + + if (!Character.isLetterOrDigit(character)) + return false; + } + return letter; + } + + /** + * Checks the last token against the given tags? + * + * @param tags the tags to check + * @return true iff the last token is in the given array + */ + protected final boolean isToken(final String[] tags) { + return isToken(fLastToken, tags); + } + + /** + * Checks the given token against the given tags? + * + * @param token the token to check + * @param tags the tags to check + * @return true iff the last token is in the given array + * @since 3.3 + */ + protected final boolean isToken(final String token, final String[] tags) { + + if (token != null) { + + for (int index= 0; index < tags.length; index++) { + + if (token.equals(tags[index])) + return true; + } + } + return false; + } + + /** + * Is the current token a single letter token surrounded by + * non-whitespace characters? + * + * @param begin the begin index + * @return true iff the token is a single letter token, + * false otherwise + */ + protected final boolean isSingleLetter(final int begin) { + if (!Character.isLetter(fContent.charAt(begin))) + return false; + + if (begin > 0 && !Character.isWhitespace(fContent.charAt(begin - 1))) + return false; + + if (begin < fContent.length() - 1 && !Character.isWhitespace(fContent.charAt(begin + 1))) + return false; + + return true; + } + + /** + * Does the specified token look like an URL? + * + * @param begin the begin index + * @return true iff this token look like an URL, + * false otherwise + */ + protected final boolean isUrlToken(final int begin) { + + for (int index= 0; index < DefaultSpellChecker.URL_PREFIXES.length; index++) { + + if (fContent.startsWith(DefaultSpellChecker.URL_PREFIXES[index], begin)) + return true; + } + return false; + } + + /** + * Does the specified token consist of whitespace only? + * + * @param begin the begin index + * @param end the end index + * @return true iff the token consists of whitespace + * only, false otherwise + */ + protected final boolean isWhitespace(final int begin, final int end) { + + for (int index= begin; index < end; index++) { + + if (!Character.isWhitespace(fContent.charAt(index))) + return false; + } + return true; + } + + /* + * @see java.util.Iterator#next() + */ + public Object next() { + + String token= nextToken(); + while (token == null && fSuccessor != BreakIterator.DONE) + token= nextToken(); + + fLastToken= token; + + return token; + } + + /** + * Advances the end index to the next word break. + */ + protected final void nextBreak() { + + fNext= fSuccessor; + fPredecessor= fSuccessor; + + fSuccessor= fWordIterator.next(); + } + + /** + * Returns the next sentence break. + * + * @return the next sentence break + */ + protected final int nextSentence() { + return ((Integer) fSentenceBreaks.getFirst()).intValue(); + } + + /** + * Determines the next token to be spell checked. + * + * @return the next token to be spell checked, or null + * iff the next token is not a candidate for spell checking. + */ + protected String nextToken() { + + String token= null; + + fPrevious= fPredecessor; + fStartsSentence= false; + + nextBreak(); + + boolean update= false; + if (fNext - fPrevious > 0) { + + if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX) { + + nextBreak(); + if (Character.isLetter(fContent.charAt(fPrevious + 1))) { + update= true; + token= fContent.substring(fPrevious, fNext); + } else + fPredecessor= fNext; + + } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_TAG_PREFIX && (Character.isLetter(fContent.charAt(fNext)) || fContent.charAt(fNext) == '/')) { + + if (fContent.startsWith(IHtmlTagConstants.HTML_CLOSE_PREFIX, fPrevious)) + nextBreak(); + + nextBreak(); + + if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_TAG_POSTFIX) { + + nextBreak(); + if (fSuccessor != BreakIterator.DONE) { + update= true; + token= fContent.substring(fPrevious, fNext); + } + } + } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_ENTITY_START && (Character.isLetter(fContent.charAt(fNext)))) { + nextBreak(); + if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_ENTITY_END) { + nextBreak(); + if (isToken(fContent.substring(fPrevious, fNext), IHtmlTagConstants.HTML_ENTITY_CODES)) { + skipTokens(fPrevious, IHtmlTagConstants.HTML_ENTITY_END); + update= true; + } else + token= fContent.substring(fPrevious, fNext); + } else + token= fContent.substring(fPrevious, fNext); + + update= true; + } else if (!isWhitespace(fPrevious, fNext) && isAlphaNumeric(fPrevious, fNext)) { + + if (isUrlToken(fPrevious)) + skipTokens(fPrevious, WHITE_SPACE_TOKEN); + else if (isToken(IJavaDocTagConstants.JAVADOC_PARAM_TAGS)) + fLastToken= null; + else if (isToken(IJavaDocTagConstants.JAVADOC_REFERENCE_TAGS)) { + fLastToken= null; + skipTokens(fPrevious, fDelimiter.charAt(0)); + } else if (fNext - fPrevious > 1 || isSingleLetter(fPrevious) && !fIsIgnoringSingleLetters) + token= fContent.substring(fPrevious, fNext); + + update= true; + } + } + + if (update && fSentenceBreaks.size() > 0) { + + if (fPrevious >= nextSentence()) { + + while (fSentenceBreaks.size() > 0 && fPrevious >= nextSentence()) + fSentenceBreaks.removeFirst(); + + fStartsSentence= (fLastToken == null) || (token != null); + } + } + return token; + } + + /* + * @see java.util.Iterator#remove() + */ + public final void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Skip the tokens until the stop character is reached. + * + * @param begin the begin index + * @param stop the stop character + */ + protected final void skipTokens(final int begin, final int stop) { + final boolean isStoppingOnWhiteSpace= stop == WHITE_SPACE_TOKEN; + int end= begin; + while (end < fContent.length()) { + char ch= fContent.charAt(end); + if (ch == stop || isStoppingOnWhiteSpace && Character.isWhitespace(ch)) + break; + end++; + } + + if (end < fContent.length()) { + + fNext= end; + fPredecessor= fNext; + + fSuccessor= fWordIterator.following(fNext); + } else + fSuccessor= BreakIterator.DONE; + } + + /* + * @see org.eclipse.spelling.done.ISpellCheckIterator#startsSentence() + */ + public final boolean startsSentence() { + return fStartsSentence; + } +} Index: src/org/eclipse/ui/texteditor/spelling/SpellingContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/spelling/SpellingContext.java,v retrieving revision 1.12 diff -u -r1.12 SpellingContext.java --- src/org/eclipse/ui/texteditor/spelling/SpellingContext.java 29 May 2008 10:54:37 -0000 1.12 +++ src/org/eclipse/ui/texteditor/spelling/SpellingContext.java 15 Dec 2010 05:46:37 -0000 @@ -12,6 +12,8 @@ import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.ui.texteditor.spelling.engine.ISpellingEngine; + /** * A spelling context allows a {@link ISpellingEngine} to retrieve information Index: src/org/eclipse/ui/texteditor/spelling/SpellingCorrectionProcessor.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/SpellingCorrectionProcessor.java diff -N src/org/eclipse/ui/texteditor/spelling/SpellingCorrectionProcessor.java --- src/org/eclipse/ui/texteditor/spelling/SpellingCorrectionProcessor.java 11 Dec 2009 12:40:32 -0000 1.8 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,119 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.ui.texteditor.spelling; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.jface.text.Position; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; -import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; -import org.eclipse.jface.text.source.Annotation; -import org.eclipse.jface.text.source.IAnnotationModel; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.TextInvocationContext; - -import org.eclipse.ui.internal.texteditor.spelling.NoCompletionsProposal; - - -/** - * Spelling correction processor used to show quick - * fixes for spelling problems. - * - * @since 3.3 - */ -public final class SpellingCorrectionProcessor implements IQuickAssistProcessor { - - - private static final ICompletionProposal[] fgNoSuggestionsProposal= new ICompletionProposal[] { new NoCompletionsProposal() }; - - - /* - * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) - */ - public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext quickAssistContext) { - ISourceViewer viewer= quickAssistContext.getSourceViewer(); - int documentOffset= quickAssistContext.getOffset(); - - int length= viewer != null ? viewer.getSelectedRange().y : -1; - TextInvocationContext context= new TextInvocationContext(viewer, documentOffset, length); - - - IAnnotationModel model= viewer.getAnnotationModel(); - if (model == null) - return fgNoSuggestionsProposal; - - List proposals= computeProposals(context, model); - if (proposals.isEmpty()) - return fgNoSuggestionsProposal; - - return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]); - } - - private boolean isAtPosition(int offset, Position pos) { - return (pos != null) && (offset >= pos.getOffset() && offset <= (pos.getOffset() + pos.getLength())); - } - - private List computeProposals(IQuickAssistInvocationContext context, IAnnotationModel model) { - int offset= context.getOffset(); - ArrayList annotationList= new ArrayList(); - Iterator iter= model.getAnnotationIterator(); - while (iter.hasNext()) { - Annotation annotation= (Annotation)iter.next(); - if (canFix(annotation)) { - Position pos= model.getPosition(annotation); - if (isAtPosition(offset, pos)) { - collectSpellingProblems(annotation, annotationList); - } - } - } - SpellingProblem[] spellingProblems= (SpellingProblem[]) annotationList.toArray(new SpellingProblem[annotationList.size()]); - return computeProposals(context, spellingProblems); - } - - private void collectSpellingProblems(Annotation annotation, List problems) { - if (annotation instanceof SpellingAnnotation) - problems.add(((SpellingAnnotation)annotation).getSpellingProblem()); - } - - private List computeProposals(IQuickAssistInvocationContext context, SpellingProblem[] spellingProblems) { - List proposals= new ArrayList(); - for (int i= 0; i < spellingProblems.length; i++) - proposals.addAll(Arrays.asList(spellingProblems[i].getProposals(context))); - - return proposals; - } - - /* - * @see IContentAssistProcessor#getErrorMessage() - */ - public String getErrorMessage() { - return null; - } - - /* - * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canFix(org.eclipse.jface.text.source.Annotation) - */ - public boolean canFix(Annotation annotation) { - return annotation instanceof SpellingAnnotation && !annotation.isMarkedDeleted(); - } - - /* - * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canAssist(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext) - */ - public boolean canAssist(IQuickAssistInvocationContext invocationContext) { - return false; - } - -} Index: src/org/eclipse/ui/texteditor/spelling/SpellingEngineDescriptor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/spelling/SpellingEngineDescriptor.java,v retrieving revision 1.12 diff -u -r1.12 SpellingEngineDescriptor.java --- src/org/eclipse/ui/texteditor/spelling/SpellingEngineDescriptor.java 11 Sep 2008 11:58:03 -0000 1.12 +++ src/org/eclipse/ui/texteditor/spelling/SpellingEngineDescriptor.java 15 Dec 2010 05:46:37 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,8 @@ import org.eclipse.ui.internal.texteditor.spelling.EmptySpellingPreferenceBlock; +import org.eclipse.ui.texteditor.spelling.engine.ISpellingEngine; + /** * Describes an extension to the spellingEngine extension point. *

@@ -36,6 +38,8 @@ private static final String CLASS_ATTRIBUTE= "class"; //$NON-NLS-1$ /** Name of the id attribute. */ private static final String ID_ATTRIBUTE= "id"; //$NON-NLS-1$ + /** Name of the contentType attribute. @since 3.7 */ + private static final String CONTENT_TYPE_ATTRIBUTE= "contentType"; //$NON-NLS-1$ /** Name of the default attribute. */ private static final String DEFAULT_ATTRIBUTE= "default"; //$NON-NLS-1$ /** Name of the preferencesClass attribute. */ @@ -47,6 +51,8 @@ private String fLabel; /** The value of the id attribute, if read. */ private String fId; + /** The value of the contentType attribute, if read. */ + private String fContentType; /** The value of the default attribute, if read. */ private Boolean fDefault; /** The bundle where this extension was defined. */ @@ -54,6 +60,7 @@ /** true iff a preferences class has been specified */ private Boolean fHasPreferences; + /** * Creates a new descriptor for element. *

@@ -75,7 +82,7 @@ public String getLabel() { if (fLabel == null) { fLabel= fConfiguration.getAttribute(LABEL_ATTRIBUTE); - Assert.isNotNull(fLabel); + Assert.isNotNull(fLabel); //TODO:does not look right - this is optional } return fLabel; } @@ -94,8 +101,21 @@ } /** + * Reads (if needed) and returns the content type of this extension. + * + * @return the content type for this extension. + * @since 3.7 + */ + public String getContentType() { + if (fContentType == null) { + fContentType= fConfiguration.getAttribute(CONTENT_TYPE_ATTRIBUTE); + } + return fContentType; + } + + /** * Creates a spelling engine as described in the extension's xml. - * + * * @return the created spelling engine * @throws CoreException if the creation failed */ Index: src/org/eclipse/ui/texteditor/spelling/SpellingService.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/spelling/SpellingService.java,v retrieving revision 1.13 diff -u -r1.13 SpellingService.java --- src/org/eclipse/ui/texteditor/spelling/SpellingService.java 29 May 2008 10:54:37 -0000 1.13 +++ src/org/eclipse/ui/texteditor/spelling/SpellingService.java 15 Dec 2010 05:46:37 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,10 +11,14 @@ package org.eclipse.ui.texteditor.spelling; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.preference.IPreferenceStore; @@ -25,6 +29,8 @@ import org.eclipse.ui.internal.texteditor.TextEditorPlugin; import org.eclipse.ui.internal.texteditor.spelling.SpellingEngineRegistry; +import org.eclipse.ui.texteditor.spelling.engine.ISpellingEngine; + /** * System wide spelling service. *

@@ -36,6 +42,9 @@ */ public class SpellingService { + /** Available spelling engines by content type */ + private Map fEngines= new HashMap(); + /** * A named preference that controls if spelling is enabled or disabled. *

@@ -97,7 +106,7 @@ collector.beginCollecting(); if (fPreferences.getBoolean(PREFERENCE_SPELLING_ENABLED)) try { - final ISpellingEngine engine= createEngine(fPreferences); + final ISpellingEngine engine= getEngine(context.getContentType(), fPreferences); if (engine != null) { ISafeRunnable runnable= new ISafeRunnable() { public void run() throws Exception { @@ -144,15 +153,44 @@ } /** - * Returns the descriptor of the active spelling engine based on the - * value of the PREFERENCE_SPELLING_ENGINE preference - * in the given preferences. - * + * Returns the descriptor of the active spelling engine based on the value of the + * PREFERENCE_SPELLING_ENGINE preference in the given preferences. + * + * @param contentType + * * @param preferences the preferences - * @return the descriptor of the active spelling engine or - * null if none could be found + * @return the descriptor of the active spelling engine or null if none could be + * found * @see SpellingService#PREFERENCE_SPELLING_ENGINE */ + public SpellingEngineDescriptor getActiveSpellingEngineDescriptor(IContentType contentType, IPreferenceStore preferences) { + SpellingEngineRegistry registry= getSpellingEngineRegistry(); + if (registry == null) + return null; + + SpellingEngineDescriptor descriptor= registry.getDescriptor(contentType); + if (descriptor == null) { + descriptor= registry.getDefaultDescriptor(); + } + return descriptor; + } + + /** + * Returns the descriptor of the active spelling engine based on the value of the + * PREFERENCE_SPELLING_ENGINE preference in the given preferences. + * + * @param contentType + * + * @param preferences the preferences + * @return the descriptor of the active spelling engine or null if none could be + * found + * @see SpellingService#PREFERENCE_SPELLING_ENGINE + * @deprecated + * + * TODO: what to do with the concept of active spelling engine? now that the engine + * is content type based? have multiple engines for a content type and one of them + * active? overkill i would say + */ public SpellingEngineDescriptor getActiveSpellingEngineDescriptor(IPreferenceStore preferences) { SpellingEngineRegistry registry= getSpellingEngineRegistry(); if (registry == null) @@ -167,24 +205,55 @@ } /** - * Creates a spelling engine based on the value of the - * PREFERENCE_SPELLING_ENGINE preference in the given - * preferences. - * + * Creates a spelling engine based on the value of the PREFERENCE_SPELLING_ENGINE + * preference in the given preferences. + * + * @param contentType + * * @param preferences the preferences - * @return the created spelling engine or null if none - * could be created + * @return the created spelling engine or null if none could be created * @throws CoreException if the creation failed * @see SpellingService#PREFERENCE_SPELLING_ENGINE */ - private ISpellingEngine createEngine(IPreferenceStore preferences) throws CoreException { - SpellingEngineDescriptor descriptor= getActiveSpellingEngineDescriptor(preferences); + private ISpellingEngine createEngine(IContentType contentType, IPreferenceStore preferences) throws CoreException { + SpellingEngineDescriptor descriptor= getActiveSpellingEngineDescriptor(contentType, preferences); if (descriptor != null) return descriptor.createEngine(); return null; } /** + * Returns a spelling engine for the given content type or null if none could be + * found. + * + * @param contentType the content type + * @param preferences + * @return a spelling engine for the given content type or null if none could be + * found + * @throws CoreException + */ + private ISpellingEngine getEngine(IContentType contentType, IPreferenceStore preferences) throws CoreException { + if (contentType == null) + return null; + + //'all content type' case is handled in SpellingEngineRegistry#getDescriptor(IContentType) + + if (fEngines.containsKey(contentType)) + return (ISpellingEngine)fEngines.get(contentType); + + //try to create engine + ISpellingEngine engine= createEngine(contentType, preferences); + if (engine != null) { + fEngines.put(contentType, engine); + return engine; + } + + return getEngine(contentType.getBaseType(), preferences); // TODO: base type?? + } + + + + /** * Returns the spelling engine registry. * * @return the spelling engine registry or null if the plug-in has been shutdown Index: src/org/eclipse/ui/texteditor/spelling/TextSpellingProblem.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/TextSpellingProblem.java diff -N src/org/eclipse/ui/texteditor/spelling/TextSpellingProblem.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/TextSpellingProblem.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,244 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; +import org.eclipse.jface.text.source.TextInvocationContext; + +import org.eclipse.ui.internal.texteditor.spelling.Messages; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +import org.eclipse.ui.texteditor.spelling.correction.AddWordProposal; +import org.eclipse.ui.texteditor.spelling.correction.ChangeCaseProposal; +import org.eclipse.ui.texteditor.spelling.correction.DisableSpellCheckingProposal; +import org.eclipse.ui.texteditor.spelling.correction.IHtmlTagConstants; +import org.eclipse.ui.texteditor.spelling.correction.IJavaDocTagConstants; +import org.eclipse.ui.texteditor.spelling.correction.ISpellingCompletionProposal; +import org.eclipse.ui.texteditor.spelling.correction.RankedWordProposal; +import org.eclipse.ui.texteditor.spelling.correction.WordCorrectionProposal; +import org.eclipse.ui.texteditor.spelling.correction.WordIgnoreProposal; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckEngine; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.ISpellEvent; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + +/** + * A {@link SpellingProblem} that adapts a {@link ISpellEvent}. + *

+ * TODO: remove {@link ISpellEvent} notification mechanism + *

+ */ + +//this was JavaSpellingProblem +public class TextSpellingProblem extends SpellingProblem { + + /** Spell event */ + private ISpellEvent fSpellEvent; + + /** + * The associated document. + * + * @since 3.3 + */ + private IDocument fDocument; + + /** + * Initialize with the given spell event. + * + * @param spellEvent the spell event + * @param document the document + */ + public TextSpellingProblem(ISpellEvent spellEvent, IDocument document) { + Assert.isLegal(document != null); + Assert.isLegal(spellEvent != null); + fSpellEvent= spellEvent; + fDocument= document; + } + + /* + * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getOffset() + */ + public int getOffset() { + return fSpellEvent.getBegin(); + } + + /* + * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getLength() + */ + public int getLength() { + return fSpellEvent.getEnd() - fSpellEvent.getBegin() + 1; + } + + /* + * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getMessage() + */ + public String getMessage() { + if (isSentenceStart() && isDictionaryMatch()) + return Messages.format(SpellingMessages.Spelling_error_case_label, new String[] { fSpellEvent.getWord() }); + + return Messages.format(SpellingMessages.Spelling_error_label, new String[] { fSpellEvent.getWord() }); + } + + /* + * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getProposals() + */ + public ICompletionProposal[] getProposals() { + return getProposals(null); + } + + /* + * @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getProposals(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext) + * @since 3.4 + */ + public ICompletionProposal[] getProposals(IQuickAssistInvocationContext context) { + String[] arguments= getArguments(); + if (arguments == null) + return new ICompletionProposal[0]; + + if (arguments[0].indexOf('&') != -1 && isIgnoringAmpersand()) + return new ICompletionProposal[0]; // no proposals for now + + final int threshold= PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD); + int size= 0; + List proposals= null; + + RankedWordProposal proposal= null; + ISpellingCompletionProposal[] result= null; + int index= 0; + + boolean fixed= false; + boolean match= false; + boolean sentence= false; + + final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); + final ISpellChecker checker= engine.getSpellChecker(); + + if (checker != null) { + + if (context == null) + context= new TextInvocationContext(null, getOffset(), getLength()); + else + context= new TextInvocationContext(context.getSourceViewer(), getOffset(), getLength()); + + // FIXME: this is a pretty ugly hack + fixed= arguments[0].charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX + || arguments[0].charAt(0) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX; + + if ((sentence && match) && !fixed) + result= new ISpellingCompletionProposal[] { new ChangeCaseProposal( + arguments, getOffset(), getLength(), context, engine + .getLocale()) }; + else { + + proposals= new ArrayList(checker.getProposals(arguments[0], + sentence)); + size= proposals.size(); + + if (threshold > 0 && size > threshold) { + + Collections.sort(proposals); + proposals= proposals + .subList(size - threshold - 1, size - 1); + size= proposals.size(); + } + + boolean extendable= !fixed ? (checker.acceptsWords() || AddWordProposal.canAskToConfigure()) : false; + result= new ISpellingCompletionProposal[size + (extendable ? 3 : 2)]; + + for (index= 0; index < size; index++) { + + proposal= (RankedWordProposal) proposals.get(index); + result[index]= new WordCorrectionProposal(proposal + .getText(), arguments, getOffset(), getLength(), + context, proposal.getRank()); + } + + if (extendable) + result[index++]= new AddWordProposal(arguments[0], context); + + result[index++]= new WordIgnoreProposal(arguments[0], context); + result[index++]= new DisableSpellCheckingProposal(context); + } + } + + return result; + } + + private boolean isIgnoringAmpersand() { + return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SPELLING_IGNORE_AMPERSAND_IN_PROPERTIES); + } + + public String[] getArguments() { + + String prefix= ""; //$NON-NLS-1$ + String postfix= ""; //$NON-NLS-1$ + String word; + try { + word= fDocument.get(getOffset(), getLength()); + } catch (BadLocationException e) { + return null; + } + + try { + + IRegion line= fDocument.getLineInformationOfOffset(getOffset()); + prefix= fDocument.get(line.getOffset(), getOffset() - line.getOffset()); + int postfixStart= getOffset() + getLength(); + postfix= fDocument.get(postfixStart, line.getOffset() + line.getLength() - postfixStart); + + } catch (BadLocationException exception) { + // Do nothing + } + return new String[] { + word, + prefix, + postfix, + isSentenceStart() ? Boolean.toString(true) : Boolean + .toString(false), + isDictionaryMatch() ? Boolean.toString(true) : Boolean + .toString(false) }; + } + + /** + * Returns true iff the corresponding word was found in the dictionary. + *

+ * NOTE: to be removed, see {@link #getProposals()} + *

+ * + * @return true iff the corresponding word was found in the dictionary + */ + public boolean isDictionaryMatch() { + return fSpellEvent.isMatch(); + } + + /** + * Returns true iff the corresponding word starts a sentence. + *

+ * NOTE: to be removed, see {@link #getProposals()} + *

+ * + * @return true iff the corresponding word starts a sentence + */ + public boolean isSentenceStart() { + return fSpellEvent.isStart(); + } + +} Index: src/org/eclipse/ui/texteditor/spelling/correction/AddWordProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/AddWordProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/AddWordProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/AddWordProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialogWithToggle; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; + +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.internal.texteditor.spelling.Messages; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; +import org.eclipse.ui.texteditor.spelling.SpellingProblem; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckEngine; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; +/** + * Proposal to add the unknown word to the dictionaries. + * + * @since 3.0 + */ +public class AddWordProposal implements ISpellingCompletionProposal { + + private static final String PREF_KEY_DO_NOT_ASK= "do_not_ask_to_install_user_dictionary"; //$NON-NLS-1$ + + /** The invocation context */ + private final IQuickAssistInvocationContext fContext; + + /** The word to add */ + private final String fWord; + + + /** + * Creates a new add word proposal + * + * @param word + * The word to add + * @param context + * The invocation context + */ + public AddWordProposal(final String word, final IQuickAssistInvocationContext context) { + fContext= context; + fWord= word; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + */ + public final void apply(final IDocument document) { + + final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); + final ISpellChecker checker= engine.getSpellChecker(); + + if (checker == null) + return; + + if (!checker.acceptsWords()) { + Shell shell= null; + if (fContext != null && fContext.getSourceViewer() != null) + shell= fContext.getSourceViewer().getTextWidget().getShell(); + + /*else + shell= JavaPlugin.getActiveWorkbenchShell();*///TODO: fix this, this code is needed + + if (!canAskToConfigure() || !askUserToConfigureUserDictionary(shell)) + return; + + String[] preferencePageIds= new String[] { "org.eclipse.ui.editors.preferencePages.Spelling" }; //$NON-NLS-1$ + PreferencesUtil.createPreferenceDialogOn(shell, preferencePageIds[0], preferencePageIds, null).open(); + } + + if (checker.acceptsWords()) { + checker.addWord(fWord); + if (fContext != null && fContext.getSourceViewer() != null) + SpellingProblem.removeAll(fContext.getSourceViewer(), fWord); + } + } + + /** + * Asks the user whether he wants to configure a user dictionary. + * + * @param shell the shell + * @return true if the user wants to configure the user dictionary + * @since 3.3 + */ + private boolean askUserToConfigureUserDictionary(Shell shell) { + MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openYesNoQuestion( + shell, + SpellingMessages.Spelling_add_askToConfigure_title, + SpellingMessages.Spelling_add_askToConfigure_question, + SpellingMessages.Spelling_add_askToConfigure_ignoreMessage, + false, + null, + null); + + PreferenceConstants.getPreferenceStore().setValue(PREF_KEY_DO_NOT_ASK, toggleDialog.getToggleState()); + + return toggleDialog.getReturnCode() == IDialogConstants.YES_ID; + } + + /** + * Tells whether this proposal can ask to + * configure a user dictionary. + * + * @return true if it can ask the user + */ + public static boolean canAskToConfigure() { + return !PreferenceConstants.getPreferenceStore().getBoolean(PREF_KEY_DO_NOT_ASK); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return Messages.format(SpellingMessages.Spelling_add_info, new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord) }); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() + */ + public final IContextInformation getContextInformation() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return Messages.format(SpellingMessages.Spelling_add_label, new String[] { fWord }); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() + */ + public Image getImage() { + return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD); + } + + /* + * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() + */ + public int getRelevance() { + return Integer.MIN_VALUE; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) + */ + public final Point getSelection(final IDocument document) { + return new Point(fContext.getOffset(), fContext.getLength()); + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/ChangeCaseProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/ChangeCaseProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/ChangeCaseProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/ChangeCaseProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +import java.util.Locale; + +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; + +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +/** + * Proposal to change the letter case of a word. + * + * @since 3.0 + */ +public class ChangeCaseProposal extends WordCorrectionProposal { + + /** + * Creates a new change case proposal. + * + * @param arguments The problem arguments associated with the spelling problem + * @param offset The offset in the document where to apply the proposal + * @param length The length in the document to apply the proposal + * @param context The invocation context for this proposal + * @param locale The locale to use for the case change + */ + public ChangeCaseProposal(final String[] arguments, final int offset, final int length, final IQuickAssistInvocationContext context, final Locale locale) { + super(Character.isLowerCase(arguments[0].charAt(0)) ? Character.toUpperCase(arguments[0].charAt(0)) + arguments[0].substring(1) : arguments[0], arguments, offset, length, context, Integer.MAX_VALUE); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return SpellingMessages.Spelling_case_label; + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/DisableSpellCheckingProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/DisableSpellCheckingProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/DisableSpellCheckingProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/DisableSpellCheckingProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +import org.eclipse.ui.texteditor.spelling.SpellingService; + + + +/** + * Proposal to disable spell checking. + * + * @since 3.3 + */ +public class DisableSpellCheckingProposal implements ISpellingCompletionProposal { + + /** The invocation context */ + private IQuickAssistInvocationContext fContext; + + /** + * Creates a new proposal. + * + * @param context the invocation context + */ + public DisableSpellCheckingProposal(IQuickAssistInvocationContext context) { + fContext= context; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + */ + public final void apply(final IDocument document) { + //IPreferenceStore store= EditorsUI.getPreferenceStore(); + IPreferenceStore store= TextEditorPlugin.getDefault().getPreferenceStore(); //TODO : is this good? + store.setValue(SpellingService.PREFERENCE_SPELLING_ENABLED, false); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return SpellingMessages.Spelling_disable_info; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() + */ + public final IContextInformation getContextInformation() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return SpellingMessages.Spelling_disable_label; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() + */ + public Image getImage() { + return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE); + } + /* + * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() + */ + public final int getRelevance() { + return Integer.MIN_VALUE + 1; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) + */ + public final Point getSelection(final IDocument document) { + return new Point(fContext.getOffset(), fContext.getLength()); + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/IHtmlTagConstants.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/IHtmlTagConstants.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/IHtmlTagConstants.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/IHtmlTagConstants.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +/** + * Html tag constants. + * + * @since 3.0 + */ + +//XXX Duplicated from JDT +public interface IHtmlTagConstants { + + /** Html tag close prefix */ + public static final String HTML_CLOSE_PREFIX= "', ' ', '&', '^', '~', '\"' }; + + /** + * Html entity start. + * @since 3.3 + */ + public static final char HTML_ENTITY_START= '&'; + /** + * Html entity end. + * @since 3.3 + */ + public static final char HTML_ENTITY_END= ';'; + + /** Html entity codes */ + public static final String[] HTML_ENTITY_CODES= new String[] { "<", ">", " ", "&", "ˆ", "˜", """ }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + + /** Html general tags */ + public static final String[] HTML_GENERAL_TAGS= new String[] { "a", "b", "blockquote", "br", "code", "dd", "dl", "dt", "em", "hr", "h1", "h2", "h3", "h4", "h5", "h6", "i", "li", "nl", "ol", "p", "pre", "q", "strong", "tbody", "td", "th", "tr", "tt", "ul" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ //$NON-NLS-20$ //$NON-NLS-21$ //$NON-NLS-22$ //$NON-NLS-23$ //$NON-NLS-24$ //$NON-NLS-25$ //$NON-NLS-26$ //$NON-NLS-27$ //$NON-NLS-28$ //$NON-NLS-29$ //$NON-NLS-30$ + + /** Html tag postfix */ + public static final char HTML_TAG_POSTFIX= '>'; + + /** Html tag prefix */ + public static final char HTML_TAG_PREFIX= '<'; +} Index: src/org/eclipse/ui/texteditor/spelling/correction/IJavaDocTagConstants.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/IJavaDocTagConstants.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/IJavaDocTagConstants.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/IJavaDocTagConstants.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + + +/** + * Javadoc tag constants. + * + * @since 3.0 + */ + +//XXX duplicated from JDT : it must not be here though. delete this in the end +public interface IJavaDocTagConstants { + + + /** Javadoc link tags */ + public static final String[] JAVADOC_LINK_TAGS= new String[] { "@docRoot", "@inheritDoc", "@link", "@linkplain" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + /** Javadoc parameter tags */ + public static final String[] JAVADOC_PARAM_TAGS= new String[] { "@exception", "@param", "@serialField", "@throws"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + /** Javadoc reference tags */ + public static final String[] JAVADOC_REFERENCE_TAGS= new String[] { "@see" }; //$NON-NLS-1$ + + /** Javadoc root tags */ + public static final String[] JAVADOC_ROOT_TAGS= new String[] { "@author", "@deprecated", "@return", "@see", "@serial", "@serialData", "@since", "@version", "@inheritDoc", "@category", "@value", "@literal", "@code", "@noinstantiate", "@noreference", "@noimplement", "@noextend", "@nooverride" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ + + /** Javadoc tag prefix */ + public static final char JAVADOC_TAG_PREFIX= '@'; +} Index: src/org/eclipse/ui/texteditor/spelling/correction/ISpellingCompletionProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/ISpellingCompletionProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/ISpellingCompletionProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/ISpellingCompletionProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; + +/** + * A completion proposal with a relevance value. + * The relevance value is used to sort the completion proposals. Proposals with higher relevance + * should be listed before proposals with lower relevance. + *

+ * This interface can be implemented by clients. + *

+ * + * @see org.eclipse.jface.text.contentassist.ICompletionProposal + * @since 2.1 + */ + +//TODO: copied from IJavaCompletionProposal +public interface ISpellingCompletionProposal extends ICompletionProposal { + + /** + * Returns the relevance of this completion proposal. + *

+ * The relevance is used to determine if this proposal is more + * relevant than another proposal.

+ * + * @return the relevance of this completion proposal in the range of [0, 100] + */ + int getRelevance(); + +} Index: src/org/eclipse/ui/texteditor/spelling/correction/JavaPluginImages.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/JavaPluginImages.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/JavaPluginImages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/JavaPluginImages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Ferenc Hechler, ferenc_hechler@users.sourceforge.net - 83258 [jar exporter] Deploy java application as executable jar + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; + +import org.osgi.framework.Bundle; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + + +/** + * Bundle of most images used by the Java plug-in. + */ +public class JavaPluginImages { + + public static final IPath ICONS_PATH= new Path("$nl$/icons/full"); //$NON-NLS-1$ + + private static final String NAME_PREFIX= "org.eclipse.jdt.ui."; //$NON-NLS-1$ + private static final int NAME_PREFIX_LENGTH= NAME_PREFIX.length(); + + // The plug-in registry + private static ImageRegistry fgImageRegistry= null; + private static HashMap fgAvoidSWTErrorMap= null; + + private static final String T_OBJ= "obj16"; //$NON-NLS-1$ + private static final String T_OVR= "ovr16"; //$NON-NLS-1$ + private static final String T_WIZBAN= "wizban"; //$NON-NLS-1$ + private static final String T_ELCL= "elcl16"; //$NON-NLS-1$ + private static final String T_DLCL= "dlcl16"; //$NON-NLS-1$ + private static final String T_ETOOL= "etool16"; //$NON-NLS-1$ + private static final String T_EVIEW= "eview16"; //$NON-NLS-1$ + + + // Keys for correction proposal. We have to put the image into the registry since "code assist" doesn't + // have a life cycle. So no chance to dispose icons. + + public static final String IMG_CORRECTION_CHANGE= NAME_PREFIX + "correction_change.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_MOVE= NAME_PREFIX + "correction_move.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_RENAME= NAME_PREFIX + "correction_rename.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_LINKED_RENAME= NAME_PREFIX + "correction_linked_rename.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_DELETE_IMPORT= NAME_PREFIX + "correction_delete_import.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_LOCAL= NAME_PREFIX + "localvariable_obj.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_REMOVE= NAME_PREFIX + "remove_correction.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_ADD= NAME_PREFIX + "add_correction.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_CAST= NAME_PREFIX + "correction_cast.gif"; //$NON-NLS-1$ + public static final String IMG_CORRECTION_MULTI_FIX= NAME_PREFIX + "correction_multi_fix.gif"; //$NON-NLS-1$ + + + public static final String IMG_OBJS_NLS_TRANSLATE= NAME_PREFIX + "translate.gif"; //$NON-NLS-1$ + public static final String IMG_OBJS_NLS_NEVER_TRANSLATE= NAME_PREFIX + "never_translate.gif"; //$NON-NLS-1$ + public static final String IMG_OBJS_NLS_SKIP= NAME_PREFIX + "skip.gif"; //$NON-NLS-1$ + + static { + createManagedFromKey(T_OBJ, IMG_CORRECTION_CHANGE); + createManagedFromKey(T_OBJ, IMG_CORRECTION_MOVE); + createManagedFromKey(T_OBJ, IMG_CORRECTION_RENAME); + createManagedFromKey(T_OBJ, IMG_CORRECTION_LINKED_RENAME); + createManagedFromKey(T_OBJ, IMG_CORRECTION_DELETE_IMPORT); + createManagedFromKey(T_OBJ, IMG_CORRECTION_LOCAL); + createManagedFromKey(T_OBJ, IMG_CORRECTION_REMOVE); + createManagedFromKey(T_OBJ, IMG_CORRECTION_ADD); + createManagedFromKey(T_OBJ, IMG_CORRECTION_CAST); + createManagedFromKey(T_OBJ, IMG_CORRECTION_MULTI_FIX); + } + + private static final class CachedImageDescriptor extends ImageDescriptor { + private ImageDescriptor fDescriptor; + private ImageData fData; + + public CachedImageDescriptor(ImageDescriptor descriptor) { + fDescriptor = descriptor; + } + + public ImageData getImageData() { + if (fData == null) { + fData= fDescriptor.getImageData(); + } + return fData; + } + } + + /** + * Returns the image managed under the given key in this registry. + * + * @param key the image's key + * @return the image managed under the given key + */ + public static Image get(String key) { + return getImageRegistry().get(key); + } + + /** + * Returns the image descriptor for the given key in this registry. Might be called in a non-UI thread. + * + * @param key the image's key + * @return the image descriptor for the given key + */ + public static ImageDescriptor getDescriptor(String key) { + if (fgImageRegistry == null) { + return (ImageDescriptor) fgAvoidSWTErrorMap.get(key); + } + return getImageRegistry().getDescriptor(key); + } + + /** + * Sets the three image descriptors for enabled, disabled, and hovered to an action. The actions + * are retrieved from the *tool16 folders. + * + * @param action the action + * @param iconName the icon name + */ + public static void setToolImageDescriptors(IAction action, String iconName) { + setImageDescriptors(action, "tool16", iconName); //$NON-NLS-1$ + } + + /** + * Sets the three image descriptors for enabled, disabled, and hovered to an action. The actions + * are retrieved from the *lcl16 folders. + * + * @param action the action + * @param iconName the icon name + */ + public static void setLocalImageDescriptors(IAction action, String iconName) { + setImageDescriptors(action, "lcl16", iconName); //$NON-NLS-1$ + } + + /* + * Helper method to access the image registry from the JavaPlugin class. + */ + /* package */ static ImageRegistry getImageRegistry() { + if (fgImageRegistry == null) { + fgImageRegistry= new ImageRegistry(); + for (Iterator iter= fgAvoidSWTErrorMap.keySet().iterator(); iter.hasNext();) { + String key= (String) iter.next(); + fgImageRegistry.put(key, (ImageDescriptor) fgAvoidSWTErrorMap.get(key)); + } + fgAvoidSWTErrorMap= null; + } + return fgImageRegistry; + } + + //---- Helper methods to access icons on the file system -------------------------------------- + + private static void setImageDescriptors(IAction action, String type, String relPath) { + ImageDescriptor id= create("d" + type, relPath, false); //$NON-NLS-1$ + if (id != null) + action.setDisabledImageDescriptor(id); + + /* + * id= create("c" + type, relPath, false); //$NON-NLS-1$ + * if (id != null) + * action.setHoverImageDescriptor(id); + */ + + ImageDescriptor descriptor= create("e" + type, relPath, true); //$NON-NLS-1$ + action.setHoverImageDescriptor(descriptor); + action.setImageDescriptor(descriptor); + } + + private static ImageDescriptor createManagedFromKey(String prefix, String key) { + return createManaged(prefix, key.substring(NAME_PREFIX_LENGTH), key); + } + + private static ImageDescriptor createManaged(String prefix, String name, String key) { + ImageDescriptor result= create(prefix, name, true); + + if (fgAvoidSWTErrorMap == null) { + fgAvoidSWTErrorMap= new HashMap(); + } + fgAvoidSWTErrorMap.put(key, result); + if (fgImageRegistry != null) { + TextEditorPlugin.logErrorMessage("Image registry already defined"); //$NON-NLS-1$ + } + return result; + } + + /* + * Creates an image descriptor for the given prefix and name in the JDT UI bundle. The path can + * contain variables like $NL$. + * If no image could be found, useMissingImageDescriptor decides if either + * the 'missing image descriptor' is returned or null. + * or null. + */ + private static ImageDescriptor create(String prefix, String name, boolean useMissingImageDescriptor) { + IPath path= ICONS_PATH.append(prefix).append(name); + return createImageDescriptor(TextEditorPlugin.getDefault().getBundle(), path, useMissingImageDescriptor); + } + + /* + * Creates an image descriptor for the given prefix and name in the JDT UI bundle. The path can + * contain variables like $NL$. + * If no image could be found, the 'missing image descriptor' is returned. + */ + private static ImageDescriptor createUnManaged(String prefix, String name) { + return create(prefix, name, true); + } + + /* + * Creates an image descriptor for the given prefix and name in the JDT UI bundle and let type descriptor cache the image data. + * If no image could be found, the 'missing image descriptor' is returned. + */ + private static ImageDescriptor createUnManagedCached(String prefix, String name) { + return new CachedImageDescriptor(create(prefix, name, true)); + } + + /* + * Creates an image descriptor for the given path in a bundle. The path can contain variables + * like $NL$. + * If no image could be found, useMissingImageDescriptor decides if either + * the 'missing image descriptor' is returned or null. + * Added for 3.1.1. + */ + public static ImageDescriptor createImageDescriptor(Bundle bundle, IPath path, boolean useMissingImageDescriptor) { + URL url= FileLocator.find(bundle, path, null); + if (url != null) { + return ImageDescriptor.createFromURL(url); + } + if (useMissingImageDescriptor) { + return ImageDescriptor.getMissingImageDescriptor(); + } + return null; + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/NoCompletionsProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/NoCompletionsProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/NoCompletionsProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/NoCompletionsProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; + +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +/** + * Proposal telling that there are no proposals available. + *

+ * Applying this proposal does nothing. + *

+ * + * @since 3.3 + */ +public final class NoCompletionsProposal implements ICompletionProposal { + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + */ + public void apply(IDocument document) { + // do nothing + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return SpellingMessages.NoCompletionsProposal_displayString; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() + */ + public Image getImage() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) + */ + public Point getSelection(IDocument document) { + return null; + } + +} Index: src/org/eclipse/ui/texteditor/spelling/correction/RankedWordProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/RankedWordProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/RankedWordProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/RankedWordProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +/** + * Ranked word proposal for quick fix and content assist. + * + * @since 3.0 + */ +public class RankedWordProposal implements Comparable { + + /** The word rank */ + private int fRank; + + /** The word text */ + private final String fText; + + /** + * Creates a new ranked word proposal. + * + * @param text + * The text of this proposal + * @param rank + * The rank of this proposal + */ + public RankedWordProposal(final String text, final int rank) { + fText= text; + fRank= rank; + } + + /* + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public final int compareTo(Object object) { + + final RankedWordProposal word= (RankedWordProposal)object; + final int rank= word.getRank(); + + if (fRank < rank) + return -1; + + if (fRank > rank) + return 1; + + return 0; + } + + /* + * @see java.lang.Object#equals(java.lang.Object) + */ + public final boolean equals(Object object) { + + if (object instanceof RankedWordProposal) + return object.hashCode() == hashCode(); + + return false; + } + + /** + * Returns the rank of the word + * + * @return The rank of the word + */ + public final int getRank() { + return fRank; + } + + /** + * Returns the text of this word. + * + * @return The text of this word + */ + public final String getText() { + return fText; + } + + /* + * @see java.lang.Object#hashCode() + */ + public final int hashCode() { + return fText.hashCode(); + } + + /** + * Sets the rank of the word. + * + * @param rank + * The rank to set + */ + public final void setRank(final int rank) { + fRank= rank; + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/SpellingCorrectionProcessor.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/SpellingCorrectionProcessor.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/SpellingCorrectionProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/SpellingCorrectionProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.correction; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; +import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.TextInvocationContext; + +import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; +import org.eclipse.ui.texteditor.spelling.SpellingProblem; + + + +/** + * Spelling correction processor used to show quick + * fixes for spelling problems. + * + * @since 3.3 + */ +public final class SpellingCorrectionProcessor implements IQuickAssistProcessor { + + + private static final ICompletionProposal[] fgNoSuggestionsProposal= new ICompletionProposal[] { new NoCompletionsProposal() }; + + + /* + * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) + */ + public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext quickAssistContext) { + ISourceViewer viewer= quickAssistContext.getSourceViewer(); + int documentOffset= quickAssistContext.getOffset(); + + int length= viewer != null ? viewer.getSelectedRange().y : -1; + TextInvocationContext context= new TextInvocationContext(viewer, documentOffset, length); + + + IAnnotationModel model= viewer.getAnnotationModel(); + if (model == null) + return fgNoSuggestionsProposal; + + List proposals= computeProposals(context, model); + if (proposals.isEmpty()) + return fgNoSuggestionsProposal; + + return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]); + } + + private boolean isAtPosition(int offset, Position pos) { + return (pos != null) && (offset >= pos.getOffset() && offset <= (pos.getOffset() + pos.getLength())); + } + + private List computeProposals(IQuickAssistInvocationContext context, IAnnotationModel model) { + int offset= context.getOffset(); + ArrayList annotationList= new ArrayList(); + Iterator iter= model.getAnnotationIterator(); + while (iter.hasNext()) { + Annotation annotation= (Annotation)iter.next(); + if (canFix(annotation)) { + Position pos= model.getPosition(annotation); + if (isAtPosition(offset, pos)) { + collectSpellingProblems(annotation, annotationList); + } + } + } + SpellingProblem[] spellingProblems= (SpellingProblem[]) annotationList.toArray(new SpellingProblem[annotationList.size()]); + return computeProposals(context, spellingProblems); + } + + private void collectSpellingProblems(Annotation annotation, List problems) { + if (annotation instanceof SpellingAnnotation) + problems.add(((SpellingAnnotation)annotation).getSpellingProblem()); + } + + private List computeProposals(IQuickAssistInvocationContext context, SpellingProblem[] spellingProblems) { + List proposals= new ArrayList(); + for (int i= 0; i < spellingProblems.length; i++) + proposals.addAll(Arrays.asList(spellingProblems[i].getProposals(context))); + + return proposals; + } + + /* + * @see IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return null; + } + + /* + * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canFix(org.eclipse.jface.text.source.Annotation) + */ + public boolean canFix(Annotation annotation) { + return annotation instanceof SpellingAnnotation && !annotation.isMarkedDeleted(); + } + + /* + * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canAssist(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext) + */ + public boolean canAssist(IQuickAssistInvocationContext invocationContext) { + return false; + } + +} Index: src/org/eclipse/ui/texteditor/spelling/correction/WordCorrectionProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/WordCorrectionProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/WordCorrectionProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/WordCorrectionProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; + +import org.eclipse.ui.internal.texteditor.spelling.Messages; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +/** + * Proposal to correct the incorrectly spelled word. + * + * @since 3.0 + */ +public class WordCorrectionProposal implements ISpellingCompletionProposal { + + /** + * Returns the html representation of the specified string. + * + * @param string + * The string to return the html representation for + * @return The html representation for the string + */ + public static String getHtmlRepresentation(final String string) { + + final int length= string.length(); + final StringBuffer buffer= new StringBuffer(string); + + for (int offset= length - 1; offset >= 0; offset--) { + + for (int index= 0; index < IHtmlTagConstants.HTML_ENTITY_CHARACTERS.length; index++) { + + if (string.charAt(offset) == IHtmlTagConstants.HTML_ENTITY_CHARACTERS[index]) { + + buffer.replace(offset, offset + 1, String.valueOf(IHtmlTagConstants.HTML_ENTITY_CODES[index])); + break; + } + } + } + return buffer.toString(); + } + + /** The invocation context */ + private final IQuickAssistInvocationContext fContext; + + /** The length in the document */ + private final int fLength; + + /** The line where to apply the correction */ + private final String fLine; + + /** The offset in the document */ + private final int fOffset; + + /** The relevance of this proposal */ + private final int fRelevance; + + /** The word to complete */ + private final String fWord; + + /** + * Creates a new word correction proposal. + * + * @param word the corrected word + * @param arguments the problem arguments associated with the spelling problem + * @param offset the offset in the document where to apply the proposal + * @param length the lenght in the document to apply the proposal + * @param context the invocation context for this proposal + * @param relevance the relevance of this proposal + */ + public WordCorrectionProposal(final String word, final String[] arguments, final int offset, final int length, final IQuickAssistInvocationContext context, final int relevance) { + + fWord= Character.isUpperCase(arguments[0].charAt(0)) ? Character.toUpperCase(word.charAt(0)) + word.substring(1) : word; + + fOffset= offset; + fLength= length; + fContext= context; + fRelevance= relevance; + + final StringBuffer buffer= new StringBuffer(80); + + buffer.append("...
"); //$NON-NLS-1$ + buffer.append(getHtmlRepresentation(arguments[1])); + buffer.append(""); //$NON-NLS-1$ + buffer.append(getHtmlRepresentation(fWord)); + buffer.append(""); //$NON-NLS-1$ + buffer.append(getHtmlRepresentation(arguments[2])); + buffer.append("
..."); //$NON-NLS-1$ + + fLine= buffer.toString(); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + */ + public final void apply(final IDocument document) { + try { + document.replace(fOffset, fLength, fWord); + } catch (BadLocationException exception) { + // Do nothing + } + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return fLine; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() + */ + public final IContextInformation getContextInformation() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return Messages.format(SpellingMessages.Spelling_correct_label, new String[] { fWord }); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() + */ + public Image getImage() { + return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME); + } + + /* + * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() + */ + public final int getRelevance() { + return fRelevance; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) + */ + public final Point getSelection(final IDocument document) { + + int offset= fContext.getOffset(); + int length= fContext.getLength(); + + final int delta= fWord.length() - fLength; + if (offset <= fOffset && offset + length >= fOffset) + length += delta; + else if (offset > fOffset && offset + length > fOffset + fLength) { + offset += delta; + length -= delta; + } else + length += delta; + + return new Point(offset, length); + } +} Index: src/org/eclipse/ui/texteditor/spelling/correction/WordIgnoreProposal.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/correction/WordIgnoreProposal.java diff -N src/org/eclipse/ui/texteditor/spelling/correction/WordIgnoreProposal.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/correction/WordIgnoreProposal.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.correction; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.internal.texteditor.spelling.Messages; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; + +import org.eclipse.ui.texteditor.spelling.SpellingProblem; +import org.eclipse.ui.texteditor.spelling.engine.ISpellCheckEngine; +import org.eclipse.ui.texteditor.spelling.engine.ISpellChecker; +import org.eclipse.ui.texteditor.spelling.engine.SpellCheckEngine; + +/** + * Proposal to ignore the word during the current editing session. + * + * @since 3.0 + */ +public class WordIgnoreProposal implements ISpellingCompletionProposal { + + /** The invocation context */ + private IQuickAssistInvocationContext fContext; + + /** The word to ignore */ + private String fWord; + + /** + * Creates a new spell ignore proposal. + * + * @param word + * The word to ignore + * @param context + * The invocation context + */ + public WordIgnoreProposal(final String word, final IQuickAssistInvocationContext context) { + fWord= word; + fContext= context; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + */ + public final void apply(final IDocument document) { + + final ISpellCheckEngine engine= SpellCheckEngine.getInstance(); + final ISpellChecker checker= engine.getSpellChecker(); + + if (checker != null) { + checker.ignoreWord(fWord); + ISourceViewer sourceViewer= fContext.getSourceViewer(); + if (sourceViewer != null) + SpellingProblem.removeAll(sourceViewer, fWord); + } + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return Messages.format(SpellingMessages.Spelling_ignore_info, new String[] { WordCorrectionProposal.getHtmlRepresentation(fWord) }); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() + */ + public final IContextInformation getContextInformation() { + return null; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return Messages.format(SpellingMessages.Spelling_ignore_label, new String[] { fWord }); + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() + */ + public Image getImage() { + return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE); + } + /* + * @see org.eclipse.jdt.ui.text.java.IJavaCompletionProposal#getRelevance() + */ + public final int getRelevance() { + return Integer.MIN_VALUE + 1; + } + + /* + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) + */ + public final Point getSelection(final IDocument document) { + return new Point(fContext.getOffset(), fContext.getLength()); + } +} Index: src/org/eclipse/ui/texteditor/spelling/engine/AbstractSpellDictionary.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/AbstractSpellDictionary.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/AbstractSpellDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/AbstractSpellDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,747 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.engine; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.MalformedInputException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.core.resources.ResourcesPlugin; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.internal.texteditor.spelling.Messages; +import org.eclipse.ui.internal.texteditor.spelling.SpellingMessages; +import org.eclipse.ui.internal.texteditor.spelling.engine.DefaultPhoneticDistanceAlgorithm; +import org.eclipse.ui.internal.texteditor.spelling.engine.DefaultPhoneticHashProvider; +import org.eclipse.ui.internal.texteditor.spelling.engine.IPhoneticDistanceAlgorithm; +import org.eclipse.ui.internal.texteditor.spelling.engine.IPhoneticHashProvider; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; +import org.eclipse.ui.texteditor.spelling.correction.RankedWordProposal; + +/** + * Partial implementation of a spell dictionary. + * + * @since 3.0 + */ +public abstract class AbstractSpellDictionary implements ISpellDictionary { + + /** + * Byte array wrapper + * @since 3.6 + */ + private static class ByteArrayWrapper { + + private static int hashCode(byte[] array) { + int prime= 31; + if (array == null) + return 0; + int result= 1; + for (int index= 0; index < array.length; index++) { + result= prime * result + array[index]; + } + return result; + } + + private byte[] byteArray; + + public ByteArrayWrapper(byte[] byteArray) { + this.byteArray= byteArray; + } + public int hashCode() { + final int prime= 31; + int result= 1; + result= prime * result + ByteArrayWrapper.hashCode(byteArray); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ByteArrayWrapper)) + return false; + ByteArrayWrapper other= (ByteArrayWrapper)obj; + if (!Arrays.equals(byteArray, other.byteArray)) + return false; + return true; + } + } + + + /** + * Canonical name for UTF-8 encoding + * @since 3.6 + */ + private static final String UTF_8= "UTF-8"; //$NON-NLS-1$ + + /** The bucket capacity */ + protected static final int BUCKET_CAPACITY= 4; + + /** The word buffer capacity */ + protected static final int BUFFER_CAPACITY= 32; + + /** The distance threshold */ + protected static final int DISTANCE_THRESHOLD= 160; + + /** + * The hash load factor + * @since 3.6 + */ + protected static final float LOAD_FACTOR= 0.85f; + + /** The phonetic distance algorithm */ + private IPhoneticDistanceAlgorithm fDistanceAlgorithm= new DefaultPhoneticDistanceAlgorithm(); + + /** The mapping from phonetic hashes to word lists */ + private final Map fHashBuckets= new HashMap(getInitialSize(), LOAD_FACTOR); + + /** The phonetic hash provider */ + private IPhoneticHashProvider fHashProvider= new DefaultPhoneticHashProvider(); + + /** Is the dictionary already loaded? */ + private boolean fLoaded= false; + /** + * Must the dictionary be loaded? + * @since 3.2 + */ + private boolean fMustLoad= true; + + /** + * Tells whether to strip non-letters at word boundaries. + * @since 3.3 + */ + boolean fIsStrippingNonLetters= true; + + /** + * Returns the initial size of dictionary. + * + * @return The initial size of dictionary. + * @since 3.6 + */ + protected int getInitialSize() { + return 32; + } + + /** + * Returns all candidates with the same phonetic hash. + * + * @param hash + * The hash to retrieve the candidates of + * @return Array of candidates for the phonetic hash + */ + protected final Object getCandidates(final String hash) { + ByteArrayWrapper hashBytes; + try { + hashBytes= new ByteArrayWrapper(hash.getBytes(UTF_8)); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return null; + } + return fHashBuckets.get(hashBytes); + } + + /** + * Returns all candidates that have a phonetic hash within a bounded + * distance to the specified word. + * + * @param word + * The word to find the nearest matches for + * @param sentence + * true iff the proposals start a new sentence, + * false otherwise + * @param hashs + * Array of close hashes to find the matches + * @return Set of ranked words with bounded distance to the specified word + */ + protected final Set getCandidates(final String word, final boolean sentence, final ArrayList hashs) { + + int distance= 0; + String hash= null; + + final StringBuffer buffer= new StringBuffer(BUFFER_CAPACITY); + final HashSet result= new HashSet(BUCKET_CAPACITY * hashs.size()); + + for (int index= 0; index < hashs.size(); index++) { + + hash= (String)hashs.get(index); + + final Object candidates= getCandidates(hash); + if (candidates == null) + continue; + else if (candidates instanceof byte[]) { + String candidate; + try { + candidate= new String((byte[])candidates, UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return result; + } + distance= fDistanceAlgorithm.getDistance(word, candidate); + if (distance < DISTANCE_THRESHOLD) { + buffer.setLength(0); + buffer.append(candidate); + if (sentence) + buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); + result.add(new RankedWordProposal(buffer.toString(), -distance)); + } + continue; + } + + final ArrayList candidateList= (ArrayList)candidates; + int candidateSize= Math.min(500, candidateList.size()); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=195357 + for (int offset= 0; offset < candidateSize; offset++) { + + String candidate; + try { + candidate= new String((byte[])candidateList.get(offset), UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return result; + } + distance= fDistanceAlgorithm.getDistance(word, candidate); + + if (distance < DISTANCE_THRESHOLD) { + + buffer.setLength(0); + buffer.append(candidate); + + if (sentence) + buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); + + result.add(new RankedWordProposal(buffer.toString(), -distance)); + } + } + } + return result; + } + + /** + * Returns all approximations that have a phonetic hash with smallest + * possible distance to the specified word. + * + * @param word + * The word to find the nearest matches for + * @param sentence + * true iff the proposals start a new sentence, + * false otherwise + * @param result + * Set of ranked words with smallest possible distance to the + * specified word + */ + protected final void getCandidates(final String word, final boolean sentence, final Set result) { + + int distance= 0; + int minimum= Integer.MAX_VALUE; + + StringBuffer buffer= new StringBuffer(BUFFER_CAPACITY); + + final Object candidates= getCandidates(fHashProvider.getHash(word)); + if (candidates == null) + return; + else if (candidates instanceof byte[]) { + String candidate; + try { + candidate= new String((byte[])candidates, UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return; + } + distance= fDistanceAlgorithm.getDistance(word, candidate); + buffer.append(candidate); + if (sentence) + buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); + result.add(new RankedWordProposal(buffer.toString(), -distance)); + return; + } + + final ArrayList candidateList= (ArrayList)candidates; + final ArrayList matches= new ArrayList(candidateList.size()); + + for (int index= 0; index < candidateList.size(); index++) { + String candidate; + try { + candidate= new String((byte[])candidateList.get(index), UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return; + } + distance= fDistanceAlgorithm.getDistance(word, candidate); + + if (distance <= minimum) { + + if (distance < minimum) + matches.clear(); + + buffer.setLength(0); + buffer.append(candidate); + + if (sentence) + buffer.setCharAt(0, Character.toUpperCase(buffer.charAt(0))); + + matches.add(new RankedWordProposal(buffer.toString(), -distance)); + minimum= distance; + } + } + + result.addAll(matches); + } + + /** + * Tells whether this dictionary is empty. + * + * @return true if this dictionary is empty + * @since 3.3 + */ + protected boolean isEmpty() { + return fHashBuckets.size() == 0; + } + + /** + * Returns the used phonetic distance algorithm. + * + * @return The phonetic distance algorithm + */ + protected final IPhoneticDistanceAlgorithm getDistanceAlgorithm() { + return fDistanceAlgorithm; + } + + /** + * Returns the used phonetic hash provider. + * + * @return The phonetic hash provider + */ + protected final IPhoneticHashProvider getHashProvider() { + return fHashProvider; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#getProposals(java.lang.String,boolean) + */ + public Set getProposals(final String word, final boolean sentence) { + + try { + + if (!fLoaded) { + synchronized (this) { + fLoaded= load(getURL()); + if (fLoaded) + compact(); + } + } + + } catch (MalformedURLException exception) { + // Do nothing + } + + final String hash= fHashProvider.getHash(word); + final char[] mutators= fHashProvider.getMutators(); + + final ArrayList neighborhood= new ArrayList((word.length() + 1) * (mutators.length + 2)); + neighborhood.add(hash); + + final Set candidates= getCandidates(word, sentence, neighborhood); + neighborhood.clear(); + + char previous= 0; + char next= 0; + + char[] characters= word.toCharArray(); + for (int index= 0; index < word.length() - 1; index++) { + + next= characters[index]; + previous= characters[index + 1]; + + characters[index]= previous; + characters[index + 1]= next; + + neighborhood.add(fHashProvider.getHash(new String(characters))); + + characters[index]= next; + characters[index + 1]= previous; + } + + final String sentinel= word + " "; //$NON-NLS-1$ + + characters= sentinel.toCharArray(); + int offset= characters.length - 1; + + while (true) { + + for (int index= 0; index < mutators.length; index++) { + + characters[offset]= mutators[index]; + neighborhood.add(fHashProvider.getHash(new String(characters))); + } + + if (offset == 0) + break; + + characters[offset]= characters[offset - 1]; + --offset; + } + + char mutated= 0; + characters= word.toCharArray(); + + for (int index= 0; index < word.length(); index++) { + + mutated= characters[index]; + for (int mutator= 0; mutator < mutators.length; mutator++) { + + characters[index]= mutators[mutator]; + neighborhood.add(fHashProvider.getHash(new String(characters))); + } + characters[index]= mutated; + } + + characters= word.toCharArray(); + final char[] deleted= new char[characters.length - 1]; + + for (int index= 0; index < deleted.length; index++) + deleted[index]= characters[index]; + + next= characters[characters.length - 1]; + offset= deleted.length; + + while (true) { + + neighborhood.add(fHashProvider.getHash(new String(characters))); + if (offset == 0) + break; + + previous= next; + next= deleted[offset - 1]; + + deleted[offset - 1]= previous; + --offset; + } + + neighborhood.remove(hash); + final Set matches= getCandidates(word, sentence, neighborhood); + + if (matches.size() == 0 && candidates.size() == 0) + getCandidates(word, sentence, candidates); + + candidates.addAll(matches); + + return candidates; + } + + /** + * Returns the URL of the dictionary word list. + * + * @throws MalformedURLException + * if the URL could not be retrieved + * @return The URL of the dictionary word list + */ + protected abstract URL getURL() throws MalformedURLException; + + /** + * Hashes the word into the dictionary. + * + * @param word + * The word to hash in the dictionary + */ + protected final void hashWord(final String word) { + + final String hash= fHashProvider.getHash(word); + ByteArrayWrapper hashBytes; + byte[] wordBytes; + try { + hashBytes= new ByteArrayWrapper(hash.getBytes(UTF_8)); + wordBytes= word.getBytes(UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return; + } + + Object bucket= fHashBuckets.get(hashBytes); + + if (bucket == null) { + fHashBuckets.put(hashBytes, wordBytes); + } else if (bucket instanceof ArrayList) { + ((ArrayList)bucket).add(wordBytes); + } else { + ArrayList list= new ArrayList(BUCKET_CAPACITY); + list.add(bucket); + list.add(wordBytes); + fHashBuckets.put(hashBytes, list); + } + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) + */ + public boolean isCorrect(String word) { + word= stripNonLetters(word); + try { + + if (!fLoaded) { + synchronized (this) { + fLoaded= load(getURL()); + if (fLoaded) + compact(); + } + } + + } catch (MalformedURLException exception) { + // Do nothing + } + + final Object candidates= getCandidates(fHashProvider.getHash(word)); + if (candidates == null) + return false; + else if (candidates instanceof byte[]) { + String candidate; + try { + candidate= new String((byte[])candidates, UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return false; + } + if (candidate.equals(word) || candidate.equals(word.toLowerCase())) + return true; + return false; + } + final ArrayList candidateList= (ArrayList)candidates; + byte[] wordBytes; + byte[] lowercaseWordBytes; + try { + wordBytes= word.getBytes(UTF_8); + lowercaseWordBytes= word.toLowerCase().getBytes(UTF_8); + } catch (UnsupportedEncodingException e) { + TextEditorPlugin.log(e); + return false; + } + for (int index= 0; index < candidateList.size(); index++) { + byte[] candidate= (byte[])candidateList.get(index); + if (Arrays.equals(candidate, wordBytes) || Arrays.equals(candidate, lowercaseWordBytes)) { + return true; + } + } + return false; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#setStripNonLetters(boolean) + * @since 3.3 + */ + public void setStripNonLetters(boolean state) { + fIsStrippingNonLetters= state; + } + + /** + * Strips non-letter characters from the given word. + *

+ * This will only happen if the corresponding preference is enabled. + *

+ * + * @param word the word to strip + * @return the stripped word + * @since 3.3 + */ + protected String stripNonLetters(String word) { + if (!fIsStrippingNonLetters) + return word; + + int i= 0; + int j= word.length() - 1; + while (i <= j && !Character.isLetter(word.charAt(i))) + i++; + if (i > j) + return ""; //$NON-NLS-1$ + + while (j > i && !Character.isLetter(word.charAt(j))) + j--; + + return word.substring(i, j+1); + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#isLoaded() + */ + public synchronized final boolean isLoaded() { + return fLoaded || fHashBuckets.size() > 0; + } + + /** + * Loads a dictionary word list from disk. + * + * @param url + * The URL of the word list to load + * @return true iff the word list could be loaded, false + * otherwise + */ + protected synchronized boolean load(final URL url) { + if (!fMustLoad) + return fLoaded; + + if (url != null) { + InputStream stream= null; + int line= 0; + try { + stream= url.openStream(); + if (stream != null) { + String word= null; + + // Setup a reader with a decoder in order to read over malformed input if needed. + CharsetDecoder decoder= Charset.forName(getEncoding()).newDecoder(); + decoder.onMalformedInput(CodingErrorAction.REPORT); + decoder.onUnmappableCharacter(CodingErrorAction.REPORT); + final BufferedReader reader= new BufferedReader(new InputStreamReader(stream, decoder)); + + boolean doRead= true; + while (doRead) { + try { + word= reader.readLine(); + } catch (MalformedInputException ex) { + // Tell the decoder to replace malformed input in order to read the line. + decoder.onMalformedInput(CodingErrorAction.REPLACE); + decoder.reset(); + word= reader.readLine(); + decoder.onMalformedInput(CodingErrorAction.REPORT); + + String message= Messages.format(SpellingMessages.AbstractSpellingDictionary_encodingError, + new String[] { word, decoder.replacement(), BasicElementLabels.getURLPart(url.toString()) }); + IStatus status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, message, ex); + TextEditorPlugin.log(status); + + doRead= word != null; + continue; + } + doRead= word != null; + if (doRead) + hashWord(word); + } + return true; + } + } catch (FileNotFoundException ex) { + String urlString= url.toString(); + String lowercaseUrlString= urlString.toLowerCase(); + if (urlString.equals(lowercaseUrlString)) + TextEditorPlugin.log(ex); + else + try { + return load(new URL(lowercaseUrlString)); + } catch (MalformedURLException e) { + TextEditorPlugin.log(e); + } + } catch (IOException exception) { + if (line > 0) { + String message= Messages.format(SpellingMessages.AbstractSpellingDictionary_encodingError, new Object[] { new Integer(line), BasicElementLabels.getURLPart(url.toString()) }); + IStatus status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, message, exception); + TextEditorPlugin.log(status); + } else + TextEditorPlugin.log(exception); + } finally { + fMustLoad= false; + try { + if (stream != null) + stream.close(); + } catch (IOException x) { + } + } + } + return false; + } + + /** + * Compacts the dictionary. + * + * @since 3.3. + */ + private void compact() { + Iterator iter= fHashBuckets.values().iterator(); + while (iter.hasNext()) { + Object element= iter.next(); + if (element instanceof ArrayList) + ((ArrayList)element).trimToSize(); + } + } + + /** + * Sets the phonetic distance algorithm to use. + * + * @param algorithm + * The phonetic distance algorithm + */ + protected final void setDistanceAlgorithm(final IPhoneticDistanceAlgorithm algorithm) { + fDistanceAlgorithm= algorithm; + } + + /** + * Sets the phonetic hash provider to use. + * + * @param provider + * The phonetic hash provider + */ + protected final void setHashProvider(final IPhoneticHashProvider provider) { + fHashProvider= provider; + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#unload() + */ + public synchronized void unload() { + fLoaded= false; + fMustLoad= true; + fHashBuckets.clear(); + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary#acceptsWords() + */ + public boolean acceptsWords() { + return false; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String) + */ + public void addWord(final String word) { + // Do nothing + } + + /** + * Returns the encoding of this dictionary. + * + * @return the encoding of this dictionary + * @since 3.3 + */ + protected String getEncoding() { + String encoding= TextEditorPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING); + if (encoding == null || encoding.length() == 0) + encoding= ResourcesPlugin.getEncoding(); + return encoding; + } + +} Index: src/org/eclipse/ui/texteditor/spelling/engine/BasicElementLabels.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/BasicElementLabels.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/BasicElementLabels.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/BasicElementLabels.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.engine; + +import java.io.File; + +import org.eclipse.osgi.util.TextProcessor; + +import org.eclipse.core.runtime.IPath; + +import org.eclipse.core.resources.IResource; + + +/** + * A label provider for basic elements like paths. The label provider will make sure that the labels are correctly + * shown in RTL environments. + * + * @since 3.4 + */ + +//XXX duplicated from org.eclipse.jdt.internal.junit.BasicElementLabels +public class BasicElementLabels { + + private BasicElementLabels() { + } + + /** + * Adds special marks so that that the given string is readable in a BIDI environment. + * + * @param string the string + * @param delimiters the additional delimiters + * @return the processed styled string + */ + private static String markLTR(String string, String delimiters) { + return TextProcessor.process(string, delimiters); + } + + /** + * Returns the label of a path. + * + * @param path the path + * @param isOSPath if true, the path represents an OS path, if false it is a workspace path. + * @return the label of the path to be used in the UI. + */ + public static String getPathLabel(IPath path, boolean isOSPath) { + String label; + if (isOSPath) { + label= path.toOSString(); + } else { + label= path.makeRelative().toString(); + } + return markLTR(label, "/\\:."); //$NON-NLS-1$ + } + + /** + * Returns the label of the path of a file. + * + * @param file the file + * @return the label of the file path to be used in the UI. + */ + public static String getPathLabel(File file) { + return markLTR(file.getAbsolutePath(), "/\\:."); //$NON-NLS-1$ + } + + /** + * Returns the label for a file pattern like '*.java' + * + * @param name the pattern + * @return the label of the pattern. + */ + public static String getFilePattern(String name) { + return markLTR(name, "*.?/\\:."); //$NON-NLS-1$ + } + + /** + * Returns the label for a URL, URI or URL part. Example is 'http://www.x.xom/s.html#1' + * + * @param name the URL string + * @return the label of the URL. + */ + public static String getURLPart(String name) { + return markLTR(name, ":@?-#/\\:."); //$NON-NLS-1$ + } + + /** + * Returns a label for a resource name. + * + * @param resource the resource + * @return the label of the resource name. + */ + public static String getResourceName(IResource resource) { + return markLTR(resource.getName(), ":."); //$NON-NLS-1$ + } + + /** + * Returns a label for a resource name. + * + * @param resourceName the resource name + * @return the label of the resource name. + */ + public static String getResourceName(String resourceName) { + return markLTR(resourceName, ":."); //$NON-NLS-1$ + } + + /** + * Returns a label for a version name. Example is '1.4.1' + * + * @param name the version string + * @return the version label + */ + public static String getVersionName(String name) { + return markLTR(name, ":."); //$NON-NLS-1$ + } + + + /** + * Returns a label for Java element name. Example is 'new Test() { ...}'. This + * method should only be used for simple element names. Use JavaElementLabels to create a label + * from a Java element. + * + * @param name the Java element name. + * @return the label for the Java element + */ + public static String getJavaElementName(String name) { + return markLTR(name, "<>()?,{}.:"); //$NON-NLS-1$ + } +} Index: src/org/eclipse/ui/texteditor/spelling/engine/HtmlTagDictionary.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/HtmlTagDictionary.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/HtmlTagDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/HtmlTagDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.net.URL; + +import org.eclipse.ui.texteditor.spelling.correction.IHtmlTagConstants; + +/** + * Dictionary for html tags. + * + * @since 3.0 + */ +public class HtmlTagDictionary extends AbstractSpellDictionary { + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName() + */ + protected final URL getURL() { + return null; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) + */ + public boolean isCorrect(final String word) { + + if (word.charAt(0) == IHtmlTagConstants.HTML_TAG_PREFIX) + return super.isCorrect(word); + + return false; + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL) + */ + protected synchronized boolean load(final URL url) { + + unload(); + + for (int index= 0; index < IHtmlTagConstants.HTML_GENERAL_TAGS.length; index++) { + + hashWord(IHtmlTagConstants.HTML_TAG_PREFIX + IHtmlTagConstants.HTML_GENERAL_TAGS[index] + IHtmlTagConstants.HTML_TAG_POSTFIX); + hashWord(IHtmlTagConstants.HTML_CLOSE_PREFIX + IHtmlTagConstants.HTML_GENERAL_TAGS[index] + IHtmlTagConstants.HTML_TAG_POSTFIX); + } + return true; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#stripNonLetters(java.lang.String) + * @since 3.3 + */ + protected String stripNonLetters(String word) { + return word; + } + +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckEngine.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckEngine.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.util.Locale; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; + + +/** + * Interface for a spell check engine. + *

+ * This engine can be configured with multiple + * dictionaries. + *

+ * + * @since 3.0 + */ +public interface ISpellCheckEngine { + + /** + * Returns a spell checker configured with the global + * dictionaries and the locale dictionary that correspond to the current + * {@linkplain PreferenceConstants#SPELLING_LOCALE locale preference}. + *

+ * Note: Changes to the spelling engine dictionaries + * are not propagated to this spell checker.

+ * + * @return a configured instance of the spell checker or null if none + * @throws IllegalStateException if called after being shut down + */ + ISpellChecker getSpellChecker() throws IllegalStateException; + + /** + * Returns the locale of the current spell check engine. + * + * @return the locale of the current spell check engine + */ + Locale getLocale(); + + /** + * Registers a global dictionary. + * + * @param dictionary the global dictionary to register + */ + void registerGlobalDictionary(ISpellDictionary dictionary); + + /** + * Registers a dictionary tuned for the specified locale with this engine. + * + * @param locale + * The locale to register the dictionary with + * @param dictionary + * The dictionary to register + */ + void registerDictionary(Locale locale, ISpellDictionary dictionary); + + /** + * Shuts down this spell check engine and its associated components. + *

+ * Further calls to this engine result in exceptions. + *

+ */ + void shutdown(); + + /** + * Unregisters a dictionary previously registered either by a call to + * registerDictionary(Locale,ISpellDictionary) or registerDictionary(ISpellDictionary). + *

+ * If the dictionary was not registered before, nothing happens.

+ * + * @param dictionary the dictionary to unregister + */ + void unregisterDictionary(ISpellDictionary dictionary); + +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckIterator.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckIterator.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckIterator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellCheckIterator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.util.Iterator; + +/** + * Interface for iterators used for spell checking. + * + * @since 3.0 + */ +public interface ISpellCheckIterator extends Iterator { + + /** + * Returns the begin index (inclusive) of the current word. + * + * @return The begin index of the current word + */ + public int getBegin(); + + /** + * Returns the end index (exclusive) of the current word. + * + * @return The end index of the current word + */ + public int getEnd(); + + /** + * Does the current word start a new sentence? + * + * @return true iff the current word starts a new sentence, false otherwise + */ + public boolean startsSentence(); + + /** + * Tells whether to ignore single letters + * from being checked. + * + * @since 3.3 + * @param state true if single letters should be ignored + */ + public void setIgnoreSingleLetters(boolean state); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellChecker.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellChecker.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellChecker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellChecker.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.util.Locale; +import java.util.Set; + + +/** + * Interface for spell checkers. + * + * @since 3.0 + */ +public interface ISpellChecker { + + /** + * Adds a dictionary to the list of active dictionaries. + * + * @param dictionary + * The dictionary to add + */ + void addDictionary(ISpellDictionary dictionary); + + /** + * Returns whether this spell checker accepts word additions. + * + * @return true if word additions are accepted, false otherwise + */ + boolean acceptsWords(); + + /** + * Adds the specified word to the set of correct words. + * + * @param word + * The word to add to the set of correct words + */ + void addWord(String word); + + /** + * Checks the specified word until calling ignoreWord(String). + * + * @param word + * The word to check + */ + void checkWord(String word); + + /** + * Checks the spelling with the spell check iterator. Implementations must + * be thread safe as this may be called inside a reconciler thread. + * + * @param listener the spell event listener + * @param iterator the iterator to use for spell checking + */ + void execute(ISpellEventListener listener, ISpellCheckIterator iterator); + + /** + * Returns the ranked proposals for a word. + * + * @param word + * The word to retrieve the proposals for + * @param sentence + * true iff the proposals should start a + * sentence, false otherwise + * @return Set of ranked proposals for the word + */ + Set getProposals(String word, boolean sentence); + + /** + * Ignores the specified word until calling checkWord(String). + * + * @param word + * The word to ignore + */ + void ignoreWord(String word); + + /** + * Is the specified word correctly spelled? Implementations must be thread + * safe as this may be called from within a reconciler thread. + * + * @param word + * The word to check its spelling + * @return true iff the word is correctly spelled, false + * otherwise + */ + boolean isCorrect(String word); + + /** + * Remove a dictionary from the list of active dictionaries. + * + * @param dictionary + * The dictionary to remove + */ + void removeDictionary(ISpellDictionary dictionary); + + /** + * Returns the current locale of the spell check engine. + * + * @return The current locale of the engine + * @since 3.3 + */ + Locale getLocale(); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellDictionary.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellDictionary.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.util.Set; + +/** + * Interface of dictionaries to use for spell checking. + * + * @since 3.0 + */ +public interface ISpellDictionary { + + /** + * Returns whether this dictionary accepts new words. + * + * @return true if this dictionary accepts new words, false otherwise + */ + public boolean acceptsWords(); + + /** + * Externalizes the specified word. + * + * @param word + * The word to externalize in the dictionary + */ + public void addWord(String word); + + /** + * Returns the ranked word proposals for an incorrectly spelled word. + * + * @param word + * The word to retrieve the proposals for + * @param sentence + * true iff the proposals start a new sentence, + * false otherwise + * @return Array of ranked word proposals + */ + public Set getProposals(String word, boolean sentence); + + /** + * Is the specified word correctly spelled? + * + * @param word the word to spell check + * @return true iff this word is correctly spelled, false otherwise + */ + public boolean isCorrect(String word); + + /** + * Is the dictionary loaded? + * + * @return true iff it is loaded, false otherwise + */ + public boolean isLoaded(); + + /** + * Empties the dictionary. + */ + public void unload(); + + /** + * Tells whether to strip non-letters from word boundaries. + * + * @param state true if non-letters should be stripped + * @since 3.3 + */ + public void setStripNonLetters(boolean state); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellEvent.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellEvent.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import java.util.Set; + +/** + * Event fired by spell checkers. + * + * @since 3.0 + */ +public interface ISpellEvent { + + /** + * Returns the begin index of the incorrectly spelled word. + * + * @return The begin index of the word + */ + public int getBegin(); + + /** + * Returns the end index of the incorrectly spelled word. + * + * @return The end index of the word + */ + public int getEnd(); + + /** + * Returns the proposals for the incorrectly spelled word. + * + * @return Array of proposals for the word + */ + public Set getProposals(); + + /** + * Returns the incorrectly spelled word. + * + * @return The incorrect word + */ + public String getWord(); + + /** + * Was the incorrectly spelled word found in the dictionary? + * + * @return true iff the word was found, false otherwise + */ + public boolean isMatch(); + + /** + * Does the incorrectly spelled word start a new sentence? + * + * @return true iff the word starts a new sentence, false otherwise + */ + public boolean isStart(); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellEventListener.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellEventListener.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellEventListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellEventListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + + + +/** + * Interface for spell event listeners. + * + * @since 3.0 + */ +public interface ISpellEventListener { + + /** + * Handles a spell event. + * + * @param event + * Event to handle + */ + public void handle(ISpellEvent event); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/ISpellingEngine.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/ISpellingEngine.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/ISpellingEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/ISpellingEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.texteditor.spelling.engine; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; + +import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; +import org.eclipse.ui.texteditor.spelling.SpellingContext; + +/** + * A spelling engine that can be contributed to the + * org.eclipse.ui.workbench.texteditor.spellingEngine extension + * point. The SpellingContext provides information about the + * content type to be checked. In general a spelling engine should at least + * support the text {@link org.eclipse.core.runtime.content.IContentType content type}. + *

+ * This interface is intended to be implemented by clients. + *

+ * + * @since 3.1 + */ +public interface ISpellingEngine { + + /** + * Checks the given regions in the given document. Reports all found + * spelling problems to the collector. + * + * @param document the document to check + * @param regions the regions to check + * @param context the context + * @param collector the problem collector + * @param monitor the progress monitor, can be null + */ + public void check(IDocument document, IRegion[] regions, SpellingContext context, ISpellingProblemCollector collector, IProgressMonitor monitor); +} Index: src/org/eclipse/ui/texteditor/spelling/engine/JavaDocTagDictionary.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/JavaDocTagDictionary.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/JavaDocTagDictionary.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/JavaDocTagDictionary.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.engine; + +import java.net.URL; + +import org.eclipse.ui.texteditor.spelling.correction.IJavaDocTagConstants; + + + +/** + * Dictionary for Javadoc tags. + * + * @since 3.0 + */ +public class JavaDocTagDictionary extends AbstractSpellDictionary implements IJavaDocTagConstants { + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName() + */ + protected final URL getURL() { + return null; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary#isCorrect(java.lang.String) + */ + public boolean isCorrect(final String word) { + + if (word.charAt(0) == JAVADOC_TAG_PREFIX) + return super.isCorrect(word); + + return false; + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL) + */ + protected synchronized boolean load(final URL url) { + + unload(); + + for (int index= 0; index < JAVADOC_LINK_TAGS.length; index++) + hashWord(JAVADOC_LINK_TAGS[index]); + + for (int index= 0; index < JAVADOC_ROOT_TAGS.length; index++) + hashWord(JAVADOC_ROOT_TAGS[index]); + + for (int index= 0; index < JAVADOC_PARAM_TAGS.length; index++) + hashWord(JAVADOC_PARAM_TAGS[index]); + + return true; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#stripNonLetters(java.lang.String) + * @since 3.3 + */ + protected String stripNonLetters(String word) { + return word; + } + +} Index: src/org/eclipse/ui/texteditor/spelling/engine/SpellCheckEngine.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/SpellCheckEngine.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/SpellCheckEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/SpellCheckEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,498 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.engine; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.core.runtime.FileLocator; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; +import org.eclipse.ui.internal.texteditor.spelling.engine.DefaultSpellChecker; +import org.eclipse.ui.internal.texteditor.spelling.engine.LocaleSensitiveSpellDictionary; +import org.eclipse.ui.internal.texteditor.spelling.engine.PersistentSpellDictionary; + +import org.eclipse.ui.texteditor.spelling.PreferenceConstants; +import org.eclipse.ui.texteditor.spelling.SpellingService; + + +/** + * Spell check engine for Java source spell checking. + * + * @since 3.0 + */ +public class SpellCheckEngine implements ISpellCheckEngine, IPropertyChangeListener { + + /** The dictionary location */ + public static final String DICTIONARY_LOCATION= "dictionaries/"; //$NON-NLS-1$ + + /** The singleton engine instance */ + private static ISpellCheckEngine fgEngine= null; + + /** + * Caches the locales of installed dictionaries. + * + * @since 3.3 + */ + private static Set fgLocalesWithInstalledDictionaries; + + /** + * Returns the locales for which this + * spell check engine has dictionaries in certain location. + * + * @param location dictionaries location + * @return The available locales for this engine + */ + private static Set getLocalesWithInstalledDictionaries(URL location) { + String[] fileNames; + try { + URL url= FileLocator.toFileURL(location); + File file= new File(url.getFile()); + if (!file.isDirectory()) + return Collections.EMPTY_SET; + fileNames= file.list(); + if (fileNames == null) + return Collections.EMPTY_SET; + } catch (IOException ex) { + TextEditorPlugin.log(ex); + return Collections.EMPTY_SET; + } + + Set localesWithInstalledDictionaries= new HashSet(); + int fileNameCount= fileNames.length; + for (int i= 0; i < fileNameCount; i++) { + String fileName= fileNames[i]; + int localeEnd= fileName.indexOf(".dictionary"); //$NON-NLS-1$ + if (localeEnd > 1) { + String localeName= fileName.substring(0, localeEnd); + int languageEnd=localeName.indexOf('_'); + if (languageEnd == -1) + localesWithInstalledDictionaries.add(new Locale(localeName)); + else if (languageEnd == 2 && localeName.length() == 5) + localesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3))); + else if (localeName.length() > 6 && localeName.charAt(5) == '_') + localesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3, 5), localeName.substring(6))); + } + } + + return localesWithInstalledDictionaries; + } + + + /** + * Returns the locales for which this + * spell check engine has dictionaries. + * + * @return The available locales for this engine + */ + public static Set getLocalesWithInstalledDictionaries() { + if (fgLocalesWithInstalledDictionaries != null) + return fgLocalesWithInstalledDictionaries; + + Enumeration locations; + try { + locations= getDictionaryLocations(); + if (locations == null) + return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET; + } catch (IOException ex) { + TextEditorPlugin.log(ex); + return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET; + } + + fgLocalesWithInstalledDictionaries= new HashSet(); + + while (locations.hasMoreElements()) { + URL location= (URL) locations.nextElement(); + Set locales= getLocalesWithInstalledDictionaries(location); + fgLocalesWithInstalledDictionaries.addAll(locales); + } + + return fgLocalesWithInstalledDictionaries; + } + + /** + * Returns the default locale for this engine. + * + * @return The default locale + */ + public static Locale getDefaultLocale() { + return Locale.getDefault(); + } + + /** + * Returns the dictionary closest to the given locale. + * + * @param locale the locale + * @return the dictionary or null if none is suitable + * @since 3.3 + */ + public ISpellDictionary findDictionary(Locale locale) { + ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(locale); + if (dictionary != null) + return dictionary; + + // Try same language + String language= locale.getLanguage(); + Iterator iter= fLocaleDictionaries.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry= (Entry)iter.next(); + Locale dictLocale= (Locale)entry.getKey(); + if (dictLocale.getLanguage().equals(language)) + return (ISpellDictionary)entry.getValue(); + } + + return null; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#findDictionary(java.util.Locale) + * @since 3.3 + */ + public static Locale findClosestLocale(Locale locale) { + if (locale == null || locale.toString().length() == 0) + return locale; + + if (getLocalesWithInstalledDictionaries().contains(locale)) + return locale; + + // Try same language + String language= locale.getLanguage(); + Iterator iter= getLocalesWithInstalledDictionaries().iterator(); + while (iter.hasNext()) { + Locale dictLocale= (Locale)iter.next(); + if (dictLocale.getLanguage().equals(language)) + return dictLocale; + } + + // Try whether American English is present + Locale defaultLocale= Locale.US; + if (getLocalesWithInstalledDictionaries().contains(defaultLocale)) + return defaultLocale; + + return null; + } + + /** + * Returns the enumeration of URLs for the dictionary locations where + * the Platform dictionaries are located. + *

+ * This is in org.eclipse.jdt.ui/dictionaries/ + * which can also be populated via fragments. + *

+ * + * @throws IOException if there is an I/O error + * @return The dictionary locations, or null iff the locations are not known + */ + public static Enumeration getDictionaryLocations() throws IOException { + final TextEditorPlugin plugin= TextEditorPlugin.getDefault(); + if (plugin != null) + return plugin.getBundle().getResources("/" + DICTIONARY_LOCATION); //$NON-NLS-1$ + return null; + } + + /** + * Returns the singleton instance of the spell check engine. + * + * @return The singleton instance of the spell check engine + */ + public static synchronized final ISpellCheckEngine getInstance() { + + if (fgEngine == null) + fgEngine= new SpellCheckEngine(); + + return fgEngine; + } + + /** + * Shuts down the singleton instance of the spell check engine. + */ + public static synchronized final void shutdownInstance() { + if (fgEngine != null) { + fgEngine.shutdown(); + fgEngine= null; + } + } + + /** The registered locale insensitive dictionaries */ + private Set fGlobalDictionaries= new HashSet(); + + /** The spell checker for fLocale */ + private ISpellChecker fChecker= null; + + /** The registered locale sensitive dictionaries */ + private Map fLocaleDictionaries= new HashMap(); + + /** The user dictionary */ + private ISpellDictionary fUserDictionary= null; + + /** + * Creates a new spell check manager. + */ + private SpellCheckEngine() { + + //TODO : fix this + //fGlobalDictionaries.add(new TaskTagDictionary()); + fGlobalDictionaries.add(new HtmlTagDictionary()); + fGlobalDictionaries.add(new JavaDocTagDictionary()); + + try { + + Locale locale= null; + final Enumeration locations= getDictionaryLocations(); + + while (locations != null && locations.hasMoreElements()) { + URL location= (URL)locations.nextElement(); + + for (final Iterator iterator= getLocalesWithInstalledDictionaries(location).iterator(); iterator.hasNext();) { + + locale= (Locale)iterator.next(); + fLocaleDictionaries.put(locale, new LocaleSensitiveSpellDictionary(locale, location)); + } + } + + } catch (IOException exception) { + // Do nothing + } + + TextEditorPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); + TextEditorPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); //TODO : is this good? + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#getSpellChecker() + */ + public synchronized final ISpellChecker getSpellChecker() throws IllegalStateException { + if (fGlobalDictionaries == null) + throw new IllegalStateException("spell checker has been shut down"); //$NON-NLS-1$ + + IPreferenceStore store= TextEditorPlugin.getDefault().getPreferenceStore(); + Locale locale= getCurrentLocale(store); + locale= Locale.US; + //TODO: user dictionary + if (/*fUserDictionary == null &&*/"".equals(locale.toString())) //$NON-NLS-1$ + return null; + + if (fChecker != null && fChecker.getLocale().equals(locale)) + return fChecker; + + resetSpellChecker(); + + fChecker= new DefaultSpellChecker(store, locale); + resetUserDictionary(); + + for (Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { + ISpellDictionary dictionary= (ISpellDictionary)iterator.next(); + fChecker.addDictionary(dictionary); + } + + ISpellDictionary dictionary= findDictionary(fChecker.getLocale()); + if (dictionary != null) + fChecker.addDictionary(dictionary); + + return fChecker; + } + + /** + * Returns the current locale of the spelling preferences. + * + * @param store the preference store + * @return The current locale of the spelling preferences + */ + private Locale getCurrentLocale(IPreferenceStore store) { + return convertToLocale(store.getString(PreferenceConstants.SPELLING_LOCALE)); + } + + public static Locale convertToLocale(String locale) { + Locale defaultLocale= SpellCheckEngine.getDefaultLocale(); + if (locale.equals(defaultLocale.toString())) + return defaultLocale; + + int length= locale.length(); + if (length >= 5) + return new Locale(locale.substring(0, 2), locale.substring(3, 5)); + + if (length == 2 && locale.indexOf('_') == -1) + return new Locale(locale); + + if (length == 3 && locale.charAt(0) == '_') + return new Locale("", locale.substring(1)); //$NON-NLS-1$ + + return new Locale(""); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale() + */ + public synchronized final Locale getLocale() { + if (fChecker == null) + return null; + + return fChecker.getLocale(); + } + + /* + * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public final void propertyChange(final PropertyChangeEvent event) { + if (event.getProperty().equals(PreferenceConstants.SPELLING_LOCALE)) { + resetSpellChecker(); + return; + } + + if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY)) { + resetUserDictionary(); + return; + } + + if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING)) { + resetUserDictionary(); + return; + } + + if (event.getProperty().equals(SpellingService.PREFERENCE_SPELLING_ENABLED) && !TextEditorPlugin.getDefault().getPreferenceStore().getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED)) { //TODO: is this good? + if (this == fgEngine) + SpellCheckEngine.shutdownInstance(); + else + shutdown(); + } + } + + /** + * Resets the current checker's user dictionary. + */ + private synchronized void resetUserDictionary() { + if (fChecker == null) + return; + + // Update user dictionary + if (fUserDictionary != null) { + fChecker.removeDictionary(fUserDictionary); + fUserDictionary.unload(); + fUserDictionary= null; + } + + IPreferenceStore store= TextEditorPlugin.getDefault().getPreferenceStore(); + String filePath= "C:\\workspaces\\jdt\\org.eclipse.jdt.ui.spelling\\en_us.dictionary"; + + //TODO: code commented for testing purpose, need to uncomment later + //store.getString(PreferenceConstants.SPELLING_USER_DICTIONARY); + + /* VariablesPlugin variablesPlugin= VariablesPlugin.getDefault(); + if (variablesPlugin == null) + return; + + IStringVariableManager variableManager= variablesPlugin.getStringVariableManager(); + try { + filePath= variableManager.performStringSubstitution(filePath); + } catch (CoreException e) { + TextEditorPlugin.log(e); + return; + } +*/ if (filePath.length() > 0) { + try { + File file= new File(filePath); + if (!file.exists() && !file.createNewFile()) + return; + + final URL url= new URL("file", null, filePath); //$NON-NLS-1$ + InputStream stream= url.openStream(); + if (stream != null) { + try { + fUserDictionary= new PersistentSpellDictionary(url); + fChecker.addDictionary(fUserDictionary); + } finally { + stream.close(); + } + } + } catch (MalformedURLException exception) { + TextEditorPlugin.log(exception); + } catch (IOException exception) { + TextEditorPlugin.log(exception); + } + } + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary) + */ + public synchronized final void registerGlobalDictionary(final ISpellDictionary dictionary) { + fGlobalDictionaries.add(dictionary); + resetSpellChecker(); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale, org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary) + */ + public synchronized final void registerDictionary(final Locale locale, final ISpellDictionary dictionary) { + fLocaleDictionaries.put(locale, dictionary); + resetSpellChecker(); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#unload() + */ + public synchronized final void shutdown() { + + TextEditorPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); + TextEditorPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); // TODO: is this good? and why is the same line twice + + ISpellDictionary dictionary= null; + for (final Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { + dictionary= (ISpellDictionary)iterator.next(); + dictionary.unload(); + } + fGlobalDictionaries= null; + + for (final Iterator iterator= fLocaleDictionaries.values().iterator(); iterator.hasNext();) { + dictionary= (ISpellDictionary)iterator.next(); + dictionary.unload(); + } + fLocaleDictionaries= null; + + fUserDictionary= null; + fChecker= null; + } + + private synchronized void resetSpellChecker() { + if (fChecker != null) { + ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(fChecker.getLocale()); + if (dictionary != null) + dictionary.unload(); + } + fChecker= null; + } + + /* + * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary) + */ + public synchronized final void unregisterDictionary(final ISpellDictionary dictionary) { + fGlobalDictionaries.remove(dictionary); + fLocaleDictionaries.values().remove(dictionary); + dictionary.unload(); + resetSpellChecker(); + } +} Index: src/org/eclipse/ui/texteditor/spelling/engine/SpellingEngine.java =================================================================== RCS file: src/org/eclipse/ui/texteditor/spelling/engine/SpellingEngine.java diff -N src/org/eclipse/ui/texteditor/spelling/engine/SpellingEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/texteditor/spelling/engine/SpellingEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.texteditor.spelling.engine; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; + +import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector; +import org.eclipse.ui.texteditor.spelling.SpellingContext; +import org.eclipse.ui.texteditor.spelling.TextSpellingProblem; + + +/** + * Internal abstract spelling engine, subclasses provide a content-type specific implementation. + * + * @since 3.1 + */ +public abstract class SpellingEngine implements ISpellingEngine { + + /** + * {@link ISpellEvent}listener that forwards events as + * {@link org.eclipse.ui.texteditor.spelling.SpellingProblem}. + */ + protected static class SpellEventListener implements ISpellEventListener { + + /** Spelling problem collector */ + private ISpellingProblemCollector fCollector; + + /** + * The document. + * @since 3.3 + */ + private IDocument fDocument; + + private int fProblemsThreshold; + private int fProblemCount; + + /** + * Initialize with the given spelling problem collector. + * + * @param collector the spelling problem collector + * @param document the document + */ + public SpellEventListener(ISpellingProblemCollector collector, IDocument document) { + fCollector= collector; + fDocument= document; + fProblemsThreshold= 100;//TODO: assigned to 100 for testing, remove later//PreferenceConstants.getPreferenceStore().getInt(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellEvent) + */ + public void handle(ISpellEvent event) { + if (isProblemsThresholdReached()) + return; + fProblemCount++; + //fCollector.accept(new JavaSpellingProblem(event, fDocument)); //TODO ??? + fCollector.accept(new TextSpellingProblem(event, fDocument)); + } + + public boolean isProblemsThresholdReached() { + return fProblemCount >= fProblemsThreshold; + } + } + + /* + * @see org.eclipse.ui.texteditor.spelling.ISpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.ui.texteditor.spelling.SpellingContext, org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector, org.eclipse.core.runtime.IProgressMonitor) + */ + public void check(IDocument document, IRegion[] regions, SpellingContext context, ISpellingProblemCollector collector, IProgressMonitor monitor) { + if (collector != null) { + final ISpellCheckEngine spellingEngine= SpellCheckEngine.getInstance(); + ISpellChecker checker= spellingEngine.getSpellChecker(); + if (checker != null) + check(document, regions, checker, collector, monitor); + } + } + + /** + * Spell checks the given document regions with the given arguments. + * + * @param document the document + * @param regions the regions + * @param checker the spell checker + * @param collector the spelling problem collector + * @param monitor the progress monitor, can be null + */ + protected abstract void check(IDocument document, IRegion[] regions, ISpellChecker checker, ISpellingProblemCollector collector, IProgressMonitor monitor); + +}