From c2e3cb4b9cb8745112aa03ca78d9958b573e9d82 Mon Sep 17 00:00:00 2001 From: Ilia Permiashkin Date: Fri, 26 Sep 2025 00:30:23 +0000 Subject: [PATCH] [grazie] Highlight style and grammar warnings in one pass Merge-request: IJ-MR-176614 Merged-by: Ilia Permiashkin GitOrigin-RevId: cf68888cb903b396ff59feee6d00dff720b19534 --- platform/analysis-impl/api-dump.txt | 3 + .../codeInspection/ProblemDescriptorBase.java | 21 ++++ .../ProblemDescriptorWithReporterName.java | 7 +- plugins/grazie/resources/META-INF/plugin.xml | 15 ++- .../inspectionDescriptions/GrazieStyle.html | 18 ---- .../grazie/ide/TextProblemSeverities.kt | 4 +- .../inspection/grammar/GrazieInspection.kt | 87 +++++++++++------ .../grazie/style/StyleInspection.java | 60 ------------ .../com/intellij/grazie/text/CheckerRunner.kt | 13 +-- .../GrazieInspectionRunner.html | 26 +++++ .../inspectionDescriptions/GrazieStyle.html | 18 ++++ .../com/intellij/grazie/GrazieTestBase.kt | 5 +- .../grazie/ide/language/ReportingTest.kt | 11 ++- .../grazie/suppression/SuppressionTests.kt | 95 +++++++++++++++++++ 14 files changed, 251 insertions(+), 132 deletions(-) delete mode 100644 plugins/grazie/resources/inspectionDescriptions/GrazieStyle.html delete mode 100644 plugins/grazie/src/main/kotlin/com/intellij/grazie/style/StyleInspection.java create mode 100644 plugins/grazie/src/main/resources/inspectionDescriptions/GrazieInspectionRunner.html create mode 100644 plugins/grazie/src/main/resources/inspectionDescriptions/GrazieStyle.html create mode 100644 plugins/grazie/src/test/kotlin/com/intellij/grazie/suppression/SuppressionTests.kt diff --git a/platform/analysis-impl/api-dump.txt b/platform/analysis-impl/api-dump.txt index 9338119ab8d4..51640620d777 100644 --- a/platform/analysis-impl/api-dump.txt +++ b/platform/analysis-impl/api-dump.txt @@ -204,6 +204,9 @@ com.intellij.codeInspection.InspectionToolResultExporter - a:suppressProblem(com.intellij.codeInspection.CommonProblemDescriptor):V - a:suppressProblem(com.intellij.codeInspection.reference.RefEntity):V - a:updateContent():V +c:com.intellij.codeInspection.ProblemDescriptorBase +- (com.intellij.psi.PsiElement,com.intellij.psi.PsiElement,java.lang.String,com.intellij.codeInspection.LocalQuickFix[],com.intellij.codeInspection.ProblemHighlightType,Z,com.intellij.openapi.util.TextRange,Z,Z,java.lang.String):V +- getTooltipTemplate():java.lang.String com.intellij.codeInspection.dataFlow.interpreter.DataFlowInterpreter - a:cancel():V - a:createClosureState(com.intellij.psi.PsiElement,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState):V diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java index 9f8f5bed4795..62c4fd7cf554 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java @@ -8,6 +8,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NlsSafe; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; @@ -35,6 +36,7 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement private TextAttributesKey myEnforcedTextAttributes; private int myLineNumber = -1; private ProblemGroup myProblemGroup; + private @NlsSafe @Nullable String tooltip; public ProblemDescriptorBase(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @@ -95,6 +97,20 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement myOnTheFly = onTheFly; } + public ProblemDescriptorBase(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull @InspectionMessage String descriptionTemplate, + @NotNull LocalQuickFix @Nullable [] fixes, + @NotNull ProblemHighlightType highlightType, + boolean isAfterEndOfLine, + @Nullable TextRange rangeInElement, + boolean showTooltip, + boolean onTheFly, + @Nullable String tooltip) { + this(startElement, endElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, rangeInElement, showTooltip, onTheFly); + this.tooltip = tooltip; + } + private static @NotNull LocalQuickFix @Nullable [] filterFixes(LocalQuickFix @Nullable [] fixes, boolean onTheFly) { if (onTheFly || fixes == null) return fixes; List filtered = ContainerUtil.filter(fixes, fix -> fix != null && fix.availableInBatchMode()); @@ -267,6 +283,11 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement return myShowTooltip; } + @Override + public @NotNull String getTooltipTemplate() { + return tooltip == null ? getDescriptionTemplate() : tooltip; + } + @Override public String toString() { PsiElement element = getPsiElement(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ProblemDescriptorWithReporterName.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ProblemDescriptorWithReporterName.java index b4f3247d3d1b..74a4d1bd59e3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ProblemDescriptorWithReporterName.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ProblemDescriptorWithReporterName.java @@ -16,8 +16,11 @@ public final class ProblemDescriptorWithReporterName extends ProblemDescriptorBa private final String myReportingToolShortName; public ProblemDescriptorWithReporterName(@NotNull ProblemDescriptorBase pd, @NotNull String reportingToolShortName) { - super(pd.getStartElement(), pd.getEndElement(), pd.getDescriptionTemplate(), pd.getFixes(), - pd.getHighlightType(), pd.isAfterEndOfLine(), pd.getTextRangeInElement(), pd.showTooltip(), pd.isOnTheFly()); + super( + pd.getStartElement(), pd.getEndElement(), pd.getDescriptionTemplate(), pd.getFixes(), + pd.getHighlightType(), pd.isAfterEndOfLine(), pd.getTextRangeInElement(), pd.showTooltip(), + pd.isOnTheFly(), pd.getTooltipTemplate() + ); myReportingToolShortName = reportingToolShortName; } diff --git a/plugins/grazie/resources/META-INF/plugin.xml b/plugins/grazie/resources/META-INF/plugin.xml index 21127b0e832e..4482cc1360ed 100644 --- a/plugins/grazie/resources/META-INF/plugin.xml +++ b/plugins/grazie/resources/META-INF/plugin.xml @@ -51,10 +51,19 @@ - + + + + - diff --git a/plugins/grazie/resources/inspectionDescriptions/GrazieStyle.html b/plugins/grazie/resources/inspectionDescriptions/GrazieStyle.html deleted file mode 100644 index 73be46096811..000000000000 --- a/plugins/grazie/resources/inspectionDescriptions/GrazieStyle.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Check the writing style defined in: -
    -
  • - Grazie rule files (e.g. .grazie.en.yaml for English) - for this project or its specific subdirectories. - To create such a file, invoke New menu on any (e.g. root) directory of the project. -
  • -
  • - Style rules in Editor | Natural languages | Rules settings -
  • -
- -This inspection only returns results via Code | Analyze Code | Run Inspection By Name... or in offline analysis. -Editor highlighting of style issues is performed independently of this inspection's settings. - - \ No newline at end of file diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/TextProblemSeverities.kt b/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/TextProblemSeverities.kt index e8b97c57a2c4..6f63e1f45288 100644 --- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/TextProblemSeverities.kt +++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/TextProblemSeverities.kt @@ -16,7 +16,7 @@ class TextProblemSeverities : SeveritiesProvider() { override fun getSeveritiesHighlightInfoTypes(): List { return listOf( TextHighlightInfoType(STYLE_SUGGESTION, STYLE_SUGGESTION_ATTRIBUTES, GrazieIcons.StyleSuggestion), - TextHighlightInfoType(GRAMMAR_ERROR, GRAMMAR_ERROR_ATTRIBUTES, AllIcons.General.InspectionsGrammar, applicableToInspections = true) + TextHighlightInfoType(GRAMMAR_ERROR, GRAMMAR_ERROR_ATTRIBUTES, AllIcons.General.InspectionsGrammar) ) } @@ -24,10 +24,8 @@ class TextProblemSeverities : SeveritiesProvider() { severity: HighlightSeverity, attributesKey: TextAttributesKey, private val icon: Icon, - private val applicableToInspections: Boolean = false, ) : HighlightInfoTypeImpl(severity, attributesKey), HighlightInfoType.Iconable { override fun getIcon(): Icon = icon - override fun isApplicableToInspections() = applicableToInspections } @Suppress("CompanionObjectInExtension") diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/inspection/grammar/GrazieInspection.kt b/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/inspection/grammar/GrazieInspection.kt index 07d3a7f1bde4..467774b91e73 100644 --- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/inspection/grammar/GrazieInspection.kt +++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/ide/inspection/grammar/GrazieInspection.kt @@ -7,11 +7,8 @@ import com.intellij.codeInspection.LocalInspectionToolSession import com.intellij.codeInspection.ProblemsHolder import com.intellij.grazie.GrazieBundle import com.intellij.grazie.GrazieConfig -import com.intellij.grazie.text.CheckerRunner -import com.intellij.grazie.text.TextContent -import com.intellij.grazie.text.TextExtractor +import com.intellij.grazie.text.* import com.intellij.grazie.text.TextExtractor.findAllTextContents -import com.intellij.grazie.text.TextProblem import com.intellij.lang.Language import com.intellij.openapi.project.DumbAware import com.intellij.openapi.util.TextRange @@ -22,36 +19,85 @@ import com.intellij.psi.PsiFile import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.util.CachedValuesManager import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization +import org.jetbrains.annotations.NonNls import java.util.* class GrazieInspection : LocalInspectionTool(), DumbAware { - override fun getDisplayName() = GrazieBundle.message("grazie.grammar.inspection.grammar.text") + class Grammar: LocalInspectionTool(), DumbAware { + override fun getShortName(): @NonNls String = GRAMMAR_INSPECTION + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + return PsiElementVisitor.EMPTY_VISITOR + } + } + + class Style: LocalInspectionTool(), DumbAware { + override fun getShortName(): @NonNls String = STYLE_INSPECTION + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + return PsiElementVisitor.EMPTY_VISITOR + } + } + + override fun getDisplayName(): String = GrazieBundle.message("grazie.grammar.inspection.grammar.text") override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { val file = holder.file - if (ignoreGrammarChecking(file) || InspectionProfileManager.hasTooLowSeverity(session, this)) { - return PsiElementVisitor.EMPTY_VISITOR - } + if (ignoreGrammarChecking(file) || hasTooLowSeverity(session)) return PsiElementVisitor.EMPTY_VISITOR val checkedDomains = checkedDomains() val areChecksDisabled = getDisabledChecker(file) return object : PsiElementVisitor() { + override fun visitWhiteSpace(space: PsiWhiteSpace) {} + override fun visitElement(element: PsiElement) { - if (element is PsiWhiteSpace || areChecksDisabled(element)) return - inspectElement(element, { !it.isStyleLike }, session, holder, checkedDomains) + if (areChecksDisabled(element)) return + + val texts = TextExtractor.findUniqueTextsAt(element, checkedDomains) + if (skipCheckingTooLargeTexts(texts)) return + + sortByPriority(texts, session.priorityRange) + .map { CheckerRunner(it) } + .map { it to it.run() } + .forEach { (runner, problems) -> + problems.forEach { problem -> + runner.toProblemDescriptors(problem, holder.isOnTheFly).forEach(holder::registerProblem) + } + } + + if (element == file) { + checkTextLevel(file, holder) + } } } } + private fun checkTextLevel(file: PsiFile, holder: ProblemsHolder) { + TreeRuleChecker.checkTextLevelProblems(file).forEach { reportProblem(it, holder) } + } + + private fun reportProblem(problem: TextProblem, holder: ProblemsHolder) { + CheckerRunner(problem.text).toProblemDescriptors(problem, holder.isOnTheFly) + .forEach { holder.registerProblem(it) } + } + + private fun hasTooLowSeverity(session: LocalInspectionToolSession): Boolean { + return inspections.all { InspectionProfileManager.hasTooLowSeverity(session, it) } + } + /** * Most of those methods are used in Grazie Pro. */ @Suppress("CompanionObjectInExtension") companion object { + private val inspections: List = listOf(Grammar(), Style()) + private const val MAX_TEXT_LENGTH_IN_PSI_ELEMENT = 50_000 private const val MAX_TEXT_LENGTH_IN_FILE = 200_000 + const val GRAMMAR_INSPECTION: String = "GrazieInspection" + const val STYLE_INSPECTION: String = "GrazieStyle" private val hasSpellChecking: Boolean by lazy { try { @@ -115,27 +161,6 @@ class GrazieInspection : LocalInspectionTool(), DumbAware { } } - @JvmStatic - fun inspectElement( - element: PsiElement, - problemFilter: (TextProblem) -> Boolean, - session: LocalInspectionToolSession, - problemsHolder: ProblemsHolder, - checkedDomains: Set, - ) { - val texts = TextExtractor.findUniqueTextsAt(element, checkedDomains) - if (skipCheckingTooLargeTexts(texts)) return - - sortByPriority(texts, session.priorityRange) - .map { CheckerRunner(it) } - .map { it to it.run().filter(problemFilter) } - .forEach { (runner, problems) -> - problems.forEach { problem -> - runner.toProblemDescriptors(problem, problemsHolder.isOnTheFly).forEach(problemsHolder::registerProblem) - } - } - } - @JvmStatic fun sortByPriority(texts: List, priorityRange: TextRange): List { return texts.sortedBy { text -> diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/style/StyleInspection.java b/plugins/grazie/src/main/kotlin/com/intellij/grazie/style/StyleInspection.java deleted file mode 100644 index 2d72f0d23e30..000000000000 --- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/style/StyleInspection.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.intellij.grazie.style; - -import com.intellij.codeInspection.LocalInspectionTool; -import com.intellij.codeInspection.LocalInspectionToolSession; -import com.intellij.codeInspection.ProblemsHolder; -import com.intellij.grazie.text.CheckerRunner; -import com.intellij.grazie.text.TextContent.TextDomain; -import com.intellij.grazie.text.TextProblem; -import com.intellij.grazie.text.TreeRuleChecker; -import com.intellij.grazie.utils.HighlightingUtil; -import com.intellij.profile.codeInspection.InspectionProfileManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiWhiteSpace; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; - -import java.util.Set; - -import static com.intellij.grazie.ide.inspection.grammar.GrazieInspection.*; - -public class StyleInspection extends LocalInspectionTool { - @Override - public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly, - @NotNull LocalInspectionToolSession session) { - PsiFile file = session.getFile(); - if (ignoreGrammarChecking(file) || InspectionProfileManager.hasTooLowSeverity(session, this)) { - return PsiElementVisitor.EMPTY_VISITOR; - } - - Set checkedDomains = HighlightingUtil.checkedDomains(); - Function1 areChecksDisabled = getDisabledChecker(file); - - return new PsiElementVisitor() { - @Override - public void visitElement(@NotNull PsiElement element) { - if (element instanceof PsiWhiteSpace || areChecksDisabled.invoke(element)) return; - - inspectElement(element, TextProblem::isStyleLike, session, holder, checkedDomains); - - if (element == file) { - checkTextLevel(file, holder); - } - } - }; - } - - private static void checkTextLevel(PsiFile file, ProblemsHolder holder) { - TreeRuleChecker.checkTextLevelProblems(file) - .stream() - .filter(TextProblem::isStyleLike) - .forEach(problem -> reportProblem(problem, holder)); - } - - private static void reportProblem(TextProblem problem, ProblemsHolder holder) { - new CheckerRunner(problem.getText()).toProblemDescriptors(problem, holder.isOnTheFly()) - .forEach(holder::registerProblem); - } -} diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/CheckerRunner.kt b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/CheckerRunner.kt index f9d71ce571ff..88f1ff454d0d 100644 --- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/CheckerRunner.kt +++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/CheckerRunner.kt @@ -5,6 +5,7 @@ package com.intellij.grazie.text import ai.grazie.nlp.tokenizer.Tokenizer import ai.grazie.nlp.tokenizer.sentence.StandardSentenceTokenizer import ai.grazie.utils.toLinkedSet +import com.intellij.codeInsight.daemon.impl.ProblemDescriptorWithReporterName import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemDescriptorBase @@ -13,6 +14,7 @@ import com.intellij.codeInspection.util.InspectionMessage import com.intellij.grazie.GrazieConfig import com.intellij.grazie.ide.fus.AcceptanceRateTracker import com.intellij.grazie.ide.fus.GrazieFUSCounter +import com.intellij.grazie.ide.inspection.grammar.GrazieInspection import com.intellij.grazie.ide.inspection.grammar.quickfix.GrazieAddExceptionQuickFix import com.intellij.grazie.ide.inspection.grammar.quickfix.GrazieCustomFixWrapper import com.intellij.grazie.ide.inspection.grammar.quickfix.GrazieReplaceTypoQuickFix @@ -139,7 +141,10 @@ class CheckerRunner(val text: TextContent) { if (isOnTheFly) { descriptor.quickFixes = toFixes(problem, descriptor) } - descriptor + ProblemDescriptorWithReporterName( + descriptor, + if (problem.isStyleLike) GrazieInspection.STYLE_INSPECTION else GrazieInspection.GRAMMAR_INSPECTION + ) } } @@ -151,15 +156,11 @@ class CheckerRunner(val text: TextContent) { @NlsContexts.Tooltip private val tooltip: String ): ProblemDescriptorBase( psi, psi, descriptionTemplate, LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false, - rangeInElement, true, onTheFly + rangeInElement, true, onTheFly, tooltip ) { var quickFixes: Array = LocalQuickFix.EMPTY_ARRAY override fun getFixes(): Array = quickFixes - - override fun getTooltipTemplate(): String { - return tooltip - } } private fun isIgnoredByStrategies(descriptor: TextProblem): Boolean { diff --git a/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieInspectionRunner.html b/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieInspectionRunner.html new file mode 100644 index 000000000000..ce3aff174698 --- /dev/null +++ b/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieInspectionRunner.html @@ -0,0 +1,26 @@ + + +Write your description here. +Start the description with a verb in 3rd person singular, like reports, detects, highlights. +In the first sentence, briefly explain what exactly the inspection helps you detect. +Make sure the sentence is not very long and complicated. +

+ The first sentence must be in a dedicated paragraph separated from the rest of the text. This will make the description easier to read. + Make sure the description doesn’t just repeat the inspection title. +

+

+ See https://plugins.jetbrains.com/docs/intellij/inspections.html#descriptions for more information. +

+

+ Embed code snippets: +

+

+// automatically highlighted according to inspection registration 'language' attribute
+
+ +

Text after this comment will only be shown in the settings of the inspection.

+ +

To open related settings directly from the description, add a link with `settings://$` optionally followed by `?$` to pre-select a UI + element.

+ + \ No newline at end of file diff --git a/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieStyle.html b/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieStyle.html new file mode 100644 index 000000000000..95c9ffe46ad8 --- /dev/null +++ b/plugins/grazie/src/main/resources/inspectionDescriptions/GrazieStyle.html @@ -0,0 +1,18 @@ + + +Check the writing style defined in: +
    +
  • + Grazie rule files (e.g. .grazie.en.yaml for English) + for this project or its specific subdirectories. + To create such a file, invoke New menu on any (e.g. root) directory of the project. +
  • +
  • + Style rules in Editor | Natural languages | Rules settings +
  • +
+ +This inspection only returns results via Code | Analyze Code | Run Inspection By Name... or in offline analysis. +Editor highlighting of style issues is performed independently of this inspection's settings. + + \ No newline at end of file diff --git a/plugins/grazie/src/test/kotlin/com/intellij/grazie/GrazieTestBase.kt b/plugins/grazie/src/test/kotlin/com/intellij/grazie/GrazieTestBase.kt index 1c1ec7ddedb6..e93e42b6e68e 100644 --- a/plugins/grazie/src/test/kotlin/com/intellij/grazie/GrazieTestBase.kt +++ b/plugins/grazie/src/test/kotlin/com/intellij/grazie/GrazieTestBase.kt @@ -10,7 +10,6 @@ import com.intellij.grazie.jlanguage.Lang import com.intellij.grazie.remote.HunspellDescriptor import com.intellij.grazie.spellcheck.GrazieCheckers import com.intellij.grazie.spellcheck.GrazieSpellCheckingInspection -import com.intellij.grazie.style.StyleInspection import com.intellij.grazie.text.TextChecker import com.intellij.grazie.text.TextContent import com.intellij.grazie.text.TextExtractor @@ -39,8 +38,8 @@ import kotlin.io.path.Path abstract class GrazieTestBase : BasePlatformTestCase() { companion object { - val inspectionTools by lazy { - arrayOf(GrazieInspection(), GrazieSpellCheckingInspection(), StyleInspection()) + val inspectionTools: Array by lazy { + arrayOf(GrazieInspection(), GrazieInspection.Grammar(), GrazieInspection.Style(), GrazieSpellCheckingInspection()) } /** diff --git a/plugins/grazie/src/test/kotlin/com/intellij/grazie/ide/language/ReportingTest.kt b/plugins/grazie/src/test/kotlin/com/intellij/grazie/ide/language/ReportingTest.kt index 22bfc384e274..134cadb72f05 100644 --- a/plugins/grazie/src/test/kotlin/com/intellij/grazie/ide/language/ReportingTest.kt +++ b/plugins/grazie/src/test/kotlin/com/intellij/grazie/ide/language/ReportingTest.kt @@ -10,6 +10,7 @@ import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.grazie.GrazieBundle import com.intellij.grazie.GrazieTestBase +import com.intellij.grazie.ide.TextProblemSeverities import com.intellij.grazie.ide.inspection.grammar.GrazieInspection import com.intellij.grazie.ide.inspection.grammar.quickfix.GrazieReplaceTypoQuickFix import com.intellij.grazie.text.* @@ -33,9 +34,11 @@ class ReportingTest : BasePlatformTestCase() { fun `test tooltip and description texts in inspection`() { val inspection = GrazieInspection() - myFixture.enableInspections(inspection) + myFixture.enableInspections(inspection, GrazieInspection.Grammar()) myFixture.configureByText("a.txt", "I have an new apple here.") - val info = assertOneElement(myFixture.doHighlighting().filter { it.inspectionToolId == inspection.id }) + val highlightings = myFixture.doHighlighting().filter { it.inspectionToolId == inspection.id } + val info = assertOneElement(highlightings) + assertEquals(TextProblemSeverities.GRAMMAR_ERROR_ATTRIBUTES, info.type.attributesKey) val message = "Use a instead of 'an' if the following word doesn't start with a vowel sound, e.g. 'a sentence', 'a university'." assertEquals(info.description, message) assertTrue(info.toolTip, info.toolTip!!.matches(Regex(".*" + Regex.escape(message) + ".*Powered by LanguageTool.*"))) @@ -50,7 +53,7 @@ class ReportingTest : BasePlatformTestCase() { } fun `test changed range highlighting`() { - myFixture.enableInspections(GrazieInspection::class.java) + myFixture.enableInspections(GrazieInspection::class.java, GrazieInspection.Grammar::class.java) myFixture.configureByText("a.txt", "Hello there! You are best person!") myFixture.checkHighlighting() @@ -101,7 +104,7 @@ class ReportingTest : BasePlatformTestCase() { } fun `test quick fix sorting`() { - myFixture.enableInspections(GrazieInspection()) + myFixture.enableInspections(GrazieInspection(), GrazieInspection.Grammar()) val testChecker = object: TextChecker() { override fun getRules(locale: Locale) = emptyList() diff --git a/plugins/grazie/src/test/kotlin/com/intellij/grazie/suppression/SuppressionTests.kt b/plugins/grazie/src/test/kotlin/com/intellij/grazie/suppression/SuppressionTests.kt new file mode 100644 index 000000000000..b2777b1d819d --- /dev/null +++ b/plugins/grazie/src/test/kotlin/com/intellij/grazie/suppression/SuppressionTests.kt @@ -0,0 +1,95 @@ +package com.intellij.grazie.suppression + +import com.intellij.grazie.GrazieTestBase +import com.intellij.grazie.ide.inspection.grammar.GrazieInspection +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_LATEST + +class SuppressionTests: GrazieTestBase() { + + override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_LATEST + + fun `test suppressing style inspection doesn't affect grammar issues`() { + myFixture.configureByText("A.java", """ + class A { + // Show is cancelled because of an cat + @SuppressWarnings("GrazieStyle") + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + } + + fun `test suppressing grammar inspection doesn't affect style issues`() { + myFixture.configureByText("A.java", """ + class A { + // Show is cancelled because of an cat + @SuppressWarnings("GrazieInspection") + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + } + + fun `test suppress style action generates necessary inspection id`() { + myFixture.configureByText("Class.java", """ + public class Class { + // Show is cancelled + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + val intention = myFixture.getAvailableIntention("Suppress for method") + assertNotNull(intention) + myFixture.launchAction(intention!!) + myFixture.checkResult(""" + public class Class { + // Show is cancelled + @SuppressWarnings("GrazieStyle") + public static void main() {} + } + """.trimIndent()) + } + + fun `test suppress grammar action generates necessary inspection id`() { + myFixture.configureByText("Class.java", """ + public class Class { + // There is an cat + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + val intention = myFixture.getAvailableIntention("Suppress for class") + assertNotNull(intention) + myFixture.launchAction(intention!!) + myFixture.checkResult(""" + @SuppressWarnings("GrazieInspection") + public class Class { + // There is an cat + public static void main() {} + } + """.trimIndent()) + } + + fun `test disabling grammar inspection`() { + myFixture.disableInspections(GrazieInspection.Grammar()) + myFixture.configureByText("Class.java", """ + public class Class { + // Show is cancelled because of an cat + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + } + + fun `test disabling style inspection`() { + myFixture.disableInspections(GrazieInspection.Style()) + myFixture.configureByText("Class.java", """ + public class Class { + // Show is cancelled because of an cat + public static void main() {} + } + """.trimIndent()) + myFixture.checkHighlighting() + } +} \ No newline at end of file