mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
Bug 363406: extensible semantic highlighting
- introduced extension point to allow plugins to add new semantic highlighters - see bug for more details Change-Id: Ic019e8a3c483fcfc42344fe4ef2139cc933c0301 Reviewed-on: https://git.eclipse.org/r/10074 Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com> Tested-by: Doug Schaefer <dschaefer@qnx.com>
This commit is contained in:
parent
d960fff7dd
commit
2bc9035f8c
9 changed files with 714 additions and 56 deletions
|
@ -644,4 +644,6 @@ RefreshExclusionContributorExtensionPoint = Refresh Exclusion Contributor
|
|||
newProjectWizard.name = C/C++ Project (prototype)
|
||||
projectTypePages = Project Type Pages
|
||||
|
||||
semanticHighlightingExtensionPoint = Semantic Highlighting Extension Point
|
||||
|
||||
UserSettingEntries.name = CDT User Setting Entries
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<extension-point id="LanguageSettingsProviderAssociation" name="%LanguageSettingsProviderAssociationExtensionPoint" schema="schema/LanguageSettingsProviderAssociation.exsd"/>
|
||||
<extension-point id="RefreshExclusionContributor" name="%RefreshExclusionContributorExtensionPoint" schema="schema/RefreshExclusionContributor.exsd"/>
|
||||
<extension-point id="projectTypePages" name="%projectTypePages" schema="schema/projectTypePages.exsd"/>
|
||||
<extension-point id="semanticHighlighting" name="%semanticHighlightingExtensionPoint" schema="schema/semanticHighlighting.exsd"/>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.core.runtime.adapters">
|
||||
|
|
245
core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd
Normal file
245
core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd
Normal file
|
@ -0,0 +1,245 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Schema file written by PDE -->
|
||||
<schema targetNamespace="org.eclipse.cdt.ui" xmlns="http://www.w3.org/2001/XMLSchema">
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.schema plugin="org.eclipse.cdt.ui" id="semanticHighligher" name="Semantic Highlighting"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
This extension point allows extensions to contribute to the semantic highlighting.
|
||||
<p>
|
||||
Extensions specify the priority of the highlighting, which determines the order in which the highlighting is invoked.
|
||||
</p>
|
||||
<p>
|
||||
This extension point supports the <code>enablement</code> tag. Properties to test on are:
|
||||
<dl>
|
||||
<li>projectNatures: type Collection; all project natures of the current project</li>
|
||||
<li>languageId: type String; the result if ILanguage.getId on the token's ITranslationUnit</li>
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
Contributed highlightings will be visible in the Code tree of the 'C/C++ - Editor - Syntax Colouring' preference page.
|
||||
</p>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
|
||||
|
||||
<element name="extension">
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.element />
|
||||
</appInfo>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref="semanticHighlighting" 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="semanticHighlighting">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref="enablement" minOccurs="0" maxOccurs="1"/>
|
||||
</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 Semantic Highlighting. The
|
||||
class must be public and implement
|
||||
<samp>org.eclipse.cdt.ui.text.ISemanticHighlighter</samp>
|
||||
with a public 0-argument constructor.
|
||||
</documentation>
|
||||
<appInfo>
|
||||
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.ui.text.ISemanticHighlighting"/>
|
||||
</appInfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="priority" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
The priority determines the order in which highlightings are given the opportunity to highlight a token. Lower values are more important.
|
||||
|
||||
The priorities of the built-in highlightings are available in org.eclipse.cdt.internal.ui.editor.SemanticHighlightings.loadBuiltInSemanticHighlightings.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="preferenceKey" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
A key to uniquely identify the highlighting's settings in the preference store.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="displayName" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
The name that is displayed for the highlighter in the Preferences window.
|
||||
</documentation>
|
||||
<appInfo>
|
||||
<meta.attribute translatable="true"/>
|
||||
</appInfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultTextColor" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
The default text color of the contributed highlighting. The value must be the integer RGB values (0-255) separated by commas. E.g., "127,0,85". Defaults to "0,0,0" (black).
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultBold" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
false by default
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultItalic" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
false by default
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultStrikethrough" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
false by default
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultUnderline" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
false by default
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="defaultEnabled" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
false by default
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="since"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
8.2
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="examples"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
The following is an example of a Semantic Highligher contribution:
|
||||
|
||||
<p>
|
||||
<pre>
|
||||
<extension
|
||||
point="org.eclipse.cdt.ui.semanticHighlighting"
|
||||
name="%extensionName"
|
||||
id="com.example.ui.semanticHighlightings">
|
||||
<semanticHighlighting
|
||||
id="com.example.ui.keywordHighlighting"
|
||||
priority="5"
|
||||
class="com.example.internal.ui.ExampleHighlighting"
|
||||
preferenceKey="example-keywords"
|
||||
displayName="%exampleHighlighting.displayName"
|
||||
defaultTextColor="127,0,85"
|
||||
defaultBold="true"
|
||||
defaultEnabled="true">
|
||||
<enablement>
|
||||
<with variable="projectNatures">
|
||||
<iterate operator="or">
|
||||
<equals value="org.eclipse.cdt.core.ccnature"/>
|
||||
</iterate>
|
||||
</with>
|
||||
<with variable="languageId">
|
||||
<or>
|
||||
<equals value="org.eclipse.cdt.core.g++"/>
|
||||
<equals value="org.eclipse.cdt.core.gcc"/>
|
||||
</or>
|
||||
</with>
|
||||
</enablement>
|
||||
</semanticHighlighting>
|
||||
</extension>
|
||||
</pre>
|
||||
</p>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="apiInfo"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
The contributed class must implement <code>org.eclipse.cdt.ui.text.ISemanticHighlighter</code>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="copyright"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
Copyright (c) 2013 QNX Software Systems 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
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Copyright (c) 2013 QNX Software Systems 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.editor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
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.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.jface.resource.DataFormatException;
|
||||
import org.eclipse.jface.resource.StringConverter;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
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.text.ISemanticHighlighter;
|
||||
import org.eclipse.cdt.ui.text.ISemanticToken;
|
||||
|
||||
public class ContributedSemanticHighlighting extends SemanticHighlighting {
|
||||
|
||||
/**
|
||||
* The configuration element needs to be cached until the class is instantiated. Instantiation is deferred
|
||||
* to avoid loading the contributing plugin when the highlighter is not actually needed.
|
||||
*/
|
||||
private IConfigurationElement configurationElement;
|
||||
private Boolean fStatus = null;
|
||||
private ISemanticHighlighter semanticHighlighter;
|
||||
|
||||
private final Expression enablementExpression;
|
||||
|
||||
private final int priority;
|
||||
private final String id;
|
||||
private final String preferenceKey;
|
||||
private final String displayName;
|
||||
|
||||
private final RGB defaultTextColor;
|
||||
private final boolean defaultBold;
|
||||
private final boolean defaultItalic;
|
||||
private final boolean defaultStrikethrough;
|
||||
private final boolean defaultUnderline;
|
||||
private final boolean defaultEnabled;
|
||||
|
||||
private static final String Attr_Class = "class"; //$NON-NLS-1$
|
||||
private static final String Attr_Priority = "priority"; //$NON-NLS-1$
|
||||
|
||||
private static final String Attr_PrefKey = "preferenceKey"; //$NON-NLS-1$
|
||||
private static final String Attr_DisplayName = "displayName"; //$NON-NLS-1$
|
||||
private static final String Attr_DefaultTextColor = "defaultTextColor"; //$NON-NLS-1$
|
||||
private static final String Attr_DefaultBold = "defaultBold"; //$NON-NLS-1$
|
||||
|
||||
private static final String Attr_DefaultItalic = "defaultItalic"; //$NON-NLS-1$
|
||||
private static final String Attr_DefaultStrikethrough = "defaultStrikethrough"; //$NON-NLS-1$
|
||||
private static final String Attr_DefaultUnderline = "defaultUnderline"; //$NON-NLS-1$
|
||||
private static final String Attr_DefaultEnabled = "defaultEnabled"; //$NON-NLS-1$
|
||||
|
||||
private static final String Var_projectNature = "projectNatures"; //$NON-NLS-1$
|
||||
private static final String Var_languageId = "languageId"; //$NON-NLS-1$
|
||||
private static final int Default_Priority = 1000;
|
||||
|
||||
public ContributedSemanticHighlighting(IConfigurationElement element) {
|
||||
configurationElement = element;
|
||||
|
||||
// required
|
||||
id = element.getDeclaringExtension().getNamespaceIdentifier() + '.'
|
||||
+ element.getDeclaringExtension().getSimpleIdentifier();
|
||||
|
||||
int pri = Default_Priority;
|
||||
String priStr = element.getAttribute(Attr_Priority);
|
||||
if (priStr != null)
|
||||
try {
|
||||
pri = Integer.parseInt(priStr);
|
||||
} catch (NumberFormatException e) {
|
||||
CUIPlugin.log("Error in priority attribute of " + id + " was " + priStr, e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
priority = pri;
|
||||
|
||||
Expression expr = null;
|
||||
IConfigurationElement[] children = element.getChildren(ExpressionTagNames.ENABLEMENT);
|
||||
switch (children.length) {
|
||||
case 0:
|
||||
fStatus = Boolean.TRUE;
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
ExpressionConverter parser = ExpressionConverter.getDefault();
|
||||
expr = parser.perform(children[0]);
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log("Error in enablement expression of " + id, e); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CUIPlugin.logError("Too many enablement expressions for " + id); //$NON-NLS-1$
|
||||
fStatus = Boolean.FALSE;
|
||||
break;
|
||||
}
|
||||
enablementExpression = expr;
|
||||
|
||||
preferenceKey = element.getAttribute(Attr_PrefKey);
|
||||
displayName = element.getAttribute(Attr_DisplayName);
|
||||
|
||||
// optional
|
||||
defaultTextColor = getRGBAttribute(element, id, Attr_DefaultTextColor);
|
||||
defaultBold = Boolean.parseBoolean(element.getAttribute(Attr_DefaultBold));
|
||||
defaultItalic = Boolean.parseBoolean(element.getAttribute(Attr_DefaultItalic));
|
||||
defaultStrikethrough = Boolean.parseBoolean(element.getAttribute(Attr_DefaultStrikethrough));
|
||||
defaultUnderline = Boolean.parseBoolean(element.getAttribute(Attr_DefaultUnderline));
|
||||
defaultEnabled = Boolean.parseBoolean(element.getAttribute(Attr_DefaultEnabled));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
private static RGB getRGBAttribute(IConfigurationElement element, String extensionId, String key) {
|
||||
String val = element.getAttribute(key);
|
||||
if (val != null)
|
||||
try {
|
||||
return StringConverter.asRGB(val);
|
||||
} catch (DataFormatException e) {
|
||||
CUIPlugin
|
||||
.log("Error in " + Attr_DefaultTextColor + " attribute of " + extensionId + ' ' + val + " is not a RGB value", e); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
|
||||
// black by default
|
||||
return new RGB(0, 0, 0);
|
||||
}
|
||||
|
||||
private ISemanticHighlighter createSemanticHighlighter() {
|
||||
|
||||
// only one try at creating the class
|
||||
if (configurationElement == null)
|
||||
return null;
|
||||
|
||||
IConfigurationElement element = configurationElement;
|
||||
configurationElement = null;
|
||||
|
||||
try {
|
||||
return (ISemanticHighlighter) element.createExecutableExtension(Attr_Class);
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log("Error in class attribute of " + id, e); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return preferenceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RGB getDefaultDefaultTextColor() {
|
||||
return defaultTextColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoldByDefault() {
|
||||
return defaultBold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItalicByDefault() {
|
||||
return defaultItalic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStrikethroughByDefault() {
|
||||
return defaultStrikethrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnderlineByDefault() {
|
||||
return defaultUnderline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return defaultEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresImplicitNames() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matches(ITranslationUnit tu) {
|
||||
|
||||
// if the enablement expression is missing or structurally invalid, then return immediately
|
||||
if (fStatus != null)
|
||||
return fStatus.booleanValue();
|
||||
|
||||
if (enablementExpression != null)
|
||||
try {
|
||||
EvaluationContext evalContext = new EvaluationContext(null, tu);
|
||||
|
||||
ICProject cProject = tu.getCProject();
|
||||
String[] natures = cProject.getProject().getDescription().getNatureIds();
|
||||
evalContext.addVariable(Var_projectNature, Arrays.asList(natures));
|
||||
|
||||
ILanguage language = tu.getLanguage();
|
||||
if( language != null )
|
||||
evalContext.addVariable(Var_languageId, language.getId());
|
||||
|
||||
return enablementExpression.evaluate(evalContext) == EvaluationResult.TRUE;
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log("Error while evaluating enablement expression for " + id, e); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
fStatus = Boolean.FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contributed ISemanticHighlighter if the receiver should be applied to the specified TU and
|
||||
* null otherwise.
|
||||
*/
|
||||
private ISemanticHighlighter getSemanticHighlighter(ITranslationUnit tu) {
|
||||
if (!matches(tu))
|
||||
return null;
|
||||
|
||||
if (semanticHighlighter == null)
|
||||
synchronized (this) {
|
||||
if (semanticHighlighter == null) {
|
||||
semanticHighlighter = createSemanticHighlighter();
|
||||
}
|
||||
}
|
||||
|
||||
return semanticHighlighter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
if (token == null)
|
||||
return false;
|
||||
|
||||
IASTTranslationUnit astTU = token.getRoot();
|
||||
if (astTU == null)
|
||||
return false;
|
||||
|
||||
ITranslationUnit tu = astTU.getOriginatingTranslationUnit();
|
||||
if (tu == null)
|
||||
return false;
|
||||
|
||||
ISemanticHighlighter highlighter = getSemanticHighlighter(tu);
|
||||
if (highlighter == null)
|
||||
return false;
|
||||
|
||||
return highlighter.consumes(token);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import org.eclipse.swt.graphics.RGB;
|
|||
import org.eclipse.ui.PlatformUI;
|
||||
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.text.ISemanticToken;
|
||||
|
||||
/**
|
||||
* Semantic highlighting.
|
||||
|
@ -100,7 +101,7 @@ public abstract class SemanticHighlighting {
|
|||
* @param token the semantic token for a {@link org.eclipse.cdt.core.dom.ast.IASTName}
|
||||
* @return <code>true</code> iff the semantic highlighting consumes the semantic token
|
||||
*/
|
||||
public abstract boolean consumes(SemanticToken token);
|
||||
public abstract boolean consumes(ISemanticToken token);
|
||||
|
||||
private String getThemeColorKey() {
|
||||
return CUIPlugin.PLUGIN_ID + "." + getPreferenceKey() + "Highlighting"; //$NON-NLS-1$//$NON-NLS-2$
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.editor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
import org.eclipse.jface.preference.PreferenceConverter;
|
||||
|
@ -56,6 +60,7 @@ import org.eclipse.cdt.core.index.IIndexFile;
|
|||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||
import org.eclipse.cdt.ui.text.ISemanticToken;
|
||||
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||
|
@ -228,7 +233,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -279,7 +284,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -330,7 +335,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTImplicitName)
|
||||
return false;
|
||||
|
@ -407,7 +412,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -461,7 +466,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTImplicitName)
|
||||
return false;
|
||||
|
@ -514,7 +519,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTImplicitName)
|
||||
return false;
|
||||
|
@ -585,7 +590,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTImplicitName)
|
||||
return false;
|
||||
|
@ -638,7 +643,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -698,7 +703,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -774,7 +779,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -836,7 +841,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof IParameter) {
|
||||
return true;
|
||||
|
@ -880,7 +885,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IBinding binding= token.getBinding();
|
||||
|
@ -927,7 +932,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof ICPPASTQualifiedName || node instanceof ICPPASTTemplateId) {
|
||||
return false;
|
||||
|
@ -977,7 +982,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IBinding binding= token.getBinding();
|
||||
|
@ -1024,7 +1029,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof IMacroBinding) {
|
||||
IASTName name= (IASTName)token.getNode();
|
||||
|
@ -1071,7 +1076,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof IMacroBinding) {
|
||||
IASTName name= (IASTName)token.getNode();
|
||||
|
@ -1118,7 +1123,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -1169,7 +1174,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof ICPPNamespace) {
|
||||
return true;
|
||||
|
@ -1213,7 +1218,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof ILabel) {
|
||||
return true;
|
||||
|
@ -1257,7 +1262,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -1313,7 +1318,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node.getTranslationUnit().isBasedOnIncompleteIndex()) {
|
||||
// Do not highlight problems is the AST is unreliable.
|
||||
|
@ -1370,7 +1375,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node= token.getNode();
|
||||
if (node instanceof IASTName) {
|
||||
IASTName name= (IASTName) node;
|
||||
|
@ -1459,7 +1464,7 @@ public class SemanticHighlightings {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean consumes(SemanticToken token) {
|
||||
public boolean consumes(ISemanticToken token) {
|
||||
IASTNode node = token.getNode();
|
||||
// So far we only have implicit names for overloaded operators and destructors,
|
||||
// so this works.
|
||||
|
@ -1545,36 +1550,106 @@ public class SemanticHighlightings {
|
|||
return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED_SUFFIX;
|
||||
}
|
||||
|
||||
private static class Key implements Comparable<Key> {
|
||||
public final int priority;
|
||||
public final String id;
|
||||
|
||||
public Key(int priority) {
|
||||
this(priority, null);
|
||||
}
|
||||
|
||||
public Key(int priority, String id) {
|
||||
this.priority = priority;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Key o) {
|
||||
if (priority < o.priority)
|
||||
return -1;
|
||||
if (o.priority < priority)
|
||||
return 1;
|
||||
|
||||
if (id == null)
|
||||
return o.id == null ? 0 : -1;
|
||||
|
||||
return o.id == null ? 1 : id.compareTo(o.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(priority);
|
||||
if (id != null) {
|
||||
str.append(' ');
|
||||
str.append(id);
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadBuiltInSemanticHighlightings(Map<Key, SemanticHighlighting> highlightings) {
|
||||
|
||||
highlightings.put(new Key(10), new MacroReferenceHighlighting()); // before all others!
|
||||
highlightings.put(new Key(20), new ProblemHighlighting());
|
||||
highlightings.put(new Key(30), new ExternalSDKHighlighting());
|
||||
highlightings.put(new Key(40), new ClassHighlighting());
|
||||
highlightings.put(new Key(50), new StaticFieldHighlighting());
|
||||
highlightings.put(new Key(60), new FieldHighlighting()); // after all other fields
|
||||
highlightings.put(new Key(70), new MethodDeclarationHighlighting());
|
||||
highlightings.put(new Key(80), new StaticMethodInvocationHighlighting());
|
||||
highlightings.put(new Key(90), new ParameterVariableHighlighting()); // before local variables
|
||||
highlightings.put(new Key(100), new LocalVariableDeclarationHighlighting());
|
||||
highlightings.put(new Key(110), new LocalVariableHighlighting());
|
||||
highlightings.put(new Key(120), new GlobalVariableHighlighting());
|
||||
highlightings.put(new Key(130), new TemplateParameterHighlighting()); // before template arguments!
|
||||
highlightings.put(new Key(140), new OverloadedOperatorHighlighting()); // before both method and function
|
||||
highlightings.put(new Key(150), new MethodHighlighting()); // before types to get ctors
|
||||
highlightings.put(new Key(160), new EnumHighlighting());
|
||||
highlightings.put(new Key(170), new MacroDefinitionHighlighting());
|
||||
highlightings.put(new Key(180), new FunctionDeclarationHighlighting());
|
||||
highlightings.put(new Key(190), new FunctionHighlighting());
|
||||
highlightings.put(new Key(200), new TypedefHighlighting());
|
||||
highlightings.put(new Key(210), new NamespaceHighlighting());
|
||||
highlightings.put(new Key(220), new LabelHighlighting());
|
||||
highlightings.put(new Key(230), new EnumeratorHighlighting());
|
||||
}
|
||||
|
||||
private static final String ExtensionPoint = "semanticHighlighting"; //$NON-NLS-1$
|
||||
|
||||
private static SemanticHighlighting[] loadSemanticHighlightings() {
|
||||
|
||||
Map<Key, SemanticHighlighting> highlightings = new TreeMap<SemanticHighlightings.Key, SemanticHighlighting>();
|
||||
|
||||
// load the built-in highlightings
|
||||
loadBuiltInSemanticHighlightings(highlightings);
|
||||
|
||||
// load the extensions
|
||||
IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(
|
||||
CUIPlugin.getPluginId(), ExtensionPoint);
|
||||
for (IConfigurationElement element : elements) {
|
||||
ContributedSemanticHighlighting contributedHighlighting = new ContributedSemanticHighlighting(
|
||||
element);
|
||||
|
||||
Key key = new Key(contributedHighlighting.getPriority(), contributedHighlighting.getId());
|
||||
highlightings.put(key, contributedHighlighting);
|
||||
}
|
||||
|
||||
return highlightings.values().toArray(new SemanticHighlighting[highlightings.size()]);
|
||||
}
|
||||
|
||||
private static final Object SemanticHighlightingsLock = new Object();
|
||||
|
||||
/**
|
||||
* @return The semantic highlightings, the order defines the precedence of matches, the first match wins.
|
||||
*/
|
||||
public static SemanticHighlighting[] getSemanticHighlightings() {
|
||||
if (fgSemanticHighlightings == null)
|
||||
fgSemanticHighlightings= new SemanticHighlighting[] {
|
||||
new MacroReferenceHighlighting(), // before all others!
|
||||
new ProblemHighlighting(),
|
||||
new ExternalSDKHighlighting(),
|
||||
new ClassHighlighting(),
|
||||
new StaticFieldHighlighting(),
|
||||
new FieldHighlighting(), // after all other fields
|
||||
new MethodDeclarationHighlighting(),
|
||||
new StaticMethodInvocationHighlighting(),
|
||||
new ParameterVariableHighlighting(), // before local variables
|
||||
new LocalVariableDeclarationHighlighting(),
|
||||
new LocalVariableHighlighting(),
|
||||
new GlobalVariableHighlighting(),
|
||||
new TemplateParameterHighlighting(), // before template arguments!
|
||||
new OverloadedOperatorHighlighting(), // before both method and function
|
||||
new MethodHighlighting(), // before types to get ctors
|
||||
new EnumHighlighting(),
|
||||
new MacroDefinitionHighlighting(),
|
||||
new FunctionDeclarationHighlighting(),
|
||||
new FunctionHighlighting(),
|
||||
new TypedefHighlighting(),
|
||||
new NamespaceHighlighting(),
|
||||
new LabelHighlighting(),
|
||||
new EnumeratorHighlighting(),
|
||||
};
|
||||
synchronized (SemanticHighlightingsLock) {
|
||||
if (fgSemanticHighlightings == null)
|
||||
fgSemanticHighlightings = loadSemanticHighlightings();
|
||||
}
|
||||
return fgSemanticHighlightings;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.ui.text.ISemanticToken;
|
||||
|
||||
/**
|
||||
* Semantic token.
|
||||
|
@ -22,7 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
|
|||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class SemanticToken {
|
||||
public final class SemanticToken implements ISemanticToken {
|
||||
/** AST node */
|
||||
private IASTNode fNode;
|
||||
|
||||
|
@ -38,6 +39,7 @@ public final class SemanticToken {
|
|||
/**
|
||||
* @return Returns the binding, can be <code>null</code>.
|
||||
*/
|
||||
@Override
|
||||
public IBinding getBinding() {
|
||||
if (!fIsBindingResolved) {
|
||||
fIsBindingResolved= true;
|
||||
|
@ -51,6 +53,7 @@ public final class SemanticToken {
|
|||
/**
|
||||
* @return the AST node
|
||||
*/
|
||||
@Override
|
||||
public IASTNode getNode() {
|
||||
return fNode;
|
||||
}
|
||||
|
@ -58,6 +61,7 @@ public final class SemanticToken {
|
|||
/**
|
||||
* @return the AST root
|
||||
*/
|
||||
@Override
|
||||
public IASTTranslationUnit getRoot() {
|
||||
if (!fIsRootResolved) {
|
||||
fIsRootResolved= true;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2013 QNX Software Systems 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.ui.text;
|
||||
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by contributors to the org.eclipse.cdt.ui.semanticHighlighting extension
|
||||
* point.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ISemanticHighlighter {
|
||||
/**
|
||||
* Returns <code>true</code> iff the semantic highlighting consumes the semantic token.
|
||||
* <p>
|
||||
* NOTE: Implementors are not allowed to keep a reference on the token or on any object retrieved from the
|
||||
* token.
|
||||
* </p>
|
||||
*
|
||||
* @param token
|
||||
* the semantic token for a {@link org.eclipse.cdt.core.dom.ast.IASTName}
|
||||
* @return <code>true</code> iff the semantic highlighting consumes the semantic token
|
||||
*/
|
||||
public boolean consumes(ISemanticToken token);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.eclipse.cdt.ui.text;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
||||
/**
|
||||
* An interface for accessing details of the token that is being highlighted.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ISemanticToken {
|
||||
/**
|
||||
* @return Returns the binding, can be <code>null</code>.
|
||||
*/
|
||||
public IBinding getBinding();
|
||||
|
||||
/**
|
||||
* @return the AST node
|
||||
*/
|
||||
public IASTNode getNode();
|
||||
|
||||
/**
|
||||
* @return the AST root
|
||||
*/
|
||||
public IASTTranslationUnit getRoot();
|
||||
}
|
Loading…
Add table
Reference in a new issue