From 598b68cfd91d6b5aa1af760cc3e9ef23f6d40f10 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 19 Jun 2012 16:25:11 +0200 Subject: [PATCH] suggest primitive types in parameter type position after an annotation --- .../completion/JavaCompletionContributor.java | 2 +- .../completion/JavaCompletionData.java | 74 ++++++++----------- .../template/JavaCodeContextType.java | 4 +- .../position/PreviousElementFilter.java | 48 ------------ .../TypeCodeFragmentIsVoidEnabledFilter.java | 38 ---------- .../keywords/charInAnnotatedParameter.java | 7 ++ .../completion/KeywordCompletionTest.java | 1 + .../com/intellij/codeInsight/TailType.java | 2 +- 8 files changed, 43 insertions(+), 133 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/psi/filters/position/PreviousElementFilter.java delete mode 100644 java/java-impl/src/com/intellij/psi/filters/types/TypeCodeFragmentIsVoidEnabledFilter.java create mode 100644 java/java-tests/testData/codeInsight/completion/keywords/charInAnnotatedParameter.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index d360d548569a..c6c77dfc3878 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -130,7 +130,7 @@ public class JavaCompletionContributor extends CompletionContributor { } if (JavaCompletionData.DECLARATION_START.accepts(position) || - JavaCompletionData.INSIDE_PARAMETER_LIST.accepts(position)) { + JavaCompletionData.isInsideParameterList(position)) { return new OrFilter(ElementClassFilter.CLASS, ElementClassFilter.PACKAGE_FILTER); } 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 c73f1185b753..c72c946efdaf 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -33,7 +33,6 @@ import com.intellij.psi.filters.classes.InterfaceFilter; import com.intellij.psi.filters.element.ReferenceOnFilter; import com.intellij.psi.filters.getters.JavaMembersGetter; import com.intellij.psi.filters.position.*; -import com.intellij.psi.filters.types.TypeCodeFragmentIsVoidEnabledFilter; import com.intellij.psi.impl.source.jsp.jspJava.JspClassLevelDeclarationStatement; import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.templateLanguages.OuterLanguageElement; @@ -71,12 +70,26 @@ public class JavaCompletionData extends JavaAwareCompletionData { new ParentElementFilter(new ClassFilter(PsiTryStatement.class))) ))); - public static final PsiJavaElementPattern.Capture INSIDE_PARAMETER_LIST = + private static final PsiJavaElementPattern.Capture INSIDE_PARAMETER_LIST = psiElement().withParent( psiElement(PsiJavaCodeReferenceElement.class).insideStarting( psiElement().withTreeParent( psiElement(PsiParameterList.class).andNot(psiElement(PsiAnnotationParameterList.class))))); + public static boolean isInsideParameterList(PsiElement position) { + PsiElement prev = PsiTreeUtil.prevVisibleLeaf(position); + PsiModifierList modifierList = PsiTreeUtil.getParentOfType(prev, PsiModifierList.class); + if (modifierList != null) { + if (PsiTreeUtil.isAncestor(modifierList, position, false)) { + return false; + } + PsiElement parent = modifierList.getParent(); + return parent instanceof PsiParameterList || parent instanceof PsiParameter && parent.getParent() instanceof PsiParameterList; + } + return INSIDE_PARAMETER_LIST.accepts(position); + } + + private static final AndFilter START_OF_CODE_FRAGMENT = new AndFilter( new ScopeFilter(new AndFilter( new ClassFilter(JavaCodeFragment.class), @@ -218,24 +231,6 @@ public class JavaCompletionData extends JavaAwareCompletionData { } protected void initVariantsInFileScope(){ -// package keyword completion - { - final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, new StartElementFilter()); - variant.addCompletion(PsiKeyword.PACKAGE, TailType.INSERT_SPACE); - registerVariant(variant); - } - -// import keyword completion - { - final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, new OrFilter( - new StartElementFilter(), - END_OF_BLOCK - )); - variant.addCompletion(PsiKeyword.IMPORT); - - registerVariant(variant); - } -// other in file scope { final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, CLASS_START); variant.includeScopeClass(PsiClass.class); @@ -246,21 +241,6 @@ public class JavaCompletionData extends JavaAwareCompletionData { registerVariant(variant); } - { - final CompletionVariant variant = new CompletionVariant(PsiTypeCodeFragment.class, new StartElementFilter()); - addPrimitiveTypes(variant, TailType.NONE); - final CompletionVariant variant1 = new CompletionVariant(PsiTypeCodeFragment.class, - new AndFilter( - new StartElementFilter(), - new TypeCodeFragmentIsVoidEnabledFilter() - ) - ); - variant1.addCompletion(PsiKeyword.VOID, TailType.NONE); - registerVariant(variant); - registerVariant(variant1); - - } - } /** @@ -406,10 +386,6 @@ public class JavaCompletionData extends JavaAwareCompletionData { } - private static void addPrimitiveTypes(CompletionVariant variant, TailType tailType){ - variant.addCompletion(PRIMITIVE_TYPES, tailType); - } - private static TailType getReturnTail(PsiElement position) { PsiElement scope = position; while(true){ @@ -516,7 +492,15 @@ public class JavaCompletionData extends JavaAwareCompletionData { result.addElement(createKeyword(position, PsiKeyword.FALSE)); } - if (INSIDE_PARAMETER_LIST.accepts(position) && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) { + if (PsiTreeUtil.prevVisibleLeaf(position) == null) { + result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD)); + result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD)); + } + else if (END_OF_BLOCK.isAcceptable(position, position) && PsiTreeUtil.getParentOfType(position, PsiMember.class) == null) { + result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD)); + } + + if (isInsideParameterList(position) && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) { result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD)); } @@ -579,7 +563,7 @@ public class JavaCompletionData extends JavaAwareCompletionData { } static boolean isAfterTypeDot(PsiElement position) { - if (INSIDE_PARAMETER_LIST.accepts(position) || position.getContainingFile() instanceof PsiJavaCodeReferenceCodeFragment) { + if (isInsideParameterList(position) || position.getContainingFile() instanceof PsiJavaCodeReferenceCodeFragment) { return false; } @@ -592,20 +576,24 @@ public class JavaCompletionData extends JavaAwareCompletionData { .afterLeaf(psiElement().withText("(").withParent(psiElement(PsiParenthesizedExpression.class, PsiTypeCastExpression.class))) .accepts(position); + boolean typeFragment = position.getContainingFile() instanceof PsiTypeCodeFragment && PsiTreeUtil.prevVisibleLeaf(position) == null; boolean declaration = DECLARATION_START.accepts(position); if (START_FOR.accepts(position) || - INSIDE_PARAMETER_LIST.accepts(position) && !AFTER_DOT.accepts(position) || + isInsideParameterList(position) && !AFTER_DOT.accepts(position) || VARIABLE_AFTER_FINAL.accepts(position) || inCast || declaration || + typeFragment || isStatementPosition(position)) { for (String primitiveType : PRIMITIVE_TYPES) { LookupElement keyword = createKeyword(position, primitiveType); - result.addElement(inCast ? keyword : new OverrideableSpace(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD)); + result.addElement(inCast || typeFragment ? keyword : new OverrideableSpace(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD)); } } if (declaration) { result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE_BEFORE_WORD)); + } else if (typeFragment && ((PsiTypeCodeFragment)position.getContainingFile()).isVoidValid()) { + result.addElement(createKeyword(position, PsiKeyword.VOID)); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java index 645d668b1a89..efdf2675c37b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java @@ -128,7 +128,7 @@ public abstract class JavaCodeContextType extends TemplateContextType { return false; } - if (JavaCompletionData.INSIDE_PARAMETER_LIST.accepts(element)) { + if (JavaCompletionData.isInsideParameterList(element)) { return false; } @@ -159,7 +159,7 @@ public abstract class JavaCodeContextType extends TemplateContextType { return false; } - return JavaCompletionData.CLASS_START.isAcceptable(element, element) || JavaCompletionData.INSIDE_PARAMETER_LIST.accepts(element); + return JavaCompletionData.CLASS_START.isAcceptable(element, element) || JavaCompletionData.isInsideParameterList(element); } } diff --git a/java/java-impl/src/com/intellij/psi/filters/position/PreviousElementFilter.java b/java/java-impl/src/com/intellij/psi/filters/position/PreviousElementFilter.java deleted file mode 100644 index 1edd056b0db8..000000000000 --- a/java/java-impl/src/com/intellij/psi/filters/position/PreviousElementFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.psi.filters.position; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.filters.FilterUtil; - -/** - * Created by IntelliJ IDEA. - * User: ik - * Date: 30.01.2003 - * Time: 13:48:00 - * To change this template use Options | File Templates. - */ -public class PreviousElementFilter extends PositionElementFilter{ - public PreviousElementFilter(){} - - public PreviousElementFilter(ElementFilter filter){ - setFilter(filter); - } - - @Override - public boolean isAcceptable(Object element, PsiElement context){ - if (!(element instanceof PsiElement)) return false; - if((element = FilterUtil.getPreviousElement((PsiElement) element, true)) != null){ - return getFilter().isAcceptable(element, context); - } - return false; - } - - public String toString(){ - return "previous(" +getFilter()+")"; - } -} diff --git a/java/java-impl/src/com/intellij/psi/filters/types/TypeCodeFragmentIsVoidEnabledFilter.java b/java/java-impl/src/com/intellij/psi/filters/types/TypeCodeFragmentIsVoidEnabledFilter.java deleted file mode 100644 index f6378f652fe3..000000000000 --- a/java/java-impl/src/com/intellij/psi/filters/types/TypeCodeFragmentIsVoidEnabledFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.psi.filters.types; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiTypeCodeFragment; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.util.ReflectionCache; - -/** - * @author dsl - */ -public class TypeCodeFragmentIsVoidEnabledFilter implements ElementFilter { - @Override - public boolean isAcceptable(Object element, PsiElement context) { - return context instanceof PsiTypeCodeFragment && - ((PsiTypeCodeFragment)context).isVoidValid(); - } - - - @Override - public boolean isClassAcceptable(Class hintClass) { - return ReflectionCache.isAssignable(hintClass, PsiTypeCodeFragment.class); - } -} diff --git a/java/java-tests/testData/codeInsight/completion/keywords/charInAnnotatedParameter.java b/java/java-tests/testData/codeInsight/completion/keywords/charInAnnotatedParameter.java new file mode 100644 index 000000000000..b62484f5118f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/keywords/charInAnnotatedParameter.java @@ -0,0 +1,7 @@ +public class Util { + + void foo(@NotNull a) { + } + + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java index 1539a06e4bfa..3a7f62eba3c3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java @@ -91,6 +91,7 @@ public class KeywordCompletionTest extends LightCompletionTestCase { public void testNullInMethodCall2() throws Exception { doTest(false); } public void testNewInMethodRefs() throws Exception { doTest(false); } public void testAbstractInInterface() throws Exception { doTest(1, "abstract"); } + public void testCharInAnnotatedParameter() throws Exception { doTest(1, "char"); } public void testTryInExpression() throws Exception { configureByFile(BASE_PATH + "/" + getTestName(true) + ".java"); diff --git a/platform/lang-api/src/com/intellij/codeInsight/TailType.java b/platform/lang-api/src/com/intellij/codeInsight/TailType.java index a82827c20b9f..6a9e3baf830b 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/TailType.java +++ b/platform/lang-api/src/com/intellij/codeInsight/TailType.java @@ -112,7 +112,7 @@ public abstract class TailType { */ public static final TailType INSERT_SPACE = new CharTailType(' ', false); /** - * insert a space unless there's one at the caret position already, followed by a sowrd + * insert a space unless there's one at the caret position already, followed by a word */ public static final TailType HUMBLE_SPACE_BEFORE_WORD = new CharTailType(' ', false) {