void (@NotNull PsiFile file, ShellcheckResponse shellcheckResponse, @NotNull AnnotationHolder holder) { super.apply(file, shellcheckResponse, holder); Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null) { return; } Collection<OuterLanguageElement> outerElements = PsiTreeUtil.findChildrenOfType(file, OuterLanguageElement.class); List<TextRange> rangesOfOuterElements = ContainerUtil.map(outerElements, el -> el.getTextRange()); for (Result result : shellcheckResponse.results) { CharSequence sequence = document.getCharsSequence(); int startOffset = ShShellcheckUtil.calcOffset(sequence, document.getLineStartOffset(result.line - 1), result.column); int endOffset = ShShellcheckUtil.calcOffset(sequence, document.getLineStartOffset(result.endLine - 1), result.endColumn); TextRange range = TextRange.create(startOffset, endOffset == startOffset ? endOffset + 1 : endOffset); // We skip results which out of scope for current file or intersect with outer language elements if (!file.getTextRange().contains(range) || ContainerUtil.exists(rangesOfOuterElements, it -> it.contains(range))) continue; long code = result.code; String message = result.message; @NonNls String scCode = "SC" + code; @NonNls String html = "<html>" + "<p>" + StringUtil.escapeXmlEntities(message) + "</p>" + "<p>See <a href='https://github.com/koalaman/shellcheck/wiki/SC" + code + "'>" + scCode + "</a>.</p>" + "</html>"; AnnotationBuilder builder = holder.newAnnotation(severity(result.level), message).range(range).tooltip(html); String formattedMessage = format(message); Fix fix = result.fix; if (fix != null && !ArrayUtil.isEmpty(fix.replacements)) { builder = builder.withFix(new ShQuickFixIntention(formattedMessage, fix, shellcheckResponse.timestamp)); } String quotedMessage = quote(formattedMessage); builder.withFix(new ShSuppressInspectionIntention(quotedMessage, scCode, startOffset)) .withFix(new ShDisableInspectionIntention(quotedMessage, scCode)) .create(); } }