grazie: convert JS/JSON/Yaml/Python grammar checking strategies to the new API

GitOrigin-RevId: f44abcb998400815f4a26f2afcde7df4c6779994
This commit is contained in:
Peter Gromov
2021-05-31 19:32:58 +02:00
committed by intellij-monorepo-bot
parent ee64710f73
commit e7b81fe125
9 changed files with 97 additions and 105 deletions

View File

@@ -1,16 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.json
import com.intellij.grazie.grammar.strategy.GrammarCheckingStrategy
import com.intellij.grazie.grammar.strategy.GrammarCheckingStrategy.TextDomain
import com.intellij.grazie.grammar.strategy.StrategyUtils
import com.intellij.grazie.grammar.strategy.impl.RuleGroup
import com.intellij.psi.PsiElement
class JsonGrammarCheckingStrategy : GrammarCheckingStrategy {
override fun isMyContextRoot(element: PsiElement) = getContextRootTextDomain(element) != TextDomain.NON_TEXT
override fun getContextRootTextDomain(root: PsiElement) = StrategyUtils.getTextDomainOrDefault(this, root, default = TextDomain.NON_TEXT)
override fun getIgnoredRuleGroup(root: PsiElement, child: PsiElement) = RuleGroup.CASING
}

View File

@@ -0,0 +1,21 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.json
import com.intellij.grazie.text.*
import com.intellij.json.psi.JsonStringLiteral
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
class JsonTextExtractor : TextExtractor() {
override fun buildTextContent(element: PsiElement, allowedDomains: MutableSet<TextContent.TextDomain>): TextContent? {
if (element is PsiComment || element is JsonStringLiteral) {
val domain = if (element is PsiComment) TextContent.TextDomain.COMMENTS else TextContent.TextDomain.LITERALS
return TextContentBuilder.FromPsi.build(element, domain)
}
return null
}
}
class JsonProblemFilter : ProblemFilter() {
override fun shouldIgnore(problem: TextProblem): Boolean = problem.fitsGroup(RuleGroup.CASING)
}

View File

@@ -4,6 +4,7 @@
</dependencies>
<extensions defaultExtensionNs="com.intellij.grazie">
<grammar.strategy language="JSON" implementationClass="com.intellij.grazie.ide.language.json.JsonGrammarCheckingStrategy"/>
<textExtractor language="JSON" implementationClass="com.intellij.grazie.ide.language.json.JsonTextExtractor"/>
<problemFilter language="JSON" implementationClass="com.intellij.grazie.ide.language.json.JsonProblemFilter"/>
</extensions>
</idea-plugin>

View File

@@ -1,42 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.yaml
import com.intellij.grazie.grammar.strategy.BaseGrammarCheckingStrategy
import com.intellij.grazie.grammar.strategy.GrammarCheckingStrategy.TextDomain
import com.intellij.grazie.grammar.strategy.StrategyUtils
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.PsiCommentImpl
import com.intellij.psi.tree.TokenSet
import com.intellij.psi.util.elementType
import org.jetbrains.yaml.YAMLTokenTypes.*
class YamlGrammarCheckingStrategy : BaseGrammarCheckingStrategy {
override fun isMyContextRoot(element: PsiElement) = getContextRootTextDomain(element) != TextDomain.NON_TEXT
override fun getContextRootTextDomain(root: PsiElement) = when (root.node.elementType) {
COMMENT -> TextDomain.COMMENTS
TEXT, SCALAR_STRING, SCALAR_DSTRING, SCALAR_LIST, SCALAR_TEXT -> TextDomain.LITERALS
else -> TextDomain.NON_TEXT
}
override fun isStealth(element: PsiElement) = when (element.node.elementType) {
INDENT -> true
SCALAR_LIST -> element.textLength == 1 && element.textContains('|')
SCALAR_TEXT -> element.textLength == 1 && element.textContains('>')
else -> false
}
override fun getStealthyRanges(root: PsiElement, text: CharSequence) = when (root) {
is PsiCommentImpl -> StrategyUtils.indentIndexes(text, setOf(' ', '\t', '#'))
else -> StrategyUtils.emptyLinkedSet()
}
override fun getWhiteSpaceTokens() = TokenSet.create(WHITESPACE, INDENT, EOL)
override fun getRootsChain(root: PsiElement): List<PsiElement> {
return if (root.elementType == COMMENT) {
StrategyUtils.getNotSoDistantSiblingsOfTypes(this, root, setOf(COMMENT)).toList()
}
else super.getRootsChain(root)
}
}

View File

@@ -0,0 +1,34 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.yaml
import com.intellij.grazie.text.TextContent
import com.intellij.grazie.text.TextContentBuilder
import com.intellij.grazie.text.TextExtractor
import com.intellij.grazie.utils.getNotSoDistantSimilarSiblings
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet
import com.intellij.psi.util.elementType
import org.jetbrains.yaml.YAMLTokenTypes.*
class YamlTextExtractor : TextExtractor() {
private val commentBuilder = TextContentBuilder.FromPsi.removingIndents(" \t#")
override fun buildTextContent(root: PsiElement, allowedDomains: MutableSet<TextContent.TextDomain>): TextContent? {
when (root.node.elementType) {
COMMENT -> {
val siblings = getNotSoDistantSimilarSiblings(root, TokenSet.create(WHITESPACE, INDENT, EOL)) { it.elementType == COMMENT }
return TextContent.joinWithWhitespace(siblings.mapNotNull { commentBuilder.build(it, TextContent.TextDomain.COMMENTS) })
}
TEXT, SCALAR_STRING, SCALAR_DSTRING, SCALAR_LIST, SCALAR_TEXT ->
return TextContentBuilder.FromPsi.excluding { isStealth(it) }.build(root, TextContent.TextDomain.LITERALS)
else -> return null
}
}
private fun isStealth(element: PsiElement) = when (element.node.elementType) {
INDENT -> true
SCALAR_LIST -> element.textLength == 1 && element.textContains('|')
SCALAR_TEXT -> element.textLength == 1 && element.textContains('>')
else -> false
}
}

View File

@@ -4,6 +4,6 @@
</dependencies>
<extensions defaultExtensionNs="com.intellij.grazie">
<grammar.strategy language="yaml" implementationClass="com.intellij.grazie.ide.language.yaml.YamlGrammarCheckingStrategy"/>
<textExtractor language="yaml" implementationClass="com.intellij.grazie.ide.language.yaml.YamlTextExtractor"/>
</extensions>
</idea-plugin>

View File

@@ -1,5 +1,6 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij.grazie">
<grammar.strategy language="Python" implementationClass="com.intellij.grazie.ide.language.python.PythonGrammarCheckingStrategy"/>
<textExtractor language="Python" implementationClass="com.intellij.grazie.ide.language.python.PythonTextExtractor"/>
<problemFilter language="Python" implementationClass="com.intellij.grazie.text.LiteralProblemFilter"/>
</extensions>
</idea-plugin>

View File

@@ -1,44 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.python
import com.intellij.grazie.grammar.strategy.BaseGrammarCheckingStrategy
import com.intellij.grazie.grammar.strategy.GrammarCheckingStrategy
import com.intellij.grazie.grammar.strategy.StrategyUtils
import com.intellij.grazie.grammar.strategy.impl.RuleGroup
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.impl.source.tree.PsiCommentImpl
import com.intellij.psi.util.elementType
import com.jetbrains.python.PyTokenTypes
import com.jetbrains.python.PyTokenTypes.FSTRING_TEXT
import com.jetbrains.python.psi.PyFormattedStringElement
import com.jetbrains.python.psi.PyStringLiteralExpression
internal class PythonGrammarCheckingStrategy : BaseGrammarCheckingStrategy {
override fun isMyContextRoot(element: PsiElement) = element is PsiCommentImpl || element.elementType in PyTokenTypes.STRING_NODES
override fun getContextRootTextDomain(root: PsiElement) = when (root.elementType) {
PyTokenTypes.DOCSTRING -> GrammarCheckingStrategy.TextDomain.DOCS
PyTokenTypes.END_OF_LINE_COMMENT -> GrammarCheckingStrategy.TextDomain.COMMENTS
in PyTokenTypes.STRING_NODES -> GrammarCheckingStrategy.TextDomain.LITERALS
else -> GrammarCheckingStrategy.TextDomain.NON_TEXT
}
override fun isAbsorb(element: PsiElement): Boolean {
if (element.parent is PyFormattedStringElement) {
return element !is LeafPsiElement || element.elementType != FSTRING_TEXT
}
return false
}
override fun getIgnoredRuleGroup(root: PsiElement, child: PsiElement) = if (root is PyStringLiteralExpression) {
RuleGroup.LITERALS
}
else null
override fun getStealthyRanges(root: PsiElement, text: CharSequence) = when (root) {
is PsiCommentImpl -> StrategyUtils.indentIndexes(text, setOf(' ', '\t', '#'))
else -> StrategyUtils.indentIndexes(text, setOf(' ', '\t'))
}
}

View File

@@ -0,0 +1,37 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.grazie.ide.language.python
import com.intellij.grazie.text.TextContent
import com.intellij.grazie.text.TextContentBuilder
import com.intellij.grazie.text.TextExtractor
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.impl.source.tree.PsiCommentImpl
import com.intellij.psi.util.elementType
import com.jetbrains.python.PyTokenTypes
import com.jetbrains.python.PyTokenTypes.FSTRING_TEXT
import com.jetbrains.python.psi.PyFormattedStringElement
internal class PythonTextExtractor : TextExtractor() {
override fun buildTextContent(root: PsiElement, allowedDomains: MutableSet<TextContent.TextDomain>): TextContent? {
val elementType = root.elementType
if (elementType in PyTokenTypes.STRING_NODES) {
val domain = if (elementType == PyTokenTypes.DOCSTRING) TextContent.TextDomain.DOCUMENTATION else TextContent.TextDomain.LITERALS
return TextContentBuilder.FromPsi.removingIndents(" \t").withUnknown(this::isUnknownFragment).build(root.parent, domain)
}
if (root is PsiCommentImpl) {
return TextContentBuilder.FromPsi.removingIndents(" \t#").build(root, TextContent.TextDomain.COMMENTS)
}
return null
}
private fun isUnknownFragment(element: PsiElement): Boolean {
if (element.parent is PyFormattedStringElement) {
return element !is LeafPsiElement || element.elementType != FSTRING_TEXT
}
return false
}
}