summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Eidsness2013-01-31 11:41:44 (EST)
committerDoug Schaefer2013-02-01 16:18:28 (EST)
commit2bc9035f8c9f52455f923e0f7a16a6e41842b067 (patch)
tree077267a7fc7021f1c369561a7985d2b8cc22d6f1
parentd960fff7ddd0f1120d1ad733b04cc880461555fe (diff)
downloadorg.eclipse.cdt-2bc9035f8c9f52455f923e0f7a16a6e41842b067.zip
org.eclipse.cdt-2bc9035f8c9f52455f923e0f7a16a6e41842b067.tar.gz
org.eclipse.cdt-2bc9035f8c9f52455f923e0f7a16a6e41842b067.tar.bz2
Bug 363406: extensible semantic highlightingrefs/changes/74/10074/2
- 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>
-rw-r--r--core/org.eclipse.cdt.ui/plugin.properties2
-rw-r--r--core/org.eclipse.cdt.ui/plugin.xml1
-rw-r--r--core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd245
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ContributedSemanticHighlighting.java272
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java9
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java171
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticToken.java12
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticHighlighter.java31
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticToken.java27
9 files changed, 714 insertions, 56 deletions
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index 82a7255..18028ba 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -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
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index e86fecf..f5655de 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -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">
diff --git a/core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd b/core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd
new file mode 100644
index 0000000..f5960fd
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/schema/semanticHighlighting.exsd
@@ -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.
+&lt;p&gt;
+Extensions specify the priority of the highlighting, which determines the order in which the highlighting is invoked.
+&lt;/p&gt;
+&lt;p&gt;
+This extension point supports the &lt;code&gt;enablement&lt;/code&gt; tag. Properties to test on are:
+&lt;dl&gt;
+&lt;li&gt;projectNatures: type Collection; all project natures of the current project&lt;/li&gt;
+&lt;li&gt;languageId: type String; the result if ILanguage.getId on the token&apos;s ITranslationUnit&lt;/li&gt;
+&lt;/dl&gt;
+&lt;/p&gt;
+&lt;p&gt;
+Contributed highlightings will be visible in the Code tree of the &apos;C/C++ - Editor - Syntax Colouring&apos; preference page.
+&lt;/p&gt;
+ </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
+&lt;samp&gt;org.eclipse.cdt.ui.text.ISemanticHighlighter&lt;/samp&gt;
+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&apos;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., &quot;127,0,85&quot;. Defaults to &quot;0,0,0&quot; (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:
+
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension
+ point=&quot;org.eclipse.cdt.ui.semanticHighlighting&quot;
+ name=&quot;%extensionName&quot;
+ id=&quot;com.example.ui.semanticHighlightings&quot;&gt;
+ &lt;semanticHighlighting
+ id=&quot;com.example.ui.keywordHighlighting&quot;
+ priority=&quot;5&quot;
+ class=&quot;com.example.internal.ui.ExampleHighlighting&quot;
+ preferenceKey=&quot;example-keywords&quot;
+ displayName=&quot;%exampleHighlighting.displayName&quot;
+ defaultTextColor=&quot;127,0,85&quot;
+ defaultBold=&quot;true&quot;
+ defaultEnabled=&quot;true&quot;&gt;
+ &lt;enablement&gt;
+ &lt;with variable=&quot;projectNatures&quot;&gt;
+ &lt;iterate operator=&quot;or&quot;&gt;
+ &lt;equals value=&quot;org.eclipse.cdt.core.ccnature&quot;/&gt;
+ &lt;/iterate&gt;
+ &lt;/with&gt;
+ &lt;with variable=&quot;languageId&quot;&gt;
+ &lt;or&gt;
+ &lt;equals value=&quot;org.eclipse.cdt.core.g++&quot;/&gt;
+ &lt;equals value=&quot;org.eclipse.cdt.core.gcc&quot;/&gt;
+ &lt;/or&gt;
+ &lt;/with&gt;
+ &lt;/enablement&gt;
+ &lt;/semanticHighlighting&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ The contributed class must implement &lt;code&gt;org.eclipse.cdt.ui.text.ISemanticHighlighter&lt;/code&gt;
+ </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>
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ContributedSemanticHighlighting.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ContributedSemanticHighlighting.java
new file mode 100644
index 0000000..ada1691
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ContributedSemanticHighlighting.java
@@ -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);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java
index a58b746..b6d72dc 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java
@@ -17,11 +17,12 @@ 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.
* Cloned from JDT.
- *
+ *
* @since 4.0
*/
public abstract class SemanticHighlighting {
@@ -81,9 +82,9 @@ public abstract class SemanticHighlighting {
* @return the display name
*/
public abstract String getDisplayName();
-
+
/**
- * Indicates that the highlighting needs to visit implicit names
+ * Indicates that the highlighting needs to visit implicit names
* (e.g. overloaded operators)
*/
public boolean requiresImplicitNames() {
@@ -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$
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
index e3df7ae..5e6da1c 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
@@ -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;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticToken.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticToken.java
index 6b34458..03b8e51 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticToken.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticToken.java
@@ -15,14 +15,15 @@ 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.
* Cloned from JDT.
- *
+ *
* @since 4.0
*/
-public final class SemanticToken {
+public final class SemanticToken implements ISemanticToken {
/** AST node */
private IASTNode fNode;
@@ -38,26 +39,29 @@ public final class SemanticToken {
/**
* @return Returns the binding, can be <code>null</code>.
*/
+ @Override
public IBinding getBinding() {
if (!fIsBindingResolved) {
fIsBindingResolved= true;
if (fNode instanceof IASTName)
fBinding= ((IASTName) fNode).resolveBinding();
}
-
+
return fBinding;
}
/**
* @return the AST node
*/
+ @Override
public IASTNode getNode() {
return fNode;
}
-
+
/**
* @return the AST root
*/
+ @Override
public IASTTranslationUnit getRoot() {
if (!fIsRootResolved) {
fIsRootResolved= true;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticHighlighter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticHighlighter.java
new file mode 100644
index 0000000..6564050
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticHighlighter.java
@@ -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);
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticToken.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticToken.java
new file mode 100644
index 0000000..c9f3d65
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ISemanticToken.java
@@ -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();
+}