From d0f7824299f529add57436501025b7918cc2692e Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 5 Jan 2012 13:32:53 +0100 Subject: [PATCH] don't insert a space after a keyword if there's already one --- .../completion/Java15CompletionData.java | 10 ++++---- .../completion/JavaAwareCompletionData.java | 2 +- .../completion/JavaCompletionData.java | 20 +++++++-------- .../JavaSmartCompletionContributor.java | 4 +-- ...RightContextInClassTypeParameters-out.java | 2 +- .../completion/keywords/extends-8-result.java | 2 +- .../keywords/methodScope-5-out.java | 2 +- .../completion/normal/FieldType_after.java | 2 +- .../com/intellij/codeInsight/TailType.java | 25 +++++++++++++++++++ .../lang/completion/GroovyCompletionData.java | 12 +++++---- .../completion/GroovyCompletionTest.groovy | 6 ++--- 11 files changed, 57 insertions(+), 30 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/Java15CompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/Java15CompletionData.java index 6559888c7898..f539c346b662 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/Java15CompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/Java15CompletionData.java @@ -31,7 +31,7 @@ public class Java15CompletionData extends JavaCompletionData { //static keyword in static import { final CompletionVariant variant = new CompletionVariant(PsiImportList.class, new LeftNeighbour(new TextFilter (PsiKeyword.IMPORT))); - variant.addCompletion(PsiKeyword.STATIC, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.STATIC, TailType.HUMBLE_SPACE); registerVariant(variant); } @@ -46,7 +46,7 @@ public class Java15CompletionData extends JavaCompletionData { final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, position); variant.includeScopeClass(PsiClass.class); - variant.addCompletion(PsiKeyword.INTERFACE, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE); registerVariant(variant); } @@ -55,7 +55,7 @@ public class Java15CompletionData extends JavaCompletionData { final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, CLASS_START); variant.includeScopeClass(PsiClass.class); - variant.addCompletion(PsiKeyword.ENUM, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.ENUM, TailType.HUMBLE_SPACE); registerVariant(variant); } @@ -68,8 +68,8 @@ public class Java15CompletionData extends JavaCompletionData { final CompletionVariant variant = new CompletionVariant(JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN); variant.includeScopeClass(PsiVariable.class, true); variant.includeScopeClass(PsiExpressionStatement.class, true); - variant.addCompletion(PsiKeyword.SUPER, TailType.INSERT_SPACE); - variant.addCompletion(PsiKeyword.EXTENDS, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.SUPER, TailType.HUMBLE_SPACE); + variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE); registerVariant(variant); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java index ac1aa851c633..37a648bbb14d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java @@ -51,7 +51,7 @@ public class JavaAwareCompletionData extends CompletionData{ if (context.shouldAddCompletionChar()) { return; } - if (tailType != TailType.NONE) { + if (tailType != TailType.NONE && tailType.isApplicable(context)) { tailType.processTail(context.getEditor(), context.getTailOffset()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index af1f43bc578a..78d73295c387 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -210,7 +210,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ // package keyword completion { final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, new StartElementFilter()); - variant.addCompletion(PsiKeyword.PACKAGE); + variant.addCompletion(PsiKeyword.PACKAGE, TailType.INSERT_SPACE); registerVariant(variant); } @@ -271,7 +271,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ // completion final CompletionVariant variant = new CompletionVariant(position); variant.includeScopeClass(PsiClass.class, true); - variant.addCompletion(PsiKeyword.EXTENDS, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE); variant.excludeScopeClass(PsiAnonymousClass.class); variant.excludeScopeClass(PsiTypeParameter.class); @@ -292,7 +292,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ // completion final CompletionVariant variant = new CompletionVariant(position); variant.includeScopeClass(PsiClass.class, true); - variant.addCompletion(PsiKeyword.IMPLEMENTS, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.IMPLEMENTS, TailType.HUMBLE_SPACE); variant.excludeScopeClass(PsiAnonymousClass.class); registerVariant(variant); @@ -304,7 +304,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ psiElement(PsiIdentifier.class).afterLeaf( psiElement().withText(string().oneOf(",", "<")).withParent(PsiTypeParameterList.class)))); //variant.includeScopeClass(PsiClass.class, true); - variant.addCompletion(PsiKeyword.EXTENDS, TailType.INSERT_SPACE); + variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE); registerVariant(variant); } } @@ -412,7 +412,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ return TailType.SEMICOLON; } - return TailType.INSERT_SPACE; + return TailType.HUMBLE_SPACE; } scope = scope.getParent(); } @@ -454,7 +454,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } if (statement != null && statement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) { if (!psiElement().withSuperParent(2, PsiSwitchStatement.class).accepts(statement)) { - result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.INSERT_SPACE)); + result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE)); } } @@ -506,13 +506,13 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } if (INSIDE_PARAMETER_LIST.accepts(position) && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) { - result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.INSERT_SPACE)); + result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE)); } if (CLASS_START.isAcceptable(position, position) && PsiTreeUtil.getNonStrictParentOfType(position, PsiLiteralExpression.class, PsiComment.class) == null) { for (String s : ModifierChooser.getKeywords(position)) { - result.addElement(new OverrideableSpace(createKeyword(position, s), TailType.INSERT_SPACE)); + result.addElement(new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE)); } } @@ -589,11 +589,11 @@ public class JavaCompletionData extends JavaAwareCompletionData{ isStatementPosition(position)) { for (String primitiveType : PRIMITIVE_TYPES) { LookupElement keyword = createKeyword(position, primitiveType); - result.addElement(inCast ? keyword : new OverrideableSpace(keyword, TailType.INSERT_SPACE)); + result.addElement(inCast ? keyword : new OverrideableSpace(keyword, TailType.HUMBLE_SPACE)); } } if (declaration) { - result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.INSERT_SPACE)); + result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE)); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 511a8529c357..ee310b9cc7e0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -264,7 +264,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { for (PsiClassType ref : method.getThrowsList().getReferencedTypes()) { final PsiClass exception = ref.resolve(); if (exception != null && throwsSet.add(exception)) { - result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.INSERT_SPACE)); + result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.HUMBLE_SPACE)); } } } @@ -282,7 +282,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { if (tryBlock == null) return; for (final PsiClassType type : ExceptionUtil.getThrownExceptions(tryBlock.getStatements())) { - result.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock).setInsertHandler(new DefaultInsertHandler()), TailType.INSERT_SPACE)); + result.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock).setInsertHandler(new DefaultInsertHandler()), TailType.HUMBLE_SPACE)); } } }); diff --git a/java/java-tests/testData/codeInsight/completion/keywords/ExtendsWithRightContextInClassTypeParameters-out.java b/java/java-tests/testData/codeInsight/completion/keywords/ExtendsWithRightContextInClassTypeParameters-out.java index c28a6e600101..26c81ac928a3 100644 --- a/java/java-tests/testData/codeInsight/completion/keywords/ExtendsWithRightContextInClassTypeParameters-out.java +++ b/java/java-tests/testData/codeInsight/completion/keywords/ExtendsWithRightContextInClassTypeParameters-out.java @@ -1,3 +1,3 @@ -class Foo A> { +class Foo A> { } diff --git a/java/java-tests/testData/codeInsight/completion/keywords/extends-8-result.java b/java/java-tests/testData/codeInsight/completion/keywords/extends-8-result.java index 46fe4caea6dc..cfcb2504f903 100644 --- a/java/java-tests/testData/codeInsight/completion/keywords/extends-8-result.java +++ b/java/java-tests/testData/codeInsight/completion/keywords/extends-8-result.java @@ -1,4 +1,4 @@ class AAA{} -class BBB extends AAA implements { +class BBB extends AAA implements { } diff --git a/java/java-tests/testData/codeInsight/completion/keywords/methodScope-5-out.java b/java/java-tests/testData/codeInsight/completion/keywords/methodScope-5-out.java index 26fd20c10a04..5ee694dc44d2 100644 --- a/java/java-tests/testData/codeInsight/completion/keywords/methodScope-5-out.java +++ b/java/java-tests/testData/codeInsight/completion/keywords/methodScope-5-out.java @@ -1,5 +1,5 @@ public class A{ - public void method(final String){ + public void method(final String){ } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java b/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java index a5209a87c687..172e9db83879 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/FieldType_after.java @@ -1,4 +1,4 @@ class A { - private long localizedStringManager; + private long localizedStringManager; } diff --git a/platform/lang-api/src/com/intellij/codeInsight/TailType.java b/platform/lang-api/src/com/intellij/codeInsight/TailType.java index cc177dfb0ced..10ece49eb3f2 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/TailType.java +++ b/platform/lang-api/src/com/intellij/codeInsight/TailType.java @@ -87,8 +87,33 @@ public abstract class TailType { return "COMMA"; } }; + /** + * insert a space, overtype if already present + */ public static final TailType SPACE = new CharTailType(' '); + /** + * always insert a space + */ public static final TailType INSERT_SPACE = new CharTailType(' ', false); + /** + * insert a space unless there's one at the caret position already + */ + public static final TailType HUMBLE_SPACE = new CharTailType(' ', false) { + + @Override + public boolean isApplicable(@NotNull InsertionContext context) { + CharSequence text = context.getDocument().getCharsSequence(); + if (text.length() > context.getTailOffset() && text.charAt(context.getTailOffset()) == ' ') { + return false; + } + return super.isApplicable(context); + } + + @Override + public String toString() { + return "HUMBLE_SPACE"; + } + }; public static final TailType DOT = new CharTailType('.'); public static final TailType CASE_COLON = new CharTailType(':'); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java index 481456ce95c8..4575552beb15 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java @@ -85,19 +85,21 @@ public class GroovyCompletionData { addTypeDefinitionKeywords(result, position); for (String keyword : addExtendsImplements(position)) { - result.addElement(keyword(keyword, TailType.INSERT_SPACE)); + result.addElement(keyword(keyword, TailType.HUMBLE_SPACE)); } registerControlCompletion(position, result); if (parent instanceof GrExpression) { - addKeywords(result, false, PsiKeyword.TRUE, PsiKeyword.FALSE, PsiKeyword.NULL, PsiKeyword.SUPER, PsiKeyword.NEW, PsiKeyword.THIS, "as"); + addKeywords(result, false, PsiKeyword.TRUE, PsiKeyword.FALSE, PsiKeyword.NULL, PsiKeyword.SUPER, PsiKeyword.THIS); + result.addElement(keyword(PsiKeyword.NEW, TailType.INSERT_SPACE)); + result.addElement(keyword("as", TailType.HUMBLE_SPACE)); } if (isInfixOperatorPosition(position)) { addKeywords(result, true, "in", PsiKeyword.INSTANCEOF); } else if (suggestThrows(position)) { - addKeywords(result, true, PsiKeyword.THROWS); + result.addElement(keyword(PsiKeyword.THROWS, TailType.INSERT_SPACE)); } else if (suggestPrimitiveTypes(position)) { boolean inCast = psiElement() .afterLeaf(psiElement().withText("(").withParent(psiElement(GrParenthesizedExpression.class, GrTypeCastExpression.class))) @@ -144,7 +146,7 @@ public class GroovyCompletionData { addKeywords(result, true, PsiKeyword.CLASS, PsiKeyword.INTERFACE, PsiKeyword.ENUM); } if (afterAtInType(position)) { - result.addElement(keyword(PsiKeyword.INTERFACE, TailType.INSERT_SPACE)); + result.addElement(keyword(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE)); } } @@ -185,7 +187,7 @@ public class GroovyCompletionData { public static void addKeywords(CompletionResultSet result, boolean space, String... keywords) { for (String s : keywords) { - result.addElement(keyword(s, space ? TailType.INSERT_SPACE : TailType.NONE)); + result.addElement(keyword(s, space ? TailType.HUMBLE_SPACE : TailType.NONE)); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index c14cbc698efe..10d443c28edc 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1064,7 +1064,7 @@ class X { } public void testInnerClassStart() { - checkSingleItemCompletion 'class Foo { cl }', 'class Foo { class }' + checkSingleItemCompletion 'class Foo { cl }', 'class Foo { class }' } public void testPropertyBeforeAccessor() { @@ -1114,8 +1114,8 @@ public class KeyVO { public void testSpaceTail() { checkCompletion 'class A ArrayList {}', ' ', 'class A extends ArrayList {}' - checkCompletion 'class A ArrayList {}', '\n', 'class A extends ArrayList {}' - checkSingleItemCompletion 'class Foo impl {}', 'class Foo implements {}' + checkCompletion 'class A ArrayList {}', '\n', 'class A extends ArrayList {}' + checkSingleItemCompletion 'class Foo impl {}', 'class Foo implements {}' } public void testPreferInterfacesInImplements() {