mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Bug 535428. Add indentation and bracket completion support in LSP4E-CPP
Change-Id: Ib9187a3ad28796305c47fe8e9543e1aed6a7bf58 Signed-off-by: Manish Khurana <mkmanishkhurana98@gmail.com>
This commit is contained in:
parent
ac81db720c
commit
1983d41afb
6 changed files with 101 additions and 15 deletions
|
@ -469,17 +469,19 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExitPolicy implements IExitPolicy {
|
private static class ExitPolicy implements IExitPolicy {
|
||||||
final char fExitCharacter;
|
final char fExitCharacter;
|
||||||
final char fEscapeCharacter;
|
final char fEscapeCharacter;
|
||||||
final Deque<BracketLevel> fStack;
|
final Deque<BracketLevel> fStack;
|
||||||
final int fSize;
|
final int fSize;
|
||||||
|
ISourceViewer sourceViewer;
|
||||||
|
|
||||||
public ExitPolicy(char exitCharacter, char escapeCharacter, Deque<BracketLevel> stack) {
|
public ExitPolicy(char exitCharacter, char escapeCharacter, Deque<BracketLevel> stack, ISourceViewer sViewer) {
|
||||||
fExitCharacter = exitCharacter;
|
fExitCharacter = exitCharacter;
|
||||||
fEscapeCharacter = escapeCharacter;
|
fEscapeCharacter = escapeCharacter;
|
||||||
fStack = stack;
|
fStack = stack;
|
||||||
fSize = fStack.size();
|
fSize = fStack.size();
|
||||||
|
sourceViewer = sViewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -496,7 +498,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
// When entering an anonymous class between the parenthesis', we don't want
|
// When entering an anonymous class between the parenthesis', we don't want
|
||||||
// to jump after the closing parenthesis when return is pressed.
|
// to jump after the closing parenthesis when return is pressed.
|
||||||
if (event.character == SWT.CR && offset > 0) {
|
if (event.character == SWT.CR && offset > 0) {
|
||||||
IDocument document = getSourceViewer().getDocument();
|
IDocument document = sourceViewer.getDocument();
|
||||||
try {
|
try {
|
||||||
if (document.getChar(offset - 1) == '{')
|
if (document.getChar(offset - 1) == '{')
|
||||||
return new ExitFlags(ILinkedModeListener.EXIT_ALL, true);
|
return new ExitFlags(ILinkedModeListener.EXIT_ALL, true);
|
||||||
|
@ -508,7 +510,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMasked(int offset) {
|
private boolean isMasked(int offset) {
|
||||||
IDocument document = getSourceViewer().getDocument();
|
IDocument document = sourceViewer.getDocument();
|
||||||
try {
|
try {
|
||||||
return fEscapeCharacter == document.getChar(offset - 1);
|
return fEscapeCharacter == document.getChar(offset - 1);
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
|
@ -603,7 +605,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BracketInserter implements VerifyKeyListener, ILinkedModeListener {
|
public static class BracketInserter implements VerifyKeyListener, ILinkedModeListener {
|
||||||
private boolean fCloseBrackets = true;
|
private boolean fCloseBrackets = true;
|
||||||
private boolean fCloseStrings = true;
|
private boolean fCloseStrings = true;
|
||||||
private boolean fCloseAngularBrackets = true;
|
private boolean fCloseAngularBrackets = true;
|
||||||
|
@ -611,6 +613,18 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
private final String CATEGORY = toString();
|
private final String CATEGORY = toString();
|
||||||
private final IPositionUpdater fUpdater = new ExclusivePositionUpdater(CATEGORY);
|
private final IPositionUpdater fUpdater = new ExclusivePositionUpdater(CATEGORY);
|
||||||
private final Deque<BracketLevel> fBracketLevelStack = new ArrayDeque<>();
|
private final Deque<BracketLevel> fBracketLevelStack = new ArrayDeque<>();
|
||||||
|
private ISourceViewer sourceViewer;
|
||||||
|
private boolean isGenericEditor;
|
||||||
|
private TextEditor fEditor;
|
||||||
|
|
||||||
|
public BracketInserter(TextEditor editor, boolean isGenericEditor) {
|
||||||
|
fEditor = editor;
|
||||||
|
this.isGenericEditor = isGenericEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceViewer(ISourceViewer sViewer) {
|
||||||
|
sourceViewer = sViewer;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCloseBracketsEnabled(boolean enabled) {
|
public void setCloseBracketsEnabled(boolean enabled) {
|
||||||
fCloseBrackets = enabled;
|
fCloseBrackets = enabled;
|
||||||
|
@ -638,8 +652,14 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
@Override
|
@Override
|
||||||
public void verifyKey(VerifyEvent event) {
|
public void verifyKey(VerifyEvent event) {
|
||||||
// Early pruning to minimize overhead for normal typing.
|
// Early pruning to minimize overhead for normal typing.
|
||||||
if (!event.doit || getInsertMode() != SMART_INSERT)
|
if (!event.doit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Need to check that it is Generic Editor or CEditor before checking "Smart Insert" mode
|
||||||
|
// because Generic Editor doesn't have a "Smart Insert" mode.
|
||||||
|
if(!isGenericEditor)
|
||||||
|
if (fEditor.getInsertMode() != SMART_INSERT)
|
||||||
|
return;
|
||||||
switch (event.character) {
|
switch (event.character) {
|
||||||
case '(':
|
case '(':
|
||||||
case '<':
|
case '<':
|
||||||
|
@ -652,7 +672,6 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ISourceViewer sourceViewer = getSourceViewer();
|
|
||||||
IDocument document = sourceViewer.getDocument();
|
IDocument document = sourceViewer.getDocument();
|
||||||
|
|
||||||
final Point selection = sourceViewer.getSelectedRange();
|
final Point selection = sourceViewer.getSelectedRange();
|
||||||
|
@ -661,7 +680,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
try {
|
try {
|
||||||
IRegion startLine = document.getLineInformationOfOffset(offset);
|
IRegion startLine = document.getLineInformationOfOffset(offset);
|
||||||
IRegion endLine = document.getLineInformationOfOffset(offset + length);
|
IRegion endLine = document.getLineInformationOfOffset(offset + length);
|
||||||
if (startLine != endLine && isBlockSelectionModeEnabled()) {
|
if (startLine != endLine && fEditor.isBlockSelectionModeEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,7 +749,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validateEditorInputState())
|
if (!fEditor.validateEditorInputState())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final char character = event.character;
|
final char character = event.character;
|
||||||
|
@ -764,7 +783,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
|
|
||||||
level.fUI = new EditorLinkedModeUI(model, sourceViewer);
|
level.fUI = new EditorLinkedModeUI(model, sourceViewer);
|
||||||
level.fUI.setSimpleMode(true);
|
level.fUI.setSimpleMode(true);
|
||||||
level.fUI.setExitPolicy(new ExitPolicy(closingCharacter, getEscapeCharacter(closingCharacter), fBracketLevelStack));
|
level.fUI.setExitPolicy(new ExitPolicy(closingCharacter, getEscapeCharacter(closingCharacter), fBracketLevelStack, sourceViewer));
|
||||||
level.fUI.setExitPosition(sourceViewer, offset + 2, 0, Integer.MAX_VALUE);
|
level.fUI.setExitPosition(sourceViewer, offset + 2, 0, Integer.MAX_VALUE);
|
||||||
level.fUI.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
|
level.fUI.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
|
||||||
level.fUI.enter();
|
level.fUI.enter();
|
||||||
|
@ -821,7 +840,6 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// remove brackets
|
// remove brackets
|
||||||
final ISourceViewer sourceViewer = getSourceViewer();
|
|
||||||
final IDocument document = sourceViewer.getDocument();
|
final IDocument document = sourceViewer.getDocument();
|
||||||
if (document instanceof IDocumentExtension) {
|
if (document instanceof IDocumentExtension) {
|
||||||
IDocumentExtension extension = (IDocumentExtension) document;
|
IDocumentExtension extension = (IDocumentExtension) document;
|
||||||
|
@ -1284,7 +1302,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
protected CPairMatcher fBracketMatcher = new CPairMatcher(BRACKETS);
|
protected CPairMatcher fBracketMatcher = new CPairMatcher(BRACKETS);
|
||||||
|
|
||||||
/** The bracket inserter. */
|
/** The bracket inserter. */
|
||||||
private final BracketInserter fBracketInserter = new BracketInserter();
|
private final BracketInserter fBracketInserter = new BracketInserter(this, false);
|
||||||
|
|
||||||
/** Listener to annotation model changes that updates the error tick in the tab image */
|
/** Listener to annotation model changes that updates the error tick in the tab image */
|
||||||
private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
|
private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
|
||||||
|
@ -2535,8 +2553,10 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
||||||
fBracketInserter.setCloseStringsEnabled(closeStrings);
|
fBracketInserter.setCloseStringsEnabled(closeStrings);
|
||||||
|
|
||||||
ISourceViewer sourceViewer = getSourceViewer();
|
ISourceViewer sourceViewer = getSourceViewer();
|
||||||
if (sourceViewer instanceof ITextViewerExtension)
|
if (sourceViewer instanceof ITextViewerExtension) {
|
||||||
|
fBracketInserter.setSourceViewer(sourceViewer);
|
||||||
((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
|
((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
|
||||||
|
}
|
||||||
|
|
||||||
if (isMarkingOccurrences())
|
if (isMarkingOccurrences())
|
||||||
installOccurrencesFinder(false);
|
installOccurrencesFinder(false);
|
||||||
|
|
|
@ -67,6 +67,11 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
private String fPartitioning;
|
private String fPartitioning;
|
||||||
private final ICProject fProject;
|
private final ICProject fProject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* boolean to skip "Smart Insert" mode check because Generic Editor doesn't have a "Smart Insert" mode.
|
||||||
|
*/
|
||||||
|
private boolean alwaysUseSmartMode = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new C auto indent strategy for the given document partitioning.
|
* Creates a new C auto indent strategy for the given document partitioning.
|
||||||
*
|
*
|
||||||
|
@ -78,6 +83,11 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
fProject = project;
|
fProject = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CAutoIndentStrategy(String partitioning, ICProject project, boolean alwaysUseSmartMode) {
|
||||||
|
this(partitioning, project);
|
||||||
|
this.alwaysUseSmartMode = alwaysUseSmartMode;
|
||||||
|
}
|
||||||
|
|
||||||
private int getBracketCount(IDocument d, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException {
|
private int getBracketCount(IDocument d, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException {
|
||||||
int bracketcount = 0;
|
int bracketcount = 0;
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
|
@ -1151,6 +1161,9 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
private boolean computeSmartMode() {
|
private boolean computeSmartMode() {
|
||||||
IWorkbenchPage page = CUIPlugin.getActivePage();
|
IWorkbenchPage page = CUIPlugin.getActivePage();
|
||||||
if (page != null) {
|
if (page != null) {
|
||||||
|
if (alwaysUseSmartMode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
IEditorPart part = page.getActiveEditor();
|
IEditorPart part = page.getActiveEditor();
|
||||||
if (part instanceof MultiPageEditorPart) {
|
if (part instanceof MultiPageEditorPart) {
|
||||||
part= (IEditorPart)part.getAdapter(ITextEditorExtension3.class);
|
part= (IEditorPart)part.getAdapter(ITextEditorExtension3.class);
|
||||||
|
|
|
@ -24,4 +24,5 @@ Export-Package: org.eclipse.lsp4e.cpp.language,
|
||||||
org.eclipse.lsp4e.cpp.language.cquery
|
org.eclipse.lsp4e.cpp.language.cquery
|
||||||
Bundle-Activator: org.eclipse.lsp4e.cpp.language.Activator
|
Bundle-Activator: org.eclipse.lsp4e.cpp.language.Activator
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Import-Package: org.eclipse.ui.texteditor
|
Import-Package: org.eclipse.ui.editors.text,
|
||||||
|
org.eclipse.ui.texteditor
|
||||||
|
|
|
@ -62,4 +62,11 @@
|
||||||
class="org.eclipse.lsp4e.cpp.language.PreferenceInitializer">
|
class="org.eclipse.lsp4e.cpp.language.PreferenceInitializer">
|
||||||
</initializer>
|
</initializer>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.genericeditor.autoEditStrategies">
|
||||||
|
<autoEditStrategy
|
||||||
|
class="org.eclipse.lsp4e.cpp.language.AutoIndentStrategyCPP"
|
||||||
|
contentType="org.eclipse.lsp4e.languages.cpp">
|
||||||
|
</autoEditStrategy>
|
||||||
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2018 Manish Khurana , Nathan Ridge 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.lsp4e.cpp.language;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class to re-use existing auto-indentation support of CEditor in Generic Editor of LSP4E-CPP.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public class AutoIndentStrategyCPP extends CAutoIndentStrategy {
|
||||||
|
|
||||||
|
public AutoIndentStrategyCPP() {
|
||||||
|
// TODO: Pass in the project so the auto edit strategy respects the project's preferences.
|
||||||
|
super(CUIPlugin.getDefault().getTextTools().getDocumentPartitioning(), null, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
|
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
|
||||||
import org.eclipse.cdt.core.model.ICLanguageKeywords;
|
import org.eclipse.cdt.core.model.ICLanguageKeywords;
|
||||||
import org.eclipse.cdt.core.model.ILanguage;
|
import org.eclipse.cdt.core.model.ILanguage;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.CEditor.BracketInserter;
|
||||||
import org.eclipse.cdt.internal.ui.text.CCodeScanner;
|
import org.eclipse.cdt.internal.ui.text.CCodeScanner;
|
||||||
import org.eclipse.cdt.internal.ui.text.CCommentScanner;
|
import org.eclipse.cdt.internal.ui.text.CCommentScanner;
|
||||||
import org.eclipse.cdt.internal.ui.text.CPreprocessorScanner;
|
import org.eclipse.cdt.internal.ui.text.CPreprocessorScanner;
|
||||||
|
@ -52,8 +53,10 @@ import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITextInputListener;
|
import org.eclipse.jface.text.ITextInputListener;
|
||||||
import org.eclipse.jface.text.ITextViewer;
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
import org.eclipse.jface.text.TextPresentation;
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.jface.text.TextViewer;
|
||||||
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
|
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
|
||||||
import org.eclipse.jface.text.rules.RuleBasedScanner;
|
import org.eclipse.jface.text.rules.RuleBasedScanner;
|
||||||
|
import org.eclipse.jface.text.source.SourceViewer;
|
||||||
import org.eclipse.lsp4e.cpp.language.cquery.CquerySemanticHighlights;
|
import org.eclipse.lsp4e.cpp.language.cquery.CquerySemanticHighlights;
|
||||||
import org.eclipse.lsp4e.cpp.language.cquery.HighlightSymbol;
|
import org.eclipse.lsp4e.cpp.language.cquery.HighlightSymbol;
|
||||||
import org.eclipse.lsp4j.Range;
|
import org.eclipse.lsp4j.Range;
|
||||||
|
@ -62,6 +65,8 @@ import org.eclipse.swt.custom.StyleRange;
|
||||||
import org.eclipse.swt.custom.StyledText;
|
import org.eclipse.swt.custom.StyledText;
|
||||||
import org.eclipse.swt.graphics.Color;
|
import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.editors.text.TextEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hack-ish reconciler to get some colors in the generic editor using the C/C++
|
* Hack-ish reconciler to get some colors in the generic editor using the C/C++
|
||||||
|
@ -77,6 +82,7 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
||||||
private CqueryLineBackgroundListener fLineBackgroundListener = new CqueryLineBackgroundListener();
|
private CqueryLineBackgroundListener fLineBackgroundListener = new CqueryLineBackgroundListener();
|
||||||
private ITextViewer textViewer;
|
private ITextViewer textViewer;
|
||||||
private TextInputListenerCPP textInputListener;
|
private TextInputListenerCPP textInputListener;
|
||||||
|
private BracketInserter fBracketInserter;
|
||||||
|
|
||||||
public static Set<PresentationReconcilerCPP> presentationReconcilers = ConcurrentHashMap.newKeySet();
|
public static Set<PresentationReconcilerCPP> presentationReconcilers = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
@ -345,6 +351,19 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
||||||
StyledText textWidget = textViewer.getTextWidget();
|
StyledText textWidget = textViewer.getTextWidget();
|
||||||
textWidget.addLineBackgroundListener(fLineBackgroundListener);
|
textWidget.addLineBackgroundListener(fLineBackgroundListener);
|
||||||
presentationReconcilers.add(this);
|
presentationReconcilers.add(this);
|
||||||
|
|
||||||
|
// Using asyncExec() to make sure that by the time Runnable runs,
|
||||||
|
// the Editor is active and we don't get a NPE.
|
||||||
|
Display.getDefault().asyncExec(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// To provide bracket auto-completion support of CEditor in Generic Editor of LSP4E-CPP
|
||||||
|
|
||||||
|
TextEditor editor = (TextEditor) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
|
||||||
|
fBracketInserter = new BracketInserter(editor, true);
|
||||||
|
fBracketInserter.setSourceViewer((SourceViewer) textViewer);
|
||||||
|
((TextViewer) textViewer).prependVerifyKeyListener(fBracketInserter);
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -352,6 +371,7 @@ public class PresentationReconcilerCPP extends CPresentationReconciler {
|
||||||
super.uninstall();
|
super.uninstall();
|
||||||
textViewer.getTextWidget().removeLineBackgroundListener(fLineBackgroundListener);
|
textViewer.getTextWidget().removeLineBackgroundListener(fLineBackgroundListener);
|
||||||
textViewer.removeTextInputListener(textInputListener);
|
textViewer.removeTextInputListener(textInputListener);
|
||||||
|
((TextViewer) textViewer).removeVerifyKeyListener(fBracketInserter);
|
||||||
presentationReconcilers.remove(this);
|
presentationReconcilers.remove(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue