mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Spell checking support in C/C++ editor. https://bugs.eclipse.org/bugs/show_bug.cgi?id=190512
This commit is contained in:
parent
97c41a004d
commit
8463aa5adf
93 changed files with 109089 additions and 97 deletions
|
@ -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() };
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,7 @@ bin.includes = about.html,\
|
|||
plugin.xml,\
|
||||
icons/,\
|
||||
plugin.properties,\
|
||||
dictionaries/,\
|
||||
templates/,\
|
||||
.,\
|
||||
META-INF/,\
|
||||
|
|
49818
core/org.eclipse.cdt.ui/dictionaries/en_GB.dictionary
Normal file
49818
core/org.eclipse.cdt.ui/dictionaries/en_GB.dictionary
Normal file
File diff suppressed because it is too large
Load diff
49752
core/org.eclipse.cdt.ui/dictionaries/en_US.dictionary
Normal file
49752
core/org.eclipse.cdt.ui/dictionaries/en_US.dictionary
Normal file
File diff suppressed because it is too large
Load diff
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_add.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_add.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 914 B |
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_change.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_change.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 B |
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_rename.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/obj16/correction_rename.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 B |
BIN
core/org.eclipse.cdt.ui/icons/obj16/never_translate.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/obj16/never_translate.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 159 B |
BIN
core/org.eclipse.cdt.ui/icons/obj16/quickassist_obj.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/obj16/quickassist_obj.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 225 B |
|
@ -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
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
182
core/org.eclipse.cdt.ui/schema/quickFixProcessors.exsd
Normal file
182
core/org.eclipse.cdt.ui/schema/quickFixProcessors.exsd
Normal 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.
|
||||
<p>
|
||||
Extension can specify which problem marker types it can handle. It will only get problems of these types to process.
|
||||
</p>
|
||||
<p>
|
||||
This extension point supports the <code>enablement</code> tag. Properties to test on are:
|
||||
<dl>
|
||||
<li>translationUnit: type ITranslationUnit; the translation unit the quick assist is applied on</li>
|
||||
|
||||
<li>projectNatures: type Collection; all project natures of the current project</li>
|
||||
</dl>
|
||||
</p>
|
||||
</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
|
||||
<samp>org.eclipse.cdt.ui.text.IQuickFixProcessor</samp>
|
||||
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:
|
||||
|
||||
<p>
|
||||
<pre>
|
||||
<extension point="org.eclipse.cdt.ui.quickFixProcessors">
|
||||
<quickFixProcessor
|
||||
id="AdvancedQuickFixProcessor"
|
||||
name="Advanced Quick Fix Processor"
|
||||
class="com.example.AdvancedQuickFixProcessor">
|
||||
<handledMarkerTypes>
|
||||
<markerType id="org.eclipse.myplugin.audits"/>
|
||||
</handledMarkerTypes>
|
||||
<enablement>
|
||||
<with variable="projectNatures">
|
||||
<iterate operator="or">
|
||||
<equals value="org.eclipse.cdt.core.cnature"/>
|
||||
</iterate>
|
||||
</with>
|
||||
</enablement>
|
||||
</quickFixProcessor>
|
||||
</extension>
|
||||
</pre>
|
||||
</p>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="apiInfo"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
The contributed class must implement <code>org.eclipse.cdt.ui.text.IQuickFixProcessor</code>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="copyright"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
Copyright (c) 2001, 2007 IBM Corporation and others.<br>
|
||||
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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
</schema>
|
|
@ -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);
|
||||
|
|
|
@ -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$
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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[] { "<", ">", " ", "&", "ˆ", "˜", """ }; //$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= '<';
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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[] { "<", ">", " ", "&", "ˆ", "˜", """ }; //$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= '<';
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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$
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue