diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/inspection/GraphQLInspectionSuppressor.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/inspection/GraphQLInspectionSuppressor.kt new file mode 100644 index 00000000000..82f5495d814 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/inspection/GraphQLInspectionSuppressor.kt @@ -0,0 +1,52 @@ +package com.apollographql.ijplugin.inspection + +import com.apollographql.ijplugin.ApolloBundle +import com.intellij.codeInspection.InspectionSuppressor +import com.intellij.codeInspection.SuppressQuickFix +import com.intellij.codeInspection.SuppressionUtil +import com.intellij.lang.jsgraphql.ide.validation.fixes.GraphQLSuppressByCommentFix +import com.intellij.lang.jsgraphql.psi.GraphQLField +import com.intellij.psi.PsiComment +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import java.util.regex.Pattern + +private val SUPPRESS_IN_LINE_COMMENT_PATTERN = Pattern.compile("#" + SuppressionUtil.COMMON_SUPPRESS_REGEXP) + +class GraphQLInspectionSuppressor : InspectionSuppressor { + override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean { + return element.isSuppressedOnSelfOrParent(toolId, SUPPRESS_IN_LINE_COMMENT_PATTERN) + } + + override fun getSuppressActions( + element: PsiElement?, + toolId: String, + ): Array { + return if (element == null) { + SuppressQuickFix.EMPTY_ARRAY + } else { + arrayOf( + GraphQLSuppressByCommentFix(toolId, GraphQLField::class.java, ApolloBundle.message("inspection.suppress.field")), + ) + } + } +} + +fun PsiElement.isSuppressedOnSelfOrParent( + toolId: String, + suppressInLineCommentPattern: Pattern, +): Boolean { + var element: PsiElement? = this + while (element != null) { + val prev = PsiTreeUtil.skipWhitespacesBackward(element) + if (prev is PsiComment) { + val text = prev.getText() + val matcher = suppressInLineCommentPattern.matcher(text) + if (matcher.matches() && SuppressionUtil.isInspectionToolIdMentioned(matcher.group(1), toolId)) { + return true + } + } + element = element.parent + } + return false +} diff --git a/intellij-plugin/src/main/resources/META-INF/plugin.xml b/intellij-plugin/src/main/resources/META-INF/plugin.xml index 451f0e95a75..208ce8b9937 100644 --- a/intellij-plugin/src/main/resources/META-INF/plugin.xml +++ b/intellij-plugin/src/main/resources/META-INF/plugin.xml @@ -152,6 +152,12 @@ level="INFO" /> + + + 3 }) + // barkVolume is unused, but the inspection is suppressed + assertTrue(highlightInfos.none { it.description == "Unused field" && it.text == "barkVolume"}) moveCaret("id") @@ -39,6 +41,7 @@ class ApolloUnusedFieldInspectionTest : ApolloTestCase() { } ... on dog { id + # noinspection ApolloUnusedField barkVolume fieldOnDogAndCat } @@ -72,6 +75,7 @@ class ApolloUnusedFieldInspectionTest : ApolloTestCase() { name ... on dog { id + # noinspection ApolloUnusedField barkVolume fieldOnDogAndCat } diff --git a/tests/intellij-plugin-test-project/src/main/graphql/AnimalsQuery.graphql b/tests/intellij-plugin-test-project/src/main/graphql/AnimalsQuery.graphql index e9e02262321..05b6676b09c 100644 --- a/tests/intellij-plugin-test-project/src/main/graphql/AnimalsQuery.graphql +++ b/tests/intellij-plugin-test-project/src/main/graphql/AnimalsQuery.graphql @@ -8,6 +8,7 @@ query animals { } ... on dog { id + # noinspection ApolloUnusedField barkVolume fieldOnDogAndCat }