diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 9e37167da366..221fbb8c613c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -231,8 +231,8 @@ public class CodeInsightUtil { @Override public int compare(PsiElement o1, PsiElement o2) { if (o1 instanceof PsiDiamondTypeElementImpl && o2 instanceof PsiDiamondTypeElementImpl) { - final PsiDiamondType.DiamondInferenceResult thisInferenceResult = new PsiDiamondType(o1.getManager(), (PsiTypeElement)o1).resolveInferredTypes(); - final PsiDiamondType.DiamondInferenceResult otherInferenceResult = new PsiDiamondType(o2.getManager(), (PsiTypeElement)o2).resolveInferredTypes(); + final PsiDiamondType.DiamondInferenceResult thisInferenceResult = new PsiDiamondTypeImpl(o1.getManager(), (PsiTypeElement)o1).resolveInferredTypes(); + final PsiDiamondType.DiamondInferenceResult otherInferenceResult = new PsiDiamondTypeImpl(o2.getManager(), (PsiTypeElement)o2).resolveInferredTypes(); return thisInferenceResult.equals(otherInferenceResult) ? 0 : 1; } return 0; 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 9fab9dbb70f6..eb109ac71a3e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -130,9 +130,10 @@ public class JavaInheritorsGetter extends CompletionProvider()", parameters.getOriginalFile()); final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0]; final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer(); - final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondType.hasDefaultConstructor(psiClass) || !PsiDiamondType.haveConstructorsGenericsParameters(psiClass); + final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondTypeImpl.hasDefaultConstructor(psiClass) || + !PsiDiamondTypeImpl.haveConstructorsGenericsParameters(psiClass); if (hasDefaultConstructorOrNoGenericsOne) { - final PsiDiamondType.DiamondInferenceResult inferenceResult = PsiDiamondType.resolveInferredTypes(initializer); + final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(initializer); if (inferenceResult.getErrorMessage() == null && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && areInferredTypesApplicable(inferenceResult.getTypes(), parameters.getOriginalPosition())) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 632f6c6f5b4f..4f61bb909273 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -34,10 +34,6 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; -import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler; -import com.intellij.refactoring.extractSuperclass.ExtractSuperclassHandler; -import com.intellij.refactoring.memberPullUp.JavaPullUpHandler; -import com.intellij.refactoring.memberPullUp.PullUpHelper; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; diff --git a/java/java-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java new file mode 100644 index 000000000000..6b3d12ed1e0e --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java @@ -0,0 +1,290 @@ +/* + * Copyright 2000-2010 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; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +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; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * User: anna + * Date: Jul 30, 2010 + */ +public class PsiDiamondTypeImpl extends PsiDiamondType { + private final PsiManager myManager; + private final PsiTypeElement myTypeElement; + private static final Logger LOG = Logger.getInstance("#" + PsiDiamondTypeImpl.class.getName()); + + public PsiDiamondTypeImpl(PsiManager manager, PsiTypeElement psiTypeElement) { + super(PsiAnnotation.EMPTY_ARRAY); + myManager = manager; + myTypeElement = psiTypeElement; + } + + @Override + public String getPresentableText() { + return ""; + } + + @Override + public String getCanonicalText() { + return ""; + } + + @Override + public String getInternalCanonicalText() { + return "Diamond Type"; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public boolean equalsToText(@NonNls String text) { + return text != null && text.isEmpty(); + } + + @Override + public A accept(PsiTypeVisitor visitor) { + return visitor.visitType(this); + } + + @Override + public GlobalSearchScope getResolveScope() { + return GlobalSearchScope.allScope(myManager.getProject()); + } + + @NotNull + @Override + public PsiType[] getSuperTypes() { + return new PsiType[]{getJavaLangObject(myManager, getResolveScope())}; + } + + @Override + public DiamondInferenceResult resolveInferredTypes() { + final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(myTypeElement, PsiNewExpression.class); + if (newExpression == null) { + return PsiDiamondTypeImpl.DiamondInferenceResult.NULL_RESULT; + } + + return resolveInferredTypes(newExpression); + } + + public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) { + return resolveInferredTypes(newExpression, newExpression); + } + + public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression, + PsiElement context) { + final PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass(); + if (anonymousClass != null) { + final PsiElement resolve = anonymousClass.getBaseClassReference().resolve(); + if (resolve instanceof PsiClass) { + return PsiDiamondTypeImpl.DiamondInferenceResult.ANONYMOUS_INNER_RESULT; + } + } + + final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getChildOfType(newExpression, PsiReferenceParameterList.class); + if (referenceParameterList != null && referenceParameterList.getTypeParameterElements().length > 0) { + return DiamondInferenceResult.EXPLICIT_CONSTRUCTOR_TYPE_ARGS; + } + + return resolveInferredTypesNoCheck(newExpression, context); + } + + public static DiamondInferenceResult resolveInferredTypesNoCheck(PsiNewExpression newExpression, PsiElement context) { + final PsiClass psiClass = findClass(newExpression); + if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; + final PsiExpressionList argumentList = newExpression.getArgumentList(); + if (argumentList == null) return DiamondInferenceResult.NULL_RESULT; + final PsiMethod constructor = findConstructor(psiClass, newExpression); + PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass); + PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params); + if (staticFactory == null) { + return DiamondInferenceResult.NULL_RESULT; + } + final PsiSubstitutor inferredSubstitutor = inferTypeParametersForStaticFactory(staticFactory, newExpression, context); + final PsiTypeParameter[] parameters = staticFactory.getTypeParameters(); + final PsiTypeParameter[] classParameters = psiClass.getTypeParameters(); + final PsiJavaCodeReferenceElement classOrAnonymousClassReference = newExpression.getClassOrAnonymousClassReference(); + LOG.assertTrue(classOrAnonymousClassReference != null); + final DiamondInferenceResult + result = new DiamondInferenceResult(classOrAnonymousClassReference.getReferenceName() + "<>", newExpression.getProject()); + for (PsiTypeParameter parameter : parameters) { + for (PsiTypeParameter classParameter : classParameters) { + if (Comparing.strEqual(classParameter.getName(), parameter.getName())) { + result.addInferredType(inferredSubstitutor.substitute(parameter)); + break; + } + } + } + return result; + } + + + @Nullable + private static PsiMethod findConstructor(PsiClass containingClass, PsiNewExpression newExpression) { + final PsiExpressionList argumentList = newExpression.getArgumentList(); + final Project project = newExpression.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + final JavaResolveResult result = + resolveHelper.resolveConstructor(facade.getElementFactory().createType(containingClass), argumentList, argumentList); + return (PsiMethod)result.getElement(); + } + + @Nullable + private static PsiClass findClass(PsiNewExpression newExpression) { + final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference(); + if (classReference != null) { + final String text = classReference.getReferenceName(); + if (text != null) { + final Project project = newExpression.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + final PsiElement qualifierElement = classReference.getQualifier(); + final String qualifier = qualifierElement != null ? qualifierElement.getText() : ""; + return resolveHelper.resolveReferencedClass(StringUtil.getQualifiedName(qualifier, text), newExpression); + } else { + return null; + } + } + return null; + } + + @Nullable + private static PsiMethod generateStaticFactory(@Nullable PsiMethod constructor, PsiClass containingClass, PsiTypeParameter[] params) { + final StringBuilder buf = new StringBuilder(); + buf.append("public static "); + buf.append("<"); + buf.append(StringUtil.join(params, new Function() { + @Override + public String fun(PsiTypeParameter psiTypeParameter) { + return psiTypeParameter.getName(); + } + }, ", ")); + buf.append(">"); + + final String qualifiedName = containingClass.getQualifiedName(); + buf.append(qualifiedName != null ? qualifiedName : containingClass.getName()); + final PsiTypeParameter[] parameters = containingClass.getTypeParameters(); + buf.append("<"); + buf.append(StringUtil.join(parameters, new Function() { + @Override + public String fun(PsiTypeParameter psiTypeParameter) { + return psiTypeParameter.getName(); + } + }, ", ")); + buf.append("> "); + + String staticFactoryName = "staticFactory"; + final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(containingClass.getProject()); + staticFactoryName = styleManager.suggestUniqueVariableName(staticFactoryName, containingClass, false); + buf.append(staticFactoryName); + if (constructor == null) { + buf.append("()"); + } + else { + buf.append("(").append(StringUtil.join(constructor.getParameterList().getParameters(), new Function() { + int myIdx = 0; + @Override + public String fun(PsiParameter psiParameter) { + return psiParameter.getType().getCanonicalText() + " p" + myIdx++; + } + }, ",")).append(")"); + } + buf.append("{}"); + + return JavaPsiFacade.getElementFactory(containingClass.getProject()).createMethodFromText(buf.toString(), constructor != null ? constructor : containingClass); + } + + private static PsiTypeParameter[] getAllTypeParams(PsiTypeParameterListOwner listOwner, PsiClass containingClass) { + Set params = new LinkedHashSet(); + if (listOwner != null) { + Collections.addAll(params, listOwner.getTypeParameters()); + } + Collections.addAll(params, containingClass.getTypeParameters()); + return params.toArray(new PsiTypeParameter[params.size()]); + } + + + private static PsiSubstitutor inferTypeParametersForStaticFactory(@NotNull PsiMethod staticFactoryMethod, + PsiNewExpression expression, + PsiElement parent) { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject()); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters(); + final PsiExpressionList argumentList = expression.getArgumentList(); + final PsiExpression[] expressions = argumentList.getExpressions(); + return resolveHelper + .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, parent, false); + } + + 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; + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java index 96bf56509231..502055854d22 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java @@ -48,7 +48,7 @@ public class PsiDiamondTypeUtil { final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements(); if (typeElements.length > 0) { if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return false; - final PsiDiamondType.DiamondInferenceResult inferenceResult = PsiDiamondType.resolveInferredTypes(expression, context); + final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(expression, context); if (inferenceResult.getErrorMessage() == null) { final List types = inferenceResult.getInferredTypes(); PsiType[] typeArguments = null; @@ -115,7 +115,7 @@ public class PsiDiamondTypeUtil { text.append('<'); final PsiTypeElement[] typeElements = referenceParameterList.getTypeParameterElements(); final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(typeElements[0], PsiNewExpression.class); - final PsiDiamondType.DiamondInferenceResult result = PsiDiamondType.resolveInferredTypesNoCheck(newExpression, newExpression); + final PsiDiamondType.DiamondInferenceResult result = PsiDiamondTypeImpl.resolveInferredTypesNoCheck(newExpression, newExpression); text.append(StringUtil.join(result.getInferredTypes(), new Function() { @Override public String fun(PsiType psiType) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index 9ccdff9f15b5..972d8094cdde 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -131,7 +131,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl continue; } else if (elementType == JavaElementType.DIAMOND_TYPE) { - cachedType = new PsiDiamondType(getManager(), this); + cachedType = new PsiDiamondTypeImpl(getManager(), this); break; } else { diff --git a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java index 5e465057c8d4..54959a7faca8 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java @@ -336,7 +336,7 @@ public class InlineUtil { if (inferenceResult.getErrorMessage() == null) { final PsiElement copy = ref.copy(); final PsiElement parent = ref.replace(initializer); - final PsiDiamondType.DiamondInferenceResult result = PsiDiamondType.resolveInferredTypes((PsiNewExpression)initializer, parent); + final PsiDiamondType.DiamondInferenceResult result = PsiDiamondTypeImpl.resolveInferredTypes((PsiNewExpression)initializer, parent); ref = parent.replace(copy); if (!result.equals(inferenceResult)) { final String inferredTypeText = StringUtil.join(inferenceResult.getTypes(), diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 84a53ba6bd5c..feced7b2b25b 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -15,235 +15,17 @@ */ package com.intellij.psi; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -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; -import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.List; -/** - * User: anna - * Date: Jul 30, 2010 - */ -public class PsiDiamondType extends PsiType { - private final PsiManager myManager; - private final PsiTypeElement myTypeElement; - private static final Logger LOG = Logger.getInstance("#" + PsiDiamondType.class.getName()); - - public PsiDiamondType(PsiManager manager, PsiTypeElement psiTypeElement) { - super(PsiAnnotation.EMPTY_ARRAY); - myManager = manager; - myTypeElement = psiTypeElement; +public abstract class PsiDiamondType extends PsiType { + public PsiDiamondType(PsiAnnotation[] annotations) { + super(annotations); } - @Override - public String getPresentableText() { - return ""; - } - - @Override - public String getCanonicalText() { - return ""; - } - - @Override - public String getInternalCanonicalText() { - return "Diamond Type"; - } - - @Override - public boolean isValid() { - return false; - } - - @Override - public boolean equalsToText(@NonNls String text) { - return text != null && text.isEmpty(); - } - - @Override - public A accept(PsiTypeVisitor visitor) { - return visitor.visitType(this); - } - - @Override - public GlobalSearchScope getResolveScope() { - return GlobalSearchScope.allScope(myManager.getProject()); - } - - @NotNull - @Override - public PsiType[] getSuperTypes() { - return new PsiType[]{getJavaLangObject(myManager, getResolveScope())}; - } - - public DiamondInferenceResult resolveInferredTypes() { - final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(myTypeElement, PsiNewExpression.class); - if (newExpression == null) { - return PsiDiamondType.DiamondInferenceResult.NULL_RESULT; - } - - return resolveInferredTypes(newExpression); - } - - public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) { - return resolveInferredTypes(newExpression, newExpression); - } - - public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression, - PsiElement context) { - final PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass(); - if (anonymousClass != null) { - final PsiElement resolve = anonymousClass.getBaseClassReference().resolve(); - if (resolve instanceof PsiClass) { - return PsiDiamondType.DiamondInferenceResult.ANONYMOUS_INNER_RESULT; - } - } - - final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getChildOfType(newExpression, PsiReferenceParameterList.class); - if (referenceParameterList != null && referenceParameterList.getTypeParameterElements().length > 0) { - return DiamondInferenceResult.EXPLICIT_CONSTRUCTOR_TYPE_ARGS; - } - - return resolveInferredTypesNoCheck(newExpression, context); - } - - public static DiamondInferenceResult resolveInferredTypesNoCheck(PsiNewExpression newExpression, PsiElement context) { - final PsiClass psiClass = findClass(newExpression); - if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; - final PsiExpressionList argumentList = newExpression.getArgumentList(); - if (argumentList == null) return DiamondInferenceResult.NULL_RESULT; - final PsiMethod constructor = findConstructor(psiClass, newExpression); - PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass); - PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params); - if (staticFactory == null) { - return DiamondInferenceResult.NULL_RESULT; - } - final PsiSubstitutor inferredSubstitutor = inferTypeParametersForStaticFactory(staticFactory, newExpression, context); - final PsiTypeParameter[] parameters = staticFactory.getTypeParameters(); - final PsiTypeParameter[] classParameters = psiClass.getTypeParameters(); - final PsiJavaCodeReferenceElement classOrAnonymousClassReference = newExpression.getClassOrAnonymousClassReference(); - LOG.assertTrue(classOrAnonymousClassReference != null); - final DiamondInferenceResult - result = new DiamondInferenceResult(classOrAnonymousClassReference.getReferenceName() + "<>", newExpression.getProject()); - for (PsiTypeParameter parameter : parameters) { - for (PsiTypeParameter classParameter : classParameters) { - if (Comparing.strEqual(classParameter.getName(), parameter.getName())) { - result.addInferredType(inferredSubstitutor.substitute(parameter)); - break; - } - } - } - return result; - } - - - @Nullable - private static PsiMethod findConstructor(PsiClass containingClass, PsiNewExpression newExpression) { - final PsiExpressionList argumentList = newExpression.getArgumentList(); - final Project project = newExpression.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final JavaResolveResult result = - resolveHelper.resolveConstructor(facade.getElementFactory().createType(containingClass), argumentList, argumentList); - return (PsiMethod)result.getElement(); - } - - @Nullable - private static PsiClass findClass(PsiNewExpression newExpression) { - final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference(); - if (classReference != null) { - final String text = classReference.getReferenceName(); - if (text != null) { - final Project project = newExpression.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final PsiElement qualifierElement = classReference.getQualifier(); - final String qualifier = qualifierElement != null ? qualifierElement.getText() : ""; - return resolveHelper.resolveReferencedClass(StringUtil.getQualifiedName(qualifier, text), newExpression); - } else { - return null; - } - } - return null; - } - - @Nullable - private static PsiMethod generateStaticFactory(@Nullable PsiMethod constructor, PsiClass containingClass, PsiTypeParameter[] params) { - final StringBuilder buf = new StringBuilder(); - buf.append("public static "); - buf.append("<"); - buf.append(StringUtil.join(params, new Function() { - @Override - public String fun(PsiTypeParameter psiTypeParameter) { - return psiTypeParameter.getName(); - } - }, ", ")); - buf.append(">"); - - final String qualifiedName = containingClass.getQualifiedName(); - buf.append(qualifiedName != null ? qualifiedName : containingClass.getName()); - final PsiTypeParameter[] parameters = containingClass.getTypeParameters(); - buf.append("<"); - buf.append(StringUtil.join(parameters, new Function() { - @Override - public String fun(PsiTypeParameter psiTypeParameter) { - return psiTypeParameter.getName(); - } - }, ", ")); - buf.append("> "); - - String staticFactoryName = "staticFactory"; - final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(containingClass.getProject()); - staticFactoryName = styleManager.suggestUniqueVariableName(staticFactoryName, containingClass, false); - buf.append(staticFactoryName); - if (constructor == null) { - buf.append("()"); - } - else { - buf.append("(").append(StringUtil.join(constructor.getParameterList().getParameters(), new Function() { - int myIdx = 0; - @Override - public String fun(PsiParameter psiParameter) { - return psiParameter.getType().getCanonicalText() + " p" + myIdx++; - } - }, ",")).append(")"); - } - buf.append("{}"); - - return JavaPsiFacade.getElementFactory(containingClass.getProject()).createMethodFromText(buf.toString(), constructor != null ? constructor : containingClass); - } - - private static PsiTypeParameter[] getAllTypeParams(PsiTypeParameterListOwner listOwner, PsiClass containingClass) { - Set params = new LinkedHashSet(); - if (listOwner != null) { - Collections.addAll(params, listOwner.getTypeParameters()); - } - Collections.addAll(params, containingClass.getTypeParameters()); - return params.toArray(new PsiTypeParameter[params.size()]); - } - - - private static PsiSubstitutor inferTypeParametersForStaticFactory(@NotNull PsiMethod staticFactoryMethod, - PsiNewExpression expression, - PsiElement parent) { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject()); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters(); - final PsiExpressionList argumentList = expression.getArgumentList(); - final PsiExpression[] expressions = argumentList.getExpressions(); - return resolveHelper - .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, parent, false); - } + public abstract DiamondInferenceResult resolveInferredTypes(); public static class DiamondInferenceResult { public static final DiamondInferenceResult EXPLICIT_CONSTRUCTOR_TYPE_ARGS = new DiamondInferenceResult() { @@ -313,7 +95,7 @@ public class PsiDiamondType extends PsiType { public String getErrorMessage() { return myErrorMessage; } - + public boolean failedToInfer() { return myErrorMessage != null; } @@ -384,46 +166,4 @@ public class PsiDiamondType extends PsiType { return result; } } - - 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; - } }