Skip to content

Commit 039faf1

Browse files
committed
Use TM4E grammar and reconsiler for code template syntax highlighting
1 parent c75dcfd commit 039faf1

File tree

4 files changed

+143
-13
lines changed

4 files changed

+143
-13
lines changed

org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/TMUIPlugin.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
import org.eclipse.jface.text.templates.TemplateContextType;
2828
import org.eclipse.jface.text.templates.persistence.TemplateStore;
2929
import org.eclipse.text.templates.ContextTypeRegistry;
30+
import org.eclipse.tm4e.core.grammar.IGrammar;
3031
import org.eclipse.tm4e.core.internal.utils.NullSafetyHelper;
32+
import org.eclipse.tm4e.registry.IGrammarDefinition;
33+
import org.eclipse.tm4e.registry.ITMScope;
34+
import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin;
3135
import org.eclipse.tm4e.ui.internal.model.TMModelManager;
3236
import org.eclipse.tm4e.ui.internal.samples.SampleManager;
3337
import org.eclipse.tm4e.ui.internal.themes.ThemeManager;
@@ -36,6 +40,7 @@
3640
import org.eclipse.tm4e.ui.templates.CommentTemplateContextType;
3741
import org.eclipse.tm4e.ui.templates.DefaultTm4eTemplateContextType;
3842
import org.eclipse.tm4e.ui.templates.DocumentationCommentTemplateContextType;
43+
import org.eclipse.tm4e.ui.templates.Tm4eLanguageTemplateContextType;
3944
import org.eclipse.tm4e.ui.themes.ColorManager;
4045
import org.eclipse.tm4e.ui.themes.IThemeManager;
4146
import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
@@ -193,7 +198,25 @@ public ContextTypeRegistry getTemplateContextRegistry() {
193198
result.addContextType(CommentTemplateContextType.CONTEXT_ID);
194199
result.addContextType(DocumentationCommentTemplateContextType.CONTEXT_ID);
195200

196-
// TODO add language-specific context types, probably from extensions
201+
// Add language-specific context types
202+
// TODO also load context types from extensions?
203+
final IGrammarDefinition[] grammarDefinitions = TMEclipseRegistryPlugin.getGrammarRegistryManager().getDefinitions();
204+
for (final IGrammarDefinition definition : grammarDefinitions) {
205+
final ITMScope languageScope = definition.getScope();
206+
final String contextTypeIdSuffix = languageScope.getQualifiedName();
207+
final IGrammar languageGrammar = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarForScope(languageScope);
208+
if (languageGrammar != null) {
209+
String name = languageGrammar.getName();
210+
if (name == null) {
211+
name = "";
212+
}
213+
name += " (" + languageScope.getName() + ")";
214+
final Tm4eLanguageTemplateContextType languageContextType = new Tm4eLanguageTemplateContextType(
215+
name, contextTypeIdSuffix);
216+
result.addContextType(languageContextType);
217+
}
218+
}
219+
197220
} else {
198221
result = NullSafetyHelper.castNonNull(contextTypeRegistry);
199222
}

org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/CustomCodeTemplatePreferencePage.java

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,36 @@
1111
*******************************************************************************/
1212
package org.eclipse.tm4e.ui.internal.preferences;
1313

14+
import java.util.Arrays;
15+
1416
import org.eclipse.jdt.annotation.Nullable;
17+
import org.eclipse.jface.text.Document;
18+
import org.eclipse.jface.text.IDocument;
19+
import org.eclipse.jface.text.presentation.IPresentationReconciler;
20+
import org.eclipse.jface.text.source.ISourceViewer;
1521
import org.eclipse.jface.text.source.SourceViewer;
22+
import org.eclipse.jface.text.source.SourceViewerConfiguration;
1623
import org.eclipse.jface.text.templates.Template;
24+
import org.eclipse.jface.viewers.IStructuredSelection;
1725
import org.eclipse.jface.window.Window;
26+
import org.eclipse.swt.SWT;
1827
import org.eclipse.swt.widgets.Composite;
1928
import org.eclipse.swt.widgets.Shell;
29+
import org.eclipse.text.templates.TemplatePersistenceData;
30+
import org.eclipse.tm4e.core.grammar.IGrammar;
31+
import org.eclipse.tm4e.registry.IGrammarDefinition;
32+
import org.eclipse.tm4e.registry.ITMScope;
33+
import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin;
2034
import org.eclipse.tm4e.ui.TMUIPlugin;
35+
import org.eclipse.tm4e.ui.internal.model.TMDocumentModel;
36+
import org.eclipse.tm4e.ui.text.TMPresentationReconciler;
2137
import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
2238

2339
public class CustomCodeTemplatePreferencePage extends TemplatePreferencePage {
2440

41+
private @Nullable TMDocumentModel model;
42+
private @Nullable TMPresentationReconciler reconsiler;
43+
2544
public CustomCodeTemplatePreferencePage() {
2645
final TMUIPlugin plugin = TMUIPlugin.getDefault();
2746
if (plugin == null) {
@@ -70,18 +89,65 @@ protected String getFormatterPreferenceKey() {
7089

7190
@Override
7291
protected SourceViewer createViewer(final @Nullable Composite parent) {
73-
final SourceViewer sourceViewer = super.createViewer(parent);
74-
7592
// TODO configure source viewer for syntax highlighting with TM4E (adapt highlighting depending on context type)
76-
// sourceViewer.configure(new SourceViewerConfiguration() {
77-
// @Override
78-
// public IPresentationReconciler getPresentationReconciler(@Nullable final ISourceViewer sourceViewer) {
79-
// // TODO check if we need special config for highlighting template variables
80-
// return new TMPresentationReconciler();
81-
// }
82-
// });
83-
84-
return sourceViewer;
93+
94+
final SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
95+
final SourceViewerConfiguration configuration = new SourceViewerConfiguration() {
96+
@Override
97+
public IPresentationReconciler getPresentationReconciler(@Nullable final ISourceViewer sourceViewer) {
98+
// TODO check if we need special config for highlighting template variables
99+
reconsiler = new TMPresentationReconciler();
100+
return reconsiler;
101+
}
102+
};
103+
viewer.configure(configuration);
104+
final IDocument document = new Document();
105+
viewer.setDocument(document);
106+
// model = TMModelManager.INSTANCE.connect(document);
107+
getTableViewer().addSelectionChangedListener(e -> selectionChanged());
108+
return viewer;
109+
}
110+
111+
private void selectionChanged() {
112+
final Template selectedTemplate = getSelectedTemplate();
113+
114+
if (selectedTemplate != null /*&& model != null*/) {
115+
116+
final String id = selectedTemplate.getContextTypeId();
117+
118+
final IGrammarDefinition[] grammarDefinitions = TMEclipseRegistryPlugin.getGrammarRegistryManager().getDefinitions();
119+
final ITMScope scope = Arrays.stream(grammarDefinitions)
120+
.map(IGrammarDefinition::getScope)
121+
.filter(s -> id.endsWith(s.getQualifiedName()))
122+
.findFirst().orElse(null);
123+
124+
if (scope != null) {
125+
final IGrammar languageGrammar = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarForScope(scope);
126+
if (languageGrammar != null && reconsiler != null) {
127+
// model.setGrammar(languageGrammar);
128+
reconsiler.setGrammar(languageGrammar);
129+
return;
130+
131+
// getViewer().invalidateTextPresentation();
132+
}
133+
134+
}
135+
}
136+
if (reconsiler != null) {
137+
reconsiler.setGrammar(null);
138+
}
139+
}
140+
141+
private @Nullable Template getSelectedTemplate() {
142+
final IStructuredSelection selection = getTableViewer().getStructuredSelection();
143+
144+
if (selection != null && selection.size() == 1) {
145+
final TemplatePersistenceData data = (TemplatePersistenceData) selection.getFirstElement();
146+
if (data != null) {
147+
return data.getTemplate();
148+
}
149+
}
150+
return null;
85151
}
86152

87153
}

org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/templates/Tm4eTemplateCompletionProcessor.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,14 @@ public TMToken getToken() {
180180
}
181181
}
182182

183-
// TODO use language-specific context type mappers from extensions
183+
// Check language-specific context types
184+
final String id = TMUIPlugin.PLUGIN_ID + ".templates.context." + textMateToken.grammarScope;
185+
final TemplateContextType contextType = plugin.getTemplateContextRegistry().getContextType(id);
186+
if (contextType != null) {
187+
return contextType;
188+
}
189+
190+
// TODO Also check language-specific context types from extensions?
184191

185192
// last option
186193
return contextTypeRegistry.getContextType(DefaultTm4eTemplateContextType.CONTEXT_ID);
@@ -225,6 +232,7 @@ protected Template[] getTemplates(final @Nullable String contextTypeId) {
225232

226233
final TemplateStore templateStore = plugin.getTemplateStore();
227234
final Template[] customTemplates = templateStore.getTemplates(contextTypeId);
235+
228236
if (customTemplates == null || customTemplates.length == 0) {
229237
return NO_TEMPLATES;
230238
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Advantest Europe GmbH and others.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Dietrich Travkin (SOLUNAR GmbH) - initial implementation
11+
*******************************************************************************/
12+
package org.eclipse.tm4e.ui.templates;
13+
14+
import org.eclipse.core.runtime.Assert;
15+
import org.eclipse.tm4e.ui.TMUIPlugin;
16+
17+
/**
18+
* Language-specific default code template context type. It is created for each language with a registered TM4E grammar.
19+
*/
20+
public class Tm4eLanguageTemplateContextType extends AbstractTm4eTemplateContextType {
21+
22+
private static final String CONTEXT_TYPE_ID_PREFIX = TMUIPlugin.PLUGIN_ID + ".templates.context."; //$NON-NLS-1$
23+
24+
public Tm4eLanguageTemplateContextType(final String contextTypeName, final String contextTypeIdSuffix) {
25+
super(CONTEXT_TYPE_ID_PREFIX + contextTypeIdSuffix, contextTypeName);
26+
}
27+
28+
public static String getContextTypeId(final String contextTypeIdSuffix) {
29+
Assert.isLegal(contextTypeIdSuffix != null && contextTypeIdSuffix.length() > 0);
30+
31+
return CONTEXT_TYPE_ID_PREFIX + contextTypeIdSuffix;
32+
}
33+
}

0 commit comments

Comments
 (0)