1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00
This commit is contained in:
Sergey Prigogin 2007-12-03 00:09:20 +00:00
parent 97c41a004d
commit 8463aa5adf
93 changed files with 109089 additions and 97 deletions

View file

@ -116,8 +116,8 @@ public class CModelBuilder2 implements IContributedModelBuilder {
/*
* @see org.eclipse.cdt.core.parser.IProblem#getArguments()
*/
public String getArguments() {
return fASTProblem.getArguments();
public String[] getArguments() {
return new String[] { fASTProblem.getArguments() };
}
/*

View file

@ -0,0 +1,19 @@
/*******************************************************************************
* Copyright (c) 2007 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser;
public interface IPersistableProblem extends IProblem {
/**
* Returns the marker type associated to this problem, if it gets persisted into a marker.
* @return the type of the marker which would be associated to the problem.
*/
String getMarkerType();
}

View file

@ -50,7 +50,7 @@ public interface IProblem
*
* @return a map between parameter names and values.
*/
String getArguments();
String[] getArguments();
/**
* Answer the file name in which the problem was found.

View file

@ -12,34 +12,23 @@ package org.eclipse.cdt.internal.core.parser.problem;
import org.eclipse.cdt.core.parser.IProblem;
/**
* @author jcamelon
*/
public abstract class BaseProblemFactory {
protected final static String PROBLEM_PATTERN = "BaseProblemFactory.problemPattern"; //$NON-NLS-1$
public IProblem createProblem(int id, int start, int end, int line, char[] file, char[] arg, boolean warn, boolean error) {
public IProblem createProblem(int id, int start, int end, int line, char[] file, String[] arg,
boolean warn, boolean error) {
return new Problem( id, start, end, line, file, arg, warn, error);
}
public boolean checkBitmask( int id, int bitmask )
{
return ( id & bitmask ) != 0;
public boolean checkBitmask(int id, int bitmask) {
return (id & bitmask) != 0;
}
protected IProblem createInternalProblem( int id, int start, int end, int line, char [] file, char[] arg, boolean warn, boolean error )
{
return createProblem( id, start, end, line, file, arg, warn, error );
protected IProblem createInternalProblem( int id, int start, int end, int line, char[] file, String[] arg,
boolean warn, boolean error) {
return createProblem(id, start, end, line, file, arg, warn, error);
}
/**
* @param id
* @param arguments
* @param line
* @param file
* @return
*/
}

View file

@ -14,11 +14,9 @@ import org.eclipse.cdt.core.parser.IProblem;
/**
* @author jcamelon
*
*/
public interface IProblemFactory {
public IProblem createProblem( int id, int start, int end, int line, char [] file, char[] arg, boolean warn, boolean error );
public String getRequiredAttributesForId( int id );
public IProblem createProblem(int id, int start, int end, int line, char[] file, String[] arg,
boolean warn, boolean error );
public String getRequiredAttributesForId(int id);
}

View file

@ -20,11 +20,9 @@ import org.eclipse.cdt.internal.core.parser.ParserMessages;
/**
* @author jcamelon
*
*/
public class Problem implements IProblem {
private final char[] arg;
private final String[] arg;
private final int id;
private final int sourceStart;
private final int sourceEnd;
@ -36,8 +34,8 @@ public class Problem implements IProblem {
private String message = null;
public Problem( int id, int start, int end, int line, char [] file, char[] arg, boolean warn, boolean error )
{
public Problem( int id, int start, int end, int line, char[] file, String[] arg,
boolean warn, boolean error) {
this.id = id;
this.sourceStart = start;
this.sourceEnd = end;
@ -48,7 +46,6 @@ public class Problem implements IProblem {
this.isError = error;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.IProblem#getID()
*/
@ -241,27 +238,26 @@ public class Problem implements IProblem {
}
protected final static String PROBLEM_PATTERN = "BaseProblemFactory.problemPattern"; //$NON-NLS-1$
public String getMessage()
{
public String getMessage() {
if( message != null )
return message;
String msg = (String) errorMessages.get( new Integer(id) );
if( msg == null )
if (msg == null)
msg = ""; //$NON-NLS-1$
if( arg != null ){
msg = MessageFormat.format( msg, new Object [] { new String(arg) } );
if (arg != null) {
msg = MessageFormat.format(msg, arg);
}
Object [] args = null;
if (originatingFileName != null)
args = new Object []{ msg, new String( originatingFileName ), new Integer( lineNumber ) };
else
args = new Object []{ msg, new String(""), new Integer( lineNumber ) }; //$NON-NLS-1$
message = ParserMessages.getFormattedString( PROBLEM_PATTERN, args );
String[] args = null;
if (originatingFileName != null) {
args = new String[] { msg, new String(originatingFileName), String.valueOf(lineNumber) };
} else {
args = new String[] { msg, "", String.valueOf(lineNumber) }; //$NON-NLS-1$
}
message = ParserMessages.getFormattedString(PROBLEM_PATTERN, args);
return message;
}
@ -269,15 +265,13 @@ public class Problem implements IProblem {
* @see org.eclipse.cdt.core.parser.IProblem#checkCategory(int)
*/
public boolean checkCategory(int bitmask) {
return ((id & bitmask) != 0 );
return (id & bitmask) != 0;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.IProblem#getArguments()
*/
public String getArguments() {
return arg != null ? String.valueOf(arg) : ""; //$NON-NLS-1$
public String[] getArguments() {
return arg;
}
}

View file

@ -19,8 +19,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.parser.scanner2.BaseScanner.MacroData;
public class ExpressionEvaluator {
private static char[] emptyCharArray = new char[0];
private static char[] EMPTY_CHAR_ARRAY = new char[0];
// The context stack
private static final int initSize = 8;
@ -786,7 +785,7 @@ public class ExpressionEvaluator {
continue;
} else if (c == ',') {
// empty arg
exp.definitions.put(arglist[currarg], emptyCharArray);
exp.definitions.put(arglist[currarg], EMPTY_CHAR_ARRAY);
continue;
} else if (c == '(') {
++parens;
@ -810,7 +809,7 @@ public class ExpressionEvaluator {
break;
}
char[] arg = emptyCharArray;
char[] arg = EMPTY_CHAR_ARRAY;
int arglen = argend - argstart + 1;
if (arglen > 0) {
arg = new char[arglen];

View file

@ -24,31 +24,15 @@ public class ScannerProblemFactory extends BaseProblemFactory implements IProble
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.IProblemFactory#createProblem(int, int, int, int, char[], java.lang.String, boolean, boolean)
*/
public IProblem createProblem(
int id,
int start,
int end,
int line,
char[] file,
char[] arg,
boolean warn,
boolean error)
{
if( checkBitmask( id, IProblem.INTERNAL_RELATED ) )
return createInternalProblem( id, start, end, line, file, arg, warn, error );
if ( checkBitmask( id, IProblem.SCANNER_RELATED ) ||
checkBitmask( id, IProblem.PREPROCESSOR_RELATED ) )
return super.createProblem(
id,
start,
end,
line,
file,
arg,
warn,
error);
public IProblem createProblem(int id, int start, int end, int line, char[] file, String[] arg,
boolean warn, boolean error) {
if (checkBitmask(id, IProblem.INTERNAL_RELATED))
return createInternalProblem(id, start, end, line, file, arg, warn, error);
if (checkBitmask(id, IProblem.SCANNER_RELATED) ||
checkBitmask(id, IProblem.PREPROCESSOR_RELATED)) {
return super.createProblem(id, start, end, line, file, arg, warn, error);
}
return null;
}

View file

@ -80,7 +80,8 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.3.0,4.0.0)",
org.eclipse.ui.navigator;bundle-version="[3.2.0,4.0.0)",
org.eclipse.cdt.refactoring;bundle-version="[5.0.0,6.0.0)",
org.eclipse.core.filesystem;bundle-version="[1.1.0,2.0.0)",
org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)"
org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)",
org.eclipse.ltk.core.refactoring
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.4
Import-Package: com.ibm.icu.text

View file

@ -12,6 +12,7 @@ bin.includes = about.html,\
plugin.xml,\
icons/,\
plugin.properties,\
dictionaries/,\
templates/,\
.,\
META-INF/,\

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View file

@ -9,6 +9,7 @@
# IBM Corporation - initial API and implementation
# Markus Schorn (Wind River Systems)
# Anton Leherbauer (Wind River Systems)
# Sergey Prigogin (Google)
###############################################################################
pluginName=C/C++ Development Tools UI
providerName=Eclipse.org
@ -344,7 +345,7 @@ Folding.label= F&olding
cCompareFontDefiniton.label= C/C++ compare text font
cCompareFontDefiniton.description= The C/C++ compare text font is used by Assembly compare/merge tools.
asmCompareFontDefiniton.label= Assembly compare text font
asmCompareFontDefiniton.description= The Asembly compare text font is used by Assembly compare/merge tools.
asmCompareFontDefiniton.description= The Assembly compare text font is used by Assembly compare/merge tools.
# External Search Editor
@ -358,6 +359,13 @@ comment.contextType.name = Comment
completionContributors=Content Assist Completion Contributor
completionProposalComputer=Completion Proposal Computer
# Quick fix
quickFixProcessorExtensionPoint=Quick Fix Processor
spellingQuickFixProcessor=Spelling Quick Fix Processor
# Spelling
cSpellingEngine.label=C/C++ spelling engine
# Indexer Preference Name
indexerPrefName=Indexer

View file

@ -23,6 +23,7 @@
<extension-point id="newCfgDialog" name="%NewCfgDialog.name" schema="schema/newCfgDialog.exsd"/>
<extension-point id="ConfigManager" name="%ConfigManager" schema="schema/ConfigManager.exsd"/>
<extension-point id="HelpInfo" name="%HelpInfo" schema="schema/HelpInfo.exsd"/>
<extension-point id="quickFixProcessors" name="%quickFixProcessorExtensionPoint" schema="schema/quickFixProcessors.exsd"/>
<extension
point="org.eclipse.core.runtime.adapters">
@ -1756,6 +1757,15 @@
name="org.eclipse.cdt.ui.indexmarker">
</type>
</extension>
<extension point="org.eclipse.ui.workbench.texteditor.spellingEngine">
<engine
preferencesClass="org.eclipse.cdt.internal.ui.preferences.SpellingPreferenceBlock"
label="%cSpellingEngine.label"
class="org.eclipse.cdt.internal.ui.text.spelling.SpellingEngineDispatcher"
default="false"
id="org.eclipse.cdt.internal.ui.text.spelling.CSpellingEngine">
</engine>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">
<initializer class="org.eclipse.cdt.ui.CUIPreferenceInitializer"/>
@ -1921,6 +1931,18 @@
</command>
</extension>
<extension
point="org.eclipse.cdt.ui.quickFixProcessors">
<quickFixProcessor
name="%spellingQuickFixProcessor"
class="org.eclipse.cdt.internal.ui.text.spelling.WordQuickFixProcessor"
id= "org.eclipse.cdt.ui.text.correction.spelling.QuickFixProcessor">
<handledMarkerTypes>
<markerType id="org.eclipse.cdt.internal.spelling"/>
</handledMarkerTypes>
</quickFixProcessor>
</extension>
<!--- Common Navigator extensions -->
<extension
point="org.eclipse.ui.navigator.navigatorContent">

View file

@ -0,0 +1,182 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.ui">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.ui" id="quickFixProcessors" name="Quick Fix Processor"/>
</appInfo>
<documentation>
This extension point allows to add a Quick Fix processor to offer new Quick Fixes on C/C++ problems.
&lt;p&gt;
Extension can specify which problem marker types it can handle. It will only get problems of these types to process.
&lt;/p&gt;
&lt;p&gt;
This extension point supports the &lt;code&gt;enablement&lt;/code&gt; tag. Properties to test on are:
&lt;dl&gt;
&lt;li&gt;translationUnit: type ITranslationUnit; the translation unit the quick assist is applied on&lt;/li&gt;
&lt;li&gt;projectNatures: type Collection; all project natures of the current project&lt;/li&gt;
&lt;/dl&gt;
&lt;/p&gt;
</documentation>
</annotation>
<include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
<element name="extension">
<complexType>
<sequence>
<element ref="quickFixProcessor" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
a fully qualified identifier of the target extension point
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
an optional identifier of the extension instance
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
an optional name of the extension instance
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="quickFixProcessor">
<complexType>
<sequence>
<element ref="enablement" minOccurs="0" maxOccurs="1"/>
<element ref="handledMarkerTypes" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
a unique identifier for the Quick Fix processor
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
a localized name of the Quick Fix processor
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
the name of the class that implements this Quick Fix processor. The
class must be public and implement
&lt;samp&gt;org.eclipse.cdt.ui.text.IQuickFixProcessor&lt;/samp&gt;
with a public 0-argument constructor.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.ui.text.IQuickFixProcessor"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="handledMarkerTypes">
<annotation>
<documentation>
Specifies the marker types of the problems this quick fix processor can handle.
If no handled marker type are specified, the processor will get problems of types org.eclipse.cdt.core.problem, org.eclipse.cdt.core.buildpath_problem and org.eclipse.cdt.core.task.
</documentation>
</annotation>
<complexType>
<sequence>
<element ref="markerType" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
<element name="markerType">
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
the marker type id of the marker that can be handled by this processor
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
4.1
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
The following is an example of a Quick Fix processor contribution:
&lt;p&gt;
&lt;pre&gt;
&lt;extension point=&quot;org.eclipse.cdt.ui.quickFixProcessors&quot;&gt;
&lt;quickFixProcessor
id=&quot;AdvancedQuickFixProcessor&quot;
name=&quot;Advanced Quick Fix Processor&quot;
class=&quot;com.example.AdvancedQuickFixProcessor&quot;&gt;
&lt;handledMarkerTypes&gt;
&lt;markerType id=&quot;org.eclipse.myplugin.audits&quot;/&gt;
&lt;/handledMarkerTypes&gt;
&lt;enablement&gt;
&lt;with variable=&quot;projectNatures&quot;&gt;
&lt;iterate operator=&quot;or&quot;&gt;
&lt;equals value=&quot;org.eclipse.cdt.core.cnature&quot;/&gt;
&lt;/iterate&gt;
&lt;/with&gt;
&lt;/enablement&gt;
&lt;/quickFixProcessor&gt;
&lt;/extension&gt;
&lt;/pre&gt;
&lt;/p&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
The contributed class must implement &lt;code&gt;org.eclipse.cdt.ui.text.IQuickFixProcessor&lt;/code&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
Copyright (c) 2001, 2007 IBM Corporation and others.&lt;br&gt;
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 &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
</documentation>
</annotation>
</schema>

View file

@ -325,6 +325,17 @@ public class CPluginImages {
public static final String IMG_EMPTY = NAME_PREFIX + "tc_empty.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_EMPTY = createManaged(T_OBJ, IMG_EMPTY);
public static final String IMG_OBJS_QUICK_ASSIST= NAME_PREFIX + "quickassist_obj.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_OBJS_QUICK_ASSIST = createManaged(T_OBJ, IMG_OBJS_QUICK_ASSIST);
public static final String IMG_CORRECTION_ADD= NAME_PREFIX + "correction_add.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_CORRECTION_ADD = createManaged(T_OBJ, IMG_CORRECTION_ADD);
public static final String IMG_CORRECTION_CHANGE= NAME_PREFIX + "correction_change.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_CORRECTION_CHANGE = createManaged(T_OBJ, IMG_CORRECTION_CHANGE);
public static final String IMG_CORRECTION_RENAME= NAME_PREFIX + "correction_rename.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_CORRECTION_RENAME = createManaged(T_OBJ, IMG_CORRECTION_RENAME);
public static final String IMG_OBJS_NLS_NEVER_TRANSLATE= NAME_PREFIX + "never_translate.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_OBJS_NLS_NEVER_TRANSLATE = createManaged(T_OBJ, IMG_OBJS_NLS_NEVER_TRANSLATE);
private static ImageDescriptor createManaged(String prefix, String name) {
return createManaged(imageRegistry, prefix, name);

View file

@ -81,6 +81,7 @@ public interface ICHelpContextIds {
public static final String PROJECT_INCLUDE_PATHS_SYMBOLS = PREFIX + "std_prop_include"; //$NON-NLS-1$
public static final String APPEARANCE_PREFERENCE_PAGE = PREFIX + "appearance_preference_page_context"; //$NON-NLS-1$
public static final String SPELLING_CONFIGURATION_BLOCK= PREFIX + "spelling_configuration_block_context"; //$NON-NLS-1$
// Console view
public static final String CLEAR_CONSOLE_ACTION = PREFIX + "clear_console_action_context"; //$NON-NLS-1$

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 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.cdt.internal.ui;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
/**
* Defines the constants used in the <code>org.eclipse.ui.themes</code>
* extension contributed by this plug-in.
*/
public interface ICThemeConstants {
String ID_PREFIX= CUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
/**
* A theme constant that holds the background color used in the code assist selection dialog.
*/
public final String CODEASSIST_PROPOSALS_BACKGROUND= ID_PREFIX + PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND;
/**
* A theme constant that holds the foreground color used in the code assist selection dialog.
*/
public final String CODEASSIST_PROPOSALS_FOREGROUND= ID_PREFIX + PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND;
}

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
@ -54,12 +55,14 @@ import org.eclipse.ui.texteditor.IMarkerUpdater;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.model.IProblemRequestor;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.parser.IPersistableProblem;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
@ -68,6 +71,7 @@ import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.core.model.IBufferFactory;
import org.eclipse.cdt.internal.ui.text.IProblemRequestorExtension;
import org.eclipse.cdt.internal.ui.text.spelling.CoreSpellingProblem;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
/**
@ -85,17 +89,17 @@ public class CDocumentProvider extends TextFileDocumentProvider {
* Annotation representing an <code>IProblem</code>.
*/
static protected class ProblemAnnotation extends Annotation implements ICAnnotation {
private static final String INDEXER_ANNOTATION_TYPE= "org.eclipse.cdt.ui.indexmarker"; //$NON-NLS-1$
private ITranslationUnit fTranslationUnit;
private List fOverlaids;
private IProblem fProblem;
public ProblemAnnotation(IProblem problem, ITranslationUnit cu) {
public ProblemAnnotation(IProblem problem, ITranslationUnit tu) {
fProblem= problem;
fTranslationUnit= cu;
setType(INDEXER_ANNOTATION_TYPE);
fTranslationUnit= tu;
setType(problem instanceof CoreSpellingProblem ?
SpellingAnnotation.TYPE : INDEXER_ANNOTATION_TYPE);
}
/*
@ -109,7 +113,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
* @see ICAnnotation#getArguments()
*/
public String[] getArguments() {
return isProblem() ? new String[]{fProblem.getArguments()} : null;
return isProblem() ? fProblem.getArguments() : null;
}
/*
@ -175,6 +179,15 @@ public class CDocumentProvider extends TextFileDocumentProvider {
public ITranslationUnit getTranslationUnit() {
return fTranslationUnit;
}
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IJavaAnnotation#getMarkerType()
*/
public String getMarkerType() {
if (fProblem instanceof IPersistableProblem)
return ((IPersistableProblem) fProblem).getMarkerType();
return null;
}
}
/**

View file

@ -169,4 +169,12 @@ public class CMarkerAnnotation extends MarkerAnnotation implements IProblemAnnot
}
return null;
}
public String getMarkerType() {
IMarker marker= getMarker();
if (marker == null || !marker.exists())
return null;
return MarkerUtilities.getMarkerType(getMarker());
}
}

View file

@ -72,7 +72,7 @@ public interface ICAnnotation {
* Adds the given annotation to the list of
* annotations which are overlaid by this annotations.
*
* @param annotation the problem annoation
* @param annotation the problem annotation
*/
void addOverlaid(ICAnnotation annotation);
@ -80,7 +80,7 @@ public interface ICAnnotation {
* Removes the given annotation from the list of
* annotations which are overlaid by this annotation.
*
* @param annotation the problem annoation
* @param annotation the problem annotation
*/
void removeOverlaid(ICAnnotation annotation);
@ -101,4 +101,13 @@ public interface ICAnnotation {
String[] getArguments();
int getId();
/**
* Returns the marker type associated to this problem or <code>null<code> if no marker type
* can be evaluated. See also {@link org.eclipse.cdt.ui.text.IProblemLocation#getMarkerType()}.
*
* @return the type of the marker which would be associated to the problem or
* <code>null<code> if no marker type can be evaluated.
*/
String getMarkerType();
}

View file

@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
@ -223,6 +224,36 @@ public final class PreferencesMessages extends NLS {
public static String TodoTaskInputDialog_error_entryExists;
public static String TodoTaskInputDialog_error_noSpace;
public static String SpellingPreferencePage_empty_threshold;
public static String SpellingPreferencePage_invalid_threshold;
public static String SpellingPreferencePage_ignore_digits_label;
public static String SpellingPreferencePage_ignore_mixed_label;
public static String SpellingPreferencePage_ignore_sentence_label;
public static String SpellingPreferencePage_ignore_upper_label;
public static String SpellingPreferencePage_ignore_url_label;
public static String SpellingPreferencePage_ignore_non_letters_label;
public static String SpellingPreferencePage_ignore_single_letters_label;
public static String SpellingPreferencePage_ignore_string_literals_label;
public static String SpellingPreferencePage_proposals_threshold;
public static String SpellingPreferencePage_problems_threshold;
public static String SpellingPreferencePage_dictionary_label;
public static String SpellingPreferencePage_encoding_label;
public static String SpellingPreferencePage_workspace_dictionary_label;
public static String SpellingPreferencePage_browse_label;
public static String SpellingPreferencePage_dictionary_error;
public static String SpellingPreferencePage_dictionary_none;
public static String SpellingPreferencePage_locale_error;
public static String SpellingPreferencePage_filedialog_title;
public static String SpellingPreferencePage_filter_dictionary_label;
public static String SpellingPreferencePage_filter_all_label;
public static String SpellingPreferencePage_enable_contentassist_label;
public static String SpellingPreferencePage_group_user;
public static String SpellingPreferencePage_group_dictionary;
public static String SpellingPreferencePage_group_dictionaries;
public static String SpellingPreferencePage_group_advanced;
public static String SpellingPreferencePage_user_dictionary_description;
public static String SpellingPreferencePage_variables;
public static String LanguageMappings_missingLanguageTitle;
public static String WorkspaceLanguagesPreferencePage_description;

View file

@ -9,6 +9,7 @@
# IBM Corporation - initial API and implementation
# Anton Leherbauer (Wind River Systems)
# Markus Schorn (Wind River Systems)
# Sergey Prigogin (Google)
###############################################################################
CEditorPreferencePage_link=C/C++ Editor Preferences. Note that some preferences may be set on the <a href="org.eclipse.ui.preferencePages.GeneralTextEditor">Text Editors</a> preference page.
@ -257,7 +258,36 @@ PathEntryVariablesBlock_addVariableButton = &New...
PathEntryVariablesBlock_editVariableButton = Edi&t...
PathEntryVariablesBlock_removeVariableButton = &Remove
# Spelling
SpellingPreferencePage_empty_threshold= A positive integer must be specified.
SpellingPreferencePage_invalid_threshold=''{0}'' is not a valid positive integer.
SpellingPreferencePage_ignore_digits_label=Ignore &words with digits
SpellingPreferencePage_ignore_mixed_label=Ignore &mixed case words
SpellingPreferencePage_ignore_sentence_label=Ignore &sentence capitalization
SpellingPreferencePage_ignore_upper_label=Ignore u&pper case words
SpellingPreferencePage_ignore_url_label=Ignore &internet addresses
SpellingPreferencePage_ignore_single_letters_label=I&gnore single letters
SpellingPreferencePage_ignore_string_literals_label=Ignore string &literals
SpellingPreferencePage_ignore_non_letters_label=Ignore &non-letters at word boundaries
SpellingPreferencePage_proposals_threshold= Ma&ximum number of correction proposals:
SpellingPreferencePage_problems_threshold= Maximum number of problems repor&ted per file:
SpellingPreferencePage_dictionary_label=Plat&form dictionary:
SpellingPreferencePage_workspace_dictionary_label=Use&r defined dictionary:
SpellingPreferencePage_browse_label=&Browse...
SpellingPreferencePage_dictionary_error=The dictionary file must be read/write accessible.
SpellingPreferencePage_dictionary_none=none
SpellingPreferencePage_encoding_label=En&coding:
SpellingPreferencePage_locale_error=There is no dictionary available for this language.
SpellingPreferencePage_filedialog_title=Select User Dictionary
SpellingPreferencePage_filter_dictionary_label=Dictionary Files
SpellingPreferencePage_filter_all_label=All Files
SpellingPreferencePage_enable_contentassist_label=Ma&ke dictionary available to content assist
SpellingPreferencePage_group_user=Options
SpellingPreferencePage_group_dictionary=Dictionary
SpellingPreferencePage_group_dictionaries=Dictionaries
SpellingPreferencePage_group_advanced=Advanced
SpellingPreferencePage_variables=&Variables...
SpellingPreferencePage_user_dictionary_description=The user dictionary is a text file with one word on each line
# Language settings
LanguageMappings_missingLanguageTitle = Missing Languages

View file

@ -0,0 +1,641 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
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.IStatus;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.ui.ide.dialogs.EncodingFieldEditor;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.cdt.internal.ui.text.spelling.SpellCheckEngine;
import org.eclipse.cdt.internal.ui.util.PixelConverter;
import org.eclipse.cdt.internal.ui.util.SWTUtil;
import org.eclipse.cdt.internal.ui.wizards.indexwizards.StringVariableSelectionDialog;
/**
* Options configuration block for spell check related settings.
*/
public class SpellingConfigurationBlock extends OptionsConfigurationBlock {
/**
* Tells whether content assist proposal block should be shown.
* Currently the spelling engine cannot return word proposals but
* only correction proposals and hence this is disabled.
*/
private static final boolean SUPPORT_CONTENT_ASSIST_PROPOSALS= false;
/** Preference keys for the preferences in this block */
private static final Key PREF_SPELLING_IGNORE_DIGITS= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_DIGITS);
private static final Key PREF_SPELLING_IGNORE_MIXED= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_MIXED);
private static final Key PREF_SPELLING_IGNORE_SENTENCE= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_SENTENCE);
private static final Key PREF_SPELLING_IGNORE_UPPER= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_UPPER);
private static final Key PREF_SPELLING_IGNORE_STRING_LITERALS= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_STRING_LITERALS);
private static final Key PREF_SPELLING_IGNORE_SINGLE_LETTERS= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS);
private static final Key PREF_SPELLING_IGNORE_NON_LETTERS= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS);
private static final Key PREF_SPELLING_IGNORE_URLS= getCDTUIKey(PreferenceConstants.SPELLING_IGNORE_URLS);
private static final Key PREF_SPELLING_LOCALE= getCDTUIKey(PreferenceConstants.SPELLING_LOCALE);
private static final Key PREF_SPELLING_PROPOSAL_THRESHOLD= getCDTUIKey(PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD);
private static final Key PREF_SPELLING_PROBLEMS_THRESHOLD= getCDTUIKey(PreferenceConstants.SPELLING_PROBLEMS_THRESHOLD);
private static final Key PREF_SPELLING_USER_DICTIONARY= getCDTUIKey(PreferenceConstants.SPELLING_USER_DICTIONARY);
private static final Key PREF_SPELLING_USER_DICTIONARY_ENCODING= getCDTUIKey(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING);
private static final Key PREF_SPELLING_ENABLE_CONTENTASSIST= getCDTUIKey(PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST);
/**
* The value for no platform dictionary.
*/
private static final String PREF_VALUE_NO_LOCALE= ""; //$NON-NLS-1$
/**
* Creates a selection dependency between a master and a slave control.
*
* @param master The master button that controls the state of the slave
* @param slave The slave control that is enabled only if the master is
* selected
*/
protected static void createSelectionDependency(final Button master, final Control slave) {
master.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent event) {
// Do nothing
}
public void widgetSelected(SelectionEvent event) {
slave.setEnabled(master.getSelection());
}
});
slave.setEnabled(master.getSelection());
}
/**
* Returns the locale codes for the locale list.
*
* @param locales
* The list of locales
* @return Array of locale codes for the list
*/
protected static String[] getDictionaryCodes(final Set locales) {
int index= 0;
Locale locale= null;
final String[] codes= new String[locales.size() + 1];
for (final Iterator iterator= locales.iterator(); iterator.hasNext();) {
locale= (Locale)iterator.next();
codes[index++]= locale.toString();
}
codes[index++]= PREF_VALUE_NO_LOCALE;
return codes;
}
/**
* Returns the display labels for the locale list.
*
* @param locales The list of locales
* @return Array of display labels for the list
*/
protected static String[] getDictionaryLabels(final Set locales) {
int index= 0;
Locale locale= null;
final String[] labels= new String[locales.size() + 1];
for (final Iterator iterator= locales.iterator(); iterator.hasNext();) {
locale= (Locale)iterator.next();
labels[index++]= locale.getDisplayName();
}
labels[index++]= PreferencesMessages.SpellingPreferencePage_dictionary_none;
return labels;
}
/**
* Validates that the file with the specified absolute path exists and can
* be opened.
*
* @param path The path of the file to validate
* @return a status without error if the path is valid
*/
protected static IStatus validateAbsoluteFilePath(String path) {
final StatusInfo status= new StatusInfo();
IStringVariableManager variableManager= VariablesPlugin.getDefault().getStringVariableManager();
try {
path= variableManager.performStringSubstitution(path);
if (path.length() > 0) {
final File file= new File(path);
if (!file.exists() && (!file.isAbsolute() || !file.getParentFile().canWrite()))
status.setError(PreferencesMessages.SpellingPreferencePage_dictionary_error);
else if (file.exists() && (!file.isFile() || !file.isAbsolute() || !file.canRead() || !file.canWrite()))
status.setError(PreferencesMessages.SpellingPreferencePage_dictionary_error);
}
} catch (CoreException e) {
status.setError(e.getLocalizedMessage());
}
return status;
}
/**
* Validates that the specified locale is available.
*
* @param localeString the locale to validate
* @return The status of the validation
*/
private static IStatus validateLocale(final String localeString) {
if (PREF_VALUE_NO_LOCALE.equals(localeString))
return new StatusInfo();
Locale locale= SpellCheckEngine.convertToLocale(localeString);
if (SpellCheckEngine.findClosestLocale(locale) != null)
return new StatusInfo();
return new StatusInfo(IStatus.ERROR, PreferencesMessages.SpellingPreferencePage_locale_error);
}
/**
* Validates that the specified number is positive.
*
* @param number the number to validate
* @return The status of the validation
*/
protected static IStatus validatePositiveNumber(final String number) {
final StatusInfo status= new StatusInfo();
if (number.length() == 0) {
status.setError(PreferencesMessages.SpellingPreferencePage_empty_threshold);
} else {
try {
final int value= Integer.parseInt(number);
if (value < 0) {
status.setError(PreferencesMessages.bind(PreferencesMessages.SpellingPreferencePage_invalid_threshold, number));
}
} catch (NumberFormatException exception) {
status.setError(PreferencesMessages.bind(PreferencesMessages.SpellingPreferencePage_invalid_threshold, number));
}
}
return status;
}
/** The dictionary path field */
private Text fDictionaryPath= null;
/** The status for the workspace dictionary file */
private IStatus fFileStatus= new StatusInfo();
/** The status for the proposal threshold */
private IStatus fThresholdStatus= new StatusInfo();
/** The status for the encoding field editor */
private IStatus fEncodingFieldEditorStatus= new StatusInfo();
/** The encoding field editor. */
private EncodingFieldEditor fEncodingEditor;
/** The encoding field editor's parent. */
private Composite fEncodingEditorParent;
/**
* All controls
*/
private Control[] fAllControls;
/**
* All previously enabled controls
*/
private Control[] fEnabledControls;
/**
* Creates a new spelling configuration block.
*
* @param context the status change listener
* @param project the Java project
* @param container the preference container
*/
public SpellingConfigurationBlock(final IStatusChangeListener context, final IProject project, IWorkbenchPreferenceContainer container) {
super(context, project, getAllKeys(), container);
IStatus status= validateAbsoluteFilePath(getValue(PREF_SPELLING_USER_DICTIONARY));
if (status.getSeverity() != IStatus.OK)
setValue(PREF_SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$
status= validateLocale(getValue(PREF_SPELLING_LOCALE));
if (status.getSeverity() != IStatus.OK)
setValue(PREF_SPELLING_LOCALE, SpellCheckEngine.getDefaultLocale().toString());
}
protected Combo addComboBox(Composite parent, String label, Key key, String[] values, String[] valueLabels, int indent) {
ControlData data= new ControlData(key, values);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= indent;
Label labelControl= new Label(parent, SWT.LEFT | SWT.WRAP);
labelControl.setText(label);
labelControl.setLayoutData(gd);
Combo comboBox= new Combo(parent, SWT.READ_ONLY);
comboBox.setItems(valueLabels);
comboBox.setData(data);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 2;
comboBox.setLayoutData(gd);
comboBox.addSelectionListener(getSelectionListener());
fLabels.put(comboBox, labelControl);
String currValue= getValue(key);
Locale locale= SpellCheckEngine.convertToLocale(currValue);
locale= SpellCheckEngine.findClosestLocale(locale);
if (locale != null)
currValue= locale.toString();
comboBox.select(data.getSelection(currValue));
fComboBoxes.add(comboBox);
return comboBox;
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
*/
protected Control createContents(final Composite parent) {
Composite composite= new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout());
List allControls= new ArrayList();
final PixelConverter converter= new PixelConverter(parent);
final String[] trueFalse= new String[] { IPreferenceStore.TRUE, IPreferenceStore.FALSE };
Group user= new Group(composite, SWT.NONE);
user.setText(PreferencesMessages.SpellingPreferencePage_group_user);
user.setLayout(new GridLayout());
user.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
allControls.add(user);
String label= PreferencesMessages.SpellingPreferencePage_ignore_digits_label;
Control slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_DIGITS, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_mixed_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_MIXED, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_sentence_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_SENTENCE, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_upper_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_UPPER, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_url_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_URLS, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_non_letters_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_NON_LETTERS, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_single_letters_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_SINGLE_LETTERS, trueFalse, 0);
allControls.add(slave);
label= PreferencesMessages.SpellingPreferencePage_ignore_string_literals_label;
slave= addCheckBox(user, label, PREF_SPELLING_IGNORE_STRING_LITERALS, trueFalse, 0);
allControls.add(slave);
final Set locales= SpellCheckEngine.getLocalesWithInstalledDictionaries();
boolean hasPlaformDictionaries= locales.size() > 0;
final Group engine= new Group(composite, SWT.NONE);
if (hasPlaformDictionaries)
engine.setText(PreferencesMessages.SpellingPreferencePage_group_dictionaries);
else
engine.setText(PreferencesMessages.SpellingPreferencePage_group_dictionary);
engine.setLayout(new GridLayout(4, false));
engine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
allControls.add(engine);
if (hasPlaformDictionaries) {
label= PreferencesMessages.SpellingPreferencePage_dictionary_label;
Combo combo= addComboBox(engine, label, PREF_SPELLING_LOCALE, getDictionaryCodes(locales), getDictionaryLabels(locales), 0);
combo.setEnabled(locales.size() > 0);
allControls.add(combo);
allControls.add(fLabels.get(combo));
new Label(engine, SWT.NONE); // placeholder
}
label= PreferencesMessages.SpellingPreferencePage_workspace_dictionary_label;
fDictionaryPath= addTextField(engine, label, PREF_SPELLING_USER_DICTIONARY, 0, 0);
GridData gd= (GridData) fDictionaryPath.getLayoutData();
gd.grabExcessHorizontalSpace= true;
gd.widthHint= converter.convertWidthInCharsToPixels(40);
allControls.add(fDictionaryPath);
allControls.add(fLabels.get(fDictionaryPath));
Composite buttons=new Composite(engine, SWT.NONE);
buttons.setLayout(new GridLayout(2,true));
buttons.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
Button button= new Button(buttons, SWT.PUSH);
button.setText(PreferencesMessages.SpellingPreferencePage_browse_label);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent event) {
handleBrowseButtonSelected();
}
});
SWTUtil.setButtonDimensionHint(button);
button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
allControls.add(button);
button=new Button(buttons, SWT.PUSH);
button.setText(PreferencesMessages.SpellingPreferencePage_variables);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleVariablesButtonSelected();
}
});
SWTUtil.setButtonDimensionHint(button);
button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
allControls.add(button);
// Description for user dictionary
new Label(engine, SWT.NONE); // filler
Label description= new Label(engine, SWT.NONE);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 3;
description.setLayoutData(gd);
description.setText(PreferencesMessages.SpellingPreferencePage_user_dictionary_description);
allControls.add(description);
createEncodingFieldEditor(engine, allControls);
Group advanced= new Group(composite, SWT.NONE);
advanced.setText(PreferencesMessages.SpellingPreferencePage_group_advanced);
advanced.setLayout(new GridLayout(3, false));
advanced.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
allControls.add(advanced);
label= PreferencesMessages.SpellingPreferencePage_problems_threshold;
int digits= 4;
Text text= addTextField(advanced, label, PREF_SPELLING_PROBLEMS_THRESHOLD, 0, converter.convertWidthInCharsToPixels(digits+1));
text.setTextLimit(digits);
allControls.add(text);
allControls.add(fLabels.get(text));
label= PreferencesMessages.SpellingPreferencePage_proposals_threshold;
digits= 3;
text= addTextField(advanced, label, PREF_SPELLING_PROPOSAL_THRESHOLD, 0, converter.convertWidthInCharsToPixels(digits+1));
text.setTextLimit(digits);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
allControls.add(text);
allControls.add(fLabels.get(text));
if (SUPPORT_CONTENT_ASSIST_PROPOSALS) {
label= PreferencesMessages.SpellingPreferencePage_enable_contentassist_label;
button= addCheckBox(advanced, label, PREF_SPELLING_ENABLE_CONTENTASSIST, trueFalse, 0);
allControls.add(button);
}
fAllControls= (Control[]) allControls.toArray(new Control[allControls.size()]);
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICHelpContextIds.SPELLING_CONFIGURATION_BLOCK);
return composite;
}
/**
* Creates the encoding field editor.
*
* @param composite the parent composite
* @param allControls list with all controls
*/
private void createEncodingFieldEditor(Composite composite, List allControls) {
Label filler= new Label(composite, SWT.NONE);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 4;
filler.setLayoutData(gd);
Label label= new Label(composite, SWT.NONE);
label.setText(PreferencesMessages.SpellingPreferencePage_encoding_label);
label.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
allControls.add(label);
fEncodingEditorParent= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout(2, false);
layout.marginWidth= 0;
layout.marginHeight= 0;
fEncodingEditorParent.setLayout(layout);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 3;
fEncodingEditorParent.setLayoutData(gd);
fEncodingEditor= new EncodingFieldEditor(PREF_SPELLING_USER_DICTIONARY_ENCODING.getName(), "", null, fEncodingEditorParent); //$NON-NLS-1$
PreferenceStore store= new PreferenceStore();
String defaultEncoding= ResourcesPlugin.getEncoding();
store.setDefault(PREF_SPELLING_USER_DICTIONARY_ENCODING.getName(), defaultEncoding);
String encoding= getValue(PREF_SPELLING_USER_DICTIONARY_ENCODING);
if (encoding != null && encoding.length() > 0)
store.setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING.getName(), encoding);
fEncodingEditor.setPreferenceStore(store);
// Redirect status messages from the field editor to the status change listener
DialogPage fakePage= new DialogPage() {
public void createControl(Composite c) {
}
public void setErrorMessage(String newMessage) {
StatusInfo status= new StatusInfo();
if (newMessage != null)
status.setError(newMessage);
fEncodingFieldEditorStatus= status;
fContext.statusChanged(StatusUtil.getMostSevere(new IStatus[] { fThresholdStatus, fFileStatus, fEncodingFieldEditorStatus }));
}
};
fEncodingEditor.setPage(fakePage);
fEncodingEditor.load();
if (encoding == null || encoding.equals(defaultEncoding) || encoding.length() == 0)
fEncodingEditor.loadDefault();
}
private static Key[] getAllKeys() {
if (SUPPORT_CONTENT_ASSIST_PROPOSALS)
return new Key[] { PREF_SPELLING_USER_DICTIONARY, PREF_SPELLING_USER_DICTIONARY_ENCODING, PREF_SPELLING_IGNORE_DIGITS, PREF_SPELLING_IGNORE_MIXED, PREF_SPELLING_IGNORE_SENTENCE, PREF_SPELLING_IGNORE_UPPER, PREF_SPELLING_IGNORE_URLS, PREF_SPELLING_IGNORE_NON_LETTERS, PREF_SPELLING_IGNORE_SINGLE_LETTERS, PREF_SPELLING_LOCALE, PREF_SPELLING_PROPOSAL_THRESHOLD, PREF_SPELLING_PROBLEMS_THRESHOLD, PREF_SPELLING_ENABLE_CONTENTASSIST, PREF_SPELLING_IGNORE_STRING_LITERALS };
else
return new Key[] { PREF_SPELLING_USER_DICTIONARY, PREF_SPELLING_USER_DICTIONARY_ENCODING, PREF_SPELLING_IGNORE_DIGITS, PREF_SPELLING_IGNORE_MIXED, PREF_SPELLING_IGNORE_SENTENCE, PREF_SPELLING_IGNORE_UPPER, PREF_SPELLING_IGNORE_URLS, PREF_SPELLING_IGNORE_NON_LETTERS, PREF_SPELLING_IGNORE_SINGLE_LETTERS, PREF_SPELLING_LOCALE, PREF_SPELLING_PROPOSAL_THRESHOLD, PREF_SPELLING_PROBLEMS_THRESHOLD, PREF_SPELLING_IGNORE_STRING_LITERALS };
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
*/
protected final String[] getFullBuildDialogStrings(final boolean workspace) {
return null;
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#performOk()
*/
public boolean performOk() {
fEncodingEditor.store();
if (fEncodingEditor.presentsDefaultValue())
setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING, ""); //$NON-NLS-1$
else
setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING, fEncodingEditor.getPreferenceStore().getString(PREF_SPELLING_USER_DICTIONARY_ENCODING.getName()));
return super.performOk();
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#performApply()
*/
public boolean performApply() {
fEncodingEditor.store();
if (fEncodingEditor.presentsDefaultValue())
setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING, ""); //$NON-NLS-1$
else
setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING, fEncodingEditor.getPreferenceStore().getString(PREF_SPELLING_USER_DICTIONARY_ENCODING.getName()));
return super.performApply();
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#performDefaults()
*/
public void performDefaults() {
super.performDefaults();
setValue(PREF_SPELLING_USER_DICTIONARY_ENCODING, ""); //$NON-NLS-1$
fEncodingEditor.getPreferenceStore().setValue(fEncodingEditor.getPreferenceName(), ResourcesPlugin.getEncoding());
fEncodingEditor.load();
fEncodingEditor.loadDefault();
}
protected void handleVariablesButtonSelected() {
StringVariableSelectionDialog dialog= new StringVariableSelectionDialog(fDictionaryPath.getShell());
if (dialog.open() == Window.OK)
fDictionaryPath.setText(fDictionaryPath.getText() + dialog.getVariableExpression());
}
/**
* Handles selections of the browse button.
*/
protected void handleBrowseButtonSelected() {
final FileDialog dialog= new FileDialog(fDictionaryPath.getShell(), SWT.OPEN);
dialog.setText(PreferencesMessages.SpellingPreferencePage_filedialog_title);
dialog.setFilterPath(fDictionaryPath.getText());
final String path= dialog.open();
if (path != null)
fDictionaryPath.setText(path);
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String,java.lang.String)
*/
protected void validateSettings(final Key key, final String oldValue, final String newValue) {
if (key == null || PREF_SPELLING_PROPOSAL_THRESHOLD.equals(key))
fThresholdStatus= validatePositiveNumber(getValue(PREF_SPELLING_PROPOSAL_THRESHOLD));
else
fThresholdStatus= new StatusInfo();
if (key == null || PREF_SPELLING_PROBLEMS_THRESHOLD.equals(key)) {
IStatus status= validatePositiveNumber(getValue(PREF_SPELLING_PROBLEMS_THRESHOLD));
fThresholdStatus= StatusUtil.getMostSevere(new IStatus[] {fThresholdStatus, status});
}
if (key == null || PREF_SPELLING_USER_DICTIONARY.equals(key))
fFileStatus= validateAbsoluteFilePath(getValue(PREF_SPELLING_USER_DICTIONARY));
fContext.statusChanged(StatusUtil.getMostSevere(new IStatus[] { fThresholdStatus, fFileStatus, fEncodingFieldEditorStatus }));
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateCheckBox(org.eclipse.swt.widgets.Button)
*/
protected void updateCheckBox(Button curr) {
super.updateCheckBox(curr);
Event event= new Event();
event.type= SWT.Selection;
event.display= curr.getDisplay();
event.widget= curr;
curr.notifyListeners(SWT.Selection, event);
}
/**
* Sets the enabled state.
*
* @param enabled the new state
*/
protected void setEnabled(boolean enabled) {
fEncodingEditor.setEnabled(enabled, fEncodingEditorParent);
if (enabled && fEnabledControls != null) {
for (int i= fEnabledControls.length - 1; i >= 0; i--)
fEnabledControls[i].setEnabled(true);
fEnabledControls= null;
}
if (!enabled && fEnabledControls == null) {
List enabledControls= new ArrayList();
for (int i= fAllControls.length - 1; i >= 0; i--) {
Control control= fAllControls[i];
if (control.isEnabled()) {
enabledControls.add(control);
control.setEnabled(false);
}
}
fEnabledControls= (Control[]) enabledControls.toArray(new Control[enabledControls.size()]);
}
}
}

View file

@ -0,0 +1,121 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.texteditor.spelling.IPreferenceStatusMonitor;
import org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
/**
* Spelling preference block
*/
public class SpellingPreferenceBlock implements ISpellingPreferenceBlock {
private class NullStatusChangeListener implements IStatusChangeListener {
/*
* @see org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
*/
public void statusChanged(IStatus status) {
}
}
private class StatusChangeListenerAdapter implements IStatusChangeListener {
private IPreferenceStatusMonitor fMonitor;
private IStatus fStatus;
public StatusChangeListenerAdapter(IPreferenceStatusMonitor monitor) {
super();
fMonitor= monitor;
}
/*
* @see org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
*/
public void statusChanged(IStatus status) {
fStatus= status;
fMonitor.statusChanged(status);
}
public IStatus getStatus() {
return fStatus;
}
}
private SpellingConfigurationBlock fBlock= new SpellingConfigurationBlock(new NullStatusChangeListener(), null, null);
private SpellingPreferenceBlock.StatusChangeListenerAdapter fStatusMonitor;
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#createControl(org.eclipse.swt.widgets.Composite)
*/
public Control createControl(Composite parent) {
return fBlock.createContents(parent);
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#initialize(org.eclipse.ui.texteditor.spelling.IPreferenceStatusMonitor)
*/
public void initialize(IPreferenceStatusMonitor statusMonitor) {
fStatusMonitor= new StatusChangeListenerAdapter(statusMonitor);
fBlock.fContext= fStatusMonitor;
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#canPerformOk()
*/
public boolean canPerformOk() {
return fStatusMonitor == null || fStatusMonitor.getStatus() == null || !fStatusMonitor.getStatus().matches(IStatus.ERROR);
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#performOk()
*/
public void performOk() {
fBlock.performOk();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#performDefaults()
*/
public void performDefaults() {
fBlock.performDefaults();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#performRevert()
*/
public void performRevert() {
fBlock.performRevert();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#dispose()
*/
public void dispose() {
fBlock.dispose();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingPreferenceBlock#setEnabled(boolean)
*/
public void setEnabled(boolean enabled) {
fBlock.setEnabled(enabled);
}
}

View file

@ -0,0 +1,120 @@
/*******************************************************************************
* 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.cdt.internal.ui.text;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.internal.ui.text.spelling.CSpellingReconcileStrategy;
/**
* Reconciling strategy for C/C++ code. This is a composite strategy containing
* the regular C/C++ model reconciler and the comment spelling strategy.
*/
public class CCompositeReconcilingStrategy extends CompositeReconcilingStrategy {
private ITextEditor fEditor;
private CReconcilingStrategy fCStrategy;
/**
* Creates a new C/C++ reconciling strategy.
*
* @param viewer the source viewer
* @param editor the editor of the strategy's reconciler
* @param documentPartitioning the document partitioning this strategy uses for configuration
*/
public CCompositeReconcilingStrategy(ISourceViewer viewer, ITextEditor editor, String documentPartitioning) {
fEditor= editor;
fCStrategy= new CReconcilingStrategy(editor);
setReconcilingStrategies(new IReconcilingStrategy[] {
fCStrategy,
new CSpellingReconcileStrategy(viewer, editor)
});
}
/**
* Returns the problem requestor for the editor's input element.
*
* @return the problem requestor for the editor's input element
*/
private IProblemRequestorExtension getProblemRequestorExtension() {
IDocumentProvider p = fEditor.getDocumentProvider();
if (p == null) {
return null;
}
IAnnotationModel m = p.getAnnotationModel(fEditor.getEditorInput());
if (m instanceof IProblemRequestorExtension)
return (IProblemRequestorExtension) m;
return null;
}
/*
* @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion, org.eclipse.jface.text.IRegion)
*/
public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
IProblemRequestorExtension e= getProblemRequestorExtension();
if (e != null) {
try {
e.beginReportingSequence();
super.reconcile(dirtyRegion, subRegion);
} finally {
e.endReportingSequence();
}
} else {
super.reconcile(dirtyRegion, subRegion);
}
}
/*
* @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
*/
public void reconcile(IRegion partition) {
IProblemRequestorExtension e= getProblemRequestorExtension();
if (e != null) {
try {
e.beginReportingSequence();
super.reconcile(partition);
} finally {
e.endReportingSequence();
}
} else {
super.reconcile(partition);
}
}
/*
* @see org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy#initialReconcile()
*/
public void initialReconcile() {
IProblemRequestorExtension e = getProblemRequestorExtension();
if (e != null) {
try {
e.beginReportingSequence();
super.initialReconcile();
} finally {
e.endReportingSequence();
}
} else {
super.initialReconcile();
}
}
/**
* Called before reconciling is started.
*/
public void aboutToBeReconciled() {
fCStrategy.aboutToBeReconciled();
}
}

View file

@ -294,7 +294,7 @@ public class CReconciler extends MonoReconciler {
* @param editor the text editor
* @param strategy the C reconciling strategy
*/
public CReconciler(ITextEditor editor, CReconcilingStrategy strategy) {
public CReconciler(ITextEditor editor, CCompositeReconcilingStrategy strategy) {
super(strategy, false);
fTextEditor= editor;
}
@ -373,7 +373,7 @@ public class CReconciler extends MonoReconciler {
* @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToBeReconciled()
*/
protected void aboutToBeReconciled() {
CReconcilingStrategy strategy= (CReconcilingStrategy)getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
CCompositeReconcilingStrategy strategy= (CCompositeReconcilingStrategy)getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
strategy.aboutToBeReconciled();
}

View file

@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin, Google
* Sergey Prigogin (Google)
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
@ -43,6 +43,7 @@ import org.eclipse.jface.text.information.IInformationPresenter;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.text.information.InformationPresenter;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.reconciler.MonoReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
@ -85,6 +86,7 @@ import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverDescriptor;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverProxy;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
import org.eclipse.cdt.internal.ui.text.correction.CCorrectionAssistant;
import org.eclipse.cdt.internal.ui.typehierarchy.THInformationControl;
import org.eclipse.cdt.internal.ui.typehierarchy.THInformationProvider;
@ -93,6 +95,7 @@ import org.eclipse.cdt.internal.ui.typehierarchy.THInformationProvider;
* Configuration for an <code>SourceViewer</code> which shows C/C++ code.
*/
public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
private CTextTools fTextTools;
private ITextEditor fTextEditor;
/**
@ -372,6 +375,16 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
return settings;
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getQuickAssistAssistant(org.eclipse.jface.text.source.ISourceViewer)
* @since 5.0
*/
public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
if (getEditor() != null)
return new CCorrectionAssistant(getEditor());
return null;
}
/*
* @see org.eclipse.ui.editors.text.TextSourceViewerConfiguration#getReconciler(org.eclipse.jface.text.source.ISourceViewer)
*/
@ -379,7 +392,9 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
if (fTextEditor != null) {
//Delay changed and non-incremental reconciler used due to
//PR 130089
MonoReconciler reconciler= new CReconciler(fTextEditor, new CReconcilingStrategy(fTextEditor));
CCompositeReconcilingStrategy strategy=
new CCompositeReconcilingStrategy(sourceViewer, fTextEditor, getConfiguredDocumentPartitioning(sourceViewer));
MonoReconciler reconciler= new CReconciler(fTextEditor, strategy);
reconciler.setIsIncrementalReconciler(false);
reconciler.setProgressMonitor(new NullProgressMonitor());
reconciler.setDelay(500);

View file

@ -0,0 +1,116 @@
/*******************************************************************************
* 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.cdt.internal.ui.text;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
/**
* A reconciling strategy consisting of a sequence of internal reconciling strategies.
* By default, all requests are passed on to the contained strategies.
*/
public class CompositeReconcilingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
/** The list of internal reconciling strategies. */
private IReconcilingStrategy[] fStrategies;
/**
* Creates a new, empty composite reconciling strategy.
*/
public CompositeReconcilingStrategy() {
}
/**
* Sets the reconciling strategies for this composite strategy.
*
* @param strategies the strategies to be set or <code>null</code>
*/
public void setReconcilingStrategies(IReconcilingStrategy[] strategies) {
fStrategies= strategies;
}
/**
* Returns the previously set strategies or <code>null</code>.
*
* @return the contained strategies or <code>null</code>
*/
public IReconcilingStrategy[] getReconcilingStrategies() {
return fStrategies;
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
*/
public void setDocument(IDocument document) {
if (fStrategies == null)
return;
for (int i= 0; i < fStrategies.length; i++)
fStrategies[i].setDocument(document);
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion, org.eclipse.jface.text.IRegion)
*/
public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
if (fStrategies == null)
return;
for (int i= 0; i < fStrategies.length; i++)
fStrategies[i].reconcile(dirtyRegion, subRegion);
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
*/
public void reconcile(IRegion partition) {
if (fStrategies == null)
return;
for (int i= 0; i < fStrategies.length; i++)
fStrategies[i].reconcile(partition);
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
*/
public void setProgressMonitor(IProgressMonitor monitor) {
if (fStrategies == null)
return;
for (int i=0; i < fStrategies.length; i++) {
if (fStrategies[i] instanceof IReconcilingStrategyExtension) {
IReconcilingStrategyExtension extension= (IReconcilingStrategyExtension) fStrategies[i];
extension.setProgressMonitor(monitor);
}
}
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
*/
public void initialReconcile() {
if (fStrategies == null)
return;
for (int i = 0; i < fStrategies.length; i++) {
if (fStrategies[i] instanceof IReconcilingStrategyExtension) {
IReconcilingStrategyExtension extension= (IReconcilingStrategyExtension) fStrategies[i];
extension.initialReconcile();
}
}
}
}

View file

@ -0,0 +1,44 @@
/*******************************************************************************
* 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.cdt.internal.ui.text;
/**
* Html tag constants.
*/
public interface IHtmlTagConstants {
/** Html tag close prefix */
public static final String HTML_CLOSE_PREFIX= "</"; //$NON-NLS-1$
/** Html entity characters */
public static final char[] HTML_ENTITY_CHARACTERS= new char[] { '<', '>', ' ', '&', '^', '~', '\"' };
/**
* Html entity start.
*/
public static final char HTML_ENTITY_START= '&';
/**
* Html entity end.
*/
public static final char HTML_ENTITY_END= ';';
/** Html entity codes */
public static final String[] HTML_ENTITY_CODES= new String[] { "&lt;", "&gt;", "&nbsp;", "&amp;", "&circ;", "&tilde;", "&quot;" }; //$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= '<';
}

View file

@ -0,0 +1,339 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.quickassist.QuickAssistAssistant;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.core.model.ASTCache;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.text.CTextTools;
import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter;
import org.eclipse.cdt.internal.ui.text.IColorManager;
public class CCorrectionAssistant extends QuickAssistAssistant {
private ITextViewer fViewer;
private ITextEditor fEditor;
private Position fPosition;
private Annotation[] fCurrentAnnotations;
private QuickAssistLightBulbUpdater fLightBulbUpdater;
/**
* Constructor for CCorrectionAssistant.
*/
public CCorrectionAssistant(ITextEditor editor) {
super();
Assert.isNotNull(editor);
fEditor= editor;
CCorrectionProcessor processor= new CCorrectionProcessor(this);
setQuickAssistProcessor(processor);
setInformationControlCreator(getInformationControlCreator());
CTextTools textTools= CUIPlugin.getDefault().getTextTools();
IColorManager manager= textTools.getColorManager();
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
Color c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, manager);
setProposalSelectorForeground(c);
c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, manager);
setProposalSelectorBackground(c);
}
public IEditorPart getEditor() {
return fEditor;
}
private IInformationControlCreator getInformationControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, new HTMLTextPresenter());
}
};
}
private static Color getColor(IPreferenceStore store, String key, IColorManager manager) {
RGB rgb= PreferenceConverter.getColor(store, key);
return manager.getColor(rgb);
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.IContentAssistant#install(org.eclipse.jface.text.ITextViewer)
*/
public void install(ISourceViewer sourceViewer) {
super.install(sourceViewer);
fViewer= sourceViewer;
fLightBulbUpdater= new QuickAssistLightBulbUpdater(fEditor, sourceViewer);
fLightBulbUpdater.install();
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ContentAssistant#uninstall()
*/
public void uninstall() {
if (fLightBulbUpdater != null) {
fLightBulbUpdater.uninstall();
fLightBulbUpdater= null;
}
super.uninstall();
}
/**
* Show completions at caret position. If current
* position does not contain quick fixes look for
* next quick fix on same line by moving from left
* to right and restarting at end of line if the
* beginning of the line is reached.
*
* @see IQuickAssistAssistant#showPossibleQuickAssists()
*/
public String showPossibleQuickAssists() {
fPosition= null;
fCurrentAnnotations= null;
if (fViewer == null || fViewer.getDocument() == null)
// Let superclass deal with this
return super.showPossibleQuickAssists();
ArrayList resultingAnnotations= new ArrayList(20);
try {
Point selectedRange= fViewer.getSelectedRange();
int currOffset= selectedRange.x;
int currLength= selectedRange.y;
boolean goToClosest= (currLength == 0);
int newOffset= collectQuickFixableAnnotations(fEditor, currOffset, goToClosest, resultingAnnotations);
if (newOffset != currOffset) {
storePosition(currOffset, currLength);
fViewer.setSelectedRange(newOffset, 0);
fViewer.revealRange(newOffset, 0);
}
} catch (BadLocationException e) {
CUIPlugin.getDefault().log(e);
}
fCurrentAnnotations= (Annotation[]) resultingAnnotations.toArray(new Annotation[resultingAnnotations.size()]);
return super.showPossibleQuickAssists();
}
private static IRegion getRegionOfInterest(ITextEditor editor, int invocationLocation) throws BadLocationException {
IDocumentProvider documentProvider= editor.getDocumentProvider();
if (documentProvider == null) {
return null;
}
IDocument document= documentProvider.getDocument(editor.getEditorInput());
if (document == null) {
return null;
}
return document.getLineInformationOfOffset(invocationLocation);
}
public static int collectQuickFixableAnnotations(ITextEditor editor, int invocationLocation, boolean goToClosest, ArrayList resultingAnnotations) throws BadLocationException {
IAnnotationModel model= CUIPlugin.getDefault().getDocumentProvider().getAnnotationModel(editor.getEditorInput());
if (model == null) {
return invocationLocation;
}
ensureUpdatedAnnotations(editor);
Iterator iter= model.getAnnotationIterator();
if (goToClosest) {
IRegion lineInfo= getRegionOfInterest(editor, invocationLocation);
if (lineInfo == null) {
return invocationLocation;
}
int rangeStart= lineInfo.getOffset();
int rangeEnd= rangeStart + lineInfo.getLength();
ArrayList allAnnotations= new ArrayList();
ArrayList allPositions= new ArrayList();
int bestOffset= Integer.MAX_VALUE;
while (iter.hasNext()) {
Annotation annot= (Annotation) iter.next();
if (CCorrectionProcessor.isQuickFixableType(annot)) {
Position pos= model.getPosition(annot);
if (pos != null && isInside(pos.offset, rangeStart, rangeEnd)) { // inside our range?
allAnnotations.add(annot);
allPositions.add(pos);
bestOffset= processAnnotation(annot, pos, invocationLocation, bestOffset);
}
}
}
if (bestOffset == Integer.MAX_VALUE) {
return invocationLocation;
}
for (int i= 0; i < allPositions.size(); i++) {
Position pos= (Position) allPositions.get(i);
if (isInside(bestOffset, pos.offset, pos.offset + pos.length)) {
resultingAnnotations.add(allAnnotations.get(i));
}
}
return bestOffset;
} else {
while (iter.hasNext()) {
Annotation annot= (Annotation) iter.next();
if (CCorrectionProcessor.isQuickFixableType(annot)) {
Position pos= model.getPosition(annot);
if (pos != null && isInside(invocationLocation, pos.offset, pos.offset + pos.length)) {
resultingAnnotations.add(annot);
}
}
}
return invocationLocation;
}
}
private static void ensureUpdatedAnnotations(ITextEditor editor) {
Object inputElement= editor.getEditorInput().getAdapter(ICElement.class);
if (inputElement instanceof ITranslationUnit) {
final ASTProvider astProvider= CUIPlugin.getDefault().getASTProvider();
astProvider.runOnAST((ITranslationUnit) inputElement, ASTProvider.WAIT_ACTIVE_ONLY, null, new ASTCache.ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
return Status.OK_STATUS;
}
});
}
}
private static int processAnnotation(Annotation annot, Position pos, int invocationLocation, int bestOffset) {
int posBegin= pos.offset;
int posEnd= posBegin + pos.length;
if (isInside(invocationLocation, posBegin, posEnd)) { // covers invocation location?
return invocationLocation;
} else if (bestOffset != invocationLocation) {
int newClosestPosition= computeBestOffset(posBegin, invocationLocation, bestOffset);
if (newClosestPosition != -1) {
if (newClosestPosition != bestOffset) { // new best
if (CCorrectionProcessor.hasCorrections(annot)) { // only jump to it if there are proposals
return newClosestPosition;
}
}
}
}
return bestOffset;
}
private static boolean isInside(int offset, int start, int end) {
return offset == start || offset == end || (offset > start && offset < end); // make sure to handle 0-length ranges
}
/**
* Computes and returns the invocation offset given a new
* position, the initial offset and the best invocation offset
* found so far.
* <p>
* The closest offset to the left of the initial offset is the
* best. If there is no offset on the left, the closest on the
* right is the best.</p>
* @return -1 is returned if the given offset is not closer or the new best offset
*/
private static int computeBestOffset(int newOffset, int invocationLocation, int bestOffset) {
if (newOffset <= invocationLocation) {
if (bestOffset > invocationLocation) {
return newOffset; // closest was on the right, prefer on the left
} else if (bestOffset <= newOffset) {
return newOffset; // we are closer or equal
}
return -1; // further away
}
if (newOffset <= bestOffset)
return newOffset; // we are closer or equal
return -1; // further away
}
/*
* @see org.eclipse.jface.text.contentassist.ContentAssistant#possibleCompletionsClosed()
*/
protected void possibleCompletionsClosed() {
super.possibleCompletionsClosed();
restorePosition();
}
private void storePosition(int currOffset, int currLength) {
fPosition= new Position(currOffset, currLength);
}
private void restorePosition() {
if (fPosition != null && !fPosition.isDeleted() && fViewer.getDocument() != null) {
fViewer.setSelectedRange(fPosition.offset, fPosition.length);
fViewer.revealRange(fPosition.offset, fPosition.length);
}
fPosition= null;
}
/**
* Returns true if the last invoked completion was called with an updated offset.
*/
public boolean isUpdatedOffset() {
return fPosition != null;
}
/**
* Returns the annotations at the current offset
*/
public Annotation[] getAnnotationsAtOffset() {
return fCurrentAnnotations;
}
}

View file

@ -0,0 +1,489 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
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.ui.IEditorPart;
import org.eclipse.ui.IMarkerHelpRegistry;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.SimpleMarkerAnnotation;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IProblemLocation;
import org.eclipse.cdt.ui.text.IQuickFixProcessor;
import org.eclipse.cdt.internal.ui.editor.ICAnnotation;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProposal;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProposalComparator;
public class CCorrectionProcessor implements IQuickAssistProcessor {
private static final String QUICKFIX_PROCESSOR_CONTRIBUTION_ID= "quickFixProcessors"; //$NON-NLS-1$
private static final String QUICKASSIST_PROCESSOR_CONTRIBUTION_ID= "quickAssistProcessors"; //$NON-NLS-1$
private static ContributedProcessorDescriptor[] fgContributedAssistProcessors= null;
private static ContributedProcessorDescriptor[] fgContributedCorrectionProcessors= null;
private static ContributedProcessorDescriptor[] getProcessorDescriptors(String contributionId, boolean testMarkerTypes) {
IConfigurationElement[] elements= Platform.getExtensionRegistry().getConfigurationElementsFor(CUIPlugin.PLUGIN_ID, contributionId);
ArrayList res= new ArrayList(elements.length);
for (int i= 0; i < elements.length; i++) {
ContributedProcessorDescriptor desc= new ContributedProcessorDescriptor(elements[i], testMarkerTypes);
IStatus status= desc.checkSyntax();
if (status.isOK()) {
res.add(desc);
} else {
CUIPlugin.getDefault().log(status);
}
}
return (ContributedProcessorDescriptor[]) res.toArray(new ContributedProcessorDescriptor[res.size()]);
}
private static ContributedProcessorDescriptor[] getCorrectionProcessors() {
if (fgContributedCorrectionProcessors == null) {
fgContributedCorrectionProcessors= getProcessorDescriptors(QUICKFIX_PROCESSOR_CONTRIBUTION_ID, true);
}
return fgContributedCorrectionProcessors;
}
private static ContributedProcessorDescriptor[] getAssistProcessors() {
if (fgContributedAssistProcessors == null) {
fgContributedAssistProcessors= getProcessorDescriptors(QUICKASSIST_PROCESSOR_CONTRIBUTION_ID, false);
}
return fgContributedAssistProcessors;
}
public static boolean hasCorrections(ITranslationUnit cu, int problemId, String markerType) {
ContributedProcessorDescriptor[] processors= getCorrectionProcessors();
SafeHasCorrections collector= new SafeHasCorrections(cu, problemId);
for (int i= 0; i < processors.length; i++) {
if (processors[i].canHandleMarkerType(markerType)) {
collector.process(processors[i]);
if (collector.hasCorrections()) {
return true;
}
}
}
return false;
}
public static boolean isQuickFixableType(Annotation annotation) {
return (annotation instanceof ICAnnotation || annotation instanceof SimpleMarkerAnnotation) && !annotation.isMarkedDeleted();
}
public static boolean hasCorrections(Annotation annotation) {
if (annotation instanceof ICAnnotation) {
ICAnnotation cAnnotation= (ICAnnotation) annotation;
int problemId= cAnnotation.getId();
if (problemId != -1) {
ITranslationUnit cu= cAnnotation.getTranslationUnit();
if (cu != null) {
return hasCorrections(cu, problemId, cAnnotation.getMarkerType());
}
}
}
if (annotation instanceof SimpleMarkerAnnotation) {
return hasCorrections(((SimpleMarkerAnnotation) annotation).getMarker());
}
return false;
}
private static boolean hasCorrections(IMarker marker) {
if (marker == null || !marker.exists())
return false;
IMarkerHelpRegistry registry= IDE.getMarkerHelpRegistry();
return registry != null && registry.hasResolutions(marker);
}
public static boolean hasAssists(CorrectionContext context) {
ContributedProcessorDescriptor[] processors= getAssistProcessors();
SafeHasAssist collector= new SafeHasAssist(context);
for (int i= 0; i < processors.length; i++) {
collector.process(processors[i]);
if (collector.hasAssists()) {
return true;
}
}
return false;
}
private CCorrectionAssistant fAssistant;
private String fErrorMessage;
/*
* Constructor for CCorrectionProcessor.
*/
public CCorrectionProcessor(CCorrectionAssistant assistant) {
fAssistant= assistant;
fAssistant.addCompletionListener(new ICompletionListener() {
public void assistSessionEnded(ContentAssistEvent event) {
fAssistant.setStatusLineVisible(false);
}
public void assistSessionStarted(ContentAssistEvent event) {
fAssistant.setStatusLineVisible(true);
}
public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
if (proposal instanceof IStatusLineProposal) {
IStatusLineProposal statusLineProposal= (IStatusLineProposal)proposal;
String message= statusLineProposal.getStatusMessage();
if (message != null) {
fAssistant.setStatusMessage(message);
} else {
fAssistant.setStatusMessage(""); //$NON-NLS-1$
}
} else {
fAssistant.setStatusMessage(""); //$NON-NLS-1$
}
}
});
}
/*
* @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
*/
public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext quickAssistContext) {
ISourceViewer viewer= quickAssistContext.getSourceViewer();
int documentOffset= quickAssistContext.getOffset();
IEditorPart part= fAssistant.getEditor();
ITranslationUnit cu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(part.getEditorInput());
IAnnotationModel model= CUIPlugin.getDefault().getDocumentProvider().getAnnotationModel(part.getEditorInput());
int length= viewer != null ? viewer.getSelectedRange().y : 0;
CorrectionContext context= new CorrectionContext(cu, viewer, documentOffset, length);
Annotation[] annotations= fAssistant.getAnnotationsAtOffset();
fErrorMessage= null;
ICompletionProposal[] res= null;
if (model != null && annotations != null) {
ArrayList proposals= new ArrayList(10);
IStatus status= collectProposals(context, model, annotations, true, !fAssistant.isUpdatedOffset(), proposals);
res= (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
if (!status.isOK()) {
fErrorMessage= status.getMessage();
CUIPlugin.getDefault().log(status);
}
}
if (res == null || res.length == 0) {
return new ICompletionProposal[]
{ new CCompletionProposal("", 0, 0, null, CorrectionMessages.NoCorrectionProposal_description, 0) }; //$NON-NLS-1$
}
if (res.length > 1) {
Arrays.sort(res, new CCompletionProposalComparator());
}
return res;
}
public static IStatus collectProposals(CorrectionContext context, IAnnotationModel model, Annotation[] annotations, boolean addQuickFixes, boolean addQuickAssists, Collection proposals) {
ArrayList problems= new ArrayList();
// collect problem locations and corrections from marker annotations
for (int i= 0; i < annotations.length; i++) {
Annotation curr= annotations[i];
if (curr instanceof ICAnnotation) {
ProblemLocation problemLocation= getProblemLocation((ICAnnotation) curr, model);
if (problemLocation != null) {
problems.add(problemLocation);
}
} else if (addQuickFixes && curr instanceof SimpleMarkerAnnotation) {
// don't collect if annotation is already a C annotation
collectMarkerProposals((SimpleMarkerAnnotation) curr, proposals);
}
}
MultiStatus resStatus= null;
IProblemLocation[] problemLocations= (IProblemLocation[]) problems.toArray(new IProblemLocation[problems.size()]);
if (addQuickFixes) {
IStatus status= collectCorrections(context, problemLocations, proposals);
if (!status.isOK()) {
resStatus= new MultiStatus(CUIPlugin.PLUGIN_ID, IStatus.ERROR, CorrectionMessages.CCorrectionProcessor_error_quickfix_message, null);
resStatus.add(status);
}
}
if (addQuickAssists) {
IStatus status= collectAssists(context, problemLocations, proposals);
if (!status.isOK()) {
if (resStatus == null) {
resStatus= new MultiStatus(CUIPlugin.PLUGIN_ID, IStatus.ERROR, CorrectionMessages.CCorrectionProcessor_error_quickassist_message, null);
}
resStatus.add(status);
}
}
if (resStatus != null) {
return resStatus;
}
return Status.OK_STATUS;
}
private static ProblemLocation getProblemLocation(ICAnnotation cAnnotation, IAnnotationModel model) {
int problemId= cAnnotation.getId();
if (problemId != -1) {
Position pos= model.getPosition((Annotation) cAnnotation);
if (pos != null) {
return new ProblemLocation(pos.getOffset(), pos.getLength(), cAnnotation); // java problems all handled by the quick assist processors
}
}
return null;
}
private static void collectMarkerProposals(SimpleMarkerAnnotation annotation, Collection proposals) {
IMarker marker= annotation.getMarker();
IMarkerResolution[] res= IDE.getMarkerHelpRegistry().getResolutions(marker);
if (res.length > 0) {
for (int i= 0; i < res.length; i++) {
proposals.add(new MarkerResolutionProposal(res[i], marker));
}
}
}
private static abstract class SafeCorrectionProcessorAccess implements ISafeRunnable {
private MultiStatus fMulti= null;
private ContributedProcessorDescriptor fDescriptor;
public void process(ContributedProcessorDescriptor[] desc) {
for (int i= 0; i < desc.length; i++) {
fDescriptor= desc[i];
SafeRunner.run(this);
}
}
public void process(ContributedProcessorDescriptor desc) {
fDescriptor= desc;
SafeRunner.run(this);
}
public void run() throws Exception {
safeRun(fDescriptor);
}
protected abstract void safeRun(ContributedProcessorDescriptor processor) throws Exception;
public void handleException(Throwable exception) {
if (fMulti == null) {
fMulti= new MultiStatus(CUIPlugin.PLUGIN_ID, IStatus.OK, CorrectionMessages.CCorrectionProcessor_error_status, null);
}
fMulti.merge(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.ERROR, CorrectionMessages.CCorrectionProcessor_error_status, exception));
}
public IStatus getStatus() {
if (fMulti == null) {
return Status.OK_STATUS;
}
return fMulti;
}
}
private static class SafeCorrectionCollector extends SafeCorrectionProcessorAccess {
private final CorrectionContext fContext;
private final Collection fProposals;
private IProblemLocation[] fLocations;
public SafeCorrectionCollector(CorrectionContext context, Collection proposals) {
fContext= context;
fProposals= proposals;
}
public void setProblemLocations(IProblemLocation[] locations) {
fLocations= locations;
}
public void safeRun(ContributedProcessorDescriptor desc) throws Exception {
IQuickFixProcessor curr= (IQuickFixProcessor) desc.getProcessor(fContext.getTranslationUnit());
if (curr != null) {
ICCompletionProposal[] res= curr.getCorrections(fContext, fLocations);
if (res != null) {
for (int k= 0; k < res.length; k++) {
fProposals.add(res[k]);
}
}
}
}
}
private static class SafeAssistCollector extends SafeCorrectionProcessorAccess {
private final CorrectionContext fContext;
private final IProblemLocation[] fLocations;
private final Collection fProposals;
public SafeAssistCollector(CorrectionContext context, IProblemLocation[] locations, Collection proposals) {
fContext= context;
fLocations= locations;
fProposals= proposals;
}
public void safeRun(ContributedProcessorDescriptor desc) throws Exception {
IQuickFixProcessor curr= (IQuickFixProcessor) desc.getProcessor(fContext.getTranslationUnit());
if (curr != null) {
ICCompletionProposal[] res= curr.getCorrections(fContext, fLocations);
if (res != null) {
for (int k= 0; k < res.length; k++) {
fProposals.add(res[k]);
}
}
}
}
}
private static class SafeHasAssist extends SafeCorrectionProcessorAccess {
private final CorrectionContext fContext;
private boolean fHasAssists;
public SafeHasAssist(CorrectionContext context) {
fContext= context;
fHasAssists= false;
}
public boolean hasAssists() {
return fHasAssists;
}
public void safeRun(ContributedProcessorDescriptor desc) throws Exception {
IQuickAssistProcessor processor= (IQuickAssistProcessor) desc.getProcessor(fContext.getTranslationUnit());
if (processor != null && processor.canAssist(fContext)) {
fHasAssists= true;
}
}
}
private static class SafeHasCorrections extends SafeCorrectionProcessorAccess {
private final ITranslationUnit fCu;
private final int fProblemId;
private boolean fHasCorrections;
public SafeHasCorrections(ITranslationUnit cu, int problemId) {
fCu= cu;
fProblemId= problemId;
fHasCorrections= false;
}
public boolean hasCorrections() {
return fHasCorrections;
}
public void safeRun(ContributedProcessorDescriptor desc) throws Exception {
IQuickFixProcessor processor= (IQuickFixProcessor) desc.getProcessor(fCu);
if (processor != null && processor.hasCorrections(fCu, fProblemId)) {
fHasCorrections= true;
}
}
}
public static IStatus collectCorrections(CorrectionContext context, IProblemLocation[] locations, Collection proposals) {
ContributedProcessorDescriptor[] processors= getCorrectionProcessors();
SafeCorrectionCollector collector= new SafeCorrectionCollector(context, proposals);
for (int i= 0; i < processors.length; i++) {
ContributedProcessorDescriptor curr= processors[i];
IProblemLocation[] handled= getHandledProblems(locations, curr);
if (handled != null) {
collector.setProblemLocations(handled);
collector.process(curr);
}
}
return collector.getStatus();
}
private static IProblemLocation[] getHandledProblems(IProblemLocation[] locations, ContributedProcessorDescriptor processor) {
// implementation tries to avoid creating a new array
boolean allHandled= true;
ArrayList res= null;
for (int i= 0; i < locations.length; i++) {
IProblemLocation curr= locations[i];
if (processor.canHandleMarkerType(curr.getMarkerType())) {
if (!allHandled) { // first handled problem
if (res == null) {
res= new ArrayList(locations.length - i);
}
res.add(curr);
}
} else if (allHandled) {
if (i > 0) { // first non handled problem
res= new ArrayList(locations.length - i);
for (int k= 0; k < i; k++) {
res.add(locations[k]);
}
}
allHandled= false;
}
}
if (allHandled) {
return locations;
}
if (res == null) {
return null;
}
return (IProblemLocation[]) res.toArray(new IProblemLocation[res.size()]);
}
public static IStatus collectAssists(CorrectionContext context, IProblemLocation[] locations, Collection proposals) {
ContributedProcessorDescriptor[] processors= getAssistProcessors();
SafeAssistCollector collector= new SafeAssistCollector(context, locations, proposals);
collector.process(processors);
return collector.getStatus();
}
/*
* @see IContentAssistProcessor#getErrorMessage()
*/
public String getErrorMessage() {
return fErrorMessage;
}
/*
* @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canFix(org.eclipse.jface.text.source.Annotation)
*/
public boolean canFix(Annotation annotation) {
return hasCorrections(annotation);
}
/*
* @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canAssist(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext)
*/
public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
if (invocationContext instanceof CorrectionContext)
return hasAssists((CorrectionContext) invocationContext);
return false;
}
}

View file

@ -0,0 +1,123 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.expressions.ExpressionTagNames;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
public final class ContributedProcessorDescriptor {
private final IConfigurationElement fConfigurationElement;
private Object fProcessorInstance;
private Boolean fStatus;
private boolean fLastResult;
private final Set fHandledMarkerTypes;
private static final String ID= "id"; //$NON-NLS-1$
private static final String CLASS= "class"; //$NON-NLS-1$
private static final String HANDLED_MARKER_TYPES= "handledMarkerTypes"; //$NON-NLS-1$
private static final String MARKER_TYPE= "markerType"; //$NON-NLS-1$
public ContributedProcessorDescriptor(IConfigurationElement element, boolean testMarkerTypes) {
fConfigurationElement= element;
fProcessorInstance= null;
fStatus= null; // undefined
if (fConfigurationElement.getChildren(ExpressionTagNames.ENABLEMENT).length == 0) {
fStatus= Boolean.TRUE;
}
fHandledMarkerTypes= testMarkerTypes ? getHandledMarkerTypes(element) : null;
}
private Set getHandledMarkerTypes(IConfigurationElement element) {
HashSet map= new HashSet(7);
IConfigurationElement[] children= element.getChildren(HANDLED_MARKER_TYPES);
for (int i= 0; i < children.length; i++) {
IConfigurationElement[] types= children[i].getChildren(MARKER_TYPE);
for (int k= 0; k < types.length; k++) {
String attribute= types[k].getAttribute(ID);
if (attribute != null) {
map.add(attribute);
}
}
}
if (map.isEmpty()) {
map.add(ICModelMarker.TASK_MARKER);
}
return map;
}
public IStatus checkSyntax() {
IConfigurationElement[] children= fConfigurationElement.getChildren(ExpressionTagNames.ENABLEMENT);
if (children.length > 1) {
String id= fConfigurationElement.getAttribute(ID);
return new StatusInfo(IStatus.ERROR, "Only one < enablement > element allowed. Disabling " + id); //$NON-NLS-1$
}
return new StatusInfo(IStatus.OK, "Syntactically correct quick assist/fix processor"); //$NON-NLS-1$
}
private boolean matches(ITranslationUnit cunit) {
if (fStatus != null) {
return fStatus.booleanValue();
}
IConfigurationElement[] children= fConfigurationElement.getChildren(ExpressionTagNames.ENABLEMENT);
if (children.length == 1) {
try {
ExpressionConverter parser= ExpressionConverter.getDefault();
Expression expression= parser.perform(children[0]);
EvaluationContext evalContext= new EvaluationContext(null, cunit);
evalContext.addVariable("compilationUnit", cunit); //$NON-NLS-1$
ICProject cProject= cunit.getCProject();
String[] natures= cProject.getProject().getDescription().getNatureIds();
evalContext.addVariable("projectNatures", Arrays.asList(natures)); //$NON-NLS-1$
fLastResult= !(expression.evaluate(evalContext) != EvaluationResult.TRUE);
return fLastResult;
} catch (CoreException e) {
CUIPlugin.getDefault().log(e);
}
}
fStatus= Boolean.FALSE;
return false;
}
public Object getProcessor(ITranslationUnit cunit) throws CoreException {
if (matches(cunit)) {
if (fProcessorInstance == null) {
fProcessorInstance= fConfigurationElement.createExecutableExtension(CLASS);
}
return fProcessorInstance;
}
return null;
}
public boolean canHandleMarkerType(String markerType) {
return fHandledMarkerTypes == null || fHandledMarkerTypes.contains(markerType);
}
}

View file

@ -0,0 +1,142 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.editor.CEditor;
/**
* Handler to be used to run a quick fix or assist by keyboard shortcut
*/
public class CorrectionCommandHandler extends AbstractHandler {
private final CEditor fEditor;
private final String fId;
private final boolean fIsAssist;
public CorrectionCommandHandler(CEditor editor, String id, boolean isAssist) {
fEditor= editor;
fId= id;
fIsAssist= isAssist;
}
/* (non-Javadoc)
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
ISelection selection= fEditor.getSelectionProvider().getSelection();
ITranslationUnit cu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
IAnnotationModel model= CUIPlugin.getDefault().getDocumentProvider().getAnnotationModel(fEditor.getEditorInput());
if (selection instanceof ITextSelection && cu != null && model != null) {
ICompletionProposal proposal= findCorrection(fId, fIsAssist, (ITextSelection) selection, cu, model);
if (proposal != null) {
invokeProposal(proposal, ((ITextSelection) selection).getOffset());
}
}
return null;
}
private ICompletionProposal findCorrection(String id, boolean isAssist, ITextSelection selection, ITranslationUnit cu, IAnnotationModel model) {
CorrectionContext context= new CorrectionContext(cu, selection.getOffset(), selection.getLength());
Collection proposals= new ArrayList(10);
if (isAssist) {
CCorrectionProcessor.collectAssists(context, new ProblemLocation[0], proposals);
} else {
try {
boolean goToClosest= selection.getLength() == 0;
Annotation[] annotations= getAnnotations(selection.getOffset(), goToClosest);
CCorrectionProcessor.collectProposals(context, model, annotations, true, false, proposals);
} catch (BadLocationException e) {
return null;
}
}
for (Iterator iter= proposals.iterator(); iter.hasNext();) {
Object curr= iter.next();
if (curr instanceof ICommandAccess) {
if (id.equals(((ICommandAccess) curr).getCommandId())) {
return (ICompletionProposal) curr;
}
}
}
return null;
}
private Annotation[] getAnnotations(int offset, boolean goToClosest) throws BadLocationException {
ArrayList resultingAnnotations= new ArrayList();
CCorrectionAssistant.collectQuickFixableAnnotations(fEditor, offset, goToClosest, resultingAnnotations);
return (Annotation[]) resultingAnnotations.toArray(new Annotation[resultingAnnotations.size()]);
}
private IDocument getDocument() {
return CUIPlugin.getDefault().getDocumentProvider().getDocument(fEditor.getEditorInput());
}
private void invokeProposal(ICompletionProposal proposal, int offset) {
if (proposal instanceof ICompletionProposalExtension2) {
ITextViewer viewer= fEditor.getViewer();
if (viewer != null) {
((ICompletionProposalExtension2) proposal).apply(viewer, (char) 0, 0, offset);
return;
}
} else if (proposal instanceof ICompletionProposalExtension) {
IDocument document= getDocument();
if (document != null) {
((ICompletionProposalExtension) proposal).apply(document, (char) 0, offset);
return;
}
}
IDocument document= getDocument();
if (document != null) {
proposal.apply(document);
}
}
public static String getShortCutString(String proposalId) {
if (proposalId != null) {
IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
if (bindingService != null) {
TriggerSequence[] activeBindingsFor= bindingService.getActiveBindingsFor(proposalId);
if (activeBindingsFor.length > 0) {
return activeBindingsFor[0].format();
}
}
}
return null;
}
}

View file

@ -0,0 +1,80 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.LegacyHandlerSubmissionExpression;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.editor.CEditor;
public class CorrectionCommandInstaller {
/**
* All correction commands must start with the following prefix.
*/
public static final String COMMAND_PREFIX= "org.eclipse.jdt.ui.correction."; //$NON-NLS-1$
/**
* Commands for quick assist must have the following suffix.
*/
public static final String ASSIST_SUFFIX= ".assist"; //$NON-NLS-1$
private List fCorrectionHandlerActivations;
public CorrectionCommandInstaller() {
fCorrectionHandlerActivations= null;
}
public void registerCommands(CEditor editor) {
IWorkbench workbench= PlatformUI.getWorkbench();
ICommandService commandService= (ICommandService) workbench.getAdapter(ICommandService.class);
IHandlerService handlerService= (IHandlerService) workbench.getAdapter(IHandlerService.class);
if (commandService == null || handlerService == null) {
return;
}
if (fCorrectionHandlerActivations != null) {
CUIPlugin.getDefault().logErrorMessage("correction handler activations not released"); //$NON-NLS-1$
}
fCorrectionHandlerActivations= new ArrayList();
Collection definedCommandIds= commandService.getDefinedCommandIds();
for (Iterator iter= definedCommandIds.iterator(); iter.hasNext();) {
String id= (String) iter.next();
if (id.startsWith(COMMAND_PREFIX)) {
boolean isAssist= id.endsWith(ASSIST_SUFFIX);
CorrectionCommandHandler handler= new CorrectionCommandHandler(editor, id, isAssist);
IHandlerActivation activation= handlerService.activateHandler(id, handler, new LegacyHandlerSubmissionExpression(null, null, editor.getSite()));
fCorrectionHandlerActivations.add(activation);
}
}
}
public void deregisterCommands() {
IHandlerService handlerService= (IHandlerService) PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
if (handlerService != null && fCorrectionHandlerActivations != null) {
handlerService.deactivateHandlers(fCorrectionHandlerActivations);
fCorrectionHandlerActivations= null;
}
}
}

View file

@ -0,0 +1,61 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.TextInvocationContext;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.text.IInvocationContext;
public class CorrectionContext extends TextInvocationContext implements IInvocationContext {
private ITranslationUnit fTranslationUnit;
/*
* Constructor for CorrectionContext.
*/
public CorrectionContext(ITranslationUnit tu, ISourceViewer sourceViewer, int offset, int length) {
super(sourceViewer, offset, length);
fTranslationUnit= tu;
}
/*
* Constructor for CorrectionContext.
*/
public CorrectionContext(ITranslationUnit tu, int offset, int length) {
this(tu, null, offset, length);
}
/**
* Returns the translation unit.
* @return an <code>ITranslationUnit</code>
*/
public ITranslationUnit getTranslationUnit() {
return fTranslationUnit;
}
/**
* Returns the length.
* @return int
*/
public int getSelectionLength() {
return Math.max(getLength(), 0);
}
/**
* Returns the offset.
* @return int
*/
public int getSelectionOffset() {
return getOffset();
}
}

View file

@ -0,0 +1,35 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import org.eclipse.osgi.util.NLS;
/**
* Helper class to get NLSed messages.
*/
public final class CorrectionMessages extends NLS {
private static final String BUNDLE_NAME= CorrectionMessages.class.getName();
static {
NLS.initializeMessages(BUNDLE_NAME, CorrectionMessages.class);
}
private CorrectionMessages() {
// Do not instantiate
}
public static String CCorrectionProcessor_error_quickassist_message;
public static String CCorrectionProcessor_error_quickfix_message;
public static String CCorrectionProcessor_error_status;
public static String MarkerResolutionProposal_additionaldesc;
public static String NoCorrectionProposal_description;
}

View file

@ -0,0 +1,18 @@
###############################################################################
# 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
# Sergey Prigogin (Google)
###############################################################################
CCorrectionProcessor_error_quickassist_message=An error occurred while computing quick assists. Check log for details.
CCorrectionProcessor_error_quickfix_message=An error occurred while computing quick fixes. Check log for details.
CCorrectionProcessor_error_status=Exception while processing quick fixes or quick assists
MarkerResolutionProposal_additionaldesc=Problem description: {0}
NoCorrectionProposal_description=No suggestions available

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
/**
* Correction proposals implement this interface to by invokable by a command.
* (e.g. keyboard shortcut)
*/
public interface ICommandAccess {
/**
* Returns the id of the command that should invoke this correction proposal
* @return the id of the command. This id must start with {@link CorrectionCommandInstaller#COMMAND_PREFIX}
* to be recognixes as correction command.
*/
String getCommandId();
}

View file

@ -0,0 +1,46 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
/**
* Html tag constants.
*/
public interface IHtmlTagConstants {
/** Html tag close prefix */
public static final String HTML_CLOSE_PREFIX= "</"; //$NON-NLS-1$
/** Html entity characters */
public static final char[] HTML_ENTITY_CHARACTERS= new char[] { '<', '>', ' ', '&', '^', '~', '\"' };
/**
* Html entity start.
*/
public static final char HTML_ENTITY_START= '&';
/**
* Html entity end.
*/
public static final char HTML_ENTITY_END= ';';
/** Html entity codes */
public static final String[] HTML_ENTITY_CODES= new String[] { "&lt;", "&gt;", "&nbsp;", "&amp;", "&circ;", "&tilde;", "&quot;" }; //$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= '<';
}

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
/**
* A proposal which is able to show a message
* on the status line of the content assistant
* in which this proposal is shown.
*
* @see org.eclipse.jface.text.contentassist.IContentAssistantExtension2
*/
public interface IStatusLineProposal {
/**
* The message to show when this proposal is
* selected by the user in the content assistant.
*
* @return The message to show, or null for no message.
*/
public String getStatusMessage();
}

View file

@ -0,0 +1,120 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
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.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolution2;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.internal.ui.CPluginImages;
public class MarkerResolutionProposal implements ICCompletionProposal {
private IMarkerResolution fResolution;
private IMarker fMarker;
/**
* Constructor for MarkerResolutionProposal.
*/
public MarkerResolutionProposal(IMarkerResolution resolution, IMarker marker) {
fResolution= resolution;
fMarker= marker;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
*/
public void apply(IDocument document) {
fResolution.run(fMarker);
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
*/
public String getAdditionalProposalInfo() {
if (fResolution instanceof IMarkerResolution2) {
return ((IMarkerResolution2) fResolution).getDescription();
}
if (fResolution instanceof ICCompletionProposal) {
return ((ICCompletionProposal) fResolution).getAdditionalProposalInfo();
}
try {
String problemDesc= (String) fMarker.getAttribute(IMarker.MESSAGE);
return CorrectionMessages.bind(CorrectionMessages.MarkerResolutionProposal_additionaldesc,
problemDesc);
} catch (CoreException e) {
CUIPlugin.getDefault().log(e);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
*/
public IContextInformation getContextInformation() {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
*/
public String getDisplayString() {
return fResolution.getLabel();
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
*/
public Image getImage() {
if (fResolution instanceof IMarkerResolution2) {
return ((IMarkerResolution2) fResolution).getImage();
}
if (fResolution instanceof ICCompletionProposal) {
return ((ICCompletionProposal) fResolution).getImage();
}
return CPluginImages.get(CPluginImages.IMG_CORRECTION_CHANGE);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.java.ICCompletionProposal#getRelevance()
*/
public int getRelevance() {
if (fResolution instanceof ICCompletionProposal) {
return ((ICCompletionProposal) fResolution).getRelevance();
}
return 10;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
*/
public Point getSelection(IDocument document) {
if (fResolution instanceof ICCompletionProposal) {
return ((ICCompletionProposal) fResolution).getSelection(document);
}
return null;
}
public String getIdString() {
return getDisplayString();
}
}

View file

@ -0,0 +1,138 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.parser.IPersistableProblem;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.ui.text.IProblemLocation;
import org.eclipse.cdt.internal.ui.editor.CMarkerAnnotation;
import org.eclipse.cdt.internal.ui.editor.ICAnnotation;
public class ProblemLocation implements IProblemLocation {
private final int fId;
private final String[] fArguments;
private final int fOffset;
private final int fLength;
private final boolean fIsError;
private final String fMarkerType;
public ProblemLocation(int offset, int length, ICAnnotation annotation) {
fId= annotation.getId();
fArguments= annotation.getArguments();
fOffset= offset;
fLength= length;
fIsError= CMarkerAnnotation.ERROR_ANNOTATION_TYPE.equals(annotation.getType());
String markerType= annotation.getMarkerType();
fMarkerType= markerType != null ? markerType : ICModelMarker.C_MODEL_PROBLEM_MARKER;
}
public ProblemLocation(int offset, int length, int id, String[] arguments, boolean isError, String markerType) {
fId= id;
fArguments= arguments;
fOffset= offset;
fLength= length;
fIsError= isError;
fMarkerType= markerType;
}
public ProblemLocation(IProblem problem) {
fId= problem.getID();
fArguments= problem.getArguments();
fOffset= problem.getSourceStart();
fLength= problem.getSourceEnd() - fOffset + 1;
fIsError= problem.isError();
fMarkerType= problem instanceof IPersistableProblem ?
((IPersistableProblem) problem).getMarkerType() : ICModelMarker.C_MODEL_PROBLEM_MARKER;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.IProblemLocation#getProblemId()
*/
public int getProblemId() {
return fId;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.IProblemLocation#getProblemArguments()
*/
public String[] getProblemArguments() {
return fArguments;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.IProblemLocation#getLength()
*/
public int getLength() {
return fLength;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.IProblemLocation#getOffset()
*/
public int getOffset() {
return fOffset;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.text.java.IProblemLocation#isError()
*/
public boolean isError() {
return fIsError;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.text.java.IProblemLocation#getMarkerType()
*/
public String getMarkerType() {
return fMarkerType;
}
public String toString() {
StringBuffer buf= new StringBuffer();
buf.append("Id: ").append(getErrorCode(fId)).append('\n'); //$NON-NLS-1$
buf.append('[').append(fOffset).append(", ").append(fLength).append(']').append('\n'); //$NON-NLS-1$
String[] arg= fArguments;
if (arg != null) {
for (int i= 0; i < arg.length; i++) {
buf.append(arg[i]);
buf.append('\n');
}
}
return buf.toString();
}
private String getErrorCode(int code) {
StringBuffer buf= new StringBuffer();
if ((code & IProblem.SCANNER_RELATED) != 0) {
buf.append("ScannerRelated + "); //$NON-NLS-1$
}
if ((code & IProblem.PREPROCESSOR_RELATED) != 0) {
buf.append("PreprocessorRelated + "); //$NON-NLS-1$
}
if ((code & IProblem.SEMANTICS_RELATED) != 0) {
buf.append("SemanticsRelated + "); //$NON-NLS-1$
}
if ((code & IProblem.INTERNAL_RELATED) != 0) {
buf.append("Internal + "); //$NON-NLS-1$
}
if ((code & IProblem.SYNTAX_RELATED) != 0) {
buf.append("Syntax + "); //$NON-NLS-1$
}
buf.append(code & IProblem.IGNORE_CATEGORIES_MASK);
return buf.toString();
}
}

View file

@ -0,0 +1,287 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.correction;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationAccessExtension;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationPresentation;
import org.eclipse.jface.text.source.ImageUtilities;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.internal.ui.viewsupport.ISelectionListenerWithAST;
import org.eclipse.cdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
/**
*
*/
public class QuickAssistLightBulbUpdater {
public static class AssistAnnotation extends Annotation implements IAnnotationPresentation {
//XXX: To be fully correct this should be a non-static fields in QuickAssistLightBulbUpdater
private static final int LAYER;
static {
Annotation annotation= new Annotation("org.eclipse.jdt.ui.warning", false, null); //$NON-NLS-1$
AnnotationPreference preference= EditorsUI.getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
if (preference != null)
LAYER= preference.getPresentationLayer() - 1;
else
LAYER= IAnnotationAccessExtension.DEFAULT_LAYER;
}
private Image fImage;
public AssistAnnotation() {
}
/*
* @see org.eclipse.jface.text.source.IAnnotationPresentation#getLayer()
*/
public int getLayer() {
return LAYER;
}
private Image getImage() {
if (fImage == null) {
fImage= CPluginImages.get(CPluginImages.IMG_OBJS_QUICK_ASSIST);
}
return fImage;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.source.Annotation#paint(org.eclipse.swt.graphics.GC, org.eclipse.swt.widgets.Canvas, org.eclipse.swt.graphics.Rectangle)
*/
public void paint(GC gc, Canvas canvas, Rectangle r) {
ImageUtilities.drawImage(getImage(), gc, canvas, r, SWT.CENTER, SWT.TOP);
}
}
private final Annotation fAnnotation;
private boolean fIsAnnotationShown;
private ITextEditor fEditor;
private ITextViewer fViewer;
private ISelectionListenerWithAST fListener;
private IPropertyChangeListener fPropertyChangeListener;
public QuickAssistLightBulbUpdater(ITextEditor part, ITextViewer viewer) {
fEditor= part;
fViewer= viewer;
fAnnotation= new AssistAnnotation();
fIsAnnotationShown= false;
fPropertyChangeListener= null;
}
public boolean isSetInPreferences() {
return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_QUICKASSIST_LIGHTBULB);
}
private void installSelectionListener() {
fListener= new ISelectionListenerWithAST() {
public void selectionChanged(IEditorPart part,
ITextSelection selection, IASTTranslationUnit astRoot) {
doSelectionChanged(selection.getOffset(), selection.getLength(), astRoot);
}
};
SelectionListenerWithASTManager.getDefault().addListener(fEditor, fListener);
}
private void uninstallSelectionListener() {
if (fListener != null) {
SelectionListenerWithASTManager.getDefault().removeListener(fEditor, fListener);
fListener= null;
}
IAnnotationModel model= getAnnotationModel();
if (model != null) {
removeLightBulb(model);
}
}
public void install() {
if (isSetInPreferences()) {
installSelectionListener();
}
if (fPropertyChangeListener == null) {
fPropertyChangeListener= new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
doPropertyChanged(event.getProperty());
}
};
PreferenceConstants.getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener);
}
}
public void uninstall() {
uninstallSelectionListener();
if (fPropertyChangeListener != null) {
PreferenceConstants.getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener= null;
}
}
protected void doPropertyChanged(String property) {
if (property.equals(PreferenceConstants.EDITOR_QUICKASSIST_LIGHTBULB)) {
if (isSetInPreferences()) {
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
if (workingCopy != null) {
installSelectionListener();
final Point point= fViewer.getSelectedRange();
ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot) {
if (astRoot != null) {
doSelectionChanged(point.x, point.y, astRoot);
}
return Status.OK_STATUS;
}
});
}
} else {
uninstallSelectionListener();
}
}
}
private ITranslationUnit getTranslationUnit() {
ICElement elem= EditorUtility.getEditorInputCElement(fEditor);
if (elem instanceof ITranslationUnit) {
return (ITranslationUnit) elem;
}
return null;
}
private IAnnotationModel getAnnotationModel() {
return CUIPlugin.getDefault().getDocumentProvider().getAnnotationModel(fEditor.getEditorInput());
}
private IDocument getDocument() {
return CUIPlugin.getDefault().getDocumentProvider().getDocument(fEditor.getEditorInput());
}
private void doSelectionChanged(int offset, int length, IASTTranslationUnit astRoot) {
final IAnnotationModel model= getAnnotationModel();
final ITranslationUnit cu= getTranslationUnit();
if (model == null || cu == null) {
return;
}
final CorrectionContext context= new CorrectionContext(cu, offset, length);
boolean hasQuickFix= hasQuickFixLightBulb(model, context.getSelectionOffset());
if (hasQuickFix) {
removeLightBulb(model);
return; // there is already a quick fix light bulb at the new location
}
calculateLightBulb(model, context);
}
/*
* Needs to be called synchronized
*/
private void calculateLightBulb(IAnnotationModel model, CorrectionContext context) {
boolean needsAnnotation= CCorrectionProcessor.hasAssists(context);
if (fIsAnnotationShown) {
model.removeAnnotation(fAnnotation);
}
if (needsAnnotation) {
model.addAnnotation(fAnnotation, new Position(context.getSelectionOffset(), context.getSelectionLength()));
}
fIsAnnotationShown= needsAnnotation;
}
private void removeLightBulb(IAnnotationModel model) {
synchronized (this) {
if (fIsAnnotationShown) {
model.removeAnnotation(fAnnotation);
fIsAnnotationShown= false;
}
}
}
/*
* Tests if there is already a quick fix light bulb on the current line
*/
private boolean hasQuickFixLightBulb(IAnnotationModel model, int offset) {
try {
IDocument document= getDocument();
if (document == null) {
return false;
}
// we access a document and annotation model from within a job
// since these are only read accesses, we won't hurt anyone else if
// this goes boink
// may throw an IndexOutOfBoundsException upon concurrent document modification
int currLine= document.getLineOfOffset(offset);
// this iterator is not protected, it may throw ConcurrentModificationExceptions
Iterator iter= model.getAnnotationIterator();
while (iter.hasNext()) {
Annotation annot= (Annotation) iter.next();
if (CCorrectionProcessor.isQuickFixableType(annot)) {
// may throw an IndexOutOfBoundsException upon concurrent annotation model changes
Position pos= model.getPosition(annot);
if (pos != null) {
// may throw an IndexOutOfBoundsException upon concurrent document modification
int startLine= document.getLineOfOffset(pos.getOffset());
if (startLine == currLine && CCorrectionProcessor.hasCorrections(annot)) {
return true;
}
}
}
}
} catch (BadLocationException e) {
// ignore
} catch (IndexOutOfBoundsException e) {
// concurrent modification - too bad, ignore
} catch (ConcurrentModificationException e) {
// concurrent modification - too bad, ignore
}
return false;
}
}

View file

@ -0,0 +1,176 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
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.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
/**
* Proposal to add the unknown word to the dictionaries.
*/
public class AddWordProposal implements ICCompletionProposal {
private static final String PREF_KEY_DO_NOT_ASK= "do_not_ask_to_install_user_dictionary"; //$NON-NLS-1$
/** The invocation context */
private final IInvocationContext 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 IInvocationContext 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;
IQuickAssistInvocationContext quickAssistContext= null;
if (fContext instanceof IQuickAssistInvocationContext)
quickAssistContext= (IQuickAssistInvocationContext)fContext;
if (!checker.acceptsWords()) {
final Shell shell;
if (quickAssistContext != null && quickAssistContext.getSourceViewer() != null)
shell= quickAssistContext.getSourceViewer().getTextWidget().getShell();
else
shell= CUIPlugin.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 (quickAssistContext != null && quickAssistContext.getSourceViewer() != null) {
SpellingProblem.removeAll(quickAssistContext.getSourceViewer(), fWord);
}
}
}
/**
* Asks the user whether he wants to configure
* a user dictionary.
*
* @param shell
* @return <code>true</code> if the user wants to configure the user dictionary
*/
private boolean askUserToConfigureUserDictionary(Shell shell) {
MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openYesNoQuestion(
shell,
Messages.Spelling_add_askToConfigure_title,
Messages.Spelling_add_askToConfigure_question,
Messages.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 <code>true</code> 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.bind(Messages.Spelling_add_info, 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.bind(Messages.Spelling_add_label, fWord);
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
*/
public Image getImage() {
return CPluginImages.get(CPluginImages.IMG_CORRECTION_ADD);
}
/*
* @see org.eclipse.cdt.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.getSelectionOffset(), fContext.getSelectionLength());
}
public String getIdString() {
return fWord;
}
}

View file

@ -0,0 +1,136 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.TypedRegion;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.ui.text.CTextTools;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEventListener;
/**
* C/C++ spelling engine
*/
public class CSpellingEngine extends SpellingEngine {
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.SpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.cdt.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) {
ISpellEventListener listener= new SpellEventListener(collector, document);
boolean isIgnoringStringLiterals= SpellingPreferences.isIgnoreStringLiterals();
try {
checker.addListener(listener);
try {
for (int i= 0; i < regions.length; i++) {
IRegion region= regions[i];
ITypedRegion[] partitions= TextUtilities.computePartitioning(document,
ICPartitions.C_PARTITIONING, region.getOffset(), region.getLength(), false);
for (int index= 0; index < partitions.length; index++) {
if (monitor != null && monitor.isCanceled())
return;
ITypedRegion partition= partitions[index];
final String type= partition.getType();
if (isIgnoringStringLiterals && type.equals(ICPartitions.C_STRING))
continue;
if (type.equals(ICPartitions.C_PREPROCESSOR)) {
CTextTools textTools = CUIPlugin.getDefault().getTextTools();
RuleBasedScanner scanner = textTools.getCppPreprocessorScanner();
scanner.setRange(document, partition.getOffset(), partition.getLength());
int firstTokenOffset = -1;
int firstTokenLength = -1;
while (true) {
IToken token = scanner.nextToken();
if (token.isEOF()) {
break;
}
if (token.isOther()) {
int offset = scanner.getTokenOffset();
int length = scanner.getTokenLength();
if (firstTokenOffset < 0) {
firstTokenOffset = offset;
firstTokenLength = length;
}
String subregionType = null;
char c = document.getChar(offset);
if (c == '"') {
if (!isIgnoringStringLiterals &&
!isIncludeDirective(document, firstTokenOffset, firstTokenLength)) {
subregionType = ICPartitions.C_STRING;
}
} else if (c == '/' && length >= 2) {
c = document.getChar(offset + 1);
if (c == '/') {
subregionType = ICPartitions.C_SINGLE_LINE_COMMENT;
} else if (c == '*') {
subregionType = ICPartitions.C_MULTI_LINE_COMMENT;
}
}
if (subregionType != null) {
TypedRegion subregion = new TypedRegion(offset, length, subregionType);
checker.execute(new SpellCheckIterator(document, subregion,
checker.getLocale()));
}
}
}
} else if (!type.equals(IDocument.DEFAULT_CONTENT_TYPE) &&
!type.equals(ICPartitions.C_CHARACTER)) {
checker.execute(new SpellCheckIterator(document, partition, checker.getLocale()));
}
}
}
} catch (BadLocationException x) {
CUIPlugin.getDefault().log(x);
}
} finally {
checker.removeListener(listener);
}
}
/**
* Returns <code>true</code> if the token at the given offset and length is an include directive.
* @param document
* @param offset
* @param length
* @return
* @throws BadLocationException
*/
private boolean isIncludeDirective(IDocument document, int offset, int length) throws BadLocationException {
while (length > 0) {
char c = document.getChar(offset);
if (c == '#' || Character.isWhitespace(c)) {
offset++;
length--;
} else if (c == 'i') {
return document.get(offset, length).startsWith("include"); //$NON-NLS-1$
} else {
break;
}
}
return false;
}
}

View file

@ -0,0 +1,202 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.internal.ui.text.correction.CorrectionContext;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent;
import org.eclipse.cdt.internal.ui.text.spelling.engine.RankedWordProposal;
/**
* A {@link SpellingProblem} that adapts a {@link ISpellEvent}.
* <p>
* TODO: remove {@link ISpellEvent} notification mechanism
* </p>
*/
public class CSpellingProblem extends SpellingProblem {
/** Spell event */
private ISpellEvent fSpellEvent;
/**
* The associated document.
*/
private IDocument fDocument;
/**
* Initialize with the given spell event.
*
* @param spellEvent the spell event
* @param document the document
*/
public CSpellingProblem(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.bind(Messages.Spelling_error_case_label, fSpellEvent.getWord());
return Messages.bind(Messages.Spelling_error_label, fSpellEvent.getWord());
}
/*
* @see org.eclipse.ui.texteditor.spelling.SpellingProblem#getProposals()
*/
public ICompletionProposal[] getProposals() {
String[] arguments= getArguments();
if (arguments == null)
return new ICompletionProposal[0];
final int threshold= SpellingPreferences.spellingProposalThreshold();
int size= 0;
List proposals= null;
RankedWordProposal proposal= null;
ICCompletionProposal[] 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) {
CorrectionContext context= new CorrectionContext(null, getOffset(), getLength());
if ((sentence && match) && !fixed) {
result= new ICCompletionProposal[] { 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 ICCompletionProposal[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;
}
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());
int end= getOffset() + getLength();
prefix= fDocument.get(line.getOffset(), getOffset()
- line.getOffset());
postfix= fDocument.get(end + 1, line.getOffset() + line.getLength()
- end);
} 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 <code>true</code> iff the corresponding word was found in the dictionary.
* <p>
* NOTE: to be removed, see {@link #getProposals()}
* </p>
*
* @return <code>true</code> iff the corresponding word was found in the dictionary
*/
public boolean isDictionaryMatch() {
return fSpellEvent.isMatch();
}
/**
* Returns <code>true</code> iff the corresponding word starts a sentence.
* <p>
* NOTE: to be removed, see {@link #getProposals()}
* </p>
*
* @return <code>true</code> iff the corresponding word starts a sentence
*/
public boolean isSentenceStart() {
return fSpellEvent.isStart();
}
}

View file

@ -0,0 +1,163 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy;
import org.eclipse.ui.texteditor.spelling.SpellingService;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.IProblemRequestor;
import org.eclipse.cdt.core.parser.IProblem;
/**
* Reconcile strategy for spell checking comments.
*/
public class CSpellingReconcileStrategy extends SpellingReconcileStrategy {
/**
* Spelling problem collector that forwards {@link SpellingProblem}s as
* {@link IProblem}s to the {@link IProblemRequestor}.
*/
private class SpellingProblemCollector implements ISpellingProblemCollector {
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept(org.eclipse.ui.texteditor.spelling.SpellingProblem)
*/
public void accept(SpellingProblem problem) {
IProblemRequestor requestor= fRequestor;
if (requestor != null) {
try {
int line= getDocument().getLineOfOffset(problem.getOffset()) + 1;
String word= getDocument().get(problem.getOffset(), problem.getLength());
boolean dictionaryMatch= false;
boolean sentenceStart= false;
if (problem instanceof CSpellingProblem) {
dictionaryMatch= ((CSpellingProblem)problem).isDictionaryMatch();
sentenceStart= ((CSpellingProblem) problem).isSentenceStart();
}
// see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=81514
IEditorInput editorInput= fEditor.getEditorInput();
if (editorInput != null) {
CoreSpellingProblem iProblem= new CoreSpellingProblem(problem.getOffset(), problem.getOffset() + problem.getLength() - 1, line, problem.getMessage(), word, dictionaryMatch, sentenceStart, getDocument(), editorInput.getName());
requestor.acceptProblem(iProblem);
}
} catch (BadLocationException x) {
// drop this SpellingProblem
}
}
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#beginCollecting()
*/
public void beginCollecting() {
if (fRequestor != null)
fRequestor.beginReporting();
}
/*
* @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#endCollecting()
*/
public void endCollecting() {
if (fRequestor != null)
fRequestor.endReporting();
}
}
/** The id of the problem */
public static final int SPELLING_PROBLEM_ID= 0x80000000;
/** Properties file content type */
private static final IContentType CXX_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE);
/** The text editor to operate on. */
private ITextEditor fEditor;
/** The problem requester. */
private IProblemRequestor fRequestor;
/**
* Creates a new comment reconcile strategy.
*
* @param viewer the source viewer
* @param editor the text editor to operate on
*/
public CSpellingReconcileStrategy(ISourceViewer viewer, ITextEditor editor) {
super(viewer, CSpellingService.getInstance());
fEditor= editor;
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
*/
public void reconcile(IRegion region) {
if (fRequestor != null && isSpellingEnabled())
super.reconcile(region);
}
private boolean isSpellingEnabled() {
return EditorsUI.getPreferenceStore().getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED);
}
/*
* @see org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy#createSpellingProblemCollector()
*/
protected ISpellingProblemCollector createSpellingProblemCollector() {
return new SpellingProblemCollector();
}
/*
* @see org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy#getContentType()
*/
protected IContentType getContentType() {
return CXX_CONTENT_TYPE;
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
*/
public void setDocument(IDocument document) {
super.setDocument(document);
updateProblemRequester();
}
/**
* Update the problem requester based on the current editor
*/
private void updateProblemRequester() {
IAnnotationModel model= getAnnotationModel();
fRequestor= (model instanceof IProblemRequestor) ? (IProblemRequestor) model : null;
}
/*
* @see org.eclipse.ui.texteditor.spelling.SpellingReconcileStrategy#getAnnotationModel()
*/
protected IAnnotationModel getAnnotationModel() {
final IDocumentProvider documentProvider= fEditor.getDocumentProvider();
if (documentProvider == null)
return null;
return documentProvider.getAnnotationModel(fEditor.getEditorInput());
}
}

View file

@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2007 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.spelling.ISpellingEngine;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingService;
/**
* Platform's SpellingService uses a spelling engine that is independent
* of the content type (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185695).
* We are providing our own SpellingService to be able to use the C/C++ specific
* spelling engine even when it is not selected in
* Preferences/General/Editors/Text Editors/Spelling.
*/
public class CSpellingService extends SpellingService {
private static CSpellingService fInstance;
private IPreferenceStore fPreferences;
private ISpellingEngine fEngine;
public static CSpellingService getInstance() {
if (fInstance == null) {
fInstance = new CSpellingService(EditorsUI.getPreferenceStore());
}
return fInstance;
}
public void check(final IDocument document, final IRegion[] regions, final SpellingContext context,
final ISpellingProblemCollector collector, final IProgressMonitor monitor) {
try {
collector.beginCollecting();
if (fPreferences.getBoolean(PREFERENCE_SPELLING_ENABLED))
if (fEngine == null) {
fEngine = new CSpellingEngine();
}
ISafeRunnable runnable= new ISafeRunnable() {
public void run() throws Exception {
fEngine.check(document, regions, context, collector, monitor);
}
public void handleException(Throwable x) {
}
};
SafeRunner.run(runnable);
} finally {
collector.endCollecting();
}
}
private CSpellingService(IPreferenceStore preferences) {
super(preferences);
fPreferences = preferences;
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import java.util.Locale;
import org.eclipse.cdt.ui.text.IInvocationContext;
/**
* Proposal to change the letter case of a word.
*/
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 IInvocationContext 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 Messages.Spelling_case_label;
}
}

View file

@ -0,0 +1,185 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.cdt.core.parser.IPersistableProblem;
/**
* Spelling problem to be accepted by problem requesters.
*/
public class CoreSpellingProblem implements IPersistableProblem {
// spelling 'marker type' name. Only virtual as spelling problems are never persisted in markers.
// marker type is used in the quickFixProcessor extension point
public static final String MARKER_TYPE= "org.eclipse.cdt.internal.spelling"; //$NON-NLS-1$
/** The end offset of the problem */
private int fSourceEnd= 0;
/** The line number of the problem */
private int fLineNumber= 1;
/** The start offset of the problem */
private int fSourceStart= 0;
/** The description of the problem */
private String fMessage;
/** The misspelled word */
private String fWord;
/** Was the word found in the dictionary? */
private boolean fMatch;
/** Does the word start a new sentence? */
private boolean fSentence;
/** The associated document */
private IDocument fDocument;
/** The originating file name */
private String fOrigin;
/**
* Initialize with the given parameters.
*
* @param start the start offset
* @param end the end offset
* @param line the line
* @param message the message
* @param word the word
* @param match <code>true</code> iff the word was found in the dictionary
* @param sentence <code>true</code> iff the word starts a sentence
* @param document the document
* @param origin the originating file name
*/
public CoreSpellingProblem(int start, int end, int line, String message, String word, boolean match, boolean sentence, IDocument document, String origin) {
super();
fSourceStart= start;
fSourceEnd= end;
fLineNumber= line;
fMessage= message;
fWord= word;
fMatch= match;
fSentence= sentence;
fDocument= document;
fOrigin= origin;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getArguments()
*/
public String[] getArguments() {
String prefix= ""; //$NON-NLS-1$
String postfix= ""; //$NON-NLS-1$
try {
IRegion line= fDocument.getLineInformationOfOffset(fSourceStart);
prefix= fDocument.get(line.getOffset(), fSourceStart - line.getOffset());
postfix= fDocument.get(fSourceEnd + 1, line.getOffset() + line.getLength() - fSourceEnd);
} catch (BadLocationException exception) {
// Do nothing
}
return new String[] { fWord, prefix, postfix, fSentence ? Boolean.toString(true) : Boolean.toString(false), fMatch ? Boolean.toString(true) : Boolean.toString(false) };
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getID()
*/
public int getID() {
return CSpellingReconcileStrategy.SPELLING_PROBLEM_ID;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getMessage()
*/
public String getMessage() {
return fMessage;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getOriginatingFileName()
*/
public char[] getOriginatingFileName() {
return fOrigin.toCharArray();
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getSourceEnd()
*/
public int getSourceEnd() {
return fSourceEnd;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getSourceLineNumber()
*/
public int getSourceLineNumber() {
return fLineNumber;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#getSourceStart()
*/
public int getSourceStart() {
return fSourceStart;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#isError()
*/
public boolean isError() {
return false;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#isWarning()
*/
public boolean isWarning() {
return true;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#setSourceStart(int)
*/
public void setSourceStart(int sourceStart) {
fSourceStart= sourceStart;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#setSourceEnd(int)
*/
public void setSourceEnd(int sourceEnd) {
fSourceEnd= sourceEnd;
}
/*
* @see org.eclipse.cdt.core.parser.IProblem#setSourceLineNumber(int)
*/
public void setSourceLineNumber(int lineNumber) {
fLineNumber= lineNumber;
}
/*
* @see org.eclipse.cdt.core.parser.CategorizedProblem#getMarkerType()
*/
public String getMarkerType() {
return MARKER_TYPE;
}
public boolean checkCategory(int bitmask) {
return (getID() & bitmask) != 0;
}
}

View file

@ -0,0 +1,99 @@
/*******************************************************************************
* Copyright (c) 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.spelling.SpellingService;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.internal.ui.CPluginImages;
/**
* Proposal to disable spell checking.
*/
public class DisableSpellCheckingProposal implements ICCompletionProposal {
private final String ID_DISABLE = "DISABLE"; //$NON-NLS-1$
/** The invocation context */
private IInvocationContext fContext;
/**
* Creates a new proposal.
*
* @param context the invocation context
*/
public DisableSpellCheckingProposal(IInvocationContext 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 Messages.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 Messages.Spelling_disable_label;
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
*/
public Image getImage() {
return CPluginImages.get(CPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE);
}
/*
* @see org.eclipse.cdt.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.getSelectionOffset(), fContext.getSelectionLength());
}
public String getIdString() {
return ID_DISABLE;
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 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 - Initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
private static final String BUNDLE_NAME = Messages.class.getName();
public static String AbstractSpellingDictionary_encodingError;
public static String Spelling_add_askToConfigure_ignoreMessage;
public static String Spelling_add_askToConfigure_question;
public static String Spelling_add_askToConfigure_title;
public static String Spelling_add_info;
public static String Spelling_add_label;
public static String Spelling_case_label;
public static String Spelling_correct_label;
public static String Spelling_disable_info;
public static String Spelling_disable_label;
public static String Spelling_error_case_label;
public static String Spelling_error_label;
public static String Spelling_ignore_info;
public static String Spelling_ignore_label;
static {
// Initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
}
}

View file

@ -0,0 +1,26 @@
###############################################################################
# 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
# Sergey Prigogin (Google)
###############################################################################
AbstractSpellingDictionary_encodingError=Could not read: ''{0}'', where the bad characters are replaced by ''{1}''. Check the encoding of the spelling dictionary ({2}).
Spelling_add_askToConfigure_ignoreMessage=&Do not show 'Add word' proposals if user dictionary is missing
Spelling_add_askToConfigure_question=A user dictionary is needed to add words.\nDo you want to configure it now?\n
Spelling_add_askToConfigure_title=Missing User Dictionary
Spelling_add_info=Adds the word ''{0}'' to the dictionary
Spelling_add_label=Add ''{0}'' to dictionary
Spelling_case_label=Change to upper case
Spelling_correct_label=Change to ''{0}''
Spelling_disable_info=Disables spell checking.
Spelling_disable_label=Disable spell checking
Spelling_error_case_label= The word ''{0}'' should have an initial upper case letter
Spelling_error_label=The word ''{0}'' is not correctly spelled
Spelling_ignore_info=Ignores ''{0}'' during the current session
Spelling_ignore_label=Ignore ''{0}'' during the current session

View file

@ -0,0 +1,429 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
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.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellDictionary;
import org.eclipse.cdt.internal.ui.text.spelling.engine.LocaleSensitiveSpellDictionary;
import org.eclipse.cdt.internal.ui.text.spelling.engine.PersistentSpellDictionary;
/**
* Spell check engine for C/C++ source spell checking.
*/
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.
*/
private static Set fgLocalesWithInstalledDictionaries;
/**
* 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;
URL location;
try {
location= getDictionaryLocation();
if (location == null)
return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
} catch (MalformedURLException ex) {
CUIPlugin.getDefault().log(ex);
return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
}
String[] fileNames;
try {
URL url= FileLocator.toFileURL(location);
File file= new File(url.getFile());
if (!file.isDirectory())
return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
fileNames= file.list();
if (fileNames == null)
return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
} catch (IOException ex) {
CUIPlugin.getDefault().log(ex);
return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
}
fgLocalesWithInstalledDictionaries= 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) {
fgLocalesWithInstalledDictionaries.add(new Locale(localeName));
} else if (languageEnd == 2 && localeName.length() == 5) {
fgLocalesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3)));
} else if (localeName.length() > 6 && localeName.charAt(5) == '_') {
fgLocalesWithInstalledDictionaries.add(new Locale(localeName.substring(0, 2), localeName.substring(3, 5), localeName.substring(6)));
}
}
}
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 <code>null</code> if none is suitable
*/
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.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine#findDictionary(java.util.Locale)
*/
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 URL for the dictionary location where
* the Platform dictionaries are located.
* <p>
* This is in <code>org.eclipse.cdt.ui/dictionaries/</code>
* which can also be populated via fragments.
* </p>
*
* @throws MalformedURLException if the URL could not be created
* @return The dictionary location, or <code>null</code> iff the location is not known
*/
public static URL getDictionaryLocation() throws MalformedURLException {
// Unfortunately, dictionaries used by JDT are not accessible,
// so we have to provide our own copies of the same files.
final CUIPlugin plugin= CUIPlugin.getDefault();
if (plugin != null)
return plugin.getBundle().getEntry("/" + 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 final synchronized ISpellCheckEngine getInstance() {
if (fgEngine == null)
fgEngine= new SpellCheckEngine();
return fgEngine;
}
/**
* Shuts down the singleton instance of the spell check engine.
*/
public static final synchronized 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());
try {
Locale locale= null;
final URL location= getDictionaryLocation();
for (final Iterator iterator= getLocalesWithInstalledDictionaries().iterator(); iterator.hasNext();) {
locale= (Locale)iterator.next();
fLocaleDictionaries.put(locale, new LocaleSensitiveSpellDictionary(locale, location));
}
} catch (MalformedURLException exception) {
// Do nothing
}
SpellingPreferences.addPropertyChangeListener(this);
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine#getSpellChecker()
*/
public final synchronized ISpellChecker getSpellChecker() throws IllegalStateException {
if (fGlobalDictionaries == null)
throw new IllegalStateException("spell checker has been shut down"); //$NON-NLS-1$
IPreferenceStore store= CUIPlugin.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(SpellingPreferences.getSpellingLocale());
}
public static Locale convertToLocale(String locale) {
Locale defaultLocale= SpellCheckEngine.getDefaultLocale();
if (locale.equals(defaultLocale.toString()))
return defaultLocale;
if (locale.length() >= 5)
return new Locale(locale.substring(0, 2), locale.substring(3, 5));
return new Locale(""); //$NON-NLS-1$
}
/*
* @see org.eclipse.cdt.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(SpellingPreferences.SPELLING_LOCALE)) {
resetSpellChecker();
return;
}
if (event.getProperty().equals(SpellingPreferences.SPELLING_USER_DICTIONARY)) {
resetUserDictionary();
return;
}
if (event.getProperty().equals(SpellingPreferences.SPELLING_USER_DICTIONARY_ENCODING)) {
resetUserDictionary();
return;
}
}
/**
* 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;
}
final String filePath= SpellingPreferences.getSpellingUserDictionary();
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.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellDictionary)
*/
public synchronized final void registerGlobalDictionary(final ISpellDictionary dictionary) {
fGlobalDictionaries.add(dictionary);
resetSpellChecker();
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale, org.eclipse.cdt.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.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine#unload()
*/
public synchronized final void shutdown() {
SpellingPreferences.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.cdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(org.eclipse.cdt.ui.text.spelling.engine.ISpellDictionary)
*/
public synchronized final void unregisterDictionary(final ISpellDictionary dictionary) {
fGlobalDictionaries.remove(dictionary);
fLocaleDictionaries.values().remove(dictionary);
dictionary.unload();
resetSpellChecker();
}
}

View file

@ -0,0 +1,336 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import java.util.LinkedList;
import java.util.Locale;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import com.ibm.icu.text.BreakIterator;
import org.eclipse.cdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckIterator;
/**
* Iterator to spell check multiline comment regions.
*/
public class SpellCheckIterator implements ISpellCheckIterator {
/** The content of the region */
protected final String fContent;
/** 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;
String content;
try {
content= document.get(region.getOffset(), region.getLength());
} 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.cdt.internal.ui.text.spelling.engine.ISpellCheckIterator#setIgnoreSingleLetters(boolean)
*/
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 <code>true</code> iff the token consists of digits and at
* least one letter only, <code>false</code> 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 <code>true</code> 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 <code>true</code> iff the last token is in the given array
*/
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 <code>true</code> iff the token is a single letter token,
* <code>false</code> 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 <code>true</code> iff this token look like an URL,
* <code>false</code> 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 <code>true</code> iff the token consists of whitespace
* only, <code>false</code> 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 <code>null</code>
* 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 (!isWhitespace(fPrevious, fNext) && isAlphaNumeric(fPrevious, fNext)) {
if (isUrlToken(fPrevious)) {
skipTokens(fPrevious, ' ');
} 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 char stop) {
int end= begin;
while (end < fContent.length() && fContent.charAt(end) != stop)
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;
}
}

View file

@ -0,0 +1,85 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEventListener;
/**
* Internal abstract spelling engine, subclasses provide a content-type specific implementation.
*/
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.
*/
private IDocument fDocument;
/**
* 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;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEventListener#handle(org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent)
*/
public void handle(ISpellEvent event) {
fCollector.accept(new CSpellingProblem(event, fDocument));
}
}
/*
* @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 <code>null</code>
*/
protected abstract void check(IDocument document, IRegion[] regions, ISpellChecker checker, ISpellingProblemCollector collector, IProgressMonitor monitor);
}

View file

@ -0,0 +1,103 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.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.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.spelling.ISpellingEngine;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingEngineDescriptor;
import org.eclipse.cdt.core.CCorePlugin;
/**
* A dispatcher that decides what spelling engine to use depending on content type.
* When C/C++ spelling engine is selected in Preferences/General/Editors/Text Editors/Spelling
* this class is called to perform spelling check for all text-based content types.
* If the content type does not match one of C/C++ content types, the spelling check
* is delegated to the default spelling engine, most likely the one provided by JDT.
*/
public class SpellingEngineDispatcher implements ISpellingEngine {
private static final String C_SPELLING_ENGINE_ID = "org.eclipse.cdt.internal.ui.text.spelling.CSpellingEngine"; //$NON-NLS-1$
/** C/C++ source content type */
private static final IContentType CHEADER_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(CCorePlugin.CONTENT_TYPE_CHEADER);
private static final IContentType CSOURCE_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE);
private static final IContentType CXXHEADER_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER);
private static final IContentType CXXSOURCE_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE);
/** Available spelling engines by content type */
private Map fEngines= new HashMap();
private ISpellingEngine defaultEngine;
/**
* Initialize concrete engines.
*/
public SpellingEngineDispatcher() {
SpellingEngine engine = new CSpellingEngine();
if (CHEADER_CONTENT_TYPE != null)
fEngines.put(CHEADER_CONTENT_TYPE, engine);
if (CSOURCE_CONTENT_TYPE != null)
fEngines.put(CSOURCE_CONTENT_TYPE, engine);
if (CXXHEADER_CONTENT_TYPE != null)
fEngines.put(CXXHEADER_CONTENT_TYPE, engine);
if (CXXSOURCE_CONTENT_TYPE != null)
fEngines.put(CXXSOURCE_CONTENT_TYPE, engine);
try {
SpellingEngineDescriptor descriptor =
EditorsUI.getSpellingService().getDefaultSpellingEngineDescriptor();
if (!C_SPELLING_ENGINE_ID.equals(descriptor.getId())) { // Do not delegate to itself.
defaultEngine = descriptor.createEngine();
}
} catch (CoreException e) {
}
}
/*
* @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= defaultEngine;
if (engine != null)
engine.check(document, regions, context, collector, monitor);
}
/**
* Returns a spelling engine for the given content type or
* <code>null</code> if none could be found.
*
* @param contentType the content type
* @return a spelling engine for the given content type or
* <code>null</code> 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());
}
}

View file

@ -0,0 +1,150 @@
/*******************************************************************************
* Copyright (c) 2007 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
/**
* This class encapsulates spelling preferences.
* If the source of spelling preferences were to move from CDT to the platform,
* this class would make refactoring easier.
*/
public class SpellingPreferences {
private static IPreferenceStore preferenceStore = PreferenceConstants.getPreferenceStore();
static final String SPELLING_LOCALE = PreferenceConstants.SPELLING_LOCALE;
static final String SPELLING_USER_DICTIONARY = PreferenceConstants.SPELLING_USER_DICTIONARY;
static final String SPELLING_USER_DICTIONARY_ENCODING = PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING;
private static final String SPELLING_PROPOSAL_THRESHOLD = PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD;
private static final String SPELLING_ENABLE_CONTENTASSIST = PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST;
private static final String SPELLING_IGNORE_DIGITS = PreferenceConstants.SPELLING_IGNORE_DIGITS;
private static final String SPELLING_IGNORE_MIXED = PreferenceConstants.SPELLING_IGNORE_MIXED;
private static final String SPELLING_IGNORE_NON_LETTERS = PreferenceConstants.SPELLING_IGNORE_NON_LETTERS;
private static final String SPELLING_IGNORE_SENTENCE = PreferenceConstants.SPELLING_IGNORE_SENTENCE;
private static final String SPELLING_IGNORE_SINGLE_LETTERS = PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS;
private static final String SPELLING_IGNORE_STRING_LITERALS = PreferenceConstants.SPELLING_IGNORE_STRING_LITERALS;
private static final String SPELLING_IGNORE_UPPER = PreferenceConstants.SPELLING_IGNORE_UPPER;
private static final String SPELLING_IGNORE_URLS = PreferenceConstants.SPELLING_IGNORE_URLS;
/**
* @see IPreferenceStore#addPropertyChangeListener(IPropertyChangeListener)
*/
public static void addPropertyChangeListener(IPropertyChangeListener listener) {
preferenceStore.addPropertyChangeListener(listener);
}
/**
* @see IPreferenceStore#removePropertyChangeListener(IPropertyChangeListener)
*/
public static void removePropertyChangeListener(IPropertyChangeListener listener) {
preferenceStore.removePropertyChangeListener(listener);
}
/**
* The locale used for spell checking.
*/
public static String getSpellingLocale() {
return preferenceStore.getString(SPELLING_LOCALE);
}
/**
* The workspace user dictionary.
*/
public static String getSpellingUserDictionary() {
return preferenceStore.getString(SPELLING_USER_DICTIONARY);
}
/**
* The encoding of the workspace user dictionary.
*/
public static String getSpellingUserDictionaryEncoding() {
return preferenceStore.getString(SPELLING_USER_DICTIONARY_ENCODING);
}
/**
* Returns the number of proposals offered during spell checking.
*/
public static int spellingProposalThreshold() {
return preferenceStore.getInt(SPELLING_PROPOSAL_THRESHOLD);
}
/**
* Returns <code>true</code> if spelling content assist is enabled.
*/
public static boolean isEnabledSpellingContentAssist() {
return preferenceStore.getBoolean(SPELLING_ENABLE_CONTENTASSIST);
}
/**
* Returns <code>true</code> if words containing digits should
* be skipped during spell checking.
*/
public static boolean isIgnoreDigits() {
return preferenceStore.getBoolean(SPELLING_IGNORE_DIGITS);
}
/**
* Returns <code>true</code> if mixed case words should be
* skipped during spell checking.
*/
public static boolean isIgnoreMixed() {
return preferenceStore.getBoolean(SPELLING_IGNORE_MIXED);
}
/**
* Returns <code>true</code> if non-letters at word boundaries
* should be ignored during spell checking.
*/
public static boolean isIgnoreNonLetters() {
return preferenceStore.getBoolean(SPELLING_IGNORE_NON_LETTERS);
}
/**
* Returns <code>true</code> if sentence capitalization should
* be ignored during spell checking.
*/
public static boolean isIgnoreSentence() {
return preferenceStore.getBoolean(SPELLING_IGNORE_SENTENCE);
}
/**
* Returns <code>true</code> if single letters
* should be ignored during spell checking.
*/
public static boolean isIgnoreSingleLetters() {
return preferenceStore.getBoolean(SPELLING_IGNORE_SINGLE_LETTERS);
}
/**
* Returns <code>true</code> if string literals
* should be ignored during spell checking.
*/
public static boolean isIgnoreStringLiterals() {
return preferenceStore.getBoolean(SPELLING_IGNORE_STRING_LITERALS);
}
/**
* Returns <code>true</code> if upper case words should be
* skipped during spell checking.
*/
public static boolean isIgnoreUpper() {
return preferenceStore.getBoolean(SPELLING_IGNORE_UPPER);
}
/**
* Returns <code>true</code> if URLs should be ignored during
* spell checking.
*/
public static boolean isIgnoreUrls() {
return preferenceStore.getBoolean(SPELLING_IGNORE_URLS);
}
}

View file

@ -0,0 +1,95 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import java.net.URL;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.internal.ui.text.spelling.engine.AbstractSpellDictionary;
/**
* Dictionary for task tags.
*/
public class TaskTagDictionary extends AbstractSpellDictionary implements IPropertyChangeListener {
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getName()
*/
protected final URL getURL() {
return null;
}
/*
* @see org.eclipse.cdt.ui.text.spelling.engine.AbstractSpellDictionary#load(java.net.URL)
*/
protected synchronized boolean load(final URL url) {
final Plugin plugin= CCorePlugin.getDefault();
if (plugin != null) {
plugin.getPluginPreferences().addPropertyChangeListener(this);
return updateTaskTags();
}
return false;
}
/*
* @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
*/
public void propertyChange(final PropertyChangeEvent event) {
if (CCorePreferenceConstants.TODO_TASK_TAGS.equals(event.getProperty()))
updateTaskTags();
}
/*
* @see org.eclipse.cdt.ui.text.spelling.engine.ISpellDictionary#unload()
*/
public synchronized void unload() {
final Plugin plugin= CCorePlugin.getDefault();
if (plugin != null)
plugin.getPluginPreferences().removePropertyChangeListener(this);
super.unload();
}
/**
* Handles the compiler task tags property change event.
*
* @return <code>true</code> if the task tags got updated
*/
protected boolean updateTaskTags() {
final String tags= CCorePlugin.getOption(CCorePreferenceConstants.TODO_TASK_TAGS);
if (tags != null) {
unload();
final StringTokenizer tokenizer= new StringTokenizer(tags, ","); //$NON-NLS-1$
while (tokenizer.hasMoreTokens())
hashWord(tokenizer.nextToken());
return true;
}
return false;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#stripNonLetters(java.lang.String)
*/
protected String stripNonLetters(String word) {
return word;
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEventListener;
/**
* Text spelling engine
*/
public class TextSpellingEngine extends SpellingEngine {
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.SpellingEngine#check(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion[], org.eclipse.cdt.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) {
ISpellEventListener listener= new SpellEventListener(collector, document);
try {
checker.addListener(listener);
for (int i= 0; i < regions.length; i++) {
if (monitor != null && monitor.isCanceled())
return;
checker.execute(new SpellCheckIterator(document, regions[i], checker.getLocale()));
}
} finally {
checker.removeListener(listener);
}
}
}

View file

@ -0,0 +1,129 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProposal;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.RankedWordProposal;
/**
* Content assist processor to complete words.
* <strong>Note:</strong> This is currently not supported because the spelling engine
* cannot return word proposals but only correction proposals.
*/
public final class WordCompletionProposalComputer implements ICompletionProposalComputer {
/** 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 CCompletionProposal(text, start, candidate.length(),
CPluginImages.get(CPluginImages.IMG_CORRECTION_RENAME), text, word.getRank()) {
/*
* @see org.eclipse.cdt.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
CUIPlugin.getDefault().log(exception);
}
}
return Collections.EMPTY_LIST;
}
private boolean contributes() {
return SpellingPreferences.isEnabledSpellingContentAssist();
}
/*
* @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.cdt.ui.text.java.IJavaCompletionProposalComputer#sessionStarted()
*/
public void sessionStarted() {
}
/*
* @see org.eclipse.cdt.ui.text.java.IJavaCompletionProposalComputer#sessionEnded()
*/
public void sessionEnded() {
}
}

View file

@ -0,0 +1,172 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.text.IHtmlTagConstants;
/**
* Proposal to correct the incorrectly spelled word.
*/
public class WordCorrectionProposal implements ICCompletionProposal {
/** The invocation context */
private final IInvocationContext 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 length 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 IInvocationContext 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("...<br>"); //$NON-NLS-1$
buffer.append(getHtmlRepresentation(arguments[1]));
buffer.append("<b>"); //$NON-NLS-1$
buffer.append(getHtmlRepresentation(fWord));
buffer.append("</b>"); //$NON-NLS-1$
buffer.append(getHtmlRepresentation(arguments[2]));
buffer.append("<br>..."); //$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.bind(Messages.Spelling_correct_label, fWord);
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
*/
public Image getImage() {
return CPluginImages.get(CPluginImages.IMG_CORRECTION_RENAME);
}
/*
* @see org.eclipse.cdt.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.getSelectionOffset();
int length= fContext.getSelectionLength();
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);
}
/**
* 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();
}
public String getIdString() {
return fWord;
}
}

View file

@ -0,0 +1,116 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling;
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.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
/**
* Proposal to ignore the word during the current editing session.
*/
public class WordIgnoreProposal implements ICCompletionProposal {
/** The invocation context */
private IInvocationContext 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 IInvocationContext 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);
if (fContext instanceof IQuickAssistInvocationContext) {
ISourceViewer sourceViewer= ((IQuickAssistInvocationContext) fContext).getSourceViewer();
if (sourceViewer != null) {
SpellingProblem.removeAll(sourceViewer, fWord);
}
}
}
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
*/
public String getAdditionalProposalInfo() {
return Messages.bind(Messages.Spelling_ignore_info, 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.bind(Messages.Spelling_ignore_label, fWord);
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
*/
public Image getImage() {
return CPluginImages.get(CPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE);
}
/*
* @see org.eclipse.cdt.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.getSelectionOffset(), fContext.getSelectionLength());
}
public String getIdString() {
return fWord;
}
}

View file

@ -0,0 +1,113 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.ui.text.IProblemLocation;
import org.eclipse.cdt.ui.text.IQuickFixProcessor;
import org.eclipse.cdt.internal.ui.text.IHtmlTagConstants;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
import org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker;
import org.eclipse.cdt.internal.ui.text.spelling.engine.RankedWordProposal;
/**
* Quick fix processor for incorrectly spelled words.
*/
public class WordQuickFixProcessor implements IQuickFixProcessor {
/**
* Creates a new word quick fix processor.
*/
public WordQuickFixProcessor() {
}
/*
* @see org.eclipse.cdt.ui.text.java.IQuickFixProcessor#getCorrections(org.eclipse.cdt.ui.text.java.ContentAssistInvocationContext,org.eclipse.cdt.ui.text.java.IProblemLocation[])
*/
public ICCompletionProposal[] getCorrections(IInvocationContext context, IProblemLocation[] locations) throws CoreException {
final int threshold= SpellingPreferences.spellingProposalThreshold();
int size= 0;
List proposals= null;
String[] arguments= null;
IProblemLocation location= null;
RankedWordProposal proposal= null;
ICCompletionProposal[] 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];
if (location.getProblemId() == CSpellingReconcileStrategy.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;
if ((sentence && match) && !fixed) {
result= new ICCompletionProposal[] { 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 ICCompletionProposal[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.cdt.ui.text.java.IQuickFixProcessor#hasCorrections(org.eclipse.cdt.core.ICompilationUnit,int)
*/
public final boolean hasCorrections(ITranslationUnit unit, int id) {
return id == CSpellingReconcileStrategy.SPELLING_PROBLEM_ID;
}
}

View file

@ -0,0 +1,608 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.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.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.text.spelling.Messages;
import org.eclipse.cdt.internal.ui.text.spelling.SpellingPreferences;
/**
* Partial implementation of a spell dictionary.
*/
public abstract class AbstractSpellDictionary implements ISpellDictionary {
/** 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 capacity */
protected static final int HASH_CAPACITY= 22 * 1024;
/** The phonetic distance algorithm */
private IPhoneticDistanceAlgorithm fDistanceAlgorithm= new DefaultPhoneticDistanceAlgorithm();
/** The mapping from phonetic hashes to word lists */
private final Map fHashBuckets= new HashMap(HASH_CAPACITY);
/** The phonetic hash provider */
private IPhoneticHashProvider fHashProvider= new DefaultPhoneticHashProvider();
/** Is the dictionary already loaded? */
private boolean fLoaded= false;
/**
* Must the dictionary be loaded?
*/
private boolean fMustLoad= true;
/**
* Tells whether to strip non-letters at word boundaries.
*/
boolean fIsStrippingNonLetters= true;
/**
* 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) {
return fHashBuckets.get(hash);
}
/**
* 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
* <code>true</code> iff the proposals start a new sentence,
* <code>false</code> 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 String) {
String candidate= (String)candidates;
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;
for (int offset= 0; offset < candidateList.size(); offset++) {
String candidate= (String)candidateList.get(offset);
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
* <code>true</code> iff the proposals start a new sentence,
* <code>false</code> 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 String) {
String candidate= (String)candidates;
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= (String)candidateList.get(index);
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 <code>true</code> if this dictionary is empty
*/
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.cdt.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);
Object bucket= fHashBuckets.get(hash);
if (bucket == null) {
fHashBuckets.put(hash, word);
} else if (bucket instanceof ArrayList) {
((ArrayList)bucket).add(word);
} else {
ArrayList list= new ArrayList(BUCKET_CAPACITY);
list.add(bucket);
list.add(word);
fHashBuckets.put(hash, list);
}
}
/*
* @see org.eclipse.cdt.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 String) {
String candidate= (String)candidates;
if (candidate.equals(word) || candidate.equals(word.toLowerCase()))
return true;
return false;
}
final ArrayList candidateList= (ArrayList)candidates;
if (candidateList.contains(word) || candidateList.contains(word.toLowerCase()))
return true;
return false;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellDictionary#setStripNonLetters(boolean)
*/
public void setStripNonLetters(boolean state) {
fIsStrippingNonLetters= state;
}
/**
* Strips non-letter characters from the given word.
* <p>
* This will only happen if the corresponding preference is enabled.
* </p>
*
* @param word the word to strip
* @return the stripped word
*/
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.cdt.ui.text.spelling.engine.ISpellDictionary#isLoaded()
*/
public final synchronized 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 <code>true</code> iff the word list could be loaded, <code>false</code>
* 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.bind(Messages.AbstractSpellingDictionary_encodingError,
new String[] { word, decoder.replacement(), url.toString() });
IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, message, ex);
CUIPlugin.getDefault().log(status);
doRead= word != null;
continue;
}
doRead= word != null;
if (doRead)
hashWord(word);
}
return true;
}
} catch (FileNotFoundException e) {
String urlString= url.toString();
String lowercaseUrlString= urlString.toLowerCase();
if (urlString.equals(lowercaseUrlString)) {
CUIPlugin.getDefault().log(e);
} else {
try {
return load(new URL(lowercaseUrlString));
} catch (MalformedURLException ex) {
CUIPlugin.getDefault().log(ex);
}
}
} catch (IOException exception) {
if (line > 0) {
String message= Messages.bind(Messages.AbstractSpellingDictionary_encodingError,
String.valueOf(line), url.toString());
IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, message, exception);
CUIPlugin.getDefault().log(status);
} else {
CUIPlugin.getDefault().log(exception);
}
} finally {
fMustLoad= false;
try {
if (stream != null)
stream.close();
} catch (IOException x) {
}
}
}
return false;
}
/**
* Compacts the dictionary.
*/
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.cdt.ui.text.spelling.engine.ISpellDictionary#unload()
*/
public synchronized void unload() {
fLoaded= false;
fMustLoad= true;
fHashBuckets.clear();
}
/*
* @see org.eclipse.cdt.ui.text.spelling.engine.ISpellDictionary#acceptsWords()
*/
public boolean acceptsWords() {
return false;
}
/*
* @see org.eclipse.cdt.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
*/
protected String getEncoding() {
String encoding= SpellingPreferences.getSpellingUserDictionaryEncoding();
if (encoding == null || encoding.length() == 0)
encoding= ResourcesPlugin.getEncoding();
return encoding;
}
}

View file

@ -0,0 +1,102 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Default phonetic distance algorithm for English words.
* <p>
* This algorithm implements the Levenshtein text edit distance.
* </p>
*/
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];
}
}

View file

@ -0,0 +1,674 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Default phonetic hash provider for english languages.
* <p>
* This algorithm uses an adapted version double metaphone algorithm by
* Lawrence Philips.
* <p>
*/
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 <code>true</code> iff the string contains one of the
* candidates, <code>false</code> 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 <code>true</code> iff the string contains one of the
* candidates, <code>false</code> 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 <code>true</code> iff the token contains a vowel, <code>false</code>
* 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;
}
}

View file

@ -0,0 +1,344 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.cdt.internal.ui.text.spelling.SpellingPreferences;
/**
* Default spell checker for standard text.
*/
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 <code>true</code> iff this word contains digits, <code>false</code> 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
* <code>true</code> iff the specified word starts a new
* sentence, <code>false</code> otherwise
* @return <code>true</code> iff the contains mixed-case letters, <code>false</code>
* 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 <code>true</code> iff this word only contains upper-case
* letters, <code>false</code> 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 <code>true</code> iff this word looks like an URL, <code>false</code>
* 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 spell event listeners. Synchronized to avoid concurrent
* modifications.
*/
private final Set fListeners= Collections.synchronizedSet(new HashSet());
/**
* The locale of this checker.
*/
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);
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.spelling.done.ISpellChecker#addListener(org.eclipse.spelling.done.ISpellEventListener)
*/
public final void addListener(final ISpellEventListener listener) {
// synchronizing is necessary as this is a write access
fListeners.add(listener);
}
/*
* @see org.eclipse.cdt.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.cdt.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.cdt.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 ISpellCheckIterator iterator) {
final boolean ignoreDigits= SpellingPreferences.isIgnoreDigits();
final boolean ignoreMixed= SpellingPreferences.isIgnoreMixed();
final boolean ignoreSentence= SpellingPreferences.isIgnoreSentence();
final boolean ignoreUpper= SpellingPreferences.isIgnoreUpper();
final boolean ignoreUrls= SpellingPreferences.isIgnoreUrls();
final boolean ignoreNonLetters= SpellingPreferences.isIgnoreNonLetters();
final boolean ignoreSingleLetters= SpellingPreferences.isIgnoreSingleLetters();
iterator.setIgnoreSingleLetters(ignoreSingleLetters);
Iterator iter= fDictionaries.iterator();
while (iter.hasNext())
((ISpellDictionary) iter.next()).setStripNonLetters(ignoreNonLetters);
String word= null;
boolean starts= false;
while (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))
fireEvent(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), starts, false));
} else {
if (!ignoreSentence && starts && Character.isLowerCase(word.charAt(0)))
fireEvent(new SpellEvent(this, word, iterator.getBegin(), iterator.getEnd(), true, true));
}
}
}
}
}
/**
* Fires the specified event.
*
* @param event
* Event to fire
*/
protected final void fireEvent(final ISpellEvent event) {
// synchronizing is necessary as this is called from execute
Set copy;
synchronized (fListeners) {
copy= new HashSet(fListeners);
}
for (final Iterator iterator= copy.iterator(); iterator.hasNext();) {
((ISpellEventListener)iterator.next()).handle(event);
}
}
/*
* @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 modifying 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.cdt.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.cdt.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.spelling.done.ISpellChecker#removeListener(org.eclipse.spelling.done.ISpellEventListener)
*/
public final void removeListener(final ISpellEventListener listener) {
// synchronizing is necessary as this is a write access
fListeners.remove(listener);
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellChecker#getLocale()
*/
public Locale getLocale() {
return fLocale;
}
}

View file

@ -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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Interface of algorithms to compute the phonetic distance between two words.
*/
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);
}

View file

@ -0,0 +1,35 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Interface of hashers to compute the phonetic hash for a word.
*/
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();
}

View file

@ -0,0 +1,83 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Locale;
import org.eclipse.cdt.internal.ui.text.spelling.SpellingPreferences;
/**
* Interface for a spell check engine.
* <p>
* This engine can be configured with multiple
* dictionaries.
* </p>
*/
public interface ISpellCheckEngine {
/**
* Returns a spell checker configured with the global
* dictionaries and the locale dictionary that correspond to the current
* {@linkplain SpellingPreferences#getSpellingLocale() locale preference}.
* <p>
* <strong>Note:</strong> Changes to the spelling engine dictionaries
* are not propagated to this spell checker.</p>
*
* @return a configured instance of the spell checker or <code>null</code> 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.
* <p>
* Further calls to this engine result in exceptions.
* </p>
*/
void shutdown();
/**
* Unregisters a dictionary previously registered either by a call to
* <code>registerDictionary(Locale,ISpellDictionary)</code> or <code>registerDictionary(ISpellDictionary)</code>.
* <p>
* If the dictionary was not registered before, nothing happens.</p>
*
* @param dictionary the dictionary to unregister
*/
void unregisterDictionary(ISpellDictionary dictionary);
}

View file

@ -0,0 +1,49 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Iterator;
/**
* Interface for iterators used for spell checking.
*/
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 <code>true<code> iff the current word starts a new sentence, <code>false</code> otherwise
*/
public boolean startsSentence();
/**
* Tells whether to ignore single letters
* from being checked.
*
* @param state <code>true</code> if single letters should be ignored
*/
public void setIgnoreSingleLetters(boolean state);
}

View file

@ -0,0 +1,113 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Locale;
import java.util.Set;
/**
* Interface for spell checkers.
*/
public interface ISpellChecker {
/**
* Adds a dictionary to the list of active dictionaries.
*
* @param dictionary The dictionary to add
*/
void addDictionary(ISpellDictionary dictionary);
/**
* Adds a spell event listener to the active listeners.
*
* @param listener The listener to add
*/
void addListener(ISpellEventListener listener);
/**
* Returns whether this spell checker accepts word additions.
*
* @return <code>true</code> if word additions are accepted, <code>false</code> 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 <code>ignoreWord(String)</code>.
*
* @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 iterator The iterator to use for spell checking
*/
void execute(ISpellCheckIterator iterator);
/**
* Returns the ranked proposals for a word.
*
* @param word The word to retrieve the proposals for
* @param sentence <code>true</code> iff the proposals should start a
* sentence, <code>false</code> otherwise
* @return Set of ranked proposals for the word
*/
Set getProposals(String word, boolean sentence);
/**
* Ignores the specified word until calling <code>checkWord(String)</code>.
*
* @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 <code>true</code> iff the word is correctly spelled, <code>false</code>
* otherwise
*/
boolean isCorrect(String word);
/**
* Remove a dictionary from the list of active dictionaries.
*
* @param dictionary The dictionary to remove
*/
void removeDictionary(ISpellDictionary dictionary);
/**
* Removes a spell event listener from the active listeners.
*
* @param listener The listener to remove
*/
void removeListener(ISpellEventListener listener);
/**
* Returns the current locale of the spell check engine.
*
* @return The current locale of the engine
*/
Locale getLocale();
}

View file

@ -0,0 +1,71 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Set;
/**
* Interface of dictionaries to use for spell checking.
*/
public interface ISpellDictionary {
/**
* Returns whether this dictionary accepts new words.
*
* @return <code>true</code> if this dictionary accepts new words, <code>false</code> 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 <code>true</code> iff the proposals start a new sentence,
* <code>false</code> 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 <code>true</code> iff this word is correctly spelled, <code>false</code> otherwise
*/
public boolean isCorrect(String word);
/**
* Is the dictionary loaded?
*
* @return <code>true</code> iff it is loaded, <code>false</code> otherwise
*/
public boolean isLoaded();
/**
* Empties the dictionary.
*/
public void unload();
/**
* Tells whether to strip non-letters from word boundaries.
*
* @param state <code>true</code> if non-letters should be stripped
*/
public void setStripNonLetters(boolean state);
}

View file

@ -0,0 +1,63 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Set;
/**
* Event fired by spell checkers.
*/
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 <code>true</code> iff the word was found, <code>false</code> otherwise
*/
public boolean isMatch();
/**
* Does the incorrectly spelled word start a new sentence?
*
* @return <code>true<code> iff the word starts a new sentence, <code>false</code> otherwise
*/
public boolean isStart();
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Interface for spell event listeners.
*/
public interface ISpellEventListener {
/**
* Handles a spell event.
*
* @param event Event to handle
*/
public void handle(ISpellEvent event);
}

View file

@ -0,0 +1,55 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.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.
*/
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.cdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL()
*/
protected final URL getURL() throws MalformedURLException {
return new URL(fLocation, fLocale.toString() + ".dictionary"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,95 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* Persistent modifiable word-list based dictionary.
*/
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.cdt.ui.text.spelling.engine.AbstractSpellDictionary#acceptsWords()
*/
public boolean acceptsWords() {
return true;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellDictionary#addWord(java.lang.String)
*/
public void addWord(final String word) {
if (isCorrect(word))
return;
OutputStreamWriter writer= 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);
}
FileOutputStream 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) {
CUIPlugin.getDefault().log(exception);
return;
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
}
}
hashWord(word);
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.AbstractSpellDictionary#getURL()
*/
protected final URL getURL() {
return fLocation;
}
}

View file

@ -0,0 +1,96 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
/**
* Ranked word proposal for quick fix and content assist.
*/
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;
}
}

View file

@ -0,0 +1,101 @@
/*******************************************************************************
* 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.spelling.engine;
import java.util.Set;
/**
* Spell event fired for words detected by a spell check iterator.
*/
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 <code>true</code> iff the word starts a new sentence,
* <code>false</code> otherwise
* @param match <code>true</code> iff the word was found in the dictionary,
* <code>false</code> 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.cdt.internal.ui.text.spelling.engine.ISpellEvent#getBegin()
*/
public final int getBegin() {
return fBegin;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent#getEnd()
*/
public final int getEnd() {
return fEnd;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent#getProposals()
*/
public final Set getProposals() {
return fChecker.getProposals(fWord, fSentence);
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent#getWord()
*/
public final String getWord() {
return fWord;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent#isMatch()
*/
public final boolean isMatch() {
return fMatch;
}
/*
* @see org.eclipse.cdt.internal.ui.text.spelling.engine.ISpellEvent#isStart()
*/
public final boolean isStart() {
return fSentence;
}
}

View file

@ -400,15 +400,20 @@ public class EditorUtility {
if (page != null) {
IEditorPart part= page.getActiveEditor();
if (part != null) {
IEditorInput editorInput= part.getEditorInput();
if (editorInput != null) {
return (ICElement)editorInput.getAdapter(ICElement.class);
}
return getEditorInputCElement(part);
}
}
return null;
}
public static ICElement getEditorInputCElement(IEditorPart part) {
IEditorInput editorInput= part.getEditorInput();
if (editorInput == null) {
return null;
}
return (ICElement) editorInput.getAdapter(ICElement.class);
}
/**
* Gets the working copy of an compilation unit opened in an editor
*

View file

@ -0,0 +1,35 @@
/*******************************************************************************
* 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.cdt.internal.ui.viewsupport;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
/**
* Listener to be informed on text selection changes in an editor (post selection), including the corresponding AST.
* The AST is shared and must not be modified.
* Listeners can be registered in a <code>SelectionListenerWithASTManager</code>.
*/
public interface ISelectionListenerWithAST {
/**
* Called when a selection has changed. The method is called in a post selection event in an background
* thread.
*
* @param part The editor part in which the selection change has occurred.
* @param selection The new text selection
* @param astRoot The AST tree corresponding to the editor's input. This AST is shared and must
* not be modified.
*/
void selectionChanged(IEditorPart part, ITextSelection selection, IASTTranslationUnit astRoot);
}

View file

@ -0,0 +1,179 @@
/*******************************************************************************
* 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.cdt.internal.ui.viewsupport;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
/**
* Infrastructure to share an AST for editor post selection listeners.
*/
public class SelectionListenerWithASTManager {
private static SelectionListenerWithASTManager fgDefault;
/**
* @return Returns the default manager instance.
*/
public static SelectionListenerWithASTManager getDefault() {
if (fgDefault == null) {
fgDefault= new SelectionListenerWithASTManager();
}
return fgDefault;
}
private final static class PartListenerGroup {
private ITextEditor fPart;
private ISelectionListener fPostSelectionListener;
private ISelectionChangedListener fSelectionListener;
private Job fCurrentJob;
private ListenerList fAstListeners;
public PartListenerGroup(ITextEditor editorPart) {
fPart= editorPart;
fCurrentJob= null;
fAstListeners= new ListenerList(ListenerList.IDENTITY);
fSelectionListener= new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection= event.getSelection();
if (selection instanceof ITextSelection) {
fireSelectionChanged((ITextSelection) selection);
}
}
};
fPostSelectionListener= new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (part == fPart && selection instanceof ITextSelection)
firePostSelectionChanged((ITextSelection) selection);
}
};
}
public boolean isEmpty() {
return fAstListeners.isEmpty();
}
public void install(ISelectionListenerWithAST listener) {
if (isEmpty()) {
fPart.getEditorSite().getPage().addPostSelectionListener(fPostSelectionListener);
ISelectionProvider selectionProvider= fPart.getSelectionProvider();
if (selectionProvider != null)
selectionProvider.addSelectionChangedListener(fSelectionListener);
}
fAstListeners.add(listener);
}
public void uninstall(ISelectionListenerWithAST listener) {
fAstListeners.remove(listener);
if (isEmpty()) {
fPart.getEditorSite().getPage().removePostSelectionListener(fPostSelectionListener);
ISelectionProvider selectionProvider= fPart.getSelectionProvider();
if (selectionProvider != null)
selectionProvider.removeSelectionChangedListener(fSelectionListener);
}
}
public void fireSelectionChanged(final ITextSelection selection) {
if (fCurrentJob != null) {
fCurrentJob.cancel();
}
}
public void firePostSelectionChanged(final ITextSelection selection) {
if (fCurrentJob != null) {
fCurrentJob.cancel();
}
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fPart.getEditorInput());
if (workingCopy == null)
return;
ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot) {
if (astRoot != null) {
Object[] listeners;
synchronized (PartListenerGroup.this) {
listeners= fAstListeners.getListeners();
}
for (int i= 0; i < listeners.length; i++) {
((ISelectionListenerWithAST) listeners[i]).selectionChanged(fPart, selection, astRoot);
}
}
return Status.OK_STATUS;
}
});
}
}
private Map fListenerGroups;
private SelectionListenerWithASTManager() {
fListenerGroups= new HashMap();
}
/**
* Registers a selection listener for the given editor part.
* @param part The editor part to listen to.
* @param listener The listener to register.
*/
public void addListener(ITextEditor part, ISelectionListenerWithAST listener) {
synchronized (this) {
PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
if (partListener == null) {
partListener= new PartListenerGroup(part);
fListenerGroups.put(part, partListener);
}
partListener.install(listener);
}
}
/**
* Unregisters a selection listener.
* @param part The editor part the listener was registered.
* @param listener The listener to unregister.
*/
public void removeListener(ITextEditor part, ISelectionListenerWithAST listener) {
synchronized (this) {
PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
if (partListener != null) {
partListener.uninstall(listener);
if (partListener.isEmpty()) {
fListenerGroups.remove(part);
}
}
}
}
}

View file

@ -9,17 +9,24 @@
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.ui;
import java.util.Locale;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.cdt.internal.ui.ICThemeConstants;
import org.eclipse.cdt.internal.ui.text.ICColorConstants;
import org.eclipse.cdt.internal.ui.text.spelling.SpellCheckEngine;
/**
* Preference constants used in the CDT-UI preference store. Clients should only read the
@ -972,6 +979,198 @@ public class PreferenceConstants {
*/
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED= "semanticHighlighting.enabled"; //$NON-NLS-1$
/**
* A named preference that controls if quick assist light bulbs are shown.
* <p>
* Value is of type <code>Boolean</code>: if <code>true</code> light bulbs are shown
* for quick assists.
* </p>
*
* @since 5.0
*/
public static final String EDITOR_QUICKASSIST_LIGHTBULB="org.eclipse.cdt.quickassist.lightbulb"; //$NON-NLS-1$
/**
* A named preference that holds the background color used in the code assist selection dialog.
* <p>
* Value is of type <code>String</code>. A RGB color value encoded as a string
* using class <code>PreferenceConverter</code>
* </p>
*
* @see org.eclipse.jface.resource.StringConverter
* @see org.eclipse.jface.preference.PreferenceConverter
*
* @since 5.0
*/
public final static String CODEASSIST_PROPOSALS_BACKGROUND= "content_assist_proposals_background"; //$NON-NLS-1$
/**
* A named preference that holds the foreground color used in the code assist selection dialog.
* <p>
* Value is of type <code>String</code>. A RGB color value encoded as a string
* using class <code>PreferenceConverter</code>
* </p>
*
* @see org.eclipse.jface.resource.StringConverter
* @see org.eclipse.jface.preference.PreferenceConverter
*
* @since 5.0
*/
public final static String CODEASSIST_PROPOSALS_FOREGROUND= "content_assist_proposals_foreground"; //$NON-NLS-1$
/**
* A named preference that controls whether words containing digits should
* be skipped during spell checking.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.0
*/
public final static String SPELLING_IGNORE_SINGLE_LETTERS= "spelling_ignore_single_letters"; //$NON-NLS-1$
/**
* A named preference that controls whether string literals
* should be ignored during spell checking.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.0
*/
public final static String SPELLING_IGNORE_STRING_LITERALS= "spelling_ignore_string_literals"; //$NON-NLS-1$
/**
* A named preference that controls whether non-letters at word boundaries
* should be ignored during spell checking.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.0
*/
public final static String SPELLING_IGNORE_NON_LETTERS= "spelling_ignore_non_letters"; //$NON-NLS-1$
/**
* A named preference that controls the locale used for spell checking.
* <p>
* Value is of type <code>String</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Integer</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>Integer</code>.
* </p>
*
* @since 5.0
*/
public final static String SPELLING_PROBLEMS_THRESHOLD= "spelling_problems_threshold"; //$NON-NLS-1$
/**
* A named preference that specifies the workspace user dictionary.
* <p>
* Value is of type <code>Integer</code>.
* </p>
*
* @since 5.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.
* <p>
* Value is of type <code>String</code>.
* </p>
*
* @since 5.0
*/
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.
*
* <strong>Note:</strong> This is currently not supported because the spelling engine
* cannot return word proposals but only correction proposals.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 5.0
*/
public final static String SPELLING_ENABLE_CONTENTASSIST= "spelling_enable_contentassist"; //$NON-NLS-1$
/**
* Returns the CDT-UI preference store.
*
@ -987,13 +1186,15 @@ public class PreferenceConstants {
* @param store the preference store to be initialized
*/
public static void initializeDefaultValues(IPreferenceStore store) {
ColorRegistry registry= PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry();
store.setDefault(PreferenceConstants.EDITOR_CORRECTION_INDICATION, false);
store.setDefault(PreferenceConstants.EDITOR_SHOW_SEGMENTS, false);
store.setDefault(PreferenceConstants.PREF_SHOW_CU_CHILDREN, true);
// Turned off by default since there are too many false reports right now
store.setDefault(PreferenceConstants.EDITOR_EVALUATE_TEMPORARY_PROBLEMS, false);
// This option has to be turned on for the spelling checker too work.
// As of 4.0, it doesn't produce false positives any more.
store.setDefault(PreferenceConstants.EDITOR_EVALUATE_TEMPORARY_PROBLEMS, true);
int sourceHoverModifier= SWT.MOD2;
String sourceHoverModifierName= Action.findModifierString(sourceHoverModifier); // Shift
@ -1088,5 +1289,81 @@ public class PreferenceConstants {
// content assist
store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.cdt.ui.textProposalCategory\0"); //$NON-NLS-1$
store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.cdt.ui.parserProposalCategory:65539\0org.eclipse.cdt.ui.textProposalCategory:65541\0org.eclipse.cdt.ui.templateProposalCategory:2\0"); //$NON-NLS-1$
setDefaultAndFireEvent(
store,
PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND,
findRGB(registry, ICThemeConstants.CODEASSIST_PROPOSALS_BACKGROUND, new RGB(255, 255, 255)));
setDefaultAndFireEvent(
store,
PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND,
findRGB(registry, ICThemeConstants.CODEASSIST_PROPOSALS_FOREGROUND, new RGB(0, 0, 0)));
// 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_STRING_LITERALS, true);
store.setDefault(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS, 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);
}
/**
* Sets the default value and fires a property
* change event if necessary.
*
* @param store the preference store
* @param key the preference key
* @param newValue the new value
* @since 5.0
*/
private static void setDefaultAndFireEvent(IPreferenceStore store, String key, RGB newValue) {
RGB oldValue= null;
if (store.isDefault(key))
oldValue= PreferenceConverter.getDefaultColor(store, key);
PreferenceConverter.setDefault(store, key, newValue);
if (oldValue != null && !oldValue.equals(newValue))
store.firePropertyChangeEvent(key, oldValue, newValue);
}
/**
* Returns the RGB for the given key in the given color registry.
*
* @param registry the color registry
* @param key the key for the constant in the registry
* @param defaultRGB the default RGB if no entry is found
* @return RGB the RGB
* @since 5.0
*/
private static RGB findRGB(ColorRegistry registry, String key, RGB defaultRGB) {
RGB rgb= registry.getRGB(key);
if (rgb != null)
return rgb;
return defaultRGB;
}
}

View file

@ -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.cdt.ui.text;
import org.eclipse.cdt.core.model.ITranslationUnit;
/**
* Context information for quick fix and quick assist processors.
* <p>
* Note: this interface is not intended to be implemented.
* </p>
*/
public interface IInvocationContext {
/**
* @return Returns the offset of the current selection
*/
int getSelectionOffset();
/**
* @return Returns the length of the current selection
*/
int getSelectionLength();
/**
* @return ITranslationUnit or null
*/
ITranslationUnit getTranslationUnit();
}

View file

@ -0,0 +1,58 @@
/*******************************************************************************
* 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.cdt.ui.text;
/**
* Problem information for quick fix and quick assist processors.
*/
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.
*/
String getMarkerType();
/**
* Returns the id of problem. Note that problem ids are defined per problem marker type.
*
* @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 <code>true</code> if the problem has error severity
*/
boolean isError();
}

View file

@ -0,0 +1,47 @@
/*******************************************************************************
* 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.cdt.ui.text;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.cdt.core.model.ITranslationUnit;
/**
* Interface to be implemented by contributors to the extension point
* <code>org.eclipse.cdt.ui.quickFixProcessors</code>.
*
* @since 5.0
*/
public interface IQuickFixProcessor {
/**
* Returns <code>true</code> if the processor has proposals for the given problem. This test should be an
* optimistic guess and be very cheap.
*
* @param unit the compilation unit
* @param problemId the problem Id. The id is of a problem of the problem type(s) this processor specified in
* the extension point.
* @return <code>true</code> if the processor has proposals for the given problem
*/
boolean hasCorrections(ITranslationUnit unit, int problemId);
/**
* Collects corrections or code manipulations for the given context.
*
* @param context Defines current compilation unit, position and a shared AST
* @param locations Problems are the current location.
* @return the corrections applicable at the location or <code>null</code> if no proposals
* can be offered
* @throws CoreException CoreException can be thrown if the operation fails
*/
ICCompletionProposal[] getCorrections(IInvocationContext context,
IProblemLocation[] locations) throws CoreException;
}