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; } } }
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())); } } } }
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); } }