mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Bug 537306 - Add implementation for "$cquery/publishSemanticHighlights"
Change-Id: I598cda18678f7b268a72e4aa5dfe9563d33727bd Signed-off-by: Manish Khurana <mkmanishkhurana98@gmail.com>
This commit is contained in:
parent
09d4a1121c
commit
02344726c8
4 changed files with 195 additions and 6 deletions
|
@ -17,6 +17,12 @@
|
|||
|
||||
package org.eclipse.lsp4e.cpp.language;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
|
||||
import org.eclipse.cdt.core.model.ICLanguageKeywords;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
|
@ -24,12 +30,12 @@ import org.eclipse.cdt.internal.ui.text.CCodeScanner;
|
|||
import org.eclipse.cdt.internal.ui.text.CCommentScanner;
|
||||
import org.eclipse.cdt.internal.ui.text.CPreprocessorScanner;
|
||||
import org.eclipse.cdt.internal.ui.text.CPresentationReconciler;
|
||||
import org.eclipse.cdt.internal.ui.text.FastCPartitioner;
|
||||
import org.eclipse.cdt.internal.ui.text.PartitionDamager;
|
||||
import org.eclipse.cdt.internal.ui.text.SingleTokenCScanner;
|
||||
import org.eclipse.cdt.internal.ui.text.TokenStore;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.ILanguageUI;
|
||||
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||
import org.eclipse.cdt.ui.text.AbstractCScanner;
|
||||
import org.eclipse.cdt.ui.text.ICColorConstants;
|
||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||
|
@ -38,6 +44,9 @@ import org.eclipse.cdt.ui.text.ITokenStore;
|
|||
import org.eclipse.cdt.ui.text.ITokenStoreFactory;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
import org.eclipse.jface.preference.PreferenceConverter;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.ITextInputListener;
|
||||
|
@ -45,7 +54,14 @@ import org.eclipse.jface.text.ITextViewer;
|
|||
import org.eclipse.jface.text.TextPresentation;
|
||||
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
|
||||
import org.eclipse.jface.text.rules.RuleBasedScanner;
|
||||
import org.eclipse.lsp4e.cpp.language.cquery.CquerySemanticHighlights;
|
||||
import org.eclipse.lsp4e.cpp.language.cquery.HighlightSymbol;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.StyleRange;
|
||||
import org.eclipse.swt.custom.StyledText;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
/**
|
||||
* Hack-ish reconciler to get some colors in the generic editor using the C/C++
|
||||
|
@ -61,6 +77,9 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
private CqueryLineBackgroundListener fLineBackgroundListener = new CqueryLineBackgroundListener();
|
||||
private ITextViewer textViewer;
|
||||
private TextInputListenerCPP textInputListener;
|
||||
|
||||
public static Set<PresentationReconcilerCPP> presentationReconcilers = ConcurrentHashMap.newKeySet();
|
||||
|
||||
protected ITokenStoreFactory getTokenStoreFactory() {
|
||||
return new ITokenStoreFactory() {
|
||||
@Override
|
||||
|
@ -154,8 +173,81 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
|
||||
@Override
|
||||
protected TextPresentation createPresentation(IRegion damage, IDocument document) {
|
||||
TextPresentation createPresentation = super.createPresentation(damage, document);
|
||||
return createPresentation;
|
||||
TextPresentation presentation = super.createPresentation(damage, document);
|
||||
|
||||
IDocument doc = textViewer.getDocument();
|
||||
URI uri = Server2ClientProtocolExtension.getUri(doc);
|
||||
|
||||
if (uri == null) {
|
||||
return presentation;
|
||||
}
|
||||
|
||||
List<HighlightSymbol> semanticHighlights = CquerySemanticHighlights.uriToSemanticHighlightsMapping.get(uri);
|
||||
|
||||
if(semanticHighlights == null) {
|
||||
return presentation;
|
||||
}
|
||||
|
||||
IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
|
||||
List<StyleRange> styleRanges = new ArrayList<>();
|
||||
|
||||
for (HighlightSymbol highlight : semanticHighlights) {
|
||||
|
||||
String highlightingName = HighlightSymbol.getHighlightingName(highlight.getKind(), highlight.getParentKind(), highlight.getStorage());
|
||||
String colorKey = PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX
|
||||
+ highlightingName + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_COLOR_SUFFIX;
|
||||
|
||||
boolean isBold = store.getBoolean(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX
|
||||
+ highlightingName + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_BOLD_SUFFIX);
|
||||
boolean isItalic = store.getBoolean(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX
|
||||
+ highlightingName + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ITALIC_SUFFIX);
|
||||
boolean isUnderline = store.getBoolean(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX
|
||||
+ highlightingName + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_UNDERLINE_SUFFIX);
|
||||
boolean isStrikethrough = store.getBoolean(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX
|
||||
+ highlightingName + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_STRIKETHROUGH_SUFFIX);
|
||||
|
||||
Color color = new Color(Display.getCurrent(),
|
||||
PreferenceConverter.getColor(CUIPlugin.getDefault().getPreferenceStore(), colorKey));
|
||||
|
||||
int damageStartOffset = damage.getOffset();
|
||||
int damageEndOffset = damageStartOffset + damage.getLength();
|
||||
|
||||
List<Range> ranges = highlight.getRanges();
|
||||
for (Range range : ranges) {
|
||||
|
||||
int offset = 0, length = 0;
|
||||
try {
|
||||
offset = doc.getLineOffset(range.getStart().getLine()) + range.getStart().getCharacter();
|
||||
length = doc.getLineOffset(range.getEnd().getLine()) + range.getEnd().getCharacter() - offset;
|
||||
} catch (BadLocationException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
if ((offset + length) >= damageStartOffset && offset < damageEndOffset) {
|
||||
|
||||
StyleRange styleRange = new StyleRange(offset, length, color, null);
|
||||
|
||||
if (isBold) {
|
||||
styleRange.fontStyle = SWT.BOLD;
|
||||
}
|
||||
if (isItalic) {
|
||||
styleRange.fontStyle |= SWT.ITALIC;
|
||||
}
|
||||
if (isUnderline) {
|
||||
styleRange.underline = true;
|
||||
}
|
||||
if (isStrikethrough) {
|
||||
styleRange.strikeout = true;
|
||||
}
|
||||
|
||||
styleRanges.add(styleRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyleRange[] styleRangesArray = new StyleRange[styleRanges.size()];
|
||||
styleRangesArray = styleRanges.toArray(styleRangesArray);
|
||||
presentation.replaceStyleRanges(styleRangesArray);
|
||||
return presentation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -218,7 +310,7 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
return fPreprocessorScanner;
|
||||
}
|
||||
|
||||
class TextInputListenerCPP implements ITextInputListener {
|
||||
public class TextInputListenerCPP implements ITextInputListener {
|
||||
|
||||
@Override
|
||||
public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
|
||||
|
@ -236,6 +328,10 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
}
|
||||
}
|
||||
|
||||
public ITextViewer getTextViewer() {
|
||||
return textViewer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void install(ITextViewer viewer) {
|
||||
super.install(viewer);
|
||||
|
@ -248,6 +344,7 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
}
|
||||
StyledText textWidget = textViewer.getTextWidget();
|
||||
textWidget.addLineBackgroundListener(fLineBackgroundListener);
|
||||
presentationReconcilers.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -255,5 +352,6 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
|||
super.uninstall();
|
||||
textViewer.getTextWidget().removeLineBackgroundListener(fLineBackgroundListener);
|
||||
textViewer.removeTextInputListener(textInputListener);
|
||||
presentationReconcilers.remove(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,16 @@
|
|||
package org.eclipse.lsp4e.cpp.language;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.jface.action.StatusLineContributionItem;
|
||||
import org.eclipse.jface.action.StatusLineManager;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.Region;
|
||||
import org.eclipse.jface.text.TextPresentation;
|
||||
import org.eclipse.lsp4e.LSPEclipseUtils;
|
||||
import org.eclipse.lsp4e.LanguageClientImpl;
|
||||
import org.eclipse.lsp4e.cpp.language.cquery.CqueryInactiveRegions;
|
||||
import org.eclipse.lsp4e.cpp.language.cquery.CquerySemanticHighlights;
|
||||
|
@ -25,7 +31,6 @@ import org.eclipse.ui.IWorkbenchWindow;
|
|||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.internal.WorkbenchWindow;
|
||||
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class Server2ClientProtocolExtension extends LanguageClientImpl {
|
||||
|
||||
|
@ -60,8 +65,46 @@ public class Server2ClientProtocolExtension extends LanguageClientImpl {
|
|||
CqueryLineBackgroundListener.fileInactiveRegionsMap.put(uri, inactiveRegions);
|
||||
}
|
||||
|
||||
public static URI getUri(IDocument document) {
|
||||
URI uri = null;
|
||||
IFile file = LSPEclipseUtils.getFile(document);
|
||||
if (file != null) {
|
||||
uri = LSPEclipseUtils.toUri(file);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
@JsonNotification("$cquery/publishSemanticHighlighting")
|
||||
public final void semanticHighlights(CquerySemanticHighlights highlights) {
|
||||
// TODO: Implement
|
||||
URI uriReceived = highlights.getUri();
|
||||
CquerySemanticHighlights.uriToSemanticHighlightsMapping.put(uriReceived, highlights.getSymbols());
|
||||
List<PresentationReconcilerCPP> matchingReconcilers = new ArrayList<>();
|
||||
|
||||
for (PresentationReconcilerCPP eachReconciler: PresentationReconcilerCPP.presentationReconcilers) {
|
||||
IDocument currentReconcilerDoc = eachReconciler.getTextViewer().getDocument();
|
||||
URI currentReconcilerUri = getUri(currentReconcilerDoc);
|
||||
|
||||
if(currentReconcilerUri == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uriReceived.equals(currentReconcilerUri)) {
|
||||
matchingReconcilers.add(eachReconciler);
|
||||
}
|
||||
}
|
||||
|
||||
Display.getDefault().asyncExec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (PresentationReconcilerCPP p: matchingReconcilers) {
|
||||
IDocument currentReconcilerDoc = p.getTextViewer().getDocument();
|
||||
if (currentReconcilerDoc == null) {
|
||||
continue;
|
||||
}
|
||||
TextPresentation textPresentation = p.createPresentation(new Region(0, currentReconcilerDoc.getLength()), currentReconcilerDoc);
|
||||
p.getTextViewer().changeTextPresentation(textPresentation, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,13 @@ package org.eclipse.lsp4e.cpp.language.cquery;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class CquerySemanticHighlights {
|
||||
private URI uri;
|
||||
private List<HighlightSymbol> symbols;
|
||||
public static ConcurrentMap<URI, List<HighlightSymbol>> uriToSemanticHighlightsMapping = new ConcurrentHashMap<>(16, 0.75f, 1);
|
||||
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
|
|
|
@ -8,16 +8,61 @@
|
|||
|
||||
package org.eclipse.lsp4e.cpp.language.cquery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class HighlightSymbol {
|
||||
private int stableId;
|
||||
private ExtendedSymbolKindType parentKind;
|
||||
private ExtendedSymbolKindType kind;
|
||||
private StorageClass storage;
|
||||
private List<Range> ranges;
|
||||
public static Map<Integer, String> semanticHighlightSymbolsMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Namespace.getValue(), SemanticHighlightings.NAMESPACE);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Class.getValue(), SemanticHighlightings.CLASS);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Method.getValue(), SemanticHighlightings.METHOD);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Constructor.getValue(), SemanticHighlightings.METHOD);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Enum.getValue(), SemanticHighlightings.ENUM);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Function.getValue(), SemanticHighlightings.FUNCTION);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.EnumMember.getValue(), SemanticHighlightings.ENUMERATOR);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.Struct.getValue(), SemanticHighlightings.CLASS);
|
||||
semanticHighlightSymbolsMap.put(SymbolKind.TypeParameter.getValue(), SemanticHighlightings.TEMPLATE_PARAMETER);
|
||||
semanticHighlightSymbolsMap.put(CquerySymbolKind.TypeAlias.getValue(), SemanticHighlightings.TYPEDEF);
|
||||
semanticHighlightSymbolsMap.put(CquerySymbolKind.Parameter.getValue(), SemanticHighlightings.PARAMETER_VARIABLE);
|
||||
semanticHighlightSymbolsMap.put(CquerySymbolKind.StaticMethod.getValue(), SemanticHighlightings.STATIC_METHOD_INVOCATION);
|
||||
semanticHighlightSymbolsMap.put(CquerySymbolKind.Macro.getValue(), SemanticHighlightings.MACRO_DEFINITION);
|
||||
}
|
||||
|
||||
public static String getHighlightingName(ExtendedSymbolKindType kind, ExtendedSymbolKindType parentKind, StorageClass storage) {
|
||||
String highlightingName = semanticHighlightSymbolsMap.get(kind.getValue());
|
||||
if (highlightingName == null) {
|
||||
if (kind.getValue() == SymbolKind.Variable.getValue()) {
|
||||
if (parentKind.getValue() == SymbolKind.Function.getValue()
|
||||
|| parentKind.getValue() == SymbolKind.Method.getValue()
|
||||
|| parentKind.getValue() == SymbolKind.Constructor.getValue()) {
|
||||
|
||||
highlightingName = SemanticHighlightings.LOCAL_VARIABLE;
|
||||
} else {
|
||||
highlightingName = SemanticHighlightings.GLOBAL_VARIABLE;
|
||||
}
|
||||
} else if (kind.getValue() == SymbolKind.Field.getValue()) {
|
||||
if (storage == StorageClass.Static) {
|
||||
highlightingName = SemanticHighlightings.STATIC_FIELD;
|
||||
} else {
|
||||
highlightingName = SemanticHighlightings.FIELD;
|
||||
}
|
||||
}
|
||||
}
|
||||
return highlightingName;
|
||||
}
|
||||
|
||||
public HighlightSymbol(int stableId, ExtendedSymbolKindType parentKind, ExtendedSymbolKindType kind,
|
||||
StorageClass storage, List<Range> ranges) {
|
||||
|
|
Loading…
Add table
Reference in a new issue