Add ERRORs check to AbstractOutOfBlockModificationTest

This commit is contained in:
Vladimir Dolzhenko
2019-11-23 23:52:04 +01:00
parent 144f721a44
commit c67222c176
43 changed files with 141 additions and 28 deletions
@@ -12,24 +12,28 @@ import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.test.InTextDirectivesUtils
object DirectiveBasedActionUtils {
fun checkForUnexpectedErrors(file: KtFile) {
fun checkForUnexpectedErrors(file: KtFile, diagnosticsProvider: (KtFile) -> Diagnostics = { it.analyzeWithContent().diagnostics }) {
if (InTextDirectivesUtils.findLinesWithPrefixesRemoved(file.text, "// DISABLE-ERRORS").isNotEmpty()) {
return
}
val expectedErrors = InTextDirectivesUtils.findLinesWithPrefixesRemoved(file.text, "// ERROR:").sorted()
val actualErrors = file.analyzeWithContent().diagnostics
.filter { it.getSeverity() == Severity.ERROR }
.map { DefaultErrorMessages.render(it).replace("\n", "<br>") }
.sorted()
val diagnostics = diagnosticsProvider(file)
val actualErrors = diagnostics
.filter { it.severity == Severity.ERROR }
.map { DefaultErrorMessages.render(it).replace("\n", "<br>") }
.sorted()
UsefulTestCase.assertOrderedEquals("All actual errors should be mentioned in test data with // ERROR: directive. But no unnecessary errors should be me mentioned",
actualErrors,
expectedErrors)
UsefulTestCase.assertOrderedEquals(
"All actual errors should be mentioned in test data with // ERROR: directive. But no unnecessary errors should be me mentioned",
actualErrors,
expectedErrors
)
}
fun checkAvailableActionsAreExpected(file: PsiFile, availableActions: Collection<IntentionAction>) {
+4
View File
@@ -1,4 +1,8 @@
// OUT_OF_CODE_BLOCK: FALSE
fun run(block: () -> Int): Int {
return block()
}
fun some(): Int = run { 12 + <caret> }
// TYPE: 1
+1
View File
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// TYPE: 0
fun main() {
fun some = 12<caret>
}
+1 -1
View File
@@ -1,5 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
class A {
init {
fun f() {
+2
View File
@@ -1,2 +1,4 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: a12
fun some() = <caret>12
+3 -2
View File
@@ -1,6 +1,7 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Function 'test' must have a body
// TYPE: \b
fun test() {<caret>
}
// TYPE: \b
@@ -1,5 +1,6 @@
// OUT_OF_CODE_BLOCK: TRUE
// (Investigation starts from parent)
// ERROR: Unresolved reference: a12
fun test() : Int = <caret>12
@@ -1,3 +1,4 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a12
fun test() : Int = 12 + <caret>12
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: a
val o = object {
fun test() {
<caret>
+1
View File
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Function 'a' without a body must be abstract
class Some {
fun <caret>
}
@@ -0,0 +1,11 @@
// OUT_OF_CODE_BLOCK: FALSE
// TYPE: '//'
// ERROR: Property must be initialized
class InClassInUninitializedPropertyAccessor {
var prop1: Int
set(value) {
<caret> println("prop.setter")
field = value
}
}
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
class Test {
val more : Int = 0
val test : Int
@@ -1,7 +1,8 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: a
val b = true
val a = 1
fun test() = if (a) {
fun test() = if (b) {
fun hello() {
<caret>
}
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
fun test() {
val some = if () {
fun other() {
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: A type annotation is required on a value parameter
interface Some
fun test() {
+2 -1
View File
@@ -1,5 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: jq
// ERROR: Unresolved reference: pria
fun main() {
jq() { pri<caret> }
}
@@ -1,6 +1,11 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: awhen
enum class A {
e1, e2, e3
}
class B(val a: A)
val B.foo: Int
get() {
return <caret>when (a) {
+9 -2
View File
@@ -1,9 +1,16 @@
// OUT_OF_CODE_BLOCK: FALSE
// TYPE: t
fun CharSequence.repeat(n: Int): String {
val sb = StringBuilder(n * length)
for (i in 1..n) {
sb.append(this)
}
return sb.toString()
}
fun twice(s: String): String {
val repeatFun: String.(Int) -> String = { t -> this.repeat(<caret>) }
return repeatFun(s, 2)
}
// TYPE: t
+2 -1
View File
@@ -1,5 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
// ERROR: Unsupported [literal prefixes and suffixes]
fun test() {
val a = 1<caret>
}
@@ -1,5 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
class Test {
class Other {
fun test() {
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: This variable must either have a type annotation or be initialized
class Test {
class Other {
@@ -1,7 +1,10 @@
// OUT_OF_CODE_BLOCK: TRUE
// TYPE: 'Int`
// TYPE: 'Int'
class InPropertyAccessorSpecifyType {
val prop1: Int
get():<caret> = 42
}
}
// TODO: Investigate
// SKIP_ANALYZE_CHECK
@@ -1,5 +1,7 @@
// OUT_OF_CODE_BLOCK: TRUE
// TYPE: '@Throws(Exception::class)`
// TYPE: '@Some("X")'
annotation class Some(val message: String)
class InPropertyAccessorWithAnnotation {
val prop1: Int
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: a12
val test : Int
get() = <caret>12
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: foao
class A {
fun foo(): Int = 12
@@ -1,5 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: foao
class A {
fun foo(): Int = 12
}
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: apri
class Test {
val a : () -> Int = { <caret>pri }
}
+2
View File
@@ -1,2 +1,4 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: printlna
fun more() { println<caret> }
@@ -0,0 +1,9 @@
// OUT_OF_CODE_BLOCK: FALSE
// TYPE: '//'
// ERROR: Property must be initialized
var prop1: Int
set(value) {
<caret> println("prop.setter")
field = value
}
+1 -1
View File
@@ -1,5 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: caall
class A {
init {
ca<caret>ll()
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
fun test() {
fun hello() {
<caret>
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
class LocalFunWithBodyInClass {
fun test() {
fun hello() {
@@ -1,4 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
object Some {
fun test() {
<caret>
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
object Some {
fun test() {
@@ -1,4 +1,5 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
interface Some
@@ -1,4 +1,7 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: This variable must either have a type annotation or be initialized
// ERROR: Type mismatch: inferred type is Unit but Int? was expected
// ERROR: Type mismatch: inferred type is Unit but Int? was expected
val test: Int? = if (true) {
fun test() {
@@ -1,6 +1,8 @@
// OUT_OF_CODE_BLOCK: FALSE
// Problem with lazy initialization of nullable properties
// TODO: Investigate
// --ERROR: Unresolved reference: q
interface Some
val test: Some? = object: Some {
@@ -1,5 +1,6 @@
// OUT_OF_CODE_BLOCK: TRUE
// SKIP_ANALYZE_CHECK
// ERROR: Function declaration must have a name
fun test() {<caret>
@@ -1,4 +1,7 @@
// RUNTIME_WITH_SCRIPT_RUNTIME
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: a
plugins {
<caret>
}
@@ -1,5 +1,7 @@
// RUNTIME_WITH_SCRIPT_RUNTIME
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Too many arguments for public final fun foo(): Int defined in ScriptTopLevelCallExpression
// ERROR: Unresolved reference: a
fun foo() = 1
foo(<caret>)
@@ -1,4 +1,8 @@
// RUNTIME_WITH_SCRIPT_RUNTIME
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: a
// ERROR: Unsupported [literal prefixes and suffixes]
1<caret>
// SKIP_ANALYZE_CHECK
@@ -13,8 +13,10 @@ import com.intellij.psi.PsiManager
import com.intellij.psi.impl.PsiModificationTrackerImpl
import com.intellij.psi.util.PsiTreeUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.trackers.outOfBlockModificationCount
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
@@ -39,6 +41,10 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
TestCase.assertNotNull("Should be valid element", element)
val oobBeforeType = ktFile.outOfBlockModificationCount
val modificationCountBeforeType = tracker.modificationCount
// have to analyze file before any change to support incremental analysis
ktFile.analyzeWithAllCompilerChecks()
myFixture.type(stringToType)
PsiDocumentManager.getInstance(myFixture.project).commitDocument(myFixture.getDocument(myFixture.file))
val oobAfterCount = ktFile.outOfBlockModificationCount
@@ -52,11 +58,17 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
+ FileUtil.loadFile(testDataFile()),
expectedOutOfBlock, oobBeforeType != oobAfterCount
)
checkForUnexpectedErrors(ktFile)
if (!isSkipCheckDefined) {
checkOOBWithDescriptorsResolve(expectedOutOfBlock)
}
}
private fun checkForUnexpectedErrors(ktFile: KtFile) {
DirectiveBasedActionUtils.checkForUnexpectedErrors(ktFile) { it.analyzeWithAllCompilerChecks().bindingContext.diagnostics }
}
private fun checkOOBWithDescriptorsResolve(expectedOutOfBlock: Boolean) {
ApplicationManager.getApplication().runReadAction {
(PsiManager.getInstance(myFixture.project).modificationTracker as PsiModificationTrackerImpl)
@@ -68,9 +68,9 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
runTest("idea/testData/codeInsight/outOfBlock/FunWithType_Initializer_Expression.kt");
}
@TestMetadata("InAntonymsObjectDeclaration.kt")
public void testInAntonymsObjectDeclaration() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InAntonymsObjectDeclaration.kt");
@TestMetadata("InAnonymousObjectDeclaration.kt")
public void testInAnonymousObjectDeclaration() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InAnonymousObjectDeclaration.kt");
}
@TestMetadata("InClass.kt")
@@ -83,6 +83,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
runTest("idea/testData/codeInsight/outOfBlock/InClassFunctionWithoutInference.kt");
}
@TestMetadata("InClassInUninitializedPropertyAccessor.kt")
public void testInClassInUninitializedPropertyAccessor() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InClassInUninitializedPropertyAccessor.kt");
}
@TestMetadata("InClassPropertyAccessor.kt")
public void testInClassPropertyAccessor() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyAccessor.kt");
@@ -218,6 +223,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
runTest("idea/testData/codeInsight/outOfBlock/InTopFun.kt");
}
@TestMetadata("InUninitializedPropertyAccessor.kt")
public void testInUninitializedPropertyAccessor() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InUninitializedPropertyAccessor.kt");
}
@TestMetadata("InitBlock.kt")
public void testInitBlock() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InitBlock.kt");