diff --git a/org.eclipse.jdt.text.tests/plugin.xml b/org.eclipse.jdt.text.tests/plugin.xml
index 49a78dccb84..22423af2496 100644
--- a/org.eclipse.jdt.text.tests/plugin.xml
+++ b/org.eclipse.jdt.text.tests/plugin.xml
@@ -47,4 +47,10 @@
+
+
+
+
diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java
index 8f02b18f676..96bb66735d3 100644
--- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java
+++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2023 IBM Corporation and others.
+ * Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -20,6 +20,7 @@
import org.eclipse.jdt.text.tests.codemining.CodeMiningTriggerTest;
import org.eclipse.jdt.text.tests.codemining.ParameterNamesCodeMiningTest;
import org.eclipse.jdt.text.tests.contentassist.ContentAssistTestSuite;
+import org.eclipse.jdt.text.tests.semantictokens.SemanticTokensProviderTest;
import org.eclipse.jdt.text.tests.spelling.SpellCheckEngineTestCase;
import org.eclipse.jdt.text.tests.templates.TemplatesTestSuite;
@@ -52,6 +53,7 @@
BracketInserterTest.class,
SpellCheckEngineTestCase.class,
SemanticHighlightingTest.class,
+ SemanticTokensProviderTest.class,
AutoboxingSemanticHighlightingTest.class,
Java23SemanticHighlightingTest.class,
NewForLoopJavaContextTest.class,
diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SampleSqlSemanticTokensProvider.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SampleSqlSemanticTokensProvider.java
new file mode 100644
index 00000000000..2f976dd568b
--- /dev/null
+++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SampleSqlSemanticTokensProvider.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2024 Broadcom Inc. and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Alex Boyko (Broadcom Inc.) - Initial implementation
+ *******************************************************************************/
+package org.eclipse.jdt.text.tests.semantictokens;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jdt.core.dom.TextBlock;
+
+import org.eclipse.jdt.ui.text.java.ISemanticTokensProvider;
+
+/**
+ * Semantic tokens are computed for string literals or text blocks starting with "SQL:" prefix.
+ *
+ * - SELECT, WHERE, IN, FROM are KEYWORD
+ * - *, <, >, ==, != etc are OPEARATOR
+ * - Words starting from capital are CLASS
+ * - Numbers are NUMBER
+ * - all other lower case starting words are LOCAL_VARIABLE
+ *
+ */
+public class SampleSqlSemanticTokensProvider implements ISemanticTokensProvider {
+
+ private static final String SQL_PREFIX = "SQL:";
+
+ @Override
+ public Collection computeSemanticTokens(CompilationUnit ast) {
+ List tokens = new ArrayList<>();
+ ast.accept(new ASTVisitor() {
+
+ @Override
+ public boolean visit(StringLiteral node) {
+ tokens.addAll(reconileEmbeddedExpression(node));
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(TextBlock node) {
+ tokens.addAll(reconileEmbeddedExpression(node));
+ return super.visit(node);
+ }
+
+ });
+ return tokens;
+ }
+
+ private List reconileEmbeddedExpression(Expression valueExp) {
+ String text = null;
+ int offset = 0;
+ if (valueExp instanceof StringLiteral sl && sl.getLiteralValue().startsWith(SQL_PREFIX)) {
+ text = sl.getEscapedValue();
+ int skip = 1 + SQL_PREFIX.length();
+ text = text.substring(skip, text.length() - 1);
+ offset = sl.getStartPosition() + skip; // +1 to skip over opening " and over "SQL:"
+ } else if (valueExp instanceof TextBlock tb && tb.getLiteralValue().startsWith(SQL_PREFIX)) {
+ text = tb.getEscapedValue();
+ int skip = 3 + SQL_PREFIX.length();
+ text = text.substring(skip, text.length() - 3);
+ offset = tb.getStartPosition() + skip; // +3 to skip over opening """ and over "SQL:"
+ }
+ return compute(text, offset);
+ }
+
+ private List compute(String text, int offset) {
+ if (text == null) {
+ return Collections.emptyList();
+ }
+ List tokens = new ArrayList<>();
+ Matcher matcher= Pattern.compile("[\\w*=>":
+ case "<":
+ case ">=":
+ case "<=":
+ case "==":
+ case "!=":
+ return TokenType.OPERATOR;
+ default:
+ if (token.length() > 0 && Character.isUpperCase(token.charAt(0))) {
+ return TokenType.CLASS;
+ }
+ return TokenType.LOCAL_VARIABLE;
+ }
+ }
+ }
+
+
+}
diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SemanticTokensProviderTest.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SemanticTokensProviderTest.java
new file mode 100644
index 00000000000..3e3d0740178
--- /dev/null
+++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/semantictokens/SemanticTokensProviderTest.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2024 Broadcom Inc. and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Alex Boyko (Broadcom Inc.) - Initial implementation
+ *******************************************************************************/
+package org.eclipse.jdt.text.tests.semantictokens;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.eclipse.jdt.text.tests.AbstractSemanticHighlightingTest;
+
+import org.eclipse.jface.text.Position;
+
+import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings;
+
+public class SemanticTokensProviderTest extends AbstractSemanticHighlightingTest {
+
+ @Rule
+ public SemanticHighlightingTestSetup shts= new SemanticHighlightingTestSetup( "/SHTest/src/STTest.java");
+
+ @Test
+ public void contributedHighlighting() throws Exception {
+ setUpSemanticHighlighting(SemanticHighlightings.CLASS);
+ setUpSemanticHighlighting(SemanticHighlightings.NUMBER);
+ setUpSemanticHighlighting(SemanticHighlightings.LOCAL_VARIABLE);
+ Position[] actual= getSemanticHighlightingPositions();
+ Position[] expected= new Position[] {
+ createPosition(0, 6, 1),
+ createPosition(1, 1, 6),
+ createPosition(1, 20, 6),
+ createPosition(1, 27, 1),
+ createPosition(1, 29, 4),
+ createPosition(1, 34, 1),
+ createPosition(1, 36, 5),
+ createPosition(1, 42, 1),
+ createPosition(1, 44, 2),
+ createPosition(1, 47, 3),
+ };
+ assertEqualPositions(expected, actual);
+ }
+
+
+}
diff --git a/org.eclipse.jdt.text.tests/testResources/semanticHighlightingTest1/STTest.java b/org.eclipse.jdt.text.tests/testResources/semanticHighlightingTest1/STTest.java
new file mode 100644
index 00000000000..c62403820c3
--- /dev/null
+++ b/org.eclipse.jdt.text.tests/testResources/semanticHighlightingTest1/STTest.java
@@ -0,0 +1,3 @@
+class A {
+ String sql = "SQL: SELECT * FROM T WHERE a == 567";
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.ui/META-INF/MANIFEST.MF
index d1e23212930..e305e62874b 100644
--- a/org.eclipse.jdt.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.ui/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Automatic-Module-Name: org.eclipse.jdt.ui
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.ui; singleton:=true
-Bundle-Version: 3.33.300.qualifier
+Bundle-Version: 3.34.0.qualifier
Bundle-Activator: org.eclipse.jdt.internal.ui.JavaPlugin
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %providerName
diff --git a/org.eclipse.jdt.ui/plugin.properties b/org.eclipse.jdt.ui/plugin.properties
index 9ea43e11949..45211236b70 100644
--- a/org.eclipse.jdt.ui/plugin.properties
+++ b/org.eclipse.jdt.ui/plugin.properties
@@ -26,6 +26,7 @@ JavaSelectRulerAction.label= Java Editor Ruler Single-Click
importExportWizards.category=Java
elementFiltersName=Java Element Filters
+semanticTokens=Java Editor Semantic Tokens for Syntax Highlighting
classpathContainerPageExtensionPoint=Classpath Container Configuration
classpathAttributeConfiguration=Classpath Attribute Configuration
@@ -38,6 +39,8 @@ javadocExportWizardPageExtensionPoint=Javadoc Export Wizard Page
cleanUpExtensionPoint=Clean Ups
+semanticTokensExtensionPoint=Semantic Tokens
+
queryParticipantsExtensionPoint=Java Query Participants
defaultClasspathContainerPage=Default Classpath Container
diff --git a/org.eclipse.jdt.ui/plugin.xml b/org.eclipse.jdt.ui/plugin.xml
index ceb88b44b7b..5c21a366586 100644
--- a/org.eclipse.jdt.ui/plugin.xml
+++ b/org.eclipse.jdt.ui/plugin.xml
@@ -34,6 +34,7 @@
+
diff --git a/org.eclipse.jdt.ui/pom.xml b/org.eclipse.jdt.ui/pom.xml
index 3818bc298e7..bd14d5f10c9 100644
--- a/org.eclipse.jdt.ui/pom.xml
+++ b/org.eclipse.jdt.ui/pom.xml
@@ -18,7 +18,7 @@
org.eclipse.jdt
org.eclipse.jdt.ui
- 3.33.300-SNAPSHOT
+ 3.34.0-SNAPSHOT
eclipse-plugin
diff --git a/org.eclipse.jdt.ui/schema/semanticTokens.exsd b/org.eclipse.jdt.ui/schema/semanticTokens.exsd
new file mode 100644
index 00000000000..7c45ce0890e
--- /dev/null
+++ b/org.eclipse.jdt.ui/schema/semanticTokens.exsd
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+ Allows contributions of semantic tokens into Java source editor. Contributions are not sorted. This extension point is experimental.
+
+
+
+
+
+
+
+
+
+ Allows contributions of semantic tokens into Java source editor. Contributions are not sorted. This extension point is experimental.
+
+
+
+
+
+
+
+
+
+ a fully qualified identifier of the target extension point
+
+
+
+
+
+
+ an optional identifier of the extension instance
+
+
+
+
+
+
+ an optional name of the extension instance
+
+
+
+
+
+
+
+
+
+
+
+
+ Contributed provider of semantic tokens
+
+
+
+
+
+
+ Instance of the class able to compute Semantic Tokens for a given Java source AST
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3.34
+
+
+
+
+
+
+
+
+ The following is an example of a Semantic Tokens Provider contribution:
+
+<p>
+<pre>
+ <extension point="org.eclipse.jdt.ui.semanticTokens">
+ <provider
+ class="org.eclipse.example.jdt.ExampleJavaSemanticTokensProvider">
+ </provider>
+ </extension>
+</pre>
+</p>
+
+
+
+
+
+
+
+
+ The contributed class must implement <code>org.eclipse.jdt.ui.text.java.ISemanticTokensProvider</code>
+
+
+
+
+
+
+
+
+ Allows contributing <code>org.eclipse.jdt.ui.text.java.ISemanticTokensProvide</code> which will colour the code with colours allowed in the Java Editor. This is useful for languages embedded into Java via annotation parameters for example such as SQL queries, Spring Expression Language snippets etc. The contributions are not sorted. It is recommneded therefore not to override semantic tokens between providers. This extension is experimental and only used by LSP4E project at the moment.
+
+
+
+
+
+
+
+
+ Copyright (c) 2024 Broadcom Inc. and others.<br>
+
+This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at <a href="https://www.eclipse.org/legal/epl-2.0">https://www.eclipse.org/legal/epl-v20.html</a>/
+
+SPDX-License-Identifier: EPL-2.0
+
+
+
+
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingManager.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingManager.java
index 0700fc38a69..7b8735cd01f 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingManager.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -36,6 +36,7 @@
import org.eclipse.jdt.ui.text.IColorManagerExtension;
import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
+import org.eclipse.jdt.internal.ui.preferences.SyntaxColorHighlighting;
import org.eclipse.jdt.internal.ui.text.JavaPresentationReconciler;
/**
@@ -54,15 +55,18 @@ static class Highlighting { // TODO: rename to HighlightingStyle
private TextAttribute fTextAttribute;
/** Enabled state */
private boolean fIsEnabled;
+ /** Preference Key */
+ private final String fPreferenceKey;
/**
* Initialize with the given text attribute.
* @param textAttribute The text attribute
* @param isEnabled the enabled state
*/
- public Highlighting(TextAttribute textAttribute, boolean isEnabled) {
+ public Highlighting(String preferenceKey, TextAttribute textAttribute, boolean isEnabled) {
setTextAttribute(textAttribute);
setEnabled(isEnabled);
+ this.fPreferenceKey = preferenceKey;
}
/**
@@ -92,6 +96,11 @@ public boolean isEnabled() {
public void setEnabled(boolean isEnabled) {
fIsEnabled= isEnabled;
}
+
+ public String getPreferenceKey() {
+ return fPreferenceKey;
+ }
+
}
/**
@@ -252,6 +261,7 @@ public int hashCode() {
private SemanticHighlighting[] fSemanticHighlightings;
/** Highlightings */
private Highlighting[] fHighlightings;
+ private Highlighting[] fSyntaxHighlightings;
/** The editor */
private JavaEditor fEditor;
@@ -338,7 +348,7 @@ private void enable() {
if (fEditor != null) {
fReconciler= createSemanticHighlightingReconciler();
- fReconciler.install(fEditor, fSourceViewer, fPresenter, fSemanticHighlightings, fHighlightings);
+ fReconciler.install(fEditor, fSourceViewer, fPresenter, fSemanticHighlightings, fHighlightings, fSyntaxHighlightings);
} else {
fPresenter.updatePresentation(null, createHardcodedPositions(), new HighlightedPosition[0]);
}
@@ -374,10 +384,9 @@ private HighlightedPosition[] createHardcodedPositions() {
* @return the corresponding highlighting
*/
private Highlighting getHighlighting(String key) {
- for (int i= 0; i < fSemanticHighlightings.length; i++) {
- SemanticHighlighting semanticHighlighting= fSemanticHighlightings[i];
- if (key.equals(semanticHighlighting.getPreferenceKey()))
- return fHighlightings[i];
+ for (Highlighting highlighting : fHighlightings) {
+ if (key.equals(highlighting.getPreferenceKey()))
+ return highlighting;
}
return null;
}
@@ -432,42 +441,58 @@ private boolean isEnabled() {
private void initializeHighlightings() {
fSemanticHighlightings= SemanticHighlightings.getSemanticHighlightings();
fHighlightings= new Highlighting[fSemanticHighlightings.length];
-
for (int i= 0, n= fSemanticHighlightings.length; i < n; i++) {
SemanticHighlighting semanticHighlighting= fSemanticHighlightings[i];
- String colorKey= SemanticHighlightings.getColorPreferenceKey(semanticHighlighting);
- addColor(colorKey);
+ String colorKey= SemanticHighlightings.getColorPreferenceKey(semanticHighlighting);
String boldKey= SemanticHighlightings.getBoldPreferenceKey(semanticHighlighting);
- int style= fPreferenceStore.getBoolean(boldKey) ? SWT.BOLD : SWT.NORMAL;
-
String italicKey= SemanticHighlightings.getItalicPreferenceKey(semanticHighlighting);
- if (fPreferenceStore.getBoolean(italicKey))
- style |= SWT.ITALIC;
-
String strikethroughKey= SemanticHighlightings.getStrikethroughPreferenceKey(semanticHighlighting);
- if (fPreferenceStore.getBoolean(strikethroughKey))
- style |= TextAttribute.STRIKETHROUGH;
-
String underlineKey= SemanticHighlightings.getUnderlinePreferenceKey(semanticHighlighting);
- if (fPreferenceStore.getBoolean(underlineKey))
- style |= TextAttribute.UNDERLINE;
-
boolean isEnabled= fPreferenceStore.getBoolean(SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting));
- fHighlightings[i]= new Highlighting(new TextAttribute(fColorManager.getColor(PreferenceConverter.getColor(fPreferenceStore, colorKey)), null, style), isEnabled);
+ fHighlightings[i]= createHighlightingFromPereferences(semanticHighlighting.getPreferenceKey(), isEnabled, colorKey, boldKey, italicKey, strikethroughKey, underlineKey);
+ }
+
+ SyntaxColorHighlighting[] syntaxHighlightings= SyntaxColorHighlighting.getSyntaxColorHighlightings();
+ fSyntaxHighlightings= new Highlighting[syntaxHighlightings.length];
+ for (int i= 0; i < syntaxHighlightings.length; i++) {
+ SyntaxColorHighlighting h= syntaxHighlightings[i];
+ fSyntaxHighlightings[i]= createHighlightingFromPereferences(h.preferenceKey(), true, h.preferenceKey(), h.getBoldPreferenceKey(), h.getItalicPreferenceKey(), h.getStrikethroughPreferenceKey(), h.getUnderlinePreferenceKey());
}
}
+ private Highlighting createHighlightingFromPereferences(String key, boolean isEnabled, String colorKey, String boldKey, String italicKey, String strikethroughKey, String underlineKey) {
+ addColor(colorKey);
+
+ int style= fPreferenceStore.getBoolean(boldKey) ? SWT.BOLD : SWT.NORMAL;
+
+ if (fPreferenceStore.getBoolean(italicKey))
+ style |= SWT.ITALIC;
+
+ if (fPreferenceStore.getBoolean(strikethroughKey))
+ style |= TextAttribute.STRIKETHROUGH;
+
+ if (fPreferenceStore.getBoolean(underlineKey))
+ style |= TextAttribute.UNDERLINE;
+
+ return new Highlighting(key, new TextAttribute(fColorManager.getColor(PreferenceConverter.getColor(fPreferenceStore, colorKey)), null, style), isEnabled);
+ }
+
/**
* Dispose the semantic highlightings.
*/
private void disposeHighlightings() {
- for (SemanticHighlighting fSemanticHighlighting : fSemanticHighlightings)
+ for (SemanticHighlighting fSemanticHighlighting : fSemanticHighlightings) {
removeColor(SemanticHighlightings.getColorPreferenceKey(fSemanticHighlighting));
+ }
+ for (Highlighting h : fSyntaxHighlightings) {
+ removeColor(h.getPreferenceKey());
+ }
fSemanticHighlightings= null;
fHighlightings= null;
+ fSyntaxHighlightings= null;
}
/*
@@ -554,6 +579,52 @@ private void handlePropertyChangeEvent(PropertyChangeEvent event) {
}
}
+ SyntaxColorHighlighting[] editorHighlightings= SyntaxColorHighlighting.getSyntaxColorHighlightings();
+ for (int i= 0, n= editorHighlightings.length; i < n; i++) {
+ SyntaxColorHighlighting h= editorHighlightings[i];
+
+ String colorKey= h.preferenceKey();
+ if (colorKey.equals(event.getProperty())) {
+ adaptToTextForegroundChange(fSyntaxHighlightings[i], event);
+ fPresenter.highlightingStyleChanged(fSyntaxHighlightings[i]);
+ refreshNeeded= true;
+ continue;
+ }
+
+ String boldKey= h.getBoldPreferenceKey();
+ if (boldKey.equals(event.getProperty())) {
+ adaptToTextStyleChange(fSyntaxHighlightings[i], event, SWT.BOLD);
+ fPresenter.highlightingStyleChanged(fSyntaxHighlightings[i]);
+ refreshNeeded= true;
+ continue;
+ }
+
+ String italicKey= h.getItalicPreferenceKey();
+ if (italicKey.equals(event.getProperty())) {
+ adaptToTextStyleChange(fSyntaxHighlightings[i], event, SWT.ITALIC);
+ fPresenter.highlightingStyleChanged(fSyntaxHighlightings[i]);
+ refreshNeeded= true;
+ continue;
+ }
+
+ String strikethroughKey= h.getStrikethroughPreferenceKey();
+ if (strikethroughKey.equals(event.getProperty())) {
+ adaptToTextStyleChange(fSyntaxHighlightings[i], event, TextAttribute.STRIKETHROUGH);
+ fPresenter.highlightingStyleChanged(fSyntaxHighlightings[i]);
+ refreshNeeded= true;
+ continue;
+ }
+
+ String underlineKey= h.getUnderlinePreferenceKey();
+ if (underlineKey.equals(event.getProperty())) {
+ adaptToTextStyleChange(fSyntaxHighlightings[i], event, TextAttribute.UNDERLINE);
+ fPresenter.highlightingStyleChanged(fSyntaxHighlightings[i]);
+ refreshNeeded= true;
+ continue;
+ }
+
+ }
+
if (refreshNeeded && fReconciler != null)
fReconciler.refresh();
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingReconciler.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingReconciler.java
index 9453d16ab8a..667bd3b73e3 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingReconciler.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SemanticHighlightingReconciler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2022 IBM Corporation and others.
+ * Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,13 +15,18 @@
package org.eclipse.jdt.internal.ui.javaeditor;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
@@ -52,6 +57,9 @@
import org.eclipse.jdt.core.dom.YieldStatement;
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jdt.ui.text.java.ISemanticTokensProvider;
+
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.HighlightedPosition;
import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.Highlighting;
@@ -259,33 +267,6 @@ public boolean visit(SimpleName node) {
return false;
}
- /**
- * Add a position with the given range and highlighting iff it does not exist already.
- * @param offset The range offset
- * @param length The range length
- * @param highlighting The highlighting
- */
- private void addPosition(int offset, int length, Highlighting highlighting) {
- boolean isExisting= false;
- // TODO: use binary search
- for (int i= 0, n= fRemovedPositions.size(); i < n; i++) {
- HighlightedPosition position= (HighlightedPosition) fRemovedPositions.get(i);
- if (position == null)
- continue;
- if (position.isEqual(offset, length, highlighting)) {
- isExisting= true;
- fRemovedPositions.set(i, null);
- fNOfRemovedPositions--;
- break;
- }
- }
-
- if (!isExisting) {
- Position position= fJobPresenter.createHighlightedPosition(offset, length, highlighting);
- fAddedPositions.add(position);
- }
- }
-
/**
* Retain the positions completely contained in the given range.
* @param offset The range offset
@@ -326,6 +307,38 @@ public boolean visit(GuardedPattern node) {
}
}
+ /**
+ * Add a position with the given range and highlighting iff it does not exist already.
+ * @param offset The range offset
+ * @param length The range length
+ * @param highlighting The highlighting
+ */
+ private void addPosition(int offset, int length, Highlighting highlighting) {
+ boolean isExisting= false;
+ // TODO: use binary search
+ for (int i= 0, n= fRemovedPositions.size(); i < n; i++) {
+ HighlightedPosition position= (HighlightedPosition) fRemovedPositions.get(i);
+ if (position == null)
+ continue;
+ if (position.isEqual(offset, length, highlighting)) {
+ isExisting= true;
+ fRemovedPositions.set(i, null);
+ fNOfRemovedPositions--;
+ break;
+ }
+ }
+
+ if (!isExisting) {
+ Position position= fJobPresenter.createHighlightedPosition(offset, length, highlighting);
+ fAddedPositions.add(position);
+ }
+ }
+
+ private static final String JAVA_EDITOR_SEMANTIC_TOKENS_EXTENSION_POINT= "org.eclipse.jdt.ui.semanticTokens"; //$NON-NLS-1$
+ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+
+ private static ISemanticTokensProvider[] fSemanticTokensProviders;
+
/** Position collector */
private PositionCollector fCollector= new PositionCollector();
@@ -339,6 +352,8 @@ public boolean visit(GuardedPattern node) {
private SemanticHighlighting[] fSemanticHighlightings;
/** Highlightings */
private Highlighting[] fHighlightings;
+ /** Syntax Highlightings */
+ private Highlighting[] fSyntaxHighlightings;
/** Background job's added highlighted positions */
private List fAddedPositions= new ArrayList<>();
@@ -369,6 +384,7 @@ public boolean visit(GuardedPattern node) {
private SemanticHighlighting[] fJobSemanticHighlightings;
/** Highlightings - cache for background thread, only valid during {@link #reconciled(CompilationUnit, boolean, IProgressMonitor)} */
private Highlighting[] fJobHighlightings;
+ private Highlighting[] fJobSyntaxHighlightings;
/**
* XXX Hack for performance reasons (should loop over fJobSemanticHighlightings can call consumes(*))
@@ -384,6 +400,30 @@ public void aboutToBeReconciled() {
// Do nothing
}
+ private static synchronized ISemanticTokensProvider[] getContributedSemanticTokensProviders() {
+ if (fSemanticTokensProviders == null) {
+ IExtensionRegistry registry= Platform.getExtensionRegistry();
+ IConfigurationElement[] elements= registry.getConfigurationElementsFor(JAVA_EDITOR_SEMANTIC_TOKENS_EXTENSION_POINT);
+ fSemanticTokensProviders = Arrays.stream(elements).map(ce -> {
+ try {
+ return (ISemanticTokensProvider) ce.createExecutableExtension(ATTR_CLASS);
+ } catch (Exception e) {
+ JavaPlugin.getDefault().getLog().error("Cannot instatiate semantic tokens provider '%s' contributed by '%s'".formatted(ce.getAttribute(ATTR_CLASS), ce.getContributor().getName()), e); //$NON-NLS-1$
+ return null;
+ }
+ }).filter(Objects::nonNull).toArray(ISemanticTokensProvider[]::new);
+ }
+ return fSemanticTokensProviders;
+ }
+
+ private List getContributedSemanticTokens(CompilationUnit ast) {
+ List contributedTokens = new ArrayList<>();
+ for (ISemanticTokensProvider provider : getContributedSemanticTokensProviders()) {
+ contributedTokens.addAll(provider.computeSemanticTokens(ast));
+ }
+ return contributedTokens;
+ }
+
/*
* @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit, boolean, IProgressMonitor)
*/
@@ -399,6 +439,7 @@ public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor pro
fJobPresenter= fPresenter;
fJobSemanticHighlightings= fSemanticHighlightings;
fJobHighlightings= fHighlightings;
+ fJobSyntaxHighlightings = fSyntaxHighlightings;
try {
if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null)
@@ -424,7 +465,9 @@ public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor pro
break;
}
}
- reconcilePositions(subtrees);
+
+ reconcilePositions(subtrees, getContributedSemanticTokens(ast));
+
}
TextPresentation textPresentation= null;
@@ -440,6 +483,7 @@ public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor pro
fJobSemanticHighlightings= null;
fJobHighlightings= null;
fJobDeprecatedMemberHighlighting= null;
+ fJobSyntaxHighlightings = null;
synchronized (fReconcileLock) {
fIsReconciling= false;
}
@@ -467,14 +511,22 @@ private void startReconcilingPositions() {
* Reconcile positions based on the AST subtrees
*
* @param subtrees the AST subtrees
+ * @param contributedTokens contributed semantic tokens data
*/
- private void reconcilePositions(ASTNode[] subtrees) {
+ private void reconcilePositions(ASTNode[] subtrees, List contributedTokens) {
// FIXME: remove positions not covered by subtrees
-
-
for (ASTNode subtree : subtrees)
subtree.accept(fCollector);
+
+ for (ISemanticTokensProvider.SemanticToken t : contributedTokens) {
+ Highlighting h = fromSemanticTokenType(t.tokenType());
+ if (h == null) {
+ JavaPlugin.logErrorMessage("Cannot find semantic highlighting for %s".formatted(t)); //$NON-NLS-1$
+ } else {
+ addPosition(t.ofset(), t.length(), h);
+ }
+ }
List oldPositions= fRemovedPositions;
List newPositions= new ArrayList<>(fNOfRemovedPositions);
for (Position current : oldPositions) {
@@ -484,6 +536,101 @@ private void reconcilePositions(ASTNode[] subtrees) {
fRemovedPositions= newPositions;
}
+ private Highlighting fromSemanticTokenType(ISemanticTokensProvider.TokenType type) {
+ if (type == null) {
+ return null;
+ }
+ switch (type) {
+ case OPERATOR:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_JAVA_OPERATOR_COLOR);
+ case SINGLE_LINE_COMMENT:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR);
+ case KEYWORD:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR);
+ case BRACKET:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_JAVA_BRACKET_COLOR);
+ case MULTI_LINE_COMMENT:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR);
+ case STRING:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_STRING_COLOR);
+ case METHOD:
+ return findSemanticHighlighting(SemanticHighlightings.METHOD);
+ case ABSTRACT_CLASS:
+ return findSemanticHighlighting(SemanticHighlightings.ABSTRACT_CLASS);
+ case ABSTRACT_METHOD_INVOCATION:
+ return findSemanticHighlighting(SemanticHighlightings.ABSTRACT_METHOD_INVOCATION);
+ case ANNOTATION:
+ return findSemanticHighlighting(SemanticHighlightings.ANNOTATION);
+ case ANNOTATION_ELEMENT_REFERENCE:
+ return findSemanticHighlighting(SemanticHighlightings.ANNOTATION_ELEMENT_REFERENCE);
+ case AUTOBOXING:
+ return findSemanticHighlighting(SemanticHighlightings.AUTOBOXING);
+ case CLASS:
+ return findSemanticHighlighting(SemanticHighlightings.CLASS);
+ case DEPRECATED_MEMBER:
+ return findSemanticHighlighting(SemanticHighlightings.DEPRECATED_MEMBER);
+ case ENUM:
+ return findSemanticHighlighting(SemanticHighlightings.ENUM);
+ case FIELD:
+ return findSemanticHighlighting(SemanticHighlightings.FIELD);
+ case INHERITED_FIELD:
+ return findSemanticHighlighting(SemanticHighlightings.INHERITED_FIELD);
+ case INHERITED_METHOD_INVOCATION:
+ return findSemanticHighlighting(SemanticHighlightings.INHERITED_METHOD_INVOCATION);
+ case INTERFACE:
+ return findSemanticHighlighting(SemanticHighlightings.INTERFACE);
+ case LOCAL_VARIABLE:
+ return findSemanticHighlighting(SemanticHighlightings.LOCAL_VARIABLE);
+ case LOCAL_VARIABLE_DECLARATION:
+ return findSemanticHighlighting(SemanticHighlightings.LOCAL_VARIABLE_DECLARATION);
+ case METHOD_DECLARATION:
+ return findSemanticHighlighting(SemanticHighlightings.METHOD_DECLARATION);
+ case NUMBER:
+ return findSemanticHighlighting(SemanticHighlightings.NUMBER);
+ case PARAMETER_VARIABLE:
+ return findSemanticHighlighting(SemanticHighlightings.PARAMETER_VARIABLE);
+ case STATIC_FIELD:
+ return findSemanticHighlighting(SemanticHighlightings.STATIC_FIELD);
+ case STATIC_FINAL_FIELD:
+ return findSemanticHighlighting(SemanticHighlightings.STATIC_FINAL_FIELD);
+ case STATIC_METHOD_INVOCATION:
+ return findSemanticHighlighting(SemanticHighlightings.STATIC_METHOD_INVOCATION);
+ case TYPE_ARGUMENT:
+ return findSemanticHighlighting(SemanticHighlightings.TYPE_ARGUMENT);
+ case TYPE_VARIABLE:
+ return findSemanticHighlighting(SemanticHighlightings.TYPE_VARIABLE);
+ case RESTRICTED_IDENTIFIER:
+ return findSemanticHighlighting(SemanticHighlightingsCore.RESTRICTED_KEYWORDS);
+ case DEFAULT:
+ default:
+ return findSyntaxHighlighting(PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR);
+ }
+ }
+
+ private Highlighting findSemanticHighlighting(String preferenceKey) {
+ for (Highlighting h : fJobHighlightings) {
+ if (Objects.equals(preferenceKey, h.getPreferenceKey())) {
+ if (!h.isEnabled()) {
+ break;
+ }
+ return h;
+ }
+ }
+ return null;
+ }
+
+ private Highlighting findSyntaxHighlighting(String key) {
+ for (Highlighting h : fJobSyntaxHighlightings) {
+ if (Objects.equals(key, h.getPreferenceKey())) {
+ if (!h.isEnabled()) {
+ break;
+ }
+ return h;
+ }
+ }
+ return null;
+ }
+
/**
* Update the presentation.
*
@@ -537,11 +684,13 @@ private void stopReconcilingPositions() {
* @param presenter the semantic highlighting presenter
* @param semanticHighlightings the semantic highlightings
* @param highlightings the highlightings
+ * @param syntaxHighlightings editor syntax highlightings
*/
- public void install(JavaEditor editor, ISourceViewer sourceViewer, SemanticHighlightingPresenter presenter, SemanticHighlighting[] semanticHighlightings, Highlighting[] highlightings) {
+ public void install(JavaEditor editor, ISourceViewer sourceViewer, SemanticHighlightingPresenter presenter, SemanticHighlighting[] semanticHighlightings, Highlighting[] highlightings, Highlighting[] syntaxHighlightings) {
fPresenter= presenter;
fSemanticHighlightings= semanticHighlightings;
fHighlightings= highlightings;
+ fSyntaxHighlightings= syntaxHighlightings;
fEditor= editor;
fSourceViewer= sourceViewer;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaEditorColoringConfigurationBlock.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaEditorColoringConfigurationBlock.java
index 125583eaf10..5a270dc56f3 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaEditorColoringConfigurationBlock.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaEditorColoringConfigurationBlock.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -289,43 +289,10 @@ public boolean hasChildren(Object element) {
}
}
- private static final String BOLD= PreferenceConstants.EDITOR_BOLD_SUFFIX;
- /**
- * Preference key suffix for italic preferences.
- * @since 3.0
- */
- private static final String ITALIC= PreferenceConstants.EDITOR_ITALIC_SUFFIX;
- /**
- * Preference key suffix for strikethrough preferences.
- * @since 3.1
- */
- private static final String STRIKETHROUGH= PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX;
- /**
- * Preference key suffix for underline preferences.
- * @since 3.1
- */
- private static final String UNDERLINE= PreferenceConstants.EDITOR_UNDERLINE_SUFFIX;
-
private static final String COMPILER_TASK_TAGS= JavaCore.COMPILER_TASK_TAGS;
/**
* The keys of the overlay store.
*/
- private final String[][] fSyntaxColorListModel= new String[][] {
- { PreferencesMessages.JavaEditorPreferencePage_javaDocKeywords, PreferenceConstants.EDITOR_JAVADOC_KEYWORD_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_javaDocHtmlTags, PreferenceConstants.EDITOR_JAVADOC_TAG_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_javaDocLinks, PreferenceConstants.EDITOR_JAVADOC_LINKS_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_javaDocOthers, PreferenceConstants.EDITOR_JAVADOC_DEFAULT_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_multiLineComment, PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_singleLineComment, PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_javaCommentTaskTags, PreferenceConstants.EDITOR_TASK_TAG_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_keywords, PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_returnKeyword, PreferenceConstants.EDITOR_JAVA_KEYWORD_RETURN_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_operators, PreferenceConstants.EDITOR_JAVA_OPERATOR_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_brackets, PreferenceConstants.EDITOR_JAVA_BRACKET_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_strings, PreferenceConstants.EDITOR_STRING_COLOR },
- { PreferencesMessages.JavaEditorPreferencePage_others, PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR },
- };
-
private final String fJavaCategory= PreferencesMessages.JavaEditorPreferencePage_coloring_category_java;
private final String fJavadocCategory= PreferencesMessages.JavaEditorPreferencePage_coloring_category_javadoc;
private final String fCommentsCategory= PreferencesMessages.JavaEditorPreferencePage_coloring_category_comments;
@@ -385,8 +352,8 @@ public JavaEditorColoringConfigurationBlock(OverlayPreferenceStore store) {
fColorManager= new JavaColorManager();
- for (String[] syntaxColor : fSyntaxColorListModel)
- fListModel.add(new HighlightingColorListItem (syntaxColor[0], syntaxColor[1], syntaxColor[1] + BOLD, syntaxColor[1] + ITALIC, syntaxColor[1] + STRIKETHROUGH, syntaxColor[1] + UNDERLINE));
+ for (SyntaxColorHighlighting syntaxColor : SyntaxColorHighlighting.getSyntaxColorHighlightings())
+ fListModel.add(new HighlightingColorListItem (syntaxColor.label(), syntaxColor.preferenceKey(), syntaxColor.getBoldPreferenceKey(), syntaxColor.getItalicPreferenceKey(), syntaxColor.getStrikethroughPreferenceKey(), syntaxColor.getUnderlinePreferenceKey()));
SemanticHighlighting[] semanticHighlightings= SemanticHighlightings.getSemanticHighlightings();
for (SemanticHighlighting semanticHighlighting : semanticHighlightings)
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/SyntaxColorHighlighting.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/SyntaxColorHighlighting.java
new file mode 100644
index 00000000000..b53cba5175a
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/SyntaxColorHighlighting.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2024 Broadcom Inc. and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Alex Boyko (Broadcom Inc.) - Initial implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.preferences;
+
+import org.eclipse.jdt.ui.PreferenceConstants;
+
+public record SyntaxColorHighlighting(String label, String preferenceKey) {
+
+ private static final String BOLD= PreferenceConstants.EDITOR_BOLD_SUFFIX;
+ private static final String ITALIC= PreferenceConstants.EDITOR_ITALIC_SUFFIX;
+ private static final String STRIKETHROUGH= PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX;
+ private static final String UNDERLINE= PreferenceConstants.EDITOR_UNDERLINE_SUFFIX;
+
+ private static SyntaxColorHighlighting[] fgSyntaxColorHighlighting = null;
+
+ public static SyntaxColorHighlighting[] getSyntaxColorHighlightings() {
+ if (fgSyntaxColorHighlighting == null) {
+ fgSyntaxColorHighlighting = new SyntaxColorHighlighting[] {
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_javaDocKeywords, PreferenceConstants.EDITOR_JAVADOC_KEYWORD_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_javaDocHtmlTags, PreferenceConstants.EDITOR_JAVADOC_TAG_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_javaDocLinks, PreferenceConstants.EDITOR_JAVADOC_LINKS_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_javaDocOthers, PreferenceConstants.EDITOR_JAVADOC_DEFAULT_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_multiLineComment, PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_singleLineComment, PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_javaCommentTaskTags, PreferenceConstants.EDITOR_TASK_TAG_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_keywords, PreferenceConstants.EDITOR_JAVA_KEYWORD_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_returnKeyword, PreferenceConstants.EDITOR_JAVA_KEYWORD_RETURN_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_operators, PreferenceConstants.EDITOR_JAVA_OPERATOR_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_brackets, PreferenceConstants.EDITOR_JAVA_BRACKET_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_strings, PreferenceConstants.EDITOR_STRING_COLOR),
+ new SyntaxColorHighlighting(PreferencesMessages.JavaEditorPreferencePage_others, PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR)
+ };
+ }
+ return fgSyntaxColorHighlighting;
+ }
+
+ public String getBoldPreferenceKey() {
+ return preferenceKey + BOLD;
+ }
+
+ public String getItalicPreferenceKey() {
+ return preferenceKey + ITALIC;
+ }
+
+ public String getStrikethroughPreferenceKey() {
+ return preferenceKey + STRIKETHROUGH;
+ }
+
+ public String getUnderlinePreferenceKey() {
+ return preferenceKey + UNDERLINE;
+ }
+
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/ISemanticTokensProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/ISemanticTokensProvider.java
new file mode 100644
index 00000000000..426868ee97d
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/ISemanticTokensProvider.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2024 Broadcom Inc. and others.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Alex Boyko (Broadcom Inc.) - Initial implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ui.text.java;
+
+import java.util.Collection;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+
+/**
+ * Computes semantic tokens contributed to the Java source editor via extension point semanticTokens
+ *
+ * @since 3.34
+ */
+public interface ISemanticTokensProvider {
+
+ record SemanticToken(int ofset, int length, TokenType tokenType) {}
+
+ enum TokenType {
+ DEFAULT,
+ OPERATOR,
+ SINGLE_LINE_COMMENT,
+ MULTI_LINE_COMMENT,
+ BRACKET,
+ STRING,
+ RESTRICTED_IDENTIFIER,
+ STATIC_FINAL_FIELD,
+ STATIC_FIELD,
+ FIELD,
+ METHOD_DECLARATION,
+ STATIC_METHOD_INVOCATION,
+ INHERITED_METHOD_INVOCATION,
+ ANNOTATION_ELEMENT_REFERENCE,
+ ABSTRACT_METHOD_INVOCATION,
+ LOCAL_VARIABLE_DECLARATION,
+ LOCAL_VARIABLE,
+ PARAMETER_VARIABLE,
+ DEPRECATED_MEMBER,
+ TYPE_VARIABLE,
+ METHOD,
+ AUTOBOXING,
+ CLASS,
+ ENUM,
+ INTERFACE,
+ ANNOTATION,
+ TYPE_ARGUMENT,
+ NUMBER,
+ ABSTRACT_CLASS,
+ INHERITED_FIELD,
+ KEYWORD,
+ }
+
+ Collection computeSemanticTokens(CompilationUnit ast);
+
+}
+
+