diamonds: additional diagnostics for cases when constructor is unresolved (IDEA-146028)

This commit is contained in:
Anna Kozlova
2015-10-06 17:36:58 +02:00
parent 5ae9332d1a
commit 2b4d30bc16
4 changed files with 50 additions and 11 deletions
@@ -58,6 +58,19 @@ public abstract class PsiDiamondType extends PsiType {
}
};
public static final DiamondInferenceResult UNRESOLVED_CONSTRUCTOR = new DiamondInferenceResult() {
@NotNull
@Override
public PsiType[] getTypes() {
return PsiType.EMPTY_ARRAY;
}
@Override
public String getErrorMessage() {
return "Cannot infer arguments (unable to resolve constructor)";
}
};
public static final DiamondInferenceResult ANONYMOUS_INNER_RESULT = new DiamondInferenceResult() {
@NotNull
@Override
@@ -147,18 +147,18 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
}
public static DiamondInferenceResult resolveInferredTypesNoCheck(final PsiNewExpression newExpression, final PsiElement context) {
final Ref<MethodCandidateInfo> staticFactoryRef = new Ref<MethodCandidateInfo>();
final Ref<JavaResolveResult> staticFactoryRef = new Ref<JavaResolveResult>();
final PsiSubstitutor inferredSubstitutor = ourDiamondGuard.doPreventingRecursion(context, false, new Computable<PsiSubstitutor>() {
@Override
public PsiSubstitutor compute() {
final MethodCandidateInfo staticFactoryCandidateInfo = context == newExpression ?
final JavaResolveResult staticFactoryCandidateInfo = context == newExpression ?
CachedValuesManager.getCachedValue(context,
new CachedValueProvider<MethodCandidateInfo>() {
new CachedValueProvider<JavaResolveResult>() {
@Nullable
@Override
public Result<MethodCandidateInfo> compute() {
return new Result<MethodCandidateInfo>(getStaticFactoryCandidateInfo(newExpression, newExpression),
PsiModificationTracker.MODIFICATION_COUNT);
public Result<JavaResolveResult> compute() {
return new Result<JavaResolveResult>(getStaticFactoryCandidateInfo(newExpression, newExpression),
PsiModificationTracker.MODIFICATION_COUNT);
}
})
: getStaticFactoryCandidateInfo(newExpression, context);
@@ -169,12 +169,18 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
if (inferredSubstitutor == null) {
return DiamondInferenceResult.NULL_RESULT;
}
final MethodCandidateInfo staticFactoryInfo = staticFactoryRef.get();
final JavaResolveResult staticFactoryInfo = staticFactoryRef.get();
if (staticFactoryInfo == null) {
LOG.error(inferredSubstitutor);
return DiamondInferenceResult.NULL_RESULT;
}
final PsiMethod staticFactory = staticFactoryInfo.getElement();
if (!(staticFactoryInfo instanceof MethodCandidateInfo)) {
return DiamondInferenceResult.UNRESOLVED_CONSTRUCTOR;
}
final PsiMethod staticFactory = ((MethodCandidateInfo)staticFactoryInfo).getElement();
final PsiTypeParameter[] parameters = staticFactory.getTypeParameters();
final PsiElement staticFactoryContext = staticFactory.getContext();
final PsiClass psiClass = PsiTreeUtil.getContextOfType(staticFactoryContext, PsiClass.class, false);
@@ -208,21 +214,24 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
return result;
}
private static MethodCandidateInfo getStaticFactoryCandidateInfo(PsiNewExpression newExpression,
PsiElement context) {
private static JavaResolveResult getStaticFactoryCandidateInfo(PsiNewExpression newExpression,
PsiElement context) {
final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
//token expected diagnostic is provided by parser
return null;
}
final PsiClass psiClass = findClass(newExpression);
if (psiClass == null) {
//should not happens: unresolved class reference would be first and inference won't start
return null;
}
final PsiMethod staticFactory = findConstructorStaticFactory(psiClass, newExpression);
if (staticFactory == null) {
return null;
//additional diagnostics: inference fails due to unresolved constructor
return JavaResolveResult.EMPTY;
}
final MethodCandidateInfo staticFactoryCandidateInfo = createMethodCandidate(staticFactory, context, false, argumentList);
@@ -0,0 +1,13 @@
class Test {
{
D<String> ds = new D<<error descr="Cannot infer arguments (unable to resolve constructor)"></error>>(9);
}
}
class D<T> {
D() {}
D(D<T> d){}
D(M<T> m){}
}
class M<K> extends D<K> {}
@@ -51,6 +51,10 @@ public class Diamond8HighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testDiagnosticMessageWhenConstructorIsUnresolved() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
}