private void analyzeDfaWithNestedClosures(
      PsiElement scope,
      ProblemsHolder holder,
      StandardDataFlowRunner dfaRunner,
      Collection<DfaMemoryState> initialStates) {
    final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor(dfaRunner);
    final RunnerResult rc =
        dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
    if (rc == RunnerResult.OK) {
      createDescription(dfaRunner, holder, visitor);

      MultiMap<PsiElement, DfaMemoryState> nestedClosures = dfaRunner.getNestedClosures();
      for (PsiElement closure : nestedClosures.keySet()) {
        analyzeDfaWithNestedClosures(closure, holder, dfaRunner, nestedClosures.get(closure));
      }
    } else if (rc == RunnerResult.TOO_COMPLEX) {
      if (scope.getParent() instanceof PsiMethod) {
        PsiMethod method = (PsiMethod) scope.getParent();
        final PsiIdentifier name = method.getNameIdentifier();
        if (name != null) { // Might be null for synthetic methods like JSP page.
          holder.registerProblem(
              name,
              InspectionsBundle.message("dataflow.too.complex"),
              ProblemHighlightType.WEAK_WARNING);
        }
      }
    }
  }
 public TextRange getTextRangeForNavigation() {
   TextRange textRange = getTextRange();
   if (textRange == null) return null;
   PsiElement element = getPsiElement();
   return InjectedLanguageManager.getInstance(element.getProject())
       .injectedToHost(element, textRange);
 }
 private void handleBranchingInstruction(
     ProblemsHolder holder,
     StandardInstructionVisitor visitor,
     Set<Instruction> trueSet,
     Set<Instruction> falseSet,
     HashSet<PsiElement> reportedAnchors,
     BranchingInstruction instruction,
     final boolean onTheFly) {
   PsiElement psiAnchor = instruction.getPsiAnchor();
   boolean underBinary = isAtRHSOfBooleanAnd(psiAnchor);
   if (instruction instanceof InstanceofInstruction
       && visitor.isInstanceofRedundant((InstanceofInstruction) instruction)) {
     if (visitor.canBeNull((BinopInstruction) instruction)) {
       holder.registerProblem(
           psiAnchor,
           InspectionsBundle.message("dataflow.message.redundant.instanceof"),
           new RedundantInstanceofFix());
     } else {
       final LocalQuickFix localQuickFix = createSimplifyBooleanExpressionFix(psiAnchor, true);
       holder.registerProblem(
           psiAnchor,
           InspectionsBundle.message(
               underBinary
                   ? "dataflow.message.constant.condition.when.reached"
                   : "dataflow.message.constant.condition",
               Boolean.toString(true)),
           localQuickFix == null ? null : new LocalQuickFix[] {localQuickFix});
     }
   } else if (psiAnchor instanceof PsiSwitchLabelStatement) {
     if (falseSet.contains(instruction)) {
       holder.registerProblem(
           psiAnchor, InspectionsBundle.message("dataflow.message.unreachable.switch.label"));
     }
   } else if (psiAnchor != null
       && !reportedAnchors.contains(psiAnchor)
       && !isFlagCheck(psiAnchor)) {
     boolean evaluatesToTrue = trueSet.contains(instruction);
     final PsiElement parent = psiAnchor.getParent();
     if (parent instanceof PsiAssignmentExpression
         && ((PsiAssignmentExpression) parent).getLExpression() == psiAnchor) {
       holder.registerProblem(
           psiAnchor,
           InspectionsBundle.message(
               "dataflow.message.pointless.assignment.expression",
               Boolean.toString(evaluatesToTrue)),
           createConditionalAssignmentFixes(
               evaluatesToTrue, (PsiAssignmentExpression) parent, onTheFly));
     } else if (!skipReportingConstantCondition(visitor, psiAnchor, evaluatesToTrue)) {
       final LocalQuickFix fix = createSimplifyBooleanExpressionFix(psiAnchor, evaluatesToTrue);
       String message =
           InspectionsBundle.message(
               underBinary
                   ? "dataflow.message.constant.condition.when.reached"
                   : "dataflow.message.constant.condition",
               Boolean.toString(evaluatesToTrue));
       holder.registerProblem(psiAnchor, message, fix == null ? null : new LocalQuickFix[] {fix});
     }
     reportedAnchors.add(psiAnchor);
   }
 }
 protected void assertPhysical(final PsiElement element) {
   if (!element.isPhysical()) {
     LOG.error(
         "Non-physical PsiElement. Physical element is required to be able to anchor the problem in the source tree: "
             + element
             + "; file: "
             + element.getContainingFile());
   }
 }
  @Nullable
  private ProblemDescriptor createDescription(
      @NotNull PsiTypeCastExpression cast, @NotNull InspectionManager manager, boolean onTheFly) {
    PsiExpression operand = cast.getOperand();
    PsiTypeElement castType = cast.getCastType();
    if (operand == null || castType == null) return null;
    PsiElement parent = cast.getParent();
    while (parent instanceof PsiParenthesizedExpression) {
      parent = parent.getParent();
    }
    if (parent instanceof PsiReferenceExpression) {
      if (IGNORE_ANNOTATED_METHODS) {
        final PsiElement gParent = parent.getParent();
        if (gParent instanceof PsiMethodCallExpression) {
          final PsiMethod psiMethod = ((PsiMethodCallExpression) gParent).resolveMethod();
          if (psiMethod != null && NullableNotNullManager.isNotNull(psiMethod)) {
            final PsiClass superClass = PsiUtil.resolveClassInType(operand.getType());
            final PsiClass containingClass = psiMethod.getContainingClass();
            if (containingClass != null
                && superClass != null
                && containingClass.isInheritor(superClass, true)) {
              for (PsiMethod method : psiMethod.findSuperMethods(superClass)) {
                if (NullableNotNullManager.isNullable(method)) {
                  return null;
                }
              }
            }
          }
        }
      }
    } else if (parent instanceof PsiExpressionList) {
      final PsiElement gParent = parent.getParent();
      if (gParent instanceof PsiMethodCallExpression && IGNORE_SUSPICIOUS_METHOD_CALLS) {
        final String message =
            SuspiciousCollectionsMethodCallsInspection.getSuspiciousMethodCallMessage(
                (PsiMethodCallExpression) gParent,
                operand.getType(),
                true,
                new ArrayList<PsiMethod>(),
                new IntArrayList());
        if (message != null) {
          return null;
        }
      }
    }

    String message =
        InspectionsBundle.message(
            "inspection.redundant.cast.problem.descriptor",
            "<code>" + operand.getText() + "</code>",
            "<code>#ref</code> #loc");
    return manager.createProblemDescriptor(
        castType, message, myQuickFixAction, ProblemHighlightType.LIKE_UNUSED_SYMBOL, onTheFly);
  }
 @Override
 public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
   if (!FileModificationService.getInstance()
       .preparePsiElementForWrite(descriptor.getPsiElement())) return;
   PsiElement castTypeElement = descriptor.getPsiElement();
   PsiTypeCastExpression cast =
       castTypeElement == null ? null : (PsiTypeCastExpression) castTypeElement.getParent();
   if (cast != null) {
     RedundantCastUtil.removeCast(cast);
   }
 }
 private static SimplifyBooleanExpressionFix createIntention(PsiElement element, boolean value) {
   if (!(element instanceof PsiExpression)) return null;
   final PsiExpression expression = (PsiExpression) element;
   while (element.getParent() instanceof PsiExpression) {
     element = element.getParent();
   }
   final SimplifyBooleanExpressionFix fix = new SimplifyBooleanExpressionFix(expression, value);
   // simplify intention already active
   if (!fix.isAvailable()
       || SimplifyBooleanExpressionFix.canBeSimplified((PsiExpression) element)) {
     return null;
   }
   return fix;
 }
 @Override
 public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
   PsiElement element = descriptor.getStartElement();
   if (!(element instanceof PsiLoopStatement)) return;
   PsiLoopStatement loop = (PsiLoopStatement) element;
   IteratorDeclaration declaration;
   declaration = IteratorDeclaration.fromLoop(loop);
   if (declaration == null) return;
   PsiStatement body = loop.getBody();
   if (!(body instanceof PsiBlockStatement)) return;
   PsiStatement[] statements = ((PsiBlockStatement) body).getCodeBlock().getStatements();
   PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
   String replacement = null;
   CommentTracker ct = new CommentTracker();
   if (statements.length == 2 && statements[1] instanceof PsiIfStatement) {
     PsiVariable variable = declaration.getNextElementVariable(statements[0]);
     if (variable == null) return;
     PsiExpression condition = ((PsiIfStatement) statements[1]).getCondition();
     if (condition == null) return;
     replacement = generateRemoveIf(declaration, ct, condition, variable.getName());
   } else if (statements.length == 1 && statements[0] instanceof PsiIfStatement) {
     PsiExpression condition = ((PsiIfStatement) statements[0]).getCondition();
     if (condition == null) return;
     PsiElement ref = declaration.findOnlyIteratorRef(condition);
     if (ref != null) {
       PsiElement call = ref.getParent().getParent();
       if (!declaration.isIteratorMethodCall(call, "next")) return;
       PsiType type = ((PsiExpression) call).getType();
       JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
       SuggestedNameInfo info =
           javaCodeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type);
       if (info.names.length == 0) {
         info =
             javaCodeStyleManager.suggestVariableName(
                 VariableKind.PARAMETER, "value", null, type);
       }
       String paramName =
           javaCodeStyleManager.suggestUniqueVariableName(info, condition, true).names[0];
       ct.replace(call, factory.createIdentifier(paramName));
       replacement = generateRemoveIf(declaration, ct, condition, paramName);
     }
   }
   if (replacement == null) return;
   ct.delete(declaration.getIterator());
   PsiElement result = ct.replaceAndRestoreComments(loop, replacement);
   LambdaCanBeMethodReferenceInspection.replaceAllLambdasWithMethodReferences(result);
   CodeStyleManager.getInstance(project).reformat(result);
 }
  private static boolean isAtRHSOfBooleanAnd(PsiElement expr) {
    PsiElement cur = expr;

    while (cur != null && !(cur instanceof PsiMember)) {
      PsiElement parent = cur.getParent();

      if (parent instanceof PsiBinaryExpression
          && cur == ((PsiBinaryExpression) parent).getROperand()) {
        return true;
      }

      cur = parent;
    }

    return false;
  }
  private static void checkMethodCall(RefElement refWhat, final PsiElement element) {
    if (!(refWhat instanceof RefMethod)) return;
    final RefMethod refMethod = (RefMethod) refWhat;
    final PsiElement psiElement = refMethod.getElement();
    if (!(psiElement instanceof PsiMethod)) return;
    final PsiMethod psiMethod = (PsiMethod) psiElement;
    if (!PsiType.BOOLEAN.equals(psiMethod.getReturnType())) return;
    element.accept(
        new JavaRecursiveElementWalkingVisitor() {
          @Override
          public void visitMethodCallExpression(PsiMethodCallExpression call) {
            super.visitMethodCallExpression(call);
            final PsiReferenceExpression methodExpression = call.getMethodExpression();
            if (methodExpression.isReferenceTo(psiMethod)) {
              if (isInvertedMethodCall(methodExpression)) return;
              refMethod.putUserData(ALWAYS_INVERTED, Boolean.FALSE);
            }
          }

          @Override
          public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
            super.visitMethodReferenceExpression(expression);
            if (expression.isReferenceTo(psiElement)) {
              refMethod.putUserData(ALWAYS_INVERTED, Boolean.FALSE);
            }
          }
        });
  }
  private void reportNullableReturns(
      DataFlowInstructionVisitor visitor,
      ProblemsHolder holder,
      Set<PsiElement> reportedAnchors,
      @NotNull PsiElement block) {
    final PsiMethod method = getScopeMethod(block);
    if (method == null || NullableStuffInspectionBase.isNullableNotInferred(method, true)) return;

    boolean notNullRequired = NullableNotNullManager.isNotNull(method);
    if (!notNullRequired && !SUGGEST_NULLABLE_ANNOTATIONS) return;

    PsiType returnType = method.getReturnType();
    // no warnings in void lambdas, where the expression is not returned anyway
    if (block instanceof PsiExpression
        && block.getParent() instanceof PsiLambdaExpression
        && returnType == PsiType.VOID) return;

    // no warnings for Void methods, where only null can be possibly returned
    if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return;

    for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) {
      assert statement instanceof PsiExpression;
      final PsiExpression expr = (PsiExpression) statement;
      if (!reportedAnchors.add(expr)) continue;

      if (notNullRequired) {
        final String text =
            isNullLiteralExpression(expr)
                ? InspectionsBundle.message("dataflow.message.return.null.from.notnull")
                : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull");
        holder.registerProblem(expr, text);
      } else if (AnnotationUtil.isAnnotatingApplicable(statement)) {
        final NullableNotNullManager manager =
            NullableNotNullManager.getInstance(expr.getProject());
        final String defaultNullable = manager.getDefaultNullable();
        final String presentableNullable = StringUtil.getShortName(defaultNullable);
        final String text =
            isNullLiteralExpression(expr)
                ? InspectionsBundle.message(
                    "dataflow.message.return.null.from.notnullable", presentableNullable)
                : InspectionsBundle.message(
                    "dataflow.message.return.nullable.from.notnullable", presentableNullable);
        final LocalQuickFix[] fixes =
            PsiTreeUtil.getParentOfType(expr, PsiMethod.class, PsiLambdaExpression.class)
                    instanceof PsiLambdaExpression
                ? LocalQuickFix.EMPTY_ARRAY
                : new LocalQuickFix[] {
                  new AnnotateMethodFix(
                      defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) {
                    @Override
                    public int shouldAnnotateBaseMethod(
                        PsiMethod method, PsiMethod superMethod, Project project) {
                      return 1;
                    }
                  }
                };
        holder.registerProblem(expr, text, fixes);
      }
    }
  }
  private static boolean isCompileConstantInIfCondition(PsiElement element) {
    if (!(element instanceof PsiReferenceExpression)) return false;
    PsiElement resolved = ((PsiReferenceExpression) element).resolve();
    if (!(resolved instanceof PsiField)) return false;
    PsiField field = (PsiField) resolved;

    if (!field.hasModifierProperty(PsiModifier.FINAL)) return false;
    if (!field.hasModifierProperty(PsiModifier.STATIC)) return false;

    PsiElement parent = element.getParent();
    if (parent instanceof PsiPrefixExpression
        && ((PsiPrefixExpression) parent).getOperationTokenType() == JavaTokenType.EXCL) {
      element = parent;
      parent = parent.getParent();
    }
    return parent instanceof PsiIfStatement && ((PsiIfStatement) parent).getCondition() == element;
  }
 private static boolean onTheLeftSideOfConditionalAssignment(final PsiElement psiAnchor) {
   final PsiElement parent = psiAnchor.getParent();
   if (parent instanceof PsiAssignmentExpression) {
     final PsiAssignmentExpression expression = (PsiAssignmentExpression) parent;
     if (expression.getLExpression() == psiAnchor) return true;
   }
   return false;
 }
 @Nullable
 private static PsiMethod getScopeMethod(PsiElement block) {
   PsiElement parent = block.getParent();
   if (parent instanceof PsiMethod) return (PsiMethod) parent;
   if (parent instanceof PsiLambdaExpression)
     return LambdaUtil.getFunctionalInterfaceMethod(
         ((PsiLambdaExpression) parent).getFunctionalInterfaceType());
   return null;
 }
 public int getLineNumber() {
   if (myLineNumber == -1) {
     PsiElement psiElement = getPsiElement();
     if (psiElement == null) return -1;
     if (!psiElement.isValid()) return -1;
     LOG.assertTrue(psiElement.isPhysical());
     PsiFile containingFile = InjectedLanguageUtil.getTopLevelFile(psiElement);
     Document document =
         PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile);
     if (document == null) return -1;
     TextRange textRange = getTextRange();
     if (textRange == null) return -1;
     textRange =
         InjectedLanguageManager.getInstance(containingFile.getProject())
             .injectedToHost(psiElement, textRange);
     myLineNumber = document.getLineNumber(textRange.getStartOffset()) + 1;
   }
   return myLineNumber;
 }
 @Override
 public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
   if (!FileModificationService.getInstance()
       .preparePsiElementForWrite(descriptor.getPsiElement())) return;
   final PsiElement psiElement = descriptor.getPsiElement();
   if (psiElement instanceof PsiInstanceOfExpression) {
     try {
       final PsiExpression compareToNull =
           JavaPsiFacade.getInstance(psiElement.getProject())
               .getElementFactory()
               .createExpressionFromText(
                   ((PsiInstanceOfExpression) psiElement).getOperand().getText() + " != null",
                   psiElement.getParent());
       psiElement.replace(compareToNull);
     } catch (IncorrectOperationException e) {
       LOG.error(e);
     }
   }
 }
  public TextRange getTextRange() {
    PsiElement startElement = getStartElement();
    PsiElement endElement = myEndSmartPointer == null ? startElement : getEndElement();
    if (startElement == null || endElement == null) {
      return null;
    }

    TextRange textRange = startElement.getTextRange();
    if (startElement == endElement) {
      if (isAfterEndOfLine())
        return new TextRange(textRange.getEndOffset(), textRange.getEndOffset());
      if (myTextRangeInElement != null) {
        return new TextRange(
            textRange.getStartOffset() + myTextRangeInElement.getStartOffset(),
            textRange.getStartOffset() + myTextRangeInElement.getEndOffset());
      }
      return textRange;
    }
    return new TextRange(textRange.getStartOffset(), endElement.getTextRange().getEndOffset());
  }
  public ProblemDescriptorImpl(
      @NotNull PsiElement startElement,
      @NotNull PsiElement endElement,
      String descriptionTemplate,
      LocalQuickFix[] fixes,
      ProblemHighlightType highlightType,
      boolean isAfterEndOfLine,
      @Nullable TextRange rangeInElement,
      final boolean tooltip,
      @Nullable HintAction hintAction,
      boolean onTheFly) {

    super(fixes, descriptionTemplate);
    myShowTooltip = tooltip;
    myHintAction = hintAction;
    PsiFile startContainingFile = startElement.getContainingFile();
    LOG.assertTrue(
        startContainingFile != null && startContainingFile.isValid() || startElement.isValid(),
        startElement);
    PsiFile endContainingFile =
        startElement == endElement ? startContainingFile : endElement.getContainingFile();
    LOG.assertTrue(
        startElement == endElement
            || endContainingFile != null && endContainingFile.isValid()
            || endElement.isValid(),
        endElement);
    assertPhysical(startElement);
    if (startElement != endElement) assertPhysical(endElement);

    final TextRange startElementRange = startElement.getTextRange();
    LOG.assertTrue(startElementRange != null, startElement);
    final TextRange endElementRange = endElement.getTextRange();
    LOG.assertTrue(endElementRange != null, endElement);
    if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) {
      if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) {
        LOG.error(
            "Empty PSI elements should not be passed to createDescriptor. Start: "
                + startElement
                + ", end: "
                + endElement);
      }
    }

    myHighlightType = highlightType;
    final Project project =
        startContainingFile == null ? startElement.getProject() : startContainingFile.getProject();
    final SmartPointerManager manager = SmartPointerManager.getInstance(project);
    myStartSmartPointer = manager.createSmartPsiElementPointer(startElement, startContainingFile);
    myEndSmartPointer =
        startElement == endElement
            ? null
            : manager.createSmartPsiElementPointer(endElement, endContainingFile);

    myAfterEndOfLine = isAfterEndOfLine;
    myTextRangeInElement = rangeInElement;
  }
  private void reportNullableArgumentsPassedToNonAnnotated(
      DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
    for (PsiElement expr :
        visitor.getProblems(NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter)) {
      if (reportedAnchors.contains(expr)) continue;

      final String text =
          isNullLiteralExpression(expr)
              ? "Passing <code>null</code> argument to non annotated parameter"
              : "Argument <code>#ref</code> #loc might be null but passed to non annotated parameter";
      LocalQuickFix[] fixes =
          createNPEFixes((PsiExpression) expr, (PsiExpression) expr, holder.isOnTheFly());
      final PsiElement parent = expr.getParent();
      if (parent instanceof PsiExpressionList) {
        final int idx = ArrayUtilRt.find(((PsiExpressionList) parent).getExpressions(), expr);
        if (idx > -1) {
          final PsiElement gParent = parent.getParent();
          if (gParent instanceof PsiCallExpression) {
            final PsiMethod psiMethod = ((PsiCallExpression) gParent).resolveMethod();
            if (psiMethod != null
                && psiMethod.getManager().isInProject(psiMethod)
                && AnnotationUtil.isAnnotatingApplicable(psiMethod)) {
              final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
              if (idx < parameters.length) {
                final AddNullableAnnotationFix addNullableAnnotationFix =
                    new AddNullableAnnotationFix(parameters[idx]);
                fixes =
                    fixes == null
                        ? new LocalQuickFix[] {addNullableAnnotationFix}
                        : ArrayUtil.append(fixes, addNullableAnnotationFix);
                holder.registerProblem(expr, text, fixes);
                reportedAnchors.add(expr);
              }
            }
          }
        }
      }
    }
  }
示例#20
0
  private static ProblemDescriptor runLocalTool(
      @NotNull PsiElement psiElement,
      @NotNull InspectionManager inspectionManager,
      @NotNull OfflineProblemDescriptor offlineProblemDescriptor,
      @NotNull LocalInspectionToolWrapper toolWrapper) {
    PsiFile containingFile = psiElement.getContainingFile();
    final ProblemsHolder holder = new ProblemsHolder(inspectionManager, containingFile, false);
    final LocalInspectionTool localTool = toolWrapper.getTool();
    final int startOffset = psiElement.getTextRange().getStartOffset();
    final int endOffset = psiElement.getTextRange().getEndOffset();
    LocalInspectionToolSession session =
        new LocalInspectionToolSession(containingFile, startOffset, endOffset);
    final PsiElementVisitor visitor = localTool.buildVisitor(holder, false, session);
    localTool.inspectionStarted(session, false);
    final PsiElement[] elementsInRange =
        getElementsIntersectingRange(containingFile, startOffset, endOffset);
    for (PsiElement element : elementsInRange) {
      element.accept(visitor);
    }
    localTool.inspectionFinished(session, holder);
    if (holder.hasResults()) {
      final List<ProblemDescriptor> list = holder.getResults();
      final int idx = offlineProblemDescriptor.getProblemIndex();
      int curIdx = 0;
      for (ProblemDescriptor descriptor : list) {
        final PsiNamedElement member = localTool.getProblemElement(descriptor.getPsiElement());
        if (psiElement instanceof PsiFile || member != null && member.equals(psiElement)) {
          if (curIdx == idx) {
            return descriptor;
          }
          curIdx++;
        }
      }
    }

    return null;
  }
 private static boolean isAssertionEffectively(PsiElement psiAnchor, boolean evaluatesToTrue) {
   PsiElement parent = psiAnchor.getParent();
   if (parent instanceof PsiAssertStatement) {
     return evaluatesToTrue;
   }
   if (parent instanceof PsiIfStatement && psiAnchor == ((PsiIfStatement) parent).getCondition()) {
     PsiStatement thenBranch = ((PsiIfStatement) parent).getThenBranch();
     if (thenBranch instanceof PsiThrowStatement) {
       return !evaluatesToTrue;
     }
     if (thenBranch instanceof PsiBlockStatement) {
       PsiStatement[] statements = ((PsiBlockStatement) thenBranch).getCodeBlock().getStatements();
       if (statements.length == 1 && statements[0] instanceof PsiThrowStatement) {
         return !evaluatesToTrue;
       }
     }
   }
   return false;
 }
  @Override
  public ProblemDescriptor[] getDescriptions(
      @NotNull PsiElement place,
      @NotNull final InspectionManager inspectionManager,
      boolean isOnTheFly) {
    final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
    place.accept(
        new JavaRecursiveElementWalkingVisitor() {
          @Override
          public void visitMethodCallExpression(PsiMethodCallExpression expression) {
            super.visitMethodCallExpression(expression);
            final PsiType[] typeArguments = expression.getTypeArguments();
            if (typeArguments.length > 0) {
              checkCallExpression(
                  expression.getMethodExpression(),
                  typeArguments,
                  expression,
                  inspectionManager,
                  problems);
            }
          }

          @Override
          public void visitNewExpression(PsiNewExpression expression) {
            super.visitNewExpression(expression);
            final PsiType[] typeArguments = expression.getTypeArguments();
            if (typeArguments.length > 0) {
              final PsiJavaCodeReferenceElement classReference = expression.getClassReference();
              if (classReference != null) {
                checkCallExpression(
                    classReference, typeArguments, expression, inspectionManager, problems);
              }
            }
          }

          @Override
          public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
            super.visitMethodReferenceExpression(expression);
            checkMethodReference(expression, inspectionManager, problems);
          }

          private void checkCallExpression(
              final PsiJavaCodeReferenceElement reference,
              final PsiType[] typeArguments,
              PsiCallExpression expression,
              final InspectionManager inspectionManager,
              final List<ProblemDescriptor> problems) {

            PsiExpressionList argumentList = expression.getArgumentList();
            if (argumentList == null) return;
            final JavaResolveResult resolveResult = reference.advancedResolve(false);

            final PsiElement element = resolveResult.getElement();
            if (element instanceof PsiMethod && resolveResult.isValidResult()) {
              PsiMethod method = (PsiMethod) element;
              final PsiTypeParameter[] typeParameters = method.getTypeParameters();
              if (typeParameters.length == typeArguments.length) {
                final PsiParameter[] parameters = method.getParameterList().getParameters();
                PsiResolveHelper resolveHelper =
                    JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper();
                final PsiSubstitutor psiSubstitutor =
                    resolveHelper.inferTypeArguments(
                        typeParameters,
                        parameters,
                        argumentList.getExpressions(),
                        PsiSubstitutor.EMPTY,
                        expression,
                        DefaultParameterTypeInferencePolicy.INSTANCE);
                for (int i = 0, length = typeParameters.length; i < length; i++) {
                  PsiTypeParameter typeParameter = typeParameters[i];
                  final PsiType inferredType =
                      psiSubstitutor.getSubstitutionMap().get(typeParameter);
                  if (!typeArguments[i].equals(inferredType)) return;
                  if (PsiUtil.resolveClassInType(method.getReturnType()) == typeParameter
                      && PsiPrimitiveType.getUnboxedType(inferredType) != null) return;
                }

                final PsiCallExpression copy =
                    (PsiCallExpression) expression.copy(); // see IDEADEV-8174
                try {
                  final PsiMethodCallExpression expr =
                      (PsiMethodCallExpression)
                          JavaPsiFacade.getInstance(copy.getProject())
                              .getElementFactory()
                              .createExpressionFromText("foo()", null);
                  copy.getTypeArgumentList().replace(expr.getTypeArgumentList());
                  if (copy.resolveMethod() != element) return;
                } catch (IncorrectOperationException e) {
                  LOG.error(e);
                  return;
                }

                final ProblemDescriptor descriptor =
                    inspectionManager.createProblemDescriptor(
                        expression.getTypeArgumentList(),
                        InspectionsBundle.message("inspection.redundant.type.problem.descriptor"),
                        myQuickFixAction,
                        ProblemHighlightType.LIKE_UNUSED_SYMBOL,
                        false);
                problems.add(descriptor);
              }
            }
          }
        });

    if (problems.isEmpty()) return null;
    return problems.toArray(new ProblemDescriptor[problems.size()]);
  }
  private void createDescription(
      StandardDataFlowRunner runner, ProblemsHolder holder, DataFlowInstructionVisitor visitor) {
    Pair<Set<Instruction>, Set<Instruction>> constConditions =
        runner.getConstConditionalExpressions();
    Set<Instruction> trueSet = constConditions.getFirst();
    Set<Instruction> falseSet = constConditions.getSecond();

    ArrayList<Instruction> allProblems = new ArrayList<Instruction>();
    allProblems.addAll(trueSet);
    allProblems.addAll(falseSet);
    allProblems.addAll(runner.getCCEInstructions());
    allProblems.addAll(StandardDataFlowRunner.getRedundantInstanceofs(runner, visitor));

    HashSet<PsiElement> reportedAnchors = new HashSet<PsiElement>();
    for (PsiElement element : visitor.getProblems(NullabilityProblem.callNPE)) {
      if (reportedAnchors.add(element)) {
        reportCallMayProduceNpe(holder, (PsiMethodCallExpression) element, holder.isOnTheFly());
      }
    }
    for (PsiElement element : visitor.getProblems(NullabilityProblem.fieldAccessNPE)) {
      if (reportedAnchors.add(element)) {
        PsiElement parent = element.getParent();
        PsiElement fieldAccess =
            parent instanceof PsiArrayAccessExpression || parent instanceof PsiReferenceExpression
                ? parent
                : element;
        reportFieldAccessMayProduceNpe(holder, element, (PsiExpression) fieldAccess);
      }
    }

    for (Instruction instruction : allProblems) {
      if (instruction instanceof TypeCastInstruction
          && reportedAnchors.add(
              ((TypeCastInstruction) instruction).getCastExpression().getCastType())) {
        reportCastMayFail(holder, (TypeCastInstruction) instruction);
      } else if (instruction instanceof BranchingInstruction) {
        handleBranchingInstruction(
            holder,
            visitor,
            trueSet,
            falseSet,
            reportedAnchors,
            (BranchingInstruction) instruction);
      }
    }

    reportNullableArguments(visitor, holder, reportedAnchors);
    reportNullableAssignments(visitor, holder, reportedAnchors);
    reportUnboxedNullables(visitor, holder, reportedAnchors);
    if (!runner.isInNullableMethod()
        && runner.isInMethod()
        && (runner.isInNotNullMethod() || SUGGEST_NULLABLE_ANNOTATIONS)) {
      reportNullableReturns(runner, visitor, holder, reportedAnchors);
    }
    if (SUGGEST_NULLABLE_ANNOTATIONS) {
      reportNullableArgumentsPassedToNonAnnotated(visitor, holder, reportedAnchors);
    }

    if (REPORT_CONSTANT_REFERENCE_VALUES) {
      reportConstantReferenceValues(holder, visitor, reportedAnchors);
    }
  }