smart completion: insert diamond iff no arg constructor is present or all constructors are generic free and no diamond inference errors occur

This commit is contained in:
anna
2011-02-21 18:36:16 +01:00
parent 110d2906da
commit 2c27958238
5 changed files with 100 additions and 2 deletions
@@ -135,8 +135,11 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
final PsiStatement statement = elementFactory
.createStatementFromText(psiType.getCanonicalText() + " v = new " + canonicalText + "<>()", 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());
@@ -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<String> d = new MyDD<String>()
}
}
class MyDD<T> {
MyDD(T t){}
}
@@ -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<String> d = new MyD<caret>
}
}
class MyDD<T> {
MyDD(T t){}
}
@@ -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");
@@ -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<Boolean>() {
@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;
}
}