private static void reportOptionalOfNullableImprovements(
      ProblemsHolder holder, Set<PsiElement> reportedAnchors, Instruction[] instructions) {
    for (Instruction instruction : instructions) {
      if (instruction instanceof MethodCallInstruction) {
        final PsiExpression[] args = ((MethodCallInstruction) instruction).getArgs();
        if (args.length != 1) continue;

        final PsiExpression expr = args[0];

        if (((MethodCallInstruction) instruction).isOptionalAlwaysNullProblem()) {
          if (!reportedAnchors.add(expr)) continue;
          holder.registerProblem(
              expr,
              "Passing <code>null</code> argument to <code>Optional</code>",
              DfaOptionalSupport.createReplaceOptionalOfNullableWithEmptyFix(expr));
        } else if (((MethodCallInstruction) instruction).isOptionalAlwaysNotNullProblem()) {
          if (!reportedAnchors.add(expr)) continue;
          holder.registerProblem(
              expr,
              "Passing a non-null argument to <code>Optional</code>",
              DfaOptionalSupport.createReplaceOptionalOfNullableWithOfFix());
        }
      }
    }
  }
 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);
   }
 }
  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);
      }
    }
  }
 @Override
 public ProblemDescriptor[] checkFile(
     @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
   ProblemsHolder problemsHolder = new ProblemsHolder(manager, file, isOnTheFly);
   checkFile(file, problemsHolder);
   return problemsHolder.getResultsArray();
 }
 private static void highlightStarArgumentTypeMismatch(
     PyArgumentList node, ProblemsHolder holder, TypeEvalContext context) {
   for (PyExpression arg : node.getArguments()) {
     if (arg instanceof PyStarArgument) {
       PyExpression content =
           PyUtil.peelArgument(PsiTreeUtil.findChildOfType(arg, PyExpression.class));
       if (content != null) {
         PyType inside_type = context.getType(content);
         if (inside_type != null && !PyTypeChecker.isUnknown(inside_type)) {
           if (((PyStarArgument) arg).isKeyword()) {
             if (!PyABCUtil.isSubtype(inside_type, PyNames.MAPPING)) {
               holder.registerProblem(
                   arg, PyBundle.message("INSP.expected.dict.got.$0", inside_type.getName()));
             }
           } else { // * arg
             if (!PyABCUtil.isSubtype(inside_type, PyNames.ITERABLE)) {
               holder.registerProblem(
                   arg, PyBundle.message("INSP.expected.iter.got.$0", inside_type.getName()));
             }
           }
         }
       }
     }
   }
 }
 public MyVisitor(@NotNull ProblemsHolder holder) {
   myHolder = holder;
   InspectionProfile profile =
       InspectionProjectProfileManager.getInstance(holder.getProject()).getInspectionProfile();
   UnusedDeclarationInspectionBase tool =
       (UnusedDeclarationInspectionBase)
           profile.getUnwrappedTool(
               UnusedDeclarationInspectionBase.SHORT_NAME, holder.getFile());
   myDeadCodeInspection = tool == null ? new UnusedDeclarationInspectionBase() : tool;
 }
  @Nullable
  public ProblemDescriptor[] checkFile(
      @NotNull PsiFile psiFile, @NotNull InspectionManager inspectionManager, boolean isOnTheFly) {
    if (!(psiFile instanceof GroovyFileBase)) {
      return super.checkFile(psiFile, inspectionManager, isOnTheFly);
    }
    final GroovyFileBase groovyFile = (GroovyFileBase) psiFile;

    final ProblemsHolder problemsHolder =
        new ProblemsHolder(inspectionManager, psiFile, isOnTheFly);
    final BaseInspectionVisitor visitor = buildGroovyVisitor(problemsHolder, isOnTheFly);
    groovyFile.accept(visitor);
    final List<ProblemDescriptor> problems = problemsHolder.getResults();
    return problems.toArray(new ProblemDescriptor[problems.size()]);
  }
  private void reportNullableArguments(
      DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
    for (PsiElement expr :
        visitor.getProblems(NullabilityProblem.passingNullableToNotNullParameter)) {
      if (!reportedAnchors.add(expr)) continue;

      final String text =
          isNullLiteralExpression(expr)
              ? InspectionsBundle.message("dataflow.message.passing.null.argument")
              : InspectionsBundle.message("dataflow.message.passing.nullable.argument");
      LocalQuickFix[] fixes =
          createNPEFixes((PsiExpression) expr, (PsiExpression) expr, holder.isOnTheFly());
      holder.registerProblem(expr, text, fixes);
    }
  }
 private void reportFieldAccessMayProduceNpe(
     ProblemsHolder holder, PsiElement elementToAssert, PsiExpression expression) {
   if (expression instanceof PsiArrayAccessExpression) {
     LocalQuickFix[] fix =
         createNPEFixes((PsiExpression) elementToAssert, expression, holder.isOnTheFly());
     holder.registerProblem(
         expression, InspectionsBundle.message("dataflow.message.npe.array.access"), fix);
   } else {
     LocalQuickFix[] fix =
         createNPEFixes((PsiExpression) elementToAssert, expression, holder.isOnTheFly());
     assert elementToAssert != null;
     holder.registerProblem(
         elementToAssert, InspectionsBundle.message("dataflow.message.npe.field.access"), fix);
   }
 }
  public static void apply(
      final String functionName,
      @NotNull final FunctionReference reference,
      final String modifiers,
      final String pattern,
      @NotNull final ProblemsHolder holder) {
    if (reference.getParameters().length >= 2 && !StringUtil.isEmpty(pattern)) {
      Matcher regexMatcher = regexTextSearch.matcher(pattern);
      if (regexMatcher.find()) {
        final boolean ignoreCase = !StringUtil.isEmpty(modifiers) && modifiers.indexOf('i') >= 0;
        final boolean startWith = !StringUtil.isEmpty(regexMatcher.group(1));

        /* analyse if pattern is the one strategy targeting */
        String strProblemDescription = null;
        if (functionName.equals("preg_match") && startWith) {
          strProblemDescription = ignoreCase ? strProblemStartIgnoreCase : strProblemStartTreatCase;
        }
        if (functionName.equals("preg_match") && !startWith) {
          strProblemDescription =
              ignoreCase ? strProblemContainsIgnoreCase : strProblemContainsTreatCase;
        }
        if (functionName.equals("preg_replace") && !startWith) {
          strProblemDescription =
              ignoreCase ? strProblemReplaceIgnoreCase : strProblemReplaceTreatCase;
        }

        if (null != strProblemDescription) {
          String strError = strProblemDescription.replace("%t%", regexMatcher.group(2));
          holder.registerProblem(
              reference, strError, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
        }
      }
    }
  }
  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);
        }
      }
    }
  }
 private static void reportUnboxedNullables(
     DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
   for (PsiElement expr : visitor.getProblems(NullabilityProblem.unboxingNullable)) {
     if (!reportedAnchors.add(expr)) continue;
     holder.registerProblem(expr, InspectionsBundle.message("dataflow.message.unboxing"));
   }
 }
 private static void checkSillyAssignment(
     PsiAssignmentExpression assignment, ProblemsHolder holder) {
   if (assignment.getOperationTokenType() != JavaTokenType.EQ) return;
   PsiExpression lExpression = assignment.getLExpression();
   PsiExpression rExpression = assignment.getRExpression();
   if (rExpression == null) return;
   lExpression = PsiUtil.deparenthesizeExpression(lExpression);
   rExpression = PsiUtil.deparenthesizeExpression(rExpression);
   if (!(lExpression instanceof PsiReferenceExpression)) return;
   PsiReferenceExpression rRef;
   if (!(rExpression instanceof PsiReferenceExpression)) {
     if (!(rExpression instanceof PsiAssignmentExpression)) return;
     final PsiAssignmentExpression rAssignmentExpression = (PsiAssignmentExpression) rExpression;
     final PsiExpression assignee =
         PsiUtil.deparenthesizeExpression(rAssignmentExpression.getLExpression());
     if (!(assignee instanceof PsiReferenceExpression)) return;
     rRef = (PsiReferenceExpression) assignee;
   } else {
     rRef = (PsiReferenceExpression) rExpression;
   }
   PsiReferenceExpression lRef = (PsiReferenceExpression) lExpression;
   PsiManager manager = assignment.getManager();
   if (!sameInstanceReferences(lRef, rRef, manager)) return;
   final PsiVariable variable = (PsiVariable) lRef.resolve();
   if (variable == null) return;
   holder.registerProblem(
       assignment,
       InspectionsBundle.message("assignment.to.itself.problem.descriptor", variable.getName()),
       ProblemHighlightType.LIKE_UNUSED_SYMBOL);
 }
  private static void visitParameterList(
      @NotNull ProblemsHolder holder,
      @Nullable GoParameters parameters,
      @NotNull String ownerType,
      @NotNull String what) {

    if (parameters == null || parameters.getParameterDeclarationList().isEmpty()) return;
    boolean hasNamed = false;
    boolean hasUnnamed = false;
    for (GoParameterDeclaration parameterDeclaration : parameters.getParameterDeclarationList()) {
      ProgressManager.checkCanceled();
      if (parameterDeclaration.getParamDefinitionList().isEmpty()) {
        hasUnnamed = true;
      } else {
        hasNamed = true;
      }

      if (hasNamed && hasUnnamed) {
        holder.registerProblem(
            parameters,
            ownerType + " has both named and unnamed " + what + " <code>#ref</code> #loc",
            ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
        return;
      }
    }
  }
Ejemplo n.º 15
0
  private static void docheckClass(final PsiClass aClass, ProblemsHolder holder) {
    if (aClass.isInterface()) return;
    final PsiField[] fields = aClass.getFields();
    final Set<PsiField> candidates = new LinkedHashSet<PsiField>();
    for (PsiField field : fields) {
      if (field.hasModifierProperty(PsiModifier.PRIVATE)
          && !(field.hasModifierProperty(PsiModifier.STATIC)
              && field.hasModifierProperty(PsiModifier.FINAL))) {
        candidates.add(field);
      }
    }

    removeFieldsReferencedFromInitializers(aClass, candidates);
    if (candidates.isEmpty()) return;

    final Set<PsiField> usedFields = new THashSet<PsiField>();
    removeReadFields(aClass, candidates, usedFields);

    if (candidates.isEmpty()) return;
    final ImplicitUsageProvider[] implicitUsageProviders =
        Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);

    for (PsiField field : candidates) {
      if (usedFields.contains(field)
          && !hasImplicitReadOrWriteUsage(field, implicitUsageProviders)) {
        final String message =
            InspectionsBundle.message("inspection.field.can.be.local.problem.descriptor");
        holder.registerProblem(field.getNameIdentifier(), message, new MyQuickFix(field));
      }
    }
  }
  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    PsiFile file = holder.getFile();
    if (!PsiUtil.isLanguageLevel5OrHigher(file)) return new PsiElementVisitor() {};

    return super.buildVisitor(holder, isOnTheFly);
  }
 private static void reportCastMayFail(ProblemsHolder holder, TypeCastInstruction instruction) {
   PsiTypeCastExpression typeCast = instruction.getCastExpression();
   PsiExpression operand = typeCast.getOperand();
   PsiTypeElement castType = typeCast.getCastType();
   assert castType != null;
   assert operand != null;
   holder.registerProblem(
       castType, InspectionsBundle.message("dataflow.message.cce", operand.getText()));
 }
  public void verifyTypeElement(
      @NotNull final PsiTypeElement psiTypeElement, @NotNull final ProblemsHolder holder) {
    final PsiElement typeParent = psiTypeElement.getParent();

    if (isVal(psiTypeElement)) {
      if (typeParent instanceof PsiField
          || (typeParent instanceof PsiParameter
              && !(((PsiParameter) typeParent).getDeclarationScope()
                  instanceof PsiForeachStatement))) {
        holder.registerProblem(
            psiTypeElement,
            "'val' works only on local variables and on foreach loops",
            ProblemHighlightType.ERROR);
      } else if (typeParent instanceof PsiLocalVariable) {
        final PsiLocalVariable psiVariable = (PsiLocalVariable) typeParent;
        final PsiExpression initializer = psiVariable.getInitializer();
        if (initializer == null) {
          holder.registerProblem(
              psiTypeElement,
              "'val' on a local variable requires an initializer expression",
              ProblemHighlightType.ERROR);
        } else if (initializer instanceof PsiArrayInitializerExpression) {
          holder.registerProblem(
              psiTypeElement,
              "'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })",
              ProblemHighlightType.ERROR);
        } else if (initializer instanceof PsiLambdaExpression) {
          holder.registerProblem(
              psiTypeElement,
              "'val' is not allowed with lambda expressions.",
              ProblemHighlightType.ERROR);
        } else {
          final PsiElement typeParentParent = typeParent.getParent();
          if (typeParentParent instanceof PsiDeclarationStatement
              && typeParentParent.getParent() instanceof PsiForStatement) {
            holder.registerProblem(
                psiTypeElement,
                "'val' is not allowed in old-style for loops",
                ProblemHighlightType.ERROR);
          }
        }
      }
    }
  }
 @NotNull
 @Override
 public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
   PsiFile psiFile = holder.getFile();
   if (psiFile.getLanguage() != JavaLanguage.INSTANCE
       || !PsiUtil.isLanguageLevel5OrHigher(psiFile)) {
     return new PsiElementVisitor() {};
   }
   return super.buildVisitor(holder, isOnTheFly);
 }
 @NotNull
 @Override
 public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
   if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) {
     return PsiElementVisitor.EMPTY_VISITOR;
   }
   return new PsiElementVisitor() {
     @Override
     public void visitElement(PsiElement element) {
       if (element instanceof PsiMethodCallExpression) {
         final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) element;
         String qName = methodCallExpression.getMethodExpression().getQualifiedName();
         if (qName == null) {
           return;
         }
         qName = StringUtil.getShortName(qName);
         final Collection<StaticPseudoFunctionalStyleMethodOptions.PipelineElement> handlerInfos =
             myOptions.findElementsByMethodName(qName);
         if (handlerInfos.isEmpty()) {
           return;
         }
         final PsiMethod method = methodCallExpression.resolveMethod();
         if (method == null) {
           return;
         }
         final PsiClass aClass = method.getContainingClass();
         if (aClass == null) {
           return;
         }
         final String classQualifiedName = aClass.getQualifiedName();
         if (classQualifiedName == null) {
           return;
         }
         StaticPseudoFunctionalStyleMethodOptions.PipelineElement suitableHandler = null;
         for (StaticPseudoFunctionalStyleMethodOptions.PipelineElement h : handlerInfos) {
           if (h.getHandlerClass().equals(classQualifiedName)) {
             suitableHandler = h;
             break;
           }
         }
         if (suitableHandler == null) {
           return;
         }
         final PseudoLambdaReplaceTemplate.ValidationInfo validationInfo =
             suitableHandler.getTemplate().validate(methodCallExpression);
         if (validationInfo != null) {
           holder.registerProblem(
               methodCallExpression.getMethodExpression(),
               "Pseudo functional style code",
               new ReplacePseudoLambdaWithLambda(suitableHandler));
         }
       }
     }
   };
 }
  @Override
  public void collectInspectionsForElement(
      @NotNull PsiField element, @NotNull ProblemsHolder problemsHolder) {
    PsiAnnotation affectedAnnotation = getAffectedAnnotation(element);

    problemsHolder.registerProblem(
        affectedAnnotation,
        "@Setter is invalid for final field",
        new RemoveAnnotationQuickFix(affectedAnnotation, element),
        new RemoveModifierFix(element, PsiModifier.FINAL));
  }
 protected final void registerError(@NotNull PsiElement location, Object... infos) {
   if (location.getTextLength() == 0) {
     return;
   }
   final InspectionGadgetsFix[] fixes = createFixes(infos);
   for (InspectionGadgetsFix fix : fixes) {
     fix.setOnTheFly(onTheFly);
   }
   final String description = inspection.buildErrorString(infos);
   holder.registerProblem(location, description, fixes);
 }
  private void reportCallMayProduceNpe(
      ProblemsHolder holder, PsiMethodCallExpression callExpression, boolean onTheFly) {
    LocalQuickFix[] fix =
        createNPEFixes(
            callExpression.getMethodExpression().getQualifierExpression(),
            callExpression,
            onTheFly);

    holder.registerProblem(
        callExpression, InspectionsBundle.message("dataflow.message.npe.method.invocation"), fix);
  }
  private static void checkMagicParameterArgument(
      @NotNull PsiParameter parameter,
      PsiExpression argument,
      @NotNull AllowedValues allowedValues,
      @NotNull ProblemsHolder holder) {
    final PsiManager manager = PsiManager.getInstance(holder.getProject());

    if (!argument.getTextRange().isEmpty()
        && !isAllowed(parameter.getDeclarationScope(), argument, allowedValues, manager)) {
      registerProblem(argument, allowedValues, holder);
    }
  }
  private static void reportNullableAssignments(
      DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
    for (PsiElement expr : visitor.getProblems(NullabilityProblem.assigningToNotNull)) {
      if (!reportedAnchors.add(expr)) continue;

      final String text =
          isNullLiteralExpression(expr)
              ? InspectionsBundle.message("dataflow.message.assigning.null")
              : InspectionsBundle.message("dataflow.message.assigning.nullable");
      holder.registerProblem(expr, text);
    }
  }
  private static void reportNullableReturns(
      StandardDataFlowRunner runner,
      DataFlowInstructionVisitor visitor,
      ProblemsHolder holder,
      Set<PsiElement> reportedAnchors) {
    for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) {
      assert statement instanceof PsiExpression;
      final PsiExpression expr = (PsiExpression) statement;
      if (!reportedAnchors.add(expr)) continue;

      if (runner.isInNotNullMethod()) {
        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);
        holder.registerProblem(
            expr,
            text,
            new AnnotateMethodFix(defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) {
              @Override
              public int shouldAnnotateBaseMethod(
                  PsiMethod method, PsiMethod superMethod, Project project) {
                return 1;
              }
            });
      }
    }
  }
  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);
              }
            }
          }
        }
      }
    }
  }
 private static void highlightMissingArguments(
     PyArgumentList node, ProblemsHolder holder, CallArgumentsMapping result) {
   ASTNode our_node = node.getNode();
   if (our_node != null) {
     ASTNode close_paren = our_node.findChildByType(PyTokenTypes.RPAR);
     if (close_paren != null) {
       for (PyNamedParameter param : result.getUnmappedParams()) {
         holder.registerProblem(
             close_paren.getPsi(),
             PyBundle.message("INSP.parameter.$0.unfilled", param.getName()));
       }
     }
   }
 }
Ejemplo n.º 29
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;
  }
  static void registerProblem(
      BnfExpression choice,
      BnfExpression branch,
      String message,
      ProblemsHolder problemsHolder,
      LocalQuickFix... fixes) {
    TextRange textRange = branch.getTextRange();
    if (textRange.isEmpty()) {
      ASTNode nextOr = TreeUtil.findSibling(branch.getNode(), BnfTypes.BNF_OP_OR);
      ASTNode prevOr = TreeUtil.findSiblingBackward(branch.getNode(), BnfTypes.BNF_OP_OR);

      int shift = choice.getTextRange().getStartOffset();
      int startOffset = prevOr != null ? prevOr.getStartOffset() - shift : 0;
      TextRange range =
          new TextRange(
              startOffset,
              nextOr != null
                  ? nextOr.getStartOffset() + 1 - shift
                  : Math.min(startOffset + 2, choice.getTextLength()));
      problemsHolder.registerProblem(choice, range, message, fixes);
    } else {
      problemsHolder.registerProblem(branch, message, fixes);
    }
  }