diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java index baa48c694966..89a928ecb034 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -135,8 +135,11 @@ public class JavaInheritorsGetter extends CompletionProvider()", parameters.getOriginalFile()); final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0]; - final PsiExpression initializer = declaredVar.getInitializer(); - psiType = initializer.getType(); + final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer(); + final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondType.hasDefaultConstructor(psiClass) || !PsiDiamondType.haveConstructorsGenericsParameters(psiClass); + if (hasDefaultConstructorOrNoGenericsOne && PsiDiamondType.resolveInferredTypes(initializer).getErrorMessage() == null) { + psiType = initializer.getType(); + } } } final LookupItem item = PsiTypeLookupItem.createLookupItem(psiType, parameters.getPosition()); diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java new file mode 100644 index 000000000000..f9430cdb29a0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2011 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. + */ +class MyClass { + public void foo() { + MyDD d = new MyDD() + } +} + +class MyDD { + MyDD(T t){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java new file mode 100644 index 000000000000..69a12ec44ec7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2011 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. + */ +class MyClass { + public void foo() { + MyDD d = new MyD + } +} + +class MyDD { + MyDD(T t){} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java index bd05bbca53c3..7ee850dac128 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType17CompletionTest.java @@ -49,6 +49,10 @@ public class SmartType17CompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testDiamondNotCollapsed() throws Exception { + doTest(); + } + private void doTest() throws Exception { configureByFile("/" + getTestName(false) + ".java"); diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 084e408129e0..5b1488918a12 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -300,4 +301,46 @@ public class PsiDiamondType extends PsiType { }); } } + + public static boolean hasDefaultConstructor(@NotNull final PsiClass psiClass) { + final PsiMethod[] constructors = psiClass.getConstructors(); + for (PsiMethod method : constructors) { + if (method.getParameterList().getParametersCount() == 0) return true; + } + return constructors.length == 0; + } + + public static boolean haveConstructorsGenericsParameters(@NotNull final PsiClass psiClass) { + for (PsiMethod method : psiClass.getConstructors()) { + for (PsiParameter parameter : method.getParameterList().getParameters()) { + final PsiType type = parameter.getType(); + final Boolean accept = type.accept(new PsiTypeVisitor() { + @Override + public Boolean visitArrayType(PsiArrayType arrayType) { + return arrayType.getComponentType().accept(this); + } + + @Override + public Boolean visitClassType(PsiClassType classType) { + for (PsiType psiType : classType.getParameters()) { + if (psiType != null) { + final Boolean typaParamFound = psiType.accept(this); + if (typaParamFound != null && typaParamFound) return true; + } + } + return PsiUtil.resolveClassInType(classType) instanceof PsiTypeParameter; + } + + @Override + public Boolean visitWildcardType(PsiWildcardType wildcardType) { + final PsiType bound = wildcardType.getBound(); + if (bound == null) return false; + return bound.accept(this); + } + }); + if (accept != null && accept.booleanValue()) return true; + } + } + return false; + } }