Bug 535428. Add indentation and bracket completion support in LSP4E-CPP
Change-Id: Ib9187a3ad28796305c47fe8e9543e1aed6a7bf58
Signed-off-by: Manish Khurana <mkmanishkhurana98@gmail.com>
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
index 90cab56..feb5059 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
@@ -469,17 +469,19 @@
}
}
- private class ExitPolicy implements IExitPolicy {
+ private static class ExitPolicy implements IExitPolicy {
final char fExitCharacter;
final char fEscapeCharacter;
final Deque<BracketLevel> fStack;
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;
fEscapeCharacter = escapeCharacter;
fStack = stack;
fSize = fStack.size();
+ sourceViewer = sViewer;
}
@Override
@@ -496,7 +498,7 @@
// When entering an anonymous class between the parenthesis', we don't want
// to jump after the closing parenthesis when return is pressed.
if (event.character == SWT.CR && offset > 0) {
- IDocument document = getSourceViewer().getDocument();
+ IDocument document = sourceViewer.getDocument();
try {
if (document.getChar(offset - 1) == '{')
return new ExitFlags(ILinkedModeListener.EXIT_ALL, true);
@@ -508,7 +510,7 @@
}
private boolean isMasked(int offset) {
- IDocument document = getSourceViewer().getDocument();
+ IDocument document = sourceViewer.getDocument();
try {
return fEscapeCharacter == document.getChar(offset - 1);
} catch (BadLocationException e) {
@@ -603,7 +605,7 @@
// }
}
- private class BracketInserter implements VerifyKeyListener, ILinkedModeListener {
+ public static class BracketInserter implements VerifyKeyListener, ILinkedModeListener {
private boolean fCloseBrackets = true;
private boolean fCloseStrings = true;
private boolean fCloseAngularBrackets = true;
@@ -611,6 +613,18 @@
private final String CATEGORY = toString();
private final IPositionUpdater fUpdater = new ExclusivePositionUpdater(CATEGORY);
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) {
fCloseBrackets = enabled;
@@ -638,8 +652,14 @@
@Override
public void verifyKey(VerifyEvent event) {
// Early pruning to minimize overhead for normal typing.
- if (!event.doit || getInsertMode() != SMART_INSERT)
+ if (!event.doit)
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) {
case '(':
case '<':
@@ -652,7 +672,6 @@
return;
}
- final ISourceViewer sourceViewer = getSourceViewer();
IDocument document = sourceViewer.getDocument();
final Point selection = sourceViewer.getSelectedRange();
@@ -661,7 +680,7 @@
try {
IRegion startLine = document.getLineInformationOfOffset(offset);
IRegion endLine = document.getLineInformationOfOffset(offset + length);
- if (startLine != endLine && isBlockSelectionModeEnabled()) {
+ if (startLine != endLine && fEditor.isBlockSelectionModeEnabled()) {
return;
}
@@ -730,7 +749,7 @@
return;
}
- if (!validateEditorInputState())
+ if (!fEditor.validateEditorInputState())
return;
final char character = event.character;
@@ -764,7 +783,7 @@
level.fUI = new EditorLinkedModeUI(model, sourceViewer);
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.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
level.fUI.enter();
@@ -821,7 +840,6 @@
return;
// remove brackets
- final ISourceViewer sourceViewer = getSourceViewer();
final IDocument document = sourceViewer.getDocument();
if (document instanceof IDocumentExtension) {
IDocumentExtension extension = (IDocumentExtension) document;
@@ -1284,7 +1302,7 @@
protected CPairMatcher fBracketMatcher = new CPairMatcher(BRACKETS);
/** 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 */
private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
@@ -2535,12 +2553,14 @@
fBracketInserter.setCloseStringsEnabled(closeStrings);
ISourceViewer sourceViewer = getSourceViewer();
- if (sourceViewer instanceof ITextViewerExtension)
+ if (sourceViewer instanceof ITextViewerExtension) {
+ fBracketInserter.setSourceViewer(sourceViewer);
((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
+ }
if (isMarkingOccurrences())
installOccurrencesFinder(false);
-
+
if(isShowingOverrideIndicators())
installOverrideIndicator(false);
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java
index 77053a6..7a95340 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java
@@ -67,6 +67,11 @@
private String fPartitioning;
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.
*
@@ -78,6 +83,11 @@
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 {
int bracketcount = 0;
while (start < end) {
@@ -1151,6 +1161,9 @@
private boolean computeSmartMode() {
IWorkbenchPage page = CUIPlugin.getActivePage();
if (page != null) {
+ if (alwaysUseSmartMode) {
+ return true;
+ }
IEditorPart part = page.getActiveEditor();
if (part instanceof MultiPageEditorPart) {
part= (IEditorPart)part.getAdapter(ITextEditorExtension3.class);
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/META-INF/MANIFEST.MF b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/META-INF/MANIFEST.MF
index b816272..68b58e7 100644
--- a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/META-INF/MANIFEST.MF
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/META-INF/MANIFEST.MF
@@ -24,4 +24,5 @@
org.eclipse.lsp4e.cpp.language.cquery
Bundle-Activator: org.eclipse.lsp4e.cpp.language.Activator
Bundle-ActivationPolicy: lazy
-Import-Package: org.eclipse.ui.texteditor
+Import-Package: org.eclipse.ui.editors.text,
+ org.eclipse.ui.texteditor
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/plugin.xml b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/plugin.xml
index 58929f9..f81c0b3 100644
--- a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/plugin.xml
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/plugin.xml
@@ -62,4 +62,11 @@
class="org.eclipse.lsp4e.cpp.language.PreferenceInitializer">
</initializer>
</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>
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/AutoIndentStrategyCPP.java b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/AutoIndentStrategyCPP.java
new file mode 100644
index 0000000..8289ef4
--- /dev/null
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/AutoIndentStrategyCPP.java
@@ -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);
+ }
+}
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/PresentationReconcilerCPP.java b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/PresentationReconcilerCPP.java
index 1b16aeb..03a756c 100644
--- a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/PresentationReconcilerCPP.java
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/PresentationReconcilerCPP.java
@@ -26,6 +26,7 @@
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
import org.eclipse.cdt.core.model.ICLanguageKeywords;
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.CCommentScanner;
import org.eclipse.cdt.internal.ui.text.CPreprocessorScanner;
@@ -52,8 +53,10 @@
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextViewer;
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.RuleBasedScanner;
+import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.lsp4e.cpp.language.cquery.CquerySemanticHighlights;
import org.eclipse.lsp4e.cpp.language.cquery.HighlightSymbol;
import org.eclipse.lsp4j.Range;
@@ -62,6 +65,8 @@
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
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++
@@ -77,6 +82,7 @@
private CqueryLineBackgroundListener fLineBackgroundListener = new CqueryLineBackgroundListener();
private ITextViewer textViewer;
private TextInputListenerCPP textInputListener;
+ private BracketInserter fBracketInserter;
public static Set<PresentationReconcilerCPP> presentationReconcilers = ConcurrentHashMap.newKeySet();
@@ -345,6 +351,19 @@
StyledText textWidget = textViewer.getTextWidget();
textWidget.addLineBackgroundListener(fLineBackgroundListener);
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
@@ -352,6 +371,7 @@
super.uninstall();
textViewer.getTextWidget().removeLineBackgroundListener(fLineBackgroundListener);
textViewer.removeTextInputListener(textInputListener);
+ ((TextViewer) textViewer).removeVerifyKeyListener(fBracketInserter);
presentationReconcilers.remove(this);
}
}