void (final ReductionSystem system, final PsiElement element) { if (element instanceof PsiVariable) { final PsiExpression initializer = ((PsiVariable)element).getInitializer(); if (initializer != null) { final PsiExpression core = PsiUtil.deparenthesizeExpression(initializer); if (core instanceof PsiArrayInitializerExpression) { final PsiExpression[] inits = ((PsiArrayInitializerExpression)core).getInitializers(); final PsiType type = getType(element); for (PsiExpression init : inits) { system.addSubtypeConstraint(evaluateType(init, system).createArrayType(), type); } } else if (core instanceof PsiNewExpression) { final PsiArrayInitializerExpression init = ((PsiNewExpression)core).getArrayInitializer(); if (init != null) { final PsiExpression[] inits = init.getInitializers(); final PsiType type = getType(element); for (PsiExpression init1 : inits) { system.addSubtypeConstraint(evaluateType(init1, system).createArrayType(), type); } } system.addSubtypeConstraint(evaluateType(core, system), getType(element)); } else { system.addSubtypeConstraint(evaluateType(core, system), getType(element)); } } if (element instanceof PsiParameter parameter) { final PsiElement declarationScope = parameter.getDeclarationScope(); if (declarationScope instanceof PsiMethod method) { final PsiSearchHelper helper = PsiSearchHelper.getInstance(myManager.getProject()); SearchScope scope = getScope(helper, method); for (PsiReference ref : ReferencesSearch.search(method, scope, true)) { final PsiElement elt = ref.getElement(); final PsiCallExpression call = PsiTreeUtil.getParentOfType(elt, PsiCallExpression.class); if (call != null) { PsiExpressionList argList = call.getArgumentList(); if (argList != null) { PsiExpression[] args = argList.getExpressions(); int index = method.getParameterList().getParameterIndex(parameter); if (index < args.length) { system.addSubtypeConstraint(evaluateType(args[index], system), myTypes.get(element)); } } } } } else if (declarationScope instanceof PsiForeachStatement) { addForEachConstraint(system, (PsiForeachStatement)declarationScope); } } return; } else if (element instanceof PsiMethod) { final PsiType reType = getType(element); element.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitReturnStatement(final @NotNull PsiReturnStatement statement) { super.visitReturnStatement(statement); final PsiExpression retExpr = statement.getReturnValue(); if (retExpr != null) { system.addSubtypeConstraint(evaluateType(retExpr, system), reType); } } @Override public void visitClass(@NotNull PsiClass aClass) {} @Override public void visitLambdaExpression(@NotNull PsiLambdaExpression expression) {} }); return; } final PsiElement root = PsiTreeUtil.getParentOfType(element, PsiStatement.class, PsiField.class); if (root != null) { final PsiAnchor anchor = PsiAnchor.create(root); if (!myVisitedConstructions.contains(anchor)) { //return from lambda is processed inside visitReturnStatement //noinspection UnsafeReturnStatementVisitor root.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitAssignmentExpression(final @NotNull PsiAssignmentExpression expression) { super.visitAssignmentExpression(expression); system .addSubtypeConstraint(evaluateType(expression.getRExpression(), system), evaluateType(expression.getLExpression(), system)); } @Override public void visitConditionalExpression(final @NotNull PsiConditionalExpression expression) { super.visitConditionalExpression(expression); system.addSubtypeConstraint(evaluateType(expression.getThenExpression(), system), evaluateType(expression.getElseExpression(), system)); system.addSubtypeConstraint(evaluateType(expression.getElseExpression(), system), evaluateType(expression.getThenExpression(), system)); } @Override public void visitCallExpression(final @NotNull PsiCallExpression expression) { super.visitCallExpression(expression); evaluateType(expression, system); } @Override public void visitReturnStatement(final @NotNull PsiReturnStatement statement) { super.visitReturnStatement(statement); final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, true, PsiLambdaExpression.class); if (method != null) { system.addSubtypeConstraint(evaluateType(statement.getReturnValue(), system), getType(method)); } } @Override public void visitTypeCastExpression(final @NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); final PsiType operandType = evaluateType(expression.getOperand(), system); final PsiType castType = evaluateType(expression, system); if (operandType == null || castType == null) return; if (Util.bindsTypeVariables(operandType)) { system.addCast(expression, operandType); } if (operandType.getDeepComponentType() instanceof PsiTypeVariable || castType.getDeepComponentType() instanceof PsiTypeVariable) { system.addSubtypeConstraint(operandType, castType); } else { final PsiClassType.ClassResolveResult operandResult = Util.resolveType(operandType); final PsiClassType.ClassResolveResult castResult = Util.resolveType(castType); final PsiClass operandClass = operandResult.getElement(); final PsiClass castClass = castResult.getElement(); if (operandClass != null && castClass != null) { if (InheritanceUtil.isInheritorOrSelf(operandClass, castClass, true)) { system.addSubtypeConstraint(operandType, castType); } } } } @Override public void visitVariable(final @NotNull PsiVariable variable) { super.visitVariable(variable); final PsiExpression init = variable.getInitializer(); if (init != null) { system.addSubtypeConstraint(evaluateType(init, system), getType(variable)); } } @Override public void visitNewExpression(final @NotNull PsiNewExpression expression) { super.visitNewExpression(expression); final PsiArrayInitializerExpression init = expression.getArrayInitializer(); if (init != null) { final PsiExpression[] inits = init.getInitializers(); final PsiType type = getType(expression); for (PsiExpression init1 : inits) { system.addSubtypeConstraint(evaluateType(init1, system).createArrayType(), type); } } } @Override public void visitReferenceExpression(final @NotNull PsiReferenceExpression expression) { final PsiExpression qualifierExpression = expression.getQualifierExpression(); if (qualifierExpression != null) { qualifierExpression.accept(this); } } }); myVisitedConstructions.add(anchor); } } }