From 1983d41afbe9129fb974f44de97eaf94be9d9741 Mon Sep 17 00:00:00 2001 From: Manish Khurana Date: Sun, 12 Aug 2018 02:09:31 +0530 Subject: Bug 535428. Add indentation and bracket completion support in LSP4E-CPP Change-Id: Ib9187a3ad28796305c47fe8e9543e1aed6a7bf58 Signed-off-by: Manish Khurana --- .../eclipse/cdt/internal/ui/editor/CEditor.java | 48 +++++++++++++++------- .../cdt/internal/ui/text/CAutoIndentStrategy.java | 13 ++++++ .../META-INF/MANIFEST.MF | 3 +- .../org.eclipse.lsp4e.cpp.language/plugin.xml | 7 ++++ .../lsp4e/cpp/language/AutoIndentStrategyCPP.java | 25 +++++++++++ .../cpp/language/PresentationReconcilerCPP.java | 20 +++++++++ 6 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/AutoIndentStrategyCPP.java 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 90cab566692..feb50599dc7 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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi } } - private class ExitPolicy implements IExitPolicy { + private static class ExitPolicy implements IExitPolicy { final char fExitCharacter; final char fEscapeCharacter; final Deque fStack; final int fSize; + ISourceViewer sourceViewer; - public ExitPolicy(char exitCharacter, char escapeCharacter, Deque stack) { + public ExitPolicy(char exitCharacter, char escapeCharacter, Deque stack, ISourceViewer sViewer) { fExitCharacter = exitCharacter; fEscapeCharacter = escapeCharacter; fStack = stack; fSize = fStack.size(); + sourceViewer = sViewer; } @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 // 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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi } 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 @@ 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 fCloseStrings = true; private boolean fCloseAngularBrackets = true; @@ -611,6 +613,18 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi private final String CATEGORY = toString(); private final IPositionUpdater fUpdater = new ExclusivePositionUpdater(CATEGORY); private final Deque 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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi @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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi return; } - final ISourceViewer sourceViewer = getSourceViewer(); IDocument document = sourceViewer.getDocument(); final Point selection = sourceViewer.getSelectedRange(); @@ -661,7 +680,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi 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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi return; } - if (!validateEditorInputState()) + if (!fEditor.validateEditorInputState()) return; 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.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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi return; // remove brackets - final ISourceViewer sourceViewer = getSourceViewer(); final IDocument document = sourceViewer.getDocument(); if (document instanceof IDocumentExtension) { IDocumentExtension extension = (IDocumentExtension) document; @@ -1284,7 +1302,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi 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 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi 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 77053a62e74..7a95340d1b3 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 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { 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 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { 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 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { 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 b8162722ac0..68b58e77ba0 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 @@ Export-Package: org.eclipse.lsp4e.cpp.language, 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 58929f970e5..f81c0b3e9f4 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"> + + + + 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 00000000000..8289ef4133d --- /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 1b16aeb9350..03a756ce3db 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 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; +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.IRegion; 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.StyleRange; 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 @@ public class PresentationReconcilerCPP extends CPresentationReconciler { private CqueryLineBackgroundListener fLineBackgroundListener = new CqueryLineBackgroundListener(); private ITextViewer textViewer; private TextInputListenerCPP textInputListener; + private BracketInserter fBracketInserter; public static Set presentationReconcilers = ConcurrentHashMap.newKeySet(); @@ -345,6 +351,19 @@ public class PresentationReconcilerCPP extends CPresentationReconciler { 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 @@ public class PresentationReconcilerCPP extends CPresentationReconciler { super.uninstall(); textViewer.getTextWidget().removeLineBackgroundListener(fLineBackgroundListener); textViewer.removeTextInputListener(textInputListener); + ((TextViewer) textViewer).removeVerifyKeyListener(fBracketInserter); presentationReconcilers.remove(this); } } -- cgit v1.2.3