Skip to content

Commit 0adff04

Browse files
committed
suppress error highlighting if error intersects template string argument
1 parent 27bb538 commit 0adff04

File tree

6 files changed

+100
-1
lines changed

6 files changed

+100
-1
lines changed

src/main/kotlin/com/intellij/StyledComponents/InjectionUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package com.intellij.StyledComponents
33
import com.intellij.lang.javascript.JSTokenTypes
44
import com.intellij.lang.javascript.psi.JSLiteralExpression
55
import com.intellij.lang.javascript.psi.ecma6.JSStringTemplateExpression
6+
import com.intellij.openapi.util.Key
67
import com.intellij.openapi.util.TextRange
78
import com.intellij.util.ArrayUtil
89
import com.intellij.util.containers.ContainerUtil
910
import java.util.ArrayList
1011

12+
val INJECTED_FILE_RANGES_KEY = Key<List<TextRange>?>("INJECTED_FILE_RANGES_KEY")
1113
private val EXTERNAL_FRAGMENT = "EXTERNAL_FRAGMENT"
1214

1315
fun getInjectionPlaces(myQuotedLiteral: JSLiteralExpression): List<StringPlace> {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.intellij.StyledComponents
2+
3+
import com.intellij.codeInsight.daemon.impl.HighlightInfo
4+
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter
5+
import com.intellij.codeInsight.highlighting.HighlightErrorFilter
6+
import com.intellij.lang.annotation.HighlightSeverity
7+
import com.intellij.psi.PsiErrorElement
8+
import com.intellij.psi.PsiFile
9+
10+
class InterpolationArgumentsErrorFilter : HighlightErrorFilter(), HighlightInfoFilter {
11+
override fun shouldHighlightErrorElement(element: PsiErrorElement): Boolean {
12+
val acceptedRanges = element.containingFile.getUserData(INJECTED_FILE_RANGES_KEY)
13+
if (acceptedRanges == null) {
14+
return true
15+
}
16+
return acceptedRanges.any { range -> range.contains(element.textRange) }
17+
}
18+
19+
override fun accept(highlightInfo: HighlightInfo, file: PsiFile?): Boolean {
20+
val acceptedRanges = file?.getUserData(INJECTED_FILE_RANGES_KEY)
21+
if (acceptedRanges == null) {
22+
return true
23+
}
24+
if (highlightInfo.severity === HighlightSeverity.WARNING
25+
|| highlightInfo.severity === HighlightSeverity.WEAK_WARNING
26+
|| highlightInfo.severity === HighlightSeverity.ERROR) {
27+
return acceptedRanges.any { range ->
28+
highlightInfo.startOffset > range.startOffset
29+
&& highlightInfo.endOffset < range.endOffset
30+
}
31+
}
32+
return true
33+
}
34+
35+
}
36+

src/main/kotlin/com/intellij/StyledComponents/StyledComponentsInjector.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ import com.intellij.lang.injection.MultiHostInjector
44
import com.intellij.lang.injection.MultiHostRegistrar
55
import com.intellij.lang.javascript.psi.JSExpression
66
import com.intellij.lang.javascript.psi.ecma6.JSStringTemplateExpression
7+
import com.intellij.openapi.util.Pair
8+
import com.intellij.openapi.util.TextRange
79
import com.intellij.patterns.ElementPattern
810
import com.intellij.patterns.PlatformPatterns
911
import com.intellij.psi.PsiElement
12+
import com.intellij.psi.PsiFile
13+
import com.intellij.psi.impl.source.tree.injected.MultiHostRegistrarImpl
14+
import com.intellij.psi.impl.source.tree.injected.Place
1015
import org.jetbrains.plugins.less.LESSLanguage
1116

1217
class StyledComponentsInjector : MultiHostInjector {
@@ -40,11 +45,22 @@ class StyledComponentsInjector : MultiHostInjector {
4045
registrar.addPlace(thePrefix, theSuffix, injectionHost, range)
4146
}
4247
registrar.doneInjecting()
48+
val result = getInjectionResult(registrar) ?: return
49+
val injectedFile = result.second
50+
val injectedFileRanges = result.first.map { TextRange(it.range.startOffset, it.range.endOffset - it.suffix.length) }
51+
52+
if (injectedFileRanges.size > 1) {
53+
injectedFile.putUserData(INJECTED_FILE_RANGES_KEY, injectedFileRanges)
54+
}
4355
}
56+
}
4457

58+
private fun getInjectionResult(registrar: MultiHostRegistrar): Pair<Place, PsiFile>? {
59+
val result = (registrar as MultiHostRegistrarImpl).result
60+
return if (result == null || result.isEmpty()) null
61+
else result[result.size - 1]
4562
}
4663
data class PlaceInfo(val elementPattern: ElementPattern<JSStringTemplateExpression>,
4764
val prefix: String? = null,
4865
val suffix: String? = null)
49-
5066
}

src/main/resources/META-INF/plugin.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@
2424

2525
<extensions defaultExtensionNs="com.intellij">
2626
<multiHostInjector implementation="com.intellij.StyledComponents.StyledComponentsInjector"/>
27+
<highlightErrorFilter implementation="com.intellij.StyledComponents.InterpolationArgumentsErrorFilter"/>
28+
<daemon.highlightInfoFilter implementation="com.intellij.StyledComponents.InterpolationArgumentsErrorFilter"/>
2729
</extensions>
2830
</idea-plugin>

src/test/HighlightingTest.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import com.intellij.psi.css.inspections.invalid.CssInvalidPropertyValueInspection
2+
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
3+
4+
class HighlightingTest : LightCodeInsightFixtureTestCase() {
5+
6+
fun testWithoutArguments_ErrorsHighlighted() {
7+
myFixture.enableInspections(CssInvalidPropertyValueInspection::class.java)
8+
doTest("var someCss = css`div {\n" +
9+
" color:<error descr=\"a term expected\"> </error>{}\n" +
10+
"<error descr=\"Unexpected terms\">}</error>;`")
11+
}
12+
13+
fun testErrorSurroundsInterpolationArgument_NotHighlighted() {
14+
myFixture.enableInspections(CssInvalidPropertyValueInspection::class.java)
15+
doTest("var someCss = css`\n" +
16+
"//should not highlight\n" +
17+
"withArgument{\n" +
18+
" border: 5px \${foobar} red;\n" +
19+
"},\n" +
20+
"//should highlight\n" +
21+
"withoutArgument {\n" +
22+
" border: 5px<error> foobar-not-acceptable red</error>;\n" +
23+
"};;`")
24+
}
25+
26+
fun testErrorAdjacentToInterpolationArgument_NotHighlighted() {
27+
doTest("var styledSomething = styled.something`\n" +
28+
" perspective: 1000px;\n" +
29+
" \${value}\n" +
30+
" \${anotherValue}\n" +
31+
"`\n" +
32+
"const Triangle = styled.span`\n" +
33+
" \${({ right }) => (right ? 'right: 0;' : 'left: 0;')}\n" +
34+
"`")
35+
}
36+
37+
private fun doTest(expected: String) {
38+
myFixture.setCaresAboutInjection(false)
39+
myFixture.configureByText("dummy.es6", expected)
40+
myFixture.testHighlighting(true, false, true)
41+
}
42+
43+
}

webstorm-styled-components.zip

3.09 KB
Binary file not shown.

0 commit comments

Comments
 (0)