diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/AbstractKotlinInspection.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/AbstractKotlinInspection.kt
index 1b6cf0da7d4..40d14fc5cce 100644
--- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/AbstractKotlinInspection.kt
+++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/AbstractKotlinInspection.kt
@@ -66,8 +66,7 @@ abstract class AbstractKotlinInspection: LocalInspectionTool(), CustomSuppressab
range: TextRange?,
vararg fixes: LocalQuickFix
) {
- if (!ApplicationManager.getApplication().isUnitTestMode &&
- !isOnTheFly && highlightType == ProblemHighlightType.INFORMATION) return
+ if (!isOnTheFly && highlightType == ProblemHighlightType.INFORMATION) return
val problemDescriptor = manager.createProblemDescriptor(element, range, description, highlightType, isOnTheFly, *fixes)
registerProblem(problemDescriptor)
}
diff --git a/idea/testData/inspections/nullableBooleanElvis/inspectionData/expected.xml b/idea/testData/inspections/nullableBooleanElvis/inspectionData/expected.xml
index a02ffb07bb0..f8700010bec 100644
--- a/idea/testData/inspections/nullableBooleanElvis/inspectionData/expected.xml
+++ b/idea/testData/inspections/nullableBooleanElvis/inspectionData/expected.xml
@@ -31,21 +31,5 @@
Equality check can be used instead of elvis for nullable boolean check
Equality check should be used instead of elvis for nullable boolean check
-
- test.kt
- 13
- light_idea_test_case
-
- Equality check can be used instead of elvis for nullable boolean check
- Equality check can be used instead of elvis for nullable boolean check
-
-
- test.kt
- 14
- light_idea_test_case
-
- Equality check can be used instead of elvis for nullable boolean check
- Equality check can be used instead of elvis for nullable boolean check
-
\ No newline at end of file
diff --git a/idea/testData/inspections/nullableBooleanElvis/test.kt b/idea/testData/inspections/nullableBooleanElvis/test.kt
index 2d976b1dc7c..b0be6c92e06 100644
--- a/idea/testData/inspections/nullableBooleanElvis/test.kt
+++ b/idea/testData/inspections/nullableBooleanElvis/test.kt
@@ -10,6 +10,6 @@ fun foo() {
if (a ?: false || !(b ?: true)) {
}
- val x = a ?: false
- val y = !(b ?: true)
+ val x = a ?: false // INFORMATION -- not reported in batch
+ val y = !(b ?: true) // INFORMATION -- not reported in batch
}
\ No newline at end of file
diff --git a/idea/testData/inspections/replaceCallWithComparison/inspectionData/expected.xml b/idea/testData/inspections/replaceCallWithComparison/inspectionData/expected.xml
index c2625acdfdf..2f227a34861 100644
--- a/idea/testData/inspections/replaceCallWithComparison/inspectionData/expected.xml
+++ b/idea/testData/inspections/replaceCallWithComparison/inspectionData/expected.xml
@@ -31,20 +31,4 @@
Can be replaced with binary operator
Call replaceable with binary operator
-
- test.kt
- 8
- light_idea_test_case
-
- Can be replaced with binary operator
- Call replaceable with binary operator
-
-
- test.kt
- 9
- light_idea_test_case
-
- Can be replaced with binary operator
- Call replaceable with binary operator
-
\ No newline at end of file
diff --git a/idea/testData/inspections/replaceCallWithComparison/test.kt b/idea/testData/inspections/replaceCallWithComparison/test.kt
index bde63e5fed4..0d87cfdac81 100644
--- a/idea/testData/inspections/replaceCallWithComparison/test.kt
+++ b/idea/testData/inspections/replaceCallWithComparison/test.kt
@@ -5,6 +5,6 @@ fun foo() {
1.compareTo(1) == 0 // NO
2.compareTo(1) > 0 // YES
0 >= 1.compareTo(2) // YES
- 2.plus(2) // YES (information)
- 2.times(2) // YES (information)
+ 2.plus(2) // YES (information) -- not reported in batch
+ 2.times(2) // YES (information) -- not reported in batch
}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt
index 759ad185a07..9232bf12ca4 100644
--- a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt
+++ b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt
@@ -1,3 +1,5 @@
+// HIGHLIGHT: INFORMATION
+
fun foo() {
var a: Boolean? = null
val x = a ?: false
diff --git a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt.after b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt.after
index 902dddf9085..ef5406bab81 100644
--- a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt.after
+++ b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt.after
@@ -1,3 +1,5 @@
+// HIGHLIGHT: INFORMATION
+
fun foo() {
var a: Boolean? = null
val x = a == true
diff --git a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt
index 05daebfe2a3..c3fc5af2821 100644
--- a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt
+++ b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt
@@ -1,3 +1,5 @@
+// HIGHLIGHT: INFORMATION
+
fun foo() {
var b: Boolean? = null
val x = !(b ?: true)
diff --git a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt.after b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt.after
index baf5d809161..d679c34edb0 100644
--- a/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt.after
+++ b/idea/testData/inspectionsLocal/nullableBooleanElvis/notInIfWithTrue.kt.after
@@ -1,3 +1,5 @@
+// HIGHLIGHT: INFORMATION
+
fun foo() {
var b: Boolean? = null
val x = b == false
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractLocalInspectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractLocalInspectionTest.kt
index 75a1a71c342..1aca0e0c712 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractLocalInspectionTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractLocalInspectionTest.kt
@@ -17,11 +17,15 @@
package org.jetbrains.kotlin.idea.inspections
import com.google.common.collect.Lists
-import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeHighlighting.HighlightDisplayLevel
+import com.intellij.codeHighlighting.Pass
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType
+import com.intellij.codeInsight.intention.EmptyIntentionAction
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
-import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.profile.codeInspection.ProjectInspectionProfileManager
+import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import junit.framework.ComparisonFailure
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils
@@ -29,7 +33,6 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.configureCompilerOptions
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.KtFile
-import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Assert
@@ -64,12 +67,16 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
}
if (candidateFiles.isEmpty()) {
- throw AssertionError(".inspection file is not found for " + testDataFile +
- "\nAdd it to base directory of test data. It should contain fully-qualified name of inspection class.")
+ throw AssertionError(
+ ".inspection file is not found for " + testDataFile +
+ "\nAdd it to base directory of test data. It should contain fully-qualified name of inspection class."
+ )
}
if (candidateFiles.size > 1) {
- throw AssertionError("Several .inspection files are available for " + testDataFile +
- "\nPlease remove some of them\n" + candidateFiles)
+ throw AssertionError(
+ "Several .inspection files are available for " + testDataFile +
+ "\nPlease remove some of them\n" + candidateFiles
+ )
}
val className = FileUtil.loadFile(candidateFiles[0]).trim { it <= ' ' }
@@ -106,9 +113,9 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
break
}
- val psiFile = myFixture.configureByFiles(*(listOf(mainFile.name) + extraFileNames).toTypedArray()).first()
+ myFixture.configureByFiles(*(listOf(mainFile.name) + extraFileNames).toTypedArray()).first()
- doTestFor(mainFile.name, psiFile.virtualFile!!, inspection, fileText)
+ doTestFor(mainFile.name, inspection, fileText)
if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) {
DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
@@ -116,90 +123,118 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
}
protected fun runInspectionWithFixesAndCheck(
- file: VirtualFile,
- inspection: AbstractKotlinInspection,
- problemExpectedString: String?,
- highlightExpectedString: String?,
- localFixTextString: String?
+ inspection: AbstractKotlinInspection,
+ expectedProblemString: String?,
+ expectedHighlightString: String?,
+ localFixTextString: String?
): Boolean {
- val problemExpected = problemExpectedString == null || problemExpectedString != "none"
- val presentation = runInspection(inspection, project, listOf(file))
- val problemDescriptors = presentation.problemDescriptors
- .filterIsInstance()
- .filter {
- val caretOffset = myFixture.caretOffset
- caretOffset in it.textRangeInElement?.shiftRight(it.psiElement.startOffset) ?: it.psiElement.textRange
- }
+ val problemExpected = expectedProblemString == null || expectedProblemString != "none"
+ myFixture.enableInspections(inspection::class.java)
+
+ // Set default level to WARNING to make possible to test DO_NOT_SHOW
+ val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project)
+ val inspectionProfile = inspectionProfileManager.currentProfile
+ val state = inspectionProfile.getToolDefaultState(inspection.shortName, project)
+ state.level = HighlightDisplayLevel.WARNING
+
+ val caretOffset = myFixture.caretOffset
+ val highlightInfos = CodeInsightTestFixtureImpl.instantiateAndRun(
+ file, editor, intArrayOf(
+ Pass.LINE_MARKERS,
+ Pass.EXTERNAL_TOOLS,
+ Pass.POPUP_HINTS,
+ Pass.UPDATE_ALL,
+ Pass.UPDATE_FOLDING,
+ Pass.WOLF
+ ), false
+ ).filter { it.description != null && caretOffset in it.startOffset..it.endOffset }
+
Assert.assertTrue(
- if (!problemExpected)
- "No problems should be detected at caret\n" +
- "Detected problems: ${problemDescriptors.joinToString { it.descriptionTemplate }}"
- else
- "Expected at least one problem at caret",
- problemExpected == problemDescriptors.isNotEmpty())
- if (!problemExpected) return false
- problemDescriptors
- .filter { it.highlightType != ProblemHighlightType.INFORMATION }
- .forEach {
- Assert.assertTrue("Problem description should not contain 'can': ${it.descriptionTemplate}",
- " can " !in it.descriptionTemplate)
- }
- if (problemExpectedString != null) {
- Assert.assertTrue("Expected the following problem at caret: $problemExpectedString\n" +
- "Active problems: ${problemDescriptors.joinToString { it.descriptionTemplate }}",
- problemDescriptors.any { it.descriptionTemplate == problemExpectedString })
+ if (!problemExpected)
+ "No problems should be detected at caret\n" +
+ "Detected problems: ${highlightInfos.joinToString { it.description }}"
+ else
+ "Expected at least one problem at caret",
+ problemExpected == highlightInfos.isNotEmpty()
+ )
+ if (!problemExpected || highlightInfos.isEmpty()) return false
+ highlightInfos
+ .filter { it.type != HighlightInfoType.INFORMATION }
+ .forEach {
+ val description = it.description
+ Assert.assertTrue(
+ "Problem description should not contain 'can': $description",
+ " can " !in description
+ )
+ }
+
+ if (expectedProblemString != null) {
+ Assert.assertTrue(
+ "Expected the following problem at caret: $expectedProblemString\n" +
+ "Active problems: ${highlightInfos.joinToString { it.description }}",
+ highlightInfos.any { it.description == expectedProblemString }
+ )
}
- if (highlightExpectedString != null) {
- Assert.assertTrue("Expected the following problem highlight type\n" +
- "Actual types: ${problemDescriptors.joinToString { it.highlightType.toString() } }",
- problemDescriptors.all { it.highlightType.toString() == highlightExpectedString })
+ val expectedHighlightType = when (expectedHighlightString) {
+ null -> null
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING.name -> HighlightDisplayLevel.WARNING.name
+ else -> expectedHighlightString
+ }
+ if (expectedHighlightType != null) {
+ Assert.assertTrue(
+ "Expected the following problem highlight type: $expectedHighlightType\n" +
+ "Actual type: ${highlightInfos.joinToString { it.type.toString() }}",
+ highlightInfos.all { expectedHighlightType in it.type.toString() }
+ )
}
- val allLocalFixActions = problemDescriptors.flatMap { problem ->
- val fixes = problem.fixes
- fixes?.toList() ?: emptyList()
- }
- val localFixActions = allLocalFixActions.filter { fix -> localFixTextString == null || fix.name == localFixTextString }
- val availableDescription = allLocalFixActions.joinToString { it.name }
+ val allLocalFixActions = highlightInfos.flatMap { it.quickFixActionMarkers }.map { it.first.action }
- val fixDescription = localFixTextString?.let { "with specified text '$localFixTextString'"} ?: ""
- TestCase.assertTrue("No fix action $fixDescription\n" +
- "Available actions: $availableDescription",
- localFixActions.isNotEmpty())
+ val localFixActions = allLocalFixActions.filter { fix -> localFixTextString == null || fix.text == localFixTextString }
+ val availableDescription = allLocalFixActions.joinToString { it.text }
- val localFixAction = localFixActions.singleOrNull()
- TestCase.assertTrue("More than one fix action $fixDescription\n" +
- "Available actions: $availableDescription",
- localFixAction != null)
+ val fixDescription = localFixTextString?.let { "with specified text '$localFixTextString'" } ?: ""
+ TestCase.assertTrue(
+ "No fix action $fixDescription\n" +
+ "Available actions: $availableDescription",
+ localFixActions.isNotEmpty()
+ )
- val problemDescriptor = problemDescriptors.find { localFixAction in it.fixes?.toList() ?: emptyList() }!!
+ val localFixAction = localFixActions.singleOrNull { it !is EmptyIntentionAction }
+ TestCase.assertTrue(
+ "More than one fix action $fixDescription\n" +
+ "Available actions: $availableDescription",
+ localFixAction != null
+ )
- project.executeWriteCommand(localFixAction!!.name, null) {
- localFixAction.applyFix(project, problemDescriptor)
+ project.executeWriteCommand(localFixAction!!.text, null) {
+ localFixAction.invoke(project, editor, file)
}
return true
}
- private fun doTestFor(mainFilePath: String, file: VirtualFile, inspection: AbstractKotlinInspection, fileText: String) {
- val problemExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
- fileText, "// $expectedProblemDirectiveName: ")
- val highlightExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
- fileText, "// $expectedProblemHighlightType: ")
+ private fun doTestFor(mainFilePath: String, inspection: AbstractKotlinInspection, fileText: String) {
+ val expectedProblemString = InTextDirectivesUtils.findStringWithPrefixes(
+ fileText, "// $expectedProblemDirectiveName: "
+ )
+ val expectedHighlightString = InTextDirectivesUtils.findStringWithPrefixes(
+ fileText, "// $expectedProblemHighlightType: "
+ )
val localFixTextString = InTextDirectivesUtils.findStringWithPrefixes(
- fileText, "// $fixTextDirectiveName: ")
+ fileText, "// $fixTextDirectiveName: "
+ )
- if (!runInspectionWithFixesAndCheck(file, inspection, problemExpectedString, highlightExpectedString, localFixTextString)) {
+ if (!runInspectionWithFixesAndCheck(inspection, expectedProblemString, expectedHighlightString, localFixTextString)) {
return
}
val canonicalPathToExpectedFile = mainFilePath + afterFileNameSuffix
try {
myFixture.checkResultByFile(canonicalPathToExpectedFile)
- }
- catch (e: ComparisonFailure) {
+ } catch (e: ComparisonFailure) {
KotlinTestUtils.assertEqualsToFile(
- File(testDataPath, canonicalPathToExpectedFile),
- editor.document.text
+ File(testDataPath, canonicalPathToExpectedFile),
+ editor.document.text
)
}
}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractMultiFileLocalInspectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractMultiFileLocalInspectionTest.kt
index 9f6c6426ee9..2a053c78d2e 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractMultiFileLocalInspectionTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/AbstractMultiFileLocalInspectionTest.kt
@@ -58,10 +58,10 @@ abstract class AbstractMultiFileLocalInspectionTest : AbstractLocalInspectionTes
val problemExpectedString = config["problem"]?.asString // null means "some problem", "none" means no problem
val localFixTextString = config["fix"]?.asString // null means "some single fix" or "none" if no problem expected
- doTest(path) test@ { _ ->
- val mainFile = myFixture.configureFromTempProjectFile(mainFilePath)
+ doTest(path) test@{ _ ->
+ myFixture.configureFromTempProjectFile(mainFilePath)
- runInspectionWithFixesAndCheck(mainFile.virtualFile, inspection, problemExpectedString, null, localFixTextString)
+ runInspectionWithFixesAndCheck(inspection, problemExpectedString, null, localFixTextString)
}
}