Report highlight errors to WolfTheProblemSolver
Relates to #KT-37702 #KTIJ-1246 Fixed Original commit: bd222a5255c2fd6f4abfce3115f81733ef9a39f3
This commit is contained in:
committed by
Space
parent
afe71f5d59
commit
8783ebc352
@@ -324,6 +324,10 @@ fun main(args: Array<String>) {
|
||||
model("checker/diagnosticsMessage")
|
||||
}
|
||||
|
||||
testClass<AbstractKotlinHighlightWolfPassTest> {
|
||||
model("checker/wolf")
|
||||
}
|
||||
|
||||
testClass<AbstractJavaAgainstKotlinSourceCheckerTest> {
|
||||
model("kotlinAndJavaChecker/javaAgainstKotlin")
|
||||
model("kotlinAndJavaChecker/javaWithKotlin")
|
||||
|
||||
+39
@@ -6,15 +6,23 @@
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.Divider
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.problems.ProblemImpl
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.problems.Problem
|
||||
import com.intellij.problems.WolfTheProblemSolver
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.util.CommonProcessors
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -44,6 +52,12 @@ abstract class AbstractKotlinHighlightingPass(file: KtFile, document: Document)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doApplyInformationToEditor() {
|
||||
super.doApplyInformationToEditor()
|
||||
|
||||
reportErrorsToWolf()
|
||||
}
|
||||
|
||||
override fun buildBindingContext(holder: AnnotationHolder): BindingContext {
|
||||
val dividedElements: List<Divider.DividedElements> = ArrayList()
|
||||
Divider.divideInsideAndOutsideAllRoots(
|
||||
@@ -153,6 +167,31 @@ abstract class AbstractKotlinHighlightingPass(file: KtFile, document: Document)
|
||||
|
||||
protected open fun shouldSuppressUnusedParameter(parameter: KtParameter): Boolean = false
|
||||
|
||||
private fun reportErrorsToWolf() {
|
||||
if (!file.viewProvider.isPhysical) return // e.g. errors in evaluate expression
|
||||
val project: Project = file.project
|
||||
if (!PsiManager.getInstance(project).isInProject(file)) return // do not report problems in libraries
|
||||
val file: VirtualFile = file.virtualFile ?: return
|
||||
|
||||
val wolf = WolfTheProblemSolver.getInstance(project)
|
||||
|
||||
val hasSyntaxErrors = wolf.hasSyntaxErrors(file)
|
||||
val problemFile = wolf.isProblemFile(file)
|
||||
|
||||
// do nothing if file has already problems
|
||||
if (hasSyntaxErrors || problemFile) return
|
||||
|
||||
val problems = convertToProblems(infos, file)
|
||||
wolf.reportProblems(file, problems)
|
||||
}
|
||||
|
||||
private fun convertToProblems(
|
||||
infos: Collection<HighlightInfo>,
|
||||
file: VirtualFile,
|
||||
hasErrorElement: Boolean = true
|
||||
): List<Problem> =
|
||||
infos.filter { it.severity == HighlightSeverity.ERROR }.map { ProblemImpl(file, it, hasErrorElement) }
|
||||
|
||||
companion object {
|
||||
fun createQuickFixes(diagnostic: Diagnostic): Collection<IntentionAction> =
|
||||
createQuickFixes(listOfNotNull(diagnostic))[diagnostic]
|
||||
|
||||
-1
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// HAS-WOLF-ERRORS: true
|
||||
// TYPE: .map
|
||||
fun diagnostic(): String = ""<caret>
|
||||
@@ -0,0 +1,5 @@
|
||||
// WOLF-ERRORS: true
|
||||
// HAS-WOLF-ERRORS: true
|
||||
// TYPE: asd
|
||||
// ERROR: Overload resolution ambiguity: <br>public final operator fun plus(other: Byte): Int defined in kotlin.Int<br>public final operator fun plus(other: Double): Double defined in kotlin.Int<br>public final operator fun plus(other: Float): Float defined in kotlin.Int<br>public final operator fun plus(other: Int): Int defined in kotlin.Int<br>public final operator fun plus(other: Long): Long defined in kotlin.Int<br>public final operator fun plus(other: Short): Int defined in kotlin.Int
|
||||
fun diagnosticAfterSyntax(): Int = 42 + <caret>
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
// HAS-WOLF-ERRORS: false
|
||||
// TYPE: +1
|
||||
fun none(): Int = 42<caret>
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
// HAS-WOLF-ERRORS: true
|
||||
// TYPE: +
|
||||
fun syntax(): Int = 42<caret>
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.jetbrains.kotlin.checkers
|
||||
|
||||
import com.intellij.codeInsight.problems.MockWolfTheProblemSolver
|
||||
import com.intellij.codeInsight.problems.WolfTheProblemSolverImpl
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.problems.ProblemListener
|
||||
import com.intellij.problems.WolfTheProblemSolver
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import com.intellij.util.ThrowableRunnable
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||
import org.jetbrains.kotlin.idea.codeInsight.AbstractOutOfBlockModificationTest
|
||||
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils.checkForUnexpectedErrors
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.runAll
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
|
||||
abstract class AbstractKotlinHighlightWolfPassTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
|
||||
private val disposable = Disposer.newDisposable("wolfTheProblemSolverParentDisposable")
|
||||
private var wolfTheProblemSolver: MockWolfTheProblemSolver? = null
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
wolfTheProblemSolver = prepareWolf(project, disposable)
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
runAll(
|
||||
// TODO: [VD] HAS TO BE UNCOMMENTED with 211
|
||||
//ThrowableRunnable { wolfTheProblemSolver?.resetDelegate() },
|
||||
ThrowableRunnable { Disposer.dispose(disposable) },
|
||||
ThrowableRunnable { super.tearDown() },
|
||||
)
|
||||
}
|
||||
|
||||
private fun prepareWolf(project: Project, parentDisposable: Disposable): MockWolfTheProblemSolver {
|
||||
val wolfTheProblemSolver = WolfTheProblemSolver.getInstance(project) as MockWolfTheProblemSolver
|
||||
|
||||
// TODO: [VD] HAS TO BE UNCOMMENTED with 211
|
||||
// val theRealSolver = WolfTheProblemSolverImpl.createInstance(project)
|
||||
// wolfTheProblemSolver.setDelegate(theRealSolver)
|
||||
// Disposer.register(parentDisposable, (theRealSolver as Disposable))
|
||||
|
||||
return wolfTheProblemSolver
|
||||
}
|
||||
|
||||
open fun doTest(filePath: String) {
|
||||
myFixture.configureByFile(fileName())
|
||||
val ktFile = file as KtFile
|
||||
|
||||
myFixture.doHighlighting()
|
||||
// have to analyze file before any change to support incremental analysis
|
||||
val diagnosticsProvider: (KtFile) -> Diagnostics = { it.analyzeWithAllCompilerChecks().bindingContext.diagnostics }
|
||||
checkForUnexpectedErrors(ktFile, diagnosticsProvider)
|
||||
val wolf = WolfTheProblemSolver.getInstance(project)
|
||||
val virtualFile = ktFile.virtualFile
|
||||
val initialWolfErrors = wolfErrors(myFixture)
|
||||
// TODO: [VD] HAS TO BE UNCOMMENTED with 211
|
||||
//TestCase.assertEquals(initialWolfErrors, wolf.isProblemFile(virtualFile) || wolf.hasSyntaxErrors(virtualFile))
|
||||
|
||||
var problemsAppeared = 0
|
||||
var problemsChanged = 0
|
||||
var problemsDisappeared = 0
|
||||
|
||||
project.messageBus.connect(disposable).subscribe(ProblemListener.TOPIC, object : ProblemListener {
|
||||
override fun problemsAppeared(file: VirtualFile) {
|
||||
problemsAppeared++
|
||||
}
|
||||
|
||||
override fun problemsChanged(file: VirtualFile) {
|
||||
problemsChanged++
|
||||
}
|
||||
|
||||
override fun problemsDisappeared(file: VirtualFile) {
|
||||
problemsDisappeared++
|
||||
}
|
||||
})
|
||||
myFixture.type(AbstractOutOfBlockModificationTest.stringToType(myFixture))
|
||||
PsiDocumentManager.getInstance(project).commitDocument(myFixture.getDocument(ktFile))
|
||||
myFixture.doHighlighting()
|
||||
|
||||
// TODO: [VD] HAS TO BE UNCOMMENTED with 211
|
||||
// val hasWolfErrors = hasWolfErrors(myFixture)
|
||||
// assertEquals(hasWolfErrors, wolf.isProblemFile(virtualFile) || wolf.hasSyntaxErrors(virtualFile))
|
||||
// if (hasWolfErrors) {
|
||||
// TestCase.assertTrue(problemsAppeared > 0)
|
||||
// } else {
|
||||
// assertEquals(0, problemsAppeared)
|
||||
// }
|
||||
// assertEquals(if (initialWolfErrors) 1 else 0, problemsDisappeared)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val HAS_WOLF_ERRORS_DIRECTIVE = "HAS-WOLF-ERRORS:"
|
||||
|
||||
fun hasWolfErrors(fixture: JavaCodeInsightTestFixture): Boolean = findBooleanDirective(fixture, HAS_WOLF_ERRORS_DIRECTIVE)
|
||||
|
||||
private const val WOLF_ERRORS_DIRECTIVE = "WOLF-ERRORS:"
|
||||
|
||||
fun wolfErrors(fixture: JavaCodeInsightTestFixture): Boolean = findBooleanDirective(fixture, WOLF_ERRORS_DIRECTIVE)
|
||||
|
||||
private fun findBooleanDirective(
|
||||
fixture: JavaCodeInsightTestFixture,
|
||||
wolfErrorsDirective: String
|
||||
): Boolean {
|
||||
val text = fixture.getDocument(fixture.file).text
|
||||
return InTextDirectivesUtils.findStringWithPrefixes(text, wolfErrorsDirective) == "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.checkers;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/checker/wolf")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class KotlinHighlightWolfPassTestGenerated extends AbstractKotlinHighlightWolfPassTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInWolf() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/checker/wolf"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("diagnostic.kt")
|
||||
public void testDiagnostic() throws Exception {
|
||||
runTest("idea/testData/checker/wolf/diagnostic.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("diagnosticAfterSyntax.kt")
|
||||
public void testDiagnosticAfterSyntax() throws Exception {
|
||||
runTest("idea/testData/checker/wolf/diagnosticAfterSyntax.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("none.kt")
|
||||
public void testNone() throws Exception {
|
||||
runTest("idea/testData/checker/wolf/none.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("syntax.kt")
|
||||
public void testSyntax() throws Exception {
|
||||
runTest("idea/testData/checker/wolf/syntax.kt");
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -13,6 +13,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import org.jetbrains.kotlin.idea.FrontendInternals
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
@@ -52,7 +53,7 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
|
||||
// have to analyze file before any change to support incremental analysis
|
||||
ktFile.analyzeWithAllCompilerChecks()
|
||||
|
||||
myFixture.type(stringToType)
|
||||
myFixture.type(stringToType(myFixture))
|
||||
PsiDocumentManager.getInstance(myFixture.project).commitDocument(myFixture.getDocument(myFixture.file))
|
||||
val oobAfterCount = ktFile.outOfBlockModificationCount
|
||||
val modificationCountAfterType = tracker.modificationCount
|
||||
@@ -116,14 +117,6 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
|
||||
}
|
||||
}
|
||||
|
||||
private val stringToType: String
|
||||
get() {
|
||||
val text = myFixture.getDocument(myFixture.file).text
|
||||
val typeDirectives =
|
||||
InTextDirectivesUtils.findStringWithPrefixes(text, TYPE_DIRECTIVE)
|
||||
return if (typeDirectives != null) StringUtil.unescapeStringCharacters(typeDirectives) else "a"
|
||||
}
|
||||
|
||||
private val expectedOutOfBlockResult: Boolean
|
||||
get() {
|
||||
val text = myFixture.getDocument(myFixture.file).text
|
||||
@@ -144,5 +137,12 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
|
||||
const val OUT_OF_CODE_BLOCK_DIRECTIVE = "OUT_OF_CODE_BLOCK:"
|
||||
const val SKIP_ANALYZE_CHECK_DIRECTIVE = "SKIP_ANALYZE_CHECK"
|
||||
const val TYPE_DIRECTIVE = "TYPE:"
|
||||
|
||||
fun stringToType(fixture: JavaCodeInsightTestFixture): String {
|
||||
val text = fixture.getDocument(fixture.file).text
|
||||
val typeDirectives =
|
||||
InTextDirectivesUtils.findStringWithPrefixes(text, TYPE_DIRECTIVE)
|
||||
return if (typeDirectives != null) StringUtil.unescapeStringCharacters(typeDirectives) else "a"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user