This commit is contained in:
Alexey Kudravtsev
2016-07-18 18:53:54 +03:00
parent f3d567744c
commit d16c32be21
@@ -39,7 +39,6 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.Stack;
@@ -155,7 +154,7 @@ public class ExpectedTypesProvider {
public static PsiType[] processExpectedTypes(@NotNull ExpectedTypeInfo[] infos,
@NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Project project) {
LinkedHashSet<PsiType> set = new LinkedHashSet<PsiType>();
LinkedHashSet<PsiType> set = new LinkedHashSet<>();
for (ExpectedTypeInfo info : infos) {
ExpectedTypeInfoImpl infoImpl = (ExpectedTypeInfoImpl)info;
@@ -193,7 +192,9 @@ public class ExpectedTypesProvider {
if (accepted != null) typeSet.add(accepted);
}
public static void processPrimitiveTypeAndSubtypes(@NotNull PsiPrimitiveType type, @NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Set<PsiType> set) {
private static void processPrimitiveTypeAndSubtypes(@NotNull PsiPrimitiveType type,
@NotNull PsiTypeVisitor<PsiType> visitor,
@NotNull Set<PsiType> set) {
if (type.equals(PsiType.BOOLEAN) || type.equals(PsiType.VOID) || type.equals(PsiType.NULL)) return;
for (int i = 0; ; i++) {
@@ -207,7 +208,7 @@ public class ExpectedTypesProvider {
if (type instanceof PsiPrimitiveType) {
if (type.equals(PsiType.BOOLEAN) || type.equals(PsiType.VOID) || type.equals(PsiType.NULL)) return;
Stack<PsiType> stack = new Stack<PsiType>();
Stack<PsiType> stack = new Stack<>();
for (int i = PRIMITIVE_TYPES.length - 1; !PRIMITIVE_TYPES[i].equals(type); i--) {
stack.push(PRIMITIVE_TYPES[i]);
}
@@ -266,7 +267,7 @@ public class ExpectedTypesProvider {
parent.accept(visitor);
for (final ExpectedTypeInfo info : visitor.myResult) {
myResult.add(createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailTypes.RPARENTH, info.getCalledMethod(),
() -> ((ExpectedTypeInfoImpl)info).getExpectedName()));
((ExpectedTypeInfoImpl)info)::getExpectedName));
}
}
}
@@ -284,7 +285,7 @@ public class ExpectedTypesProvider {
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
if (myForCompletion) {
final MyParentVisitor visitor = new MyParentVisitor(expression, myForCompletion, myClassProvider, myVoidable, myUsedAfter);
final MyParentVisitor visitor = new MyParentVisitor(expression, true, myClassProvider, myVoidable, myUsedAfter);
expression.getParent().accept(visitor);
myResult.addAll(visitor.myResult);
return;
@@ -315,12 +316,14 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
myExpr = (PsiExpression)myExpr.getParent();
expression.getParent().accept(this);
}
@Override public void visitAnnotationArrayInitializer(@NotNull PsiArrayInitializerMemberValue initializer) {
@Override
public void visitAnnotationArrayInitializer(@NotNull PsiArrayInitializerMemberValue initializer) {
PsiElement parent = initializer.getParent();
while (parent instanceof PsiArrayInitializerMemberValue) {
parent = parent.getParent();
@@ -338,7 +341,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitNameValuePair(@NotNull PsiNameValuePair pair) {
@Override
public void visitNameValuePair(@NotNull PsiNameValuePair pair) {
final PsiType type = getAnnotationMethodType(pair);
if (type == null) return;
if (type instanceof PsiArrayType) {
@@ -373,7 +377,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitReturnStatement(PsiReturnStatement statement) {
@Override
public void visitReturnStatement(PsiReturnStatement statement) {
final PsiMethod method;
final PsiType type;
final boolean tailTypeSemicolon;
@@ -414,19 +419,23 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitIfStatement(PsiIfStatement statement) {
@Override
public void visitIfStatement(PsiIfStatement statement) {
myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.IF_RPARENTH));
}
@Override public void visitWhileStatement(PsiWhileStatement statement) {
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH));
}
@Override public void visitDoWhileStatement(PsiDoWhileStatement statement) {
@Override
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH));
}
@Override public void visitForStatement(@NotNull PsiForStatement statement) {
@Override
public void visitForStatement(@NotNull PsiForStatement statement) {
if (myExpr.equals(statement.getCondition())) {
myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.SEMICOLON));
}
@@ -443,7 +452,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
@Override
public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
if (myExpr.equals(statement.getIteratedValue())) {
PsiType type = statement.getIterationParameter().getType();
@@ -455,7 +465,7 @@ public class ExpectedTypesProvider {
PsiClass iterableClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Iterable", statement.getResolveScope());
if (iterableClass != null && iterableClass.getTypeParameters().length == 1) {
Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
Map<PsiTypeParameter, PsiType> map = new HashMap<>();
map.put(iterableClass.getTypeParameters()[0], PsiWildcardType.createExtends(manager, type));
PsiType iterableType = factory.createType(iterableClass, factory.createSubstitutor(map));
myResult.add(createInfoImpl(iterableType, iterableType));
@@ -463,7 +473,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
@Override
public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
myResult.add(createInfoImpl(PsiType.LONG, PsiType.INT));
if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
return;
@@ -488,19 +499,22 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) {
@Override
public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) {
PsiElementFactory factory = JavaPsiFacade.getInstance(statement.getProject()).getElementFactory();
PsiType objectType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, myExpr.getResolveScope());
myResult.add(createInfoImpl(objectType, objectType));
}
@Override public void visitVariable(@NotNull PsiVariable variable) {
@Override
public void visitVariable(@NotNull PsiVariable variable) {
PsiType type = variable.getType();
TailType tail = variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON;
myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tail, null, getPropertyName(variable)));
}
@Override public void visitAssignmentExpression(@NotNull PsiAssignmentExpression assignment) {
@Override
public void visitAssignmentExpression(@NotNull PsiAssignmentExpression assignment) {
if (myExpr.equals(assignment.getRExpression())) {
PsiExpression lExpr = assignment.getLExpression();
PsiType type = lExpr.getType();
@@ -542,6 +556,7 @@ public class ExpectedTypesProvider {
}
}
@NotNull
private static TailType getAssignmentRValueTailType(@NotNull PsiAssignmentExpression assignment) {
if (assignment.getParent() instanceof PsiExpressionStatement) {
if (!(assignment.getParent().getParent() instanceof PsiForStatement)) {
@@ -556,7 +571,8 @@ public class ExpectedTypesProvider {
return TailType.NONE;
}
@Override public void visitExpressionList(@NotNull PsiExpressionList list) {
@Override
public void visitExpressionList(@NotNull PsiExpressionList list) {
PsiResolveHelper helper = JavaPsiFacade.getInstance(list.getProject()).getResolveHelper();
PsiElement parent = list.getParent();
if (parent instanceof PsiMethodCallExpression) {
@@ -590,7 +606,7 @@ public class ExpectedTypesProvider {
final JavaResolveResult[] candidates = PsiDiamondTypeImpl.collectStaticFactories(newExpr, DuplicateConflictResolver.INSTANCE);
if (candidates != null) {
final PsiExpressionList argumentList = newExpr.getArgumentList();
Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(ContainerUtil.map(candidates, (candidate) -> (CandidateInfo)candidate, CandidateInfo.EMPTY_ARRAY), argumentList, myExpr, myForCompletion));
Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(ContainerUtil.map(candidates, candidate -> (CandidateInfo)candidate, CandidateInfo.EMPTY_ARRAY), argumentList, myExpr, myForCompletion));
}
return;
}
@@ -618,7 +634,7 @@ public class ExpectedTypesProvider {
private void getExpectedTypesForConstructorCall(@NotNull final PsiClass referencedClass,
@NotNull final PsiExpressionList argumentList,
final PsiSubstitutor substitutor) {
List<CandidateInfo> array = new ArrayList<CandidateInfo>();
List<CandidateInfo> array = new ArrayList<>();
for (PsiMethod constructor : referencedClass.getConstructors()) {
array.add(new MethodCandidateInfo(constructor, substitutor, false, false, argumentList, null, argumentList.getExpressionTypes(), null));
}
@@ -633,7 +649,7 @@ public class ExpectedTypesProvider {
if (index < 0) return; // broken syntax
if (myForCompletion && index == 0) {
final MyParentVisitor visitor = new MyParentVisitor(expr, myForCompletion, myClassProvider, myVoidable, myUsedAfter);
final MyParentVisitor visitor = new MyParentVisitor(expr, true, myClassProvider, myVoidable, myUsedAfter);
myExpr = (PsiExpression)myExpr.getParent();
expr.getParent().accept(visitor);
myResult.addAll(visitor.myResult);
@@ -641,7 +657,7 @@ public class ExpectedTypesProvider {
for (int i = 0; i < myResult.size(); i++) {
final ExpectedTypeInfo info = myResult.get(i);
myResult.set(i, createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.NONE, info.getCalledMethod(),
() -> ((ExpectedTypeInfoImpl)info).getExpectedName()
((ExpectedTypeInfoImpl)info)::getExpectedName
));
}
}
@@ -802,7 +818,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitNewExpression(@NotNull PsiNewExpression expression) {
@Override
public void visitNewExpression(@NotNull PsiNewExpression expression) {
PsiExpression[] arrayDimensions = expression.getArrayDimensions();
for (PsiExpression dimension : arrayDimensions) {
if (myExpr.equals(dimension)) {
@@ -812,7 +829,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expr) {
@Override
public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expr) {
if (myExpr.equals(expr.getIndexExpression())) {
myResult.add(createInfoImpl(PsiType.INT, PsiType.INT));
}
@@ -824,7 +842,7 @@ public class ExpectedTypesProvider {
}
PsiElement parent = expr.getParent();
MyParentVisitor visitor = new MyParentVisitor(expr, myForCompletion, myClassProvider, myVoidable, myUsedAfter);
MyParentVisitor visitor = new MyParentVisitor(expr, false, myClassProvider, myVoidable, myUsedAfter);
myExpr = (PsiExpression)myExpr.getParent();
parent.accept(visitor);
ExpectedTypeInfo[] componentTypeInfo = visitor.getResult();
@@ -832,8 +850,7 @@ public class ExpectedTypesProvider {
myResult.addAll(anyArrayType());
}
else {
for (int i = 0; i < componentTypeInfo.length; i++) {
ExpectedTypeInfo compInfo = componentTypeInfo[i];
for (ExpectedTypeInfo compInfo : componentTypeInfo) {
PsiType expectedArrayType = compInfo.getType().createArrayType();
myResult.add(createInfoImpl(expectedArrayType, expectedArrayType));
}
@@ -841,7 +858,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitConditionalExpression(@NotNull PsiConditionalExpression expr) {
@Override
public void visitConditionalExpression(@NotNull PsiConditionalExpression expr) {
if (myExpr.equals(expr.getCondition())) {
if (myForCompletion) {
myExpr = expr;
@@ -856,7 +874,7 @@ public class ExpectedTypesProvider {
for (int i = 0; i < types.length; i++) {
final ExpectedTypeInfo info = types[i];
types[i] = createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.COND_EXPR_COLON, info.getCalledMethod(),
() -> ((ExpectedTypeInfoImpl)info).getExpectedName());
((ExpectedTypeInfoImpl)info)::getExpectedName);
}
Collections.addAll(myResult, types);
}
@@ -868,7 +886,8 @@ public class ExpectedTypesProvider {
}
}
@Override public void visitThrowStatement(@NotNull PsiThrowStatement statement) {
@Override
public void visitThrowStatement(@NotNull PsiThrowStatement statement) {
if (statement.getException() == myExpr) {
PsiManager manager = statement.getManager();
PsiType throwableType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Throwable", myExpr.getResolveScope());
@@ -889,20 +908,19 @@ public class ExpectedTypesProvider {
throwsTypes = new PsiClassType[]{exceptionType};
}
for (int i = 0; i < throwsTypes.length; i++) {
for (PsiType throwsType : throwsTypes) {
myResult.add(createInfoImpl(
myExpr instanceof PsiTypeCastExpression && myForCompletion ?
throwsTypes[i] :
throwableType,
myExpr instanceof PsiTypeCastExpression && myForCompletion ? throwsType : throwableType,
ExpectedTypeInfo.TYPE_OR_SUBTYPE,
throwsTypes[i],
throwsType,
TailType.SEMICOLON
));
}
}
}
@Override public void visitCodeFragment(@NotNull JavaCodeFragment codeFragment) {
@Override
public void visitCodeFragment(@NotNull JavaCodeFragment codeFragment) {
if (codeFragment instanceof PsiExpressionCodeFragment) {
final PsiType type = ((PsiExpressionCodeFragment)codeFragment).getExpectedType();
if (type != null) {
@@ -924,7 +942,7 @@ public class ExpectedTypesProvider {
? PsiTreeUtil.getParentOfType(argument, PsiMethod.class) : null;
PsiResolveHelper helper = JavaPsiFacade.getInstance(myExpr.getProject()).getResolveHelper();
List<CandidateInfo> methodCandidates = new ArrayList<CandidateInfo>();
List<CandidateInfo> methodCandidates = new ArrayList<>();
for (CandidateInfo candidate : allCandidates) {
PsiElement element = candidate.getElement();
if (element instanceof PsiMethod && helper.isAccessible((PsiMember)element, argumentList, null) && element != toExclude) {
@@ -950,7 +968,7 @@ public class ExpectedTypesProvider {
ParameterTypeInferencePolicy policy = forCompletion ? CompletionParameterTypeInferencePolicy.INSTANCE : DefaultParameterTypeInferencePolicy.INSTANCE;
Set<ExpectedTypeInfo> array = new LinkedHashSet<ExpectedTypeInfo>();
Set<ExpectedTypeInfo> array = new LinkedHashSet<>();
for (CandidateInfo candidateInfo : methodCandidates) {
PsiMethod method = (PsiMethod)candidateInfo.getElement();
PsiSubstitutor substitutor;
@@ -958,7 +976,7 @@ public class ExpectedTypesProvider {
final MethodCandidateInfo info = (MethodCandidateInfo)candidateInfo;
substitutor = MethodCandidateInfo.ourOverloadGuard
.doPreventingRecursion(argumentList, false, () -> info.inferTypeArguments(policy, args, true));
if (!info.isStaticsScopeCorrect() && method != null && !method.hasModifierProperty(PsiModifier.STATIC)) continue;
if (!info.isStaticsScopeCorrect() && !method.hasModifierProperty(PsiModifier.STATIC)) continue;
}
else {
substitutor = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(argumentList, false, candidateInfo::getSubstitutor);
@@ -1208,7 +1226,7 @@ public class ExpectedTypesProvider {
final PsiManager manager = methodCallExpr.getManager();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
final PsiMethod[] methods = myClassProvider.findDeclaredMethods(reference.getManager(), reference.getReferenceName());
Set<ExpectedTypeInfo> types = new THashSet<ExpectedTypeInfo>();
Set<ExpectedTypeInfo> types = new THashSet<>();
for (PsiMethod method : methods) {
final PsiClass aClass = method.getContainingClass();
if (aClass == null || !facade.getResolveHelper().isAccessible(method, reference, aClass)) continue;
@@ -1231,7 +1249,7 @@ public class ExpectedTypesProvider {
private ExpectedTypeInfo[] findClassesWithDeclaredField(@NotNull PsiReferenceExpression expression) {
final JavaPsiFacade facade = JavaPsiFacade.getInstance(expression.getProject());
PsiField[] fields = myClassProvider.findDeclaredFields(expression.getManager(), expression.getReferenceName());
List<ExpectedTypeInfo> types = new ArrayList<ExpectedTypeInfo>();
List<ExpectedTypeInfo> types = new ArrayList<>();
for (PsiField field : fields) {
final PsiClass aClass = field.getContainingClass();
if (aClass == null || !facade.getResolveHelper().isAccessible(field, expression, aClass)) continue;