Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Prigogin2014-05-20 01:52:07 +0000
committerSergey Prigogin2014-05-20 01:52:07 +0000
commit5b6571f5d9e52cc7005ec4950958d6fc8c4cd391 (patch)
tree84550a8127892b45880625c6bfa9a68b43dbdf84
parentc91dfd42d0be07d301cde5ede628bc28a1c0a647 (diff)
downloadorg.eclipse.cdt-5b6571f5d9e52cc7005ec4950958d6fc8c4cd391.tar.gz
org.eclipse.cdt-5b6571f5d9e52cc7005ec4950958d6fc8c4cd391.tar.xz
org.eclipse.cdt-5b6571f5d9e52cc7005ec4950958d6fc8c4cd391.zip
Bug 435235 - Automatically close opening brace of list initializer
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java42
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java57
2 files changed, 84 insertions, 15 deletions
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java
index f52d394efc5..a255c58552d 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 IBM Corporation 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
@@ -77,7 +78,7 @@ public class BracketInserterTest extends TestCase {
// Document offsets.
private static final int INCLUDE_OFFSET= 9;
- private static final int BODY_OFFSET= 212;
+ private static final int BODY_OFFSET= 213;
private static final int ARGS_OFFSET= 184;
private static final int BRACKETS_OFFSET= 262;
@@ -123,7 +124,7 @@ public class BracketInserterTest extends TestCase {
IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(path);
assertTrue(file != null && file.exists());
try {
- return (CEditor)EditorTestHelper.openInEditor(file, true);
+ return (CEditor) EditorTestHelper.openInEditor(file, true);
} catch (PartInitException e) {
fail();
return null;
@@ -175,19 +176,19 @@ public class BracketInserterTest extends TestCase {
setCaret(BODY_OFFSET);
type("((((");
- // delete two levels
+ // Delete two levels.
linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION);
linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION);
assertEquals("(())", fDocument.get(BODY_OFFSET, 4));
assertEquals(BODY_OFFSET + 2, getCaret());
- // delete the second-last level
+ // Delete the second-last level
linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION);
assertEquals("()", fDocument.get(BODY_OFFSET, 2));
assertEquals(BODY_OFFSET + 1, getCaret());
- // delete last level
+ // Delete last level
linkedType(SWT.BS, false, ILinkedModeListener.EXTERNAL_MODIFICATION);
assertEquals(TU_CONTENTS, fDocument.get());
assertEquals(BODY_OFFSET, getCaret());
@@ -304,18 +305,18 @@ public class BracketInserterTest extends TestCase {
setCaret(BODY_OFFSET);
type("#define MACRO ");
int offset = getCaret();
- // enter opening quote (should be closed again)
+ // Enter opening quote (should be closed again).
type('"');
assertEquals("\"\"", fDocument.get(offset, 2));
assertSingleLinkedPosition(offset + 1);
- // enter closing quote (should not add a quote, but proceed cursor)
+ // Enter closing quote (should not add a quote, but proceed cursor).
type('"');
assertEquals("\"\"", fDocument.get(offset, 2));
assertEquals(offset + 2, getCaret());
- // delete closing quote and enter quote again
+ // Delete closing quote and enter quote again.
type(SWT.BS);
assertEquals("\"", fDocument.get(offset, 1));
int length = fDocument.getLength();
@@ -358,6 +359,23 @@ public class BracketInserterTest extends TestCase {
assertSingleLinkedPosition(BODY_OFFSET + 5);
}
+ public void testCurlyBraceInsideParentheses() throws Exception {
+ setCaret(BODY_OFFSET);
+ type("f({");
+
+ assertEquals("f({})", fDocument.get(BODY_OFFSET, 5));
+ assertSingleLinkedPosition(BODY_OFFSET + 3, true);
+ }
+
+ public void testCurlyBraceOutsideParentheses() throws Exception {
+ setCaret(BODY_OFFSET);
+ type("struct A {");
+
+ assertFalse("}".equals(fDocument.get(BODY_OFFSET + 10, 1)));
+ assertEquals(BODY_OFFSET + 10, getCaret());
+ assertFalse(LinkedModeModel.hasInstalledModel(fDocument));
+ }
+
public void testAngleBracketsInInclude() throws Exception {
setCaret(INCLUDE_OFFSET);
type('<');
@@ -396,9 +414,13 @@ public class BracketInserterTest extends TestCase {
/* utilities */
private void assertSingleLinkedPosition(int offset) {
+ assertSingleLinkedPosition(offset, false);
+ }
+
+ private void assertSingleLinkedPosition(int offset, boolean nested) {
assertEquals(offset, getCaret());
- LinkedPosition position= assertModel(false).findPosition(new LinkedPosition(fDocument, offset, 0));
+ LinkedPosition position= assertModel(nested).findPosition(new LinkedPosition(fDocument, offset, 0));
assertNotNull(position);
assertEquals(offset, position.getOffset());
assertEquals(0, position.getLength());
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 9ba249fe3e5..f1c134b171f 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
@@ -535,6 +535,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
private boolean fCloseBrackets = true;
private boolean fCloseStrings = true;
private boolean fCloseAngularBrackets = true;
+ private boolean fCloseBraces = true;
private final String CATEGORY = toString();
private IPositionUpdater fUpdater = new ExclusivePositionUpdater(CATEGORY);
private Deque<BracketLevel> fBracketLevelStack = new ArrayDeque<>();
@@ -551,6 +552,10 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
fCloseAngularBrackets = enabled;
}
+ public void setCloseBracesEnabled(boolean enabled) {
+ fCloseBraces = enabled;
+ }
+
private boolean isAngularIntroducer(String identifier) {
return identifier.length() > 0 && (Character.isUpperCase(identifier.charAt(0))
|| angularIntroducers.contains(identifier)
@@ -560,13 +565,14 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
@Override
public void verifyKey(VerifyEvent event) {
- // Early pruning to slow down normal typing as little as possible.
+ // Early pruning to minimize overhead for normal typing.
if (!event.doit || getInsertMode() != SMART_INSERT)
return;
switch (event.character) {
case '(':
case '<':
case '[':
+ case '{':
case '\'':
case '\"':
break;
@@ -624,6 +630,16 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
return;
break;
+ case '{':
+ // An opening brace inside parentheses probably starts an initializer list -
+ // close it.
+ if (!fCloseBraces
+ || nextToken == Symbols.TokenIDENT
+ || next != null && next.length() > 1
+ || !isInsideParentheses(scanner, offset - 1))
+ return;
+ break;
+
case '\'':
case '"':
if (!fCloseStrings
@@ -687,6 +703,24 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
}
}
+ private boolean isInsideParentheses(CHeuristicScanner scanner, int offset) {
+ int depth = 0;
+ // Limit the scanning distance to 100 tokens.
+ for (int i = 0; i < 100; i++) {
+ int token = scanner.previousToken(offset, 0);
+ if (token == Symbols.TokenLPAREN) {
+ if (--depth < 0)
+ return true;
+ } else if (token == Symbols.TokenRPAREN) {
+ ++depth;
+ } else if (token == Symbols.TokenEOF) {
+ return false;
+ }
+ offset = scanner.getPosition();
+ }
+ return false;
+ }
+
private boolean isInsideStringInPreprocessorDirective(ITypedRegion partition, IDocument document, int offset) throws BadLocationException {
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType()) && offset < document.getLength()) {
// Use temporary document to test whether offset is inside non-default partition.
@@ -706,7 +740,6 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
@Override
public void left(LinkedModeModel environment, int flags) {
-
final BracketLevel level = fBracketLevelStack.pop();
if (flags != ILinkedModeListener.EXTERNAL_MODIFICATION)
@@ -1197,6 +1230,8 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
private static final String CLOSE_BRACKETS = PreferenceConstants.EDITOR_CLOSE_BRACKETS;
/** Preference key for automatically closing angular brackets */
private static final String CLOSE_ANGULAR_BRACKETS = PreferenceConstants.EDITOR_CLOSE_ANGULAR_BRACKETS;
+ /** Preference key for automatically closing curly braces */
+ private static final String CLOSE_BRACES = PreferenceConstants.EDITOR_CLOSE_BRACES;
/** Preference key for compiler task tags */
private static final String TODO_TASK_TAGS = CCorePreferenceConstants.TODO_TASK_TAGS;
@@ -1532,6 +1567,11 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
return;
}
+ if (CLOSE_BRACES.equals(property)) {
+ fBracketInserter.setCloseBracesEnabled(newBooleanValue);
+ return;
+ }
+
if (CLOSE_STRINGS.equals(property)) {
fBracketInserter.setCloseStringsEnabled(newBooleanValue);
return;
@@ -2403,11 +2443,13 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
IPreferenceStore preferenceStore = getPreferenceStore();
boolean closeBrackets = preferenceStore.getBoolean(CLOSE_BRACKETS);
boolean closeAngularBrackets = preferenceStore.getBoolean(CLOSE_ANGULAR_BRACKETS);
+ boolean closeBraces = preferenceStore.getBoolean(CLOSE_BRACES);
boolean closeStrings = preferenceStore.getBoolean(CLOSE_STRINGS);
fBracketInserter.setCloseBracketsEnabled(closeBrackets);
- fBracketInserter.setCloseStringsEnabled(closeStrings);
fBracketInserter.setCloseAngularBracketsEnabled(closeAngularBrackets);
+ fBracketInserter.setCloseAngularBracketsEnabled(closeBraces);
+ fBracketInserter.setCloseStringsEnabled(closeStrings);
ISourceViewer sourceViewer = getSourceViewer();
if (sourceViewer instanceof ITextViewerExtension)
@@ -2867,8 +2909,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
return false;
try {
- return isBracket(document.getChar(offset - 1)) &&
- isBracket(document.getChar(offset));
+ return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
} catch (BadLocationException e) {
return false;
}
@@ -2904,6 +2945,12 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
case ']':
return '[';
+ case '{':
+ return '}';
+
+ case '}':
+ return '{';
+
case '"':
return character;

Back to the top