PsiVariable (@NotNull PsiMethod method, @NotNull PsiVariable castedVar, @NotNull PsiTypeCastExpression expression) { if (InstanceOfUtils.isUncheckedCast(expression)) return null; PsiTypeElement expressionCastType = expression.getCastType(); if (expressionCastType == null) return null; final PsiCodeBlock methodBody = method.getBody(); if (methodBody == null) return null; final TextRange expressionTextRange = expression.getTextRange(); if (expressionTextRange == null) return null; PsiExpression operand = PsiUtil.skipParenthesizedExprDown(expression.getOperand()); if (operand == null) return null; PsiType castType = expressionCastType.getType(); List<PsiTypeCastExpression> found = SyntaxTraverser.psiTraverser(method) .filter(PsiTypeCastExpression.class) .filter(cast -> EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(cast.getOperand(), operand)) .filter(cast -> { PsiTypeElement typeElement = cast.getCastType(); return typeElement != null && InstanceOfUtils.typeCompatible(typeElement.getType(), castType, operand); }) .toList(); PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(method.getProject()); for (PsiTypeCastExpression occurrence : found) { if (!isAtRightLocation(expression, expressionTextRange, occurrence)) continue; final PsiLocalVariable variable = getVariable(occurrence); if (variable != null && resolveHelper.resolveReferencedVariable(variable.getName(), expression) == variable && !isChangedBetween(castedVar, methodBody, occurrence, expression) && !isChangedBetween(variable, methodBody, occurrence, expression)) { return variable; } } PsiInstanceOfExpression instanceOf = InstanceOfUtils.findPatternCandidate(expression); if (instanceOf != null) { PsiPattern pattern = instanceOf.getPattern(); PsiPatternVariable patternVariable = JavaPsiPatternUtil.getPatternVariable(pattern); if (patternVariable != null && !isChangedBetween(castedVar, methodBody, instanceOf, expression) && !isChangedBetween(patternVariable, methodBody, instanceOf, expression)) { return patternVariable; } } List<PsiAssignmentExpression> narrowVariables = SyntaxTraverser.psiTraverser(method) .filter(PsiAssignmentExpression.class) .filter(assignment -> EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(assignment.getLExpression(), operand)) .filter(assignment -> { PsiExpression narrowVariable = assignment.getRExpression(); return narrowVariable != null && narrowVariable.getType() != null && InstanceOfUtils.typeCompatible(narrowVariable.getType(), castType, operand); }) .toList(); for (PsiAssignmentExpression narrowVariable : narrowVariables) { if (!isAtRightLocation(expression, expressionTextRange, narrowVariable)) continue; final PsiLocalVariable declaration = getVariable(narrowVariable); if (declaration != null && resolveHelper.resolveReferencedVariable(declaration.getName(), expression) == declaration && !isChangedBetween(castedVar, methodBody, narrowVariable, expression) && !isChangedBetween(declaration, methodBody, narrowVariable, expression)) { return declaration; } } if (!(operand instanceof PsiReferenceExpression wideReferenceExpression) || !(wideReferenceExpression.resolve() instanceof PsiLocalVariable wideVariable)) return null; PsiExpression narrowExpression = wideVariable.getInitializer(); if (!(narrowExpression instanceof PsiReferenceExpression narrowReferenceExpression) || !(narrowReferenceExpression.resolve() instanceof PsiVariable narrowVariable) || narrowExpression.getType() == null || !InstanceOfUtils.typeCompatible(narrowExpression.getType(), castType, operand)) return null; if (!isAtRightLocation(expression, expressionTextRange, narrowExpression)) return null; if (narrowVariable.getName() == null || resolveHelper.resolveReferencedVariable(narrowVariable.getName(), expression) != narrowVariable || isChangedBetween(castedVar, methodBody, narrowExpression, expression) || isChangedBetween(narrowVariable, methodBody, narrowExpression, expression)) return null; return narrowVariable; }