Implement jspecify marks processing in the tests properly, by adding specific handler and cleanuper
This commit is contained in:
+8
-11
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.codeMetaInfo
|
||||
|
||||
import com.intellij.util.containers.Stack
|
||||
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo
|
||||
import java.io.File
|
||||
|
||||
@@ -55,21 +54,24 @@ object CodeMetaInfoRenderer {
|
||||
checkOpenedAndCloseStringIfNeeded(opened, offset, builder)
|
||||
val matchedCodeMetaInfos = sortedMetaInfos[offset] ?: emptyList()
|
||||
if (matchedCodeMetaInfos.isNotEmpty()) {
|
||||
openStartTag(builder)
|
||||
val iterator = matchedCodeMetaInfos.listIterator()
|
||||
var current: CodeMetaInfo? = iterator.next()
|
||||
|
||||
if (current != null) builder.append(current.tagPrefix)
|
||||
|
||||
while (current != null) {
|
||||
val next: CodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null
|
||||
opened.push(current)
|
||||
builder.append(current.asString())
|
||||
when {
|
||||
next == null ->
|
||||
closeStartTag(builder)
|
||||
builder.append(current.tagPostfix)
|
||||
next.end == current.end ->
|
||||
builder.append(", ")
|
||||
else ->
|
||||
closeStartAndOpenNewTag(builder)
|
||||
else -> {
|
||||
builder.append(current.tagPostfix)
|
||||
builder.append(next.tagPrefix)
|
||||
}
|
||||
}
|
||||
current = next
|
||||
}
|
||||
@@ -84,16 +86,11 @@ object CodeMetaInfoRenderer {
|
||||
return metaInfos.sortedWith(metaInfoComparator)
|
||||
}
|
||||
|
||||
private fun closeString(result: StringBuilder) = result.append("<!>")
|
||||
private fun openStartTag(result: StringBuilder) = result.append("<!")
|
||||
private fun closeStartTag(result: StringBuilder) = result.append("!>")
|
||||
private fun closeStartAndOpenNewTag(result: StringBuilder) = result.append("!><!")
|
||||
|
||||
private fun checkOpenedAndCloseStringIfNeeded(opened: Stack<CodeMetaInfo>, end: Int, result: StringBuilder) {
|
||||
var prev: CodeMetaInfo? = null
|
||||
while (!opened.isEmpty() && end == opened.peek().end) {
|
||||
if (prev == null || prev.start != opened.peek().start)
|
||||
closeString(result)
|
||||
result.append(opened.peek().closingTag)
|
||||
prev = opened.pop()
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -14,5 +14,9 @@ interface CodeMetaInfo {
|
||||
val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration
|
||||
val attributes: MutableList<String>
|
||||
|
||||
val tagPrefix: String get() = "<!"
|
||||
val tagPostfix: String get() = "!>"
|
||||
val closingTag: String get() = "<!>"
|
||||
|
||||
fun asString(): String
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.codeMetaInfo.model
|
||||
|
||||
import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.JspecifyCodeMetaInfoRenderConfiguration
|
||||
|
||||
class JspecifyMarkerCodeMetaInfo(
|
||||
override val start: Int,
|
||||
override val end: Int,
|
||||
val offset: Int,
|
||||
val name: String
|
||||
) : CodeMetaInfo {
|
||||
override val tagPrefix = "\n${" ".repeat(offset)}// "
|
||||
override val tagPostfix = ""
|
||||
override val closingTag = ""
|
||||
|
||||
override val renderConfiguration = JspecifyCodeMetaInfoRenderConfiguration
|
||||
|
||||
override val tag = renderConfiguration.getTag(this)
|
||||
|
||||
override val attributes: MutableList<String> = mutableListOf()
|
||||
|
||||
override fun asString(): String = renderConfiguration.asString(this)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.codeMetaInfo.renderConfigurations
|
||||
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.JspecifyMarkerCodeMetaInfo
|
||||
|
||||
object JspecifyCodeMetaInfoRenderConfiguration : AbstractCodeMetaInfoRenderConfiguration() {
|
||||
override fun asString(codeMetaInfo: CodeMetaInfo): String {
|
||||
if (codeMetaInfo !is JspecifyMarkerCodeMetaInfo) return ""
|
||||
return getTag(codeMetaInfo)
|
||||
}
|
||||
|
||||
fun getTag(codeMetaInfo: JspecifyMarkerCodeMetaInfo): String {
|
||||
return codeMetaInfo.name
|
||||
}
|
||||
}
|
||||
compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/strictMode/Defaults.fir.kt
Vendored
+1
-1
@@ -35,7 +35,7 @@ fun main(a: Defaults, x: Foo): Unit {
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.mixed(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
a.mixed(x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
Vendored
+1
-1
@@ -35,7 +35,7 @@ fun main(a: Defaults, x: Foo): Unit {
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.mixed(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
a.mixed(x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class Derived extends Base { }
|
||||
fun main(a: IgnoreAnnotations, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a.foo(x, null)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class Derived extends Base { }
|
||||
fun main(a: IgnoreAnnotations, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a.foo(x, null)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
|
||||
+2
-2
@@ -24,13 +24,13 @@ fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeP
|
||||
a2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
+2
-2
@@ -24,13 +24,13 @@ fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeP
|
||||
a2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
Vendored
+1
-1
@@ -29,7 +29,7 @@ public class Derived extends Base {
|
||||
fun main(a: Simple, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a.foo(x, null)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
a.bar().foo()
|
||||
|
||||
Vendored
+1
-1
@@ -29,7 +29,7 @@ public class Derived extends Base {
|
||||
fun main(a: Simple, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a.foo(x, null)<!UNSAFE_CALL!>.<!>foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, x)<!UNSAFE_CALL!>.<!>foo()
|
||||
|
||||
a.bar().foo()
|
||||
|
||||
+5
-5
@@ -21,27 +21,27 @@ public class B<T> {
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a2.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
b1.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
b2.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
|
||||
+5
-5
@@ -21,27 +21,27 @@ public class B<T> {
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
a2.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
b1.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
b2.bar<<!UPPER_BOUND_VIOLATED!>T?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
+9
-11
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: AnnotatedBoundsOfWildcard.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -42,9 +40,9 @@ fun main(
|
||||
|
||||
b: AnnotatedBoundsOfWildcard
|
||||
): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superAsIs(aAnyNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superAsIs(aAnyNotNullNotNullNull)
|
||||
b.superAsIs(aAnyNotNullNullNotNull)
|
||||
b.superAsIs(aAnyNotNullNullNull)
|
||||
@@ -54,13 +52,13 @@ fun main(
|
||||
b.superNotNull(aAnyNotNullNullNotNull)
|
||||
b.superNotNull(aAnyNotNullNullNull)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNullNull)
|
||||
|
||||
b.extendsAsIs(aNotNullNotNullNotNull)
|
||||
@@ -69,11 +67,11 @@ fun main(
|
||||
b.extendsAsIs(aNotNullNullNull)
|
||||
|
||||
b.extendsNotNull(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNullNull)
|
||||
|
||||
b.extendsNullable(aNotNullNotNullNotNull)
|
||||
|
||||
+9
-11
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: AnnotatedBoundsOfWildcard.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -42,9 +40,9 @@ fun main(
|
||||
|
||||
b: AnnotatedBoundsOfWildcard
|
||||
): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superAsIs(aAnyNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superAsIs(aAnyNotNullNotNullNull)
|
||||
b.superAsIs(aAnyNotNullNullNotNull)
|
||||
b.superAsIs(aAnyNotNullNullNull)
|
||||
@@ -54,13 +52,13 @@ fun main(
|
||||
b.superNotNull(aAnyNotNullNullNotNull)
|
||||
b.superNotNull(aAnyNotNullNullNull)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.superNullable(aAnyNotNullNullNull)
|
||||
|
||||
b.extendsAsIs(aNotNullNotNullNotNull)
|
||||
@@ -69,11 +67,11 @@ fun main(
|
||||
b.extendsAsIs(aNotNullNullNull)
|
||||
|
||||
b.extendsNotNull(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.extendsNotNull(aNotNullNullNull)
|
||||
|
||||
b.extendsNullable(aNotNullNotNullNotNull)
|
||||
|
||||
Vendored
+1
-1
@@ -34,7 +34,7 @@ fun main(a: Defaults, x: Foo): Unit {
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.mixed(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.mixed(x)<!>.foo()
|
||||
|
||||
Vendored
+1
-1
@@ -34,7 +34,7 @@ fun main(a: Defaults, x: Foo): Unit {
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.mixed(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.mixed(x)<!>.foo()
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class Derived extends Base { }
|
||||
fun main(a: IgnoreAnnotations, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(x, null)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, x)<!>.foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class Derived extends Base { }
|
||||
fun main(a: IgnoreAnnotations, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(x, null)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, x)<!>.foo()
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
|
||||
+3
-5
@@ -1,6 +1,4 @@
|
||||
// !LANGUAGE: +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: NonPlatformTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -16,14 +14,14 @@ public class Test {}
|
||||
fun <T : Test> main(a1: NonPlatformTypeParameter<Any?>, a2: NonPlatformTypeParameter<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
a1.bar<Test?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.bar<T>(null)
|
||||
a1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.foo(null)
|
||||
a2.bar<Test?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar<T>(null)
|
||||
a2.bar<T>(x)
|
||||
}
|
||||
+3
-5
@@ -1,6 +1,4 @@
|
||||
// !LANGUAGE: +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: NonPlatformTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -16,14 +14,14 @@ public class Test {}
|
||||
fun <T : Test> main(a1: NonPlatformTypeParameter<Any?>, a2: NonPlatformTypeParameter<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
a1.bar<Test?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.bar<T>(null)
|
||||
a1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.foo(null)
|
||||
a2.bar<Test?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar<T>(null)
|
||||
a2.bar<T>(x)
|
||||
}
|
||||
+4
-6
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -16,23 +14,23 @@ public class Test {}
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.foo(null)
|
||||
a1.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.bar(x, null)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -16,23 +14,22 @@ public class Test {}
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.foo(null)
|
||||
a1.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, null)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
Vendored
+5
-7
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: SelfType.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -39,20 +37,20 @@ public class CKN extends C<@Nullable CK> {}
|
||||
// FILE: main.kt
|
||||
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
|
||||
ak.foo(ak)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ak.foo(null)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
akn.foo(null)
|
||||
|
||||
bk.foo(bk)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
bk.foo(null)
|
||||
|
||||
ck.foo(ck)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ck.foo(null)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ckn.foo(null)
|
||||
}
|
||||
Vendored
+5
-7
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: SelfType.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -39,20 +37,20 @@ public class CKN extends C<@Nullable CK> {}
|
||||
// FILE: main.kt
|
||||
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
|
||||
ak.foo(ak)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ak.foo(null)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
akn.foo(null)
|
||||
|
||||
bk.foo(bk)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
bk.foo(null)
|
||||
|
||||
ck.foo(ck)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ck.foo(null)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
ckn.foo(null)
|
||||
}
|
||||
Vendored
+1
-1
@@ -28,7 +28,7 @@ public class Derived extends Base {
|
||||
fun main(a: Simple, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(x, null)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, x)<!>.foo()
|
||||
|
||||
a.bar().foo()
|
||||
|
||||
Vendored
+1
-1
@@ -28,7 +28,7 @@ public class Derived extends Base {
|
||||
fun main(a: Simple, x: Derived): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(x, null)<!>.foo()
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, x)<!>.foo()
|
||||
|
||||
a.bar().foo()
|
||||
|
||||
+5
-7
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: TypeArgumentsFromParameterBounds.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -33,16 +31,16 @@ fun main(
|
||||
a: A, b: B
|
||||
): Unit {
|
||||
a.bar(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNullNull)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.bar(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.bar(aNotNullNotNullNull)
|
||||
b.bar(aNotNullNullNotNull)
|
||||
b.bar(aNotNullNullNull)
|
||||
|
||||
+5
-7
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: TypeArgumentsFromParameterBounds.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -33,16 +31,16 @@ fun main(
|
||||
a: A, b: B
|
||||
): Unit {
|
||||
a.bar(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a.bar(aNotNullNullNull)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.bar(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.bar(aNotNullNotNullNull)
|
||||
b.bar(aNotNullNullNotNull)
|
||||
b.bar(aNotNullNullNull)
|
||||
|
||||
+7
-9
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: A.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -21,27 +19,27 @@ public class B<T> {
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.bar<T?>(null)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar<T?>(null)
|
||||
a2.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b1.bar<T?>(null)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b2.bar<T?>(null)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
|
||||
+7
-9
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: A.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -21,27 +19,27 @@ public class B<T> {
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a1.bar<T?>(null)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
a2.bar<T?>(null)
|
||||
a2.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b1.bar<T?>(null)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b2.bar<T?>(null)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: WildcardsWithDefault.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -23,11 +21,11 @@ fun main(
|
||||
b: WildcardsWithDefault
|
||||
): Unit {
|
||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNullNull)
|
||||
|
||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
||||
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
// JSPECIFY_MUTE
|
||||
|
||||
// FILE: WildcardsWithDefault.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@@ -23,11 +21,11 @@ fun main(
|
||||
b: WildcardsWithDefault
|
||||
): Unit {
|
||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNotNullNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
||||
// jspecify_nullness_mismatch
|
||||
// jspecify_nullness_mismatch{mute}
|
||||
b.noBoundsNotNull(aNotNullNullNull)
|
||||
|
||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
||||
|
||||
-5
@@ -59,11 +59,6 @@ object JvmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
val JSPECIFY_MUTE by directive(
|
||||
"Skip jspecify checks for compliance Kotlin diagnostics to jspecify marks",
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
val STRING_CONCAT by enumDirective<JvmStringConcat>(
|
||||
description = "Configure mode of string concatenation",
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.test.frontend.classic.handlers
|
||||
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.JspecifyMarkerCodeMetaInfo
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.test.directives.ForeignAnnotationsDirectives
|
||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.globalMetadataInfoHandler
|
||||
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
|
||||
import org.jetbrains.kotlin.utils.ReportLevel
|
||||
|
||||
// Not that this diagnostic handler should be included only with `ClassicDiagnosticsHandler` and go after it
|
||||
class JspecifyDiagnosticComplianceHandler(testServices: TestServices) : ClassicFrontendAnalysisHandler(testServices) {
|
||||
override fun processModule(module: TestModule, info: ClassicFrontendOutputArtifact) {
|
||||
val jspecifyMode = module.directives[ForeignAnnotationsDirectives.JSPECIFY_STATE].singleOrNull()
|
||||
?: JavaTypeEnhancementState.DEFAULT_REPORT_LEVEL_FOR_JSPECIFY
|
||||
|
||||
for ((testFile, ktFile) in info.allKtFiles) {
|
||||
val reportedDiagnostics =
|
||||
testServices.globalMetadataInfoHandler.getReportedMetaInfosForFile(testFile).filterIsInstance<DiagnosticCodeMetaInfo>()
|
||||
for (metaInfo in reportedDiagnostics) {
|
||||
val jspecifyMark = diagnosticsToJspecifyMarks.getValue(jspecifyMode)[metaInfo.diagnostic.factory] ?: continue
|
||||
val fileLines = ktFile.text.lines()
|
||||
val fileLinePositions =
|
||||
fileLines.map { it.length }.runningReduce { sumLength, length -> sumLength + length + System.lineSeparator().length }
|
||||
val lineIndexToPasteJspecifyMark = fileLinePositions.indexOfLast { it < metaInfo.start }
|
||||
val positionToPasteJspecifyMark = fileLinePositions[lineIndexToPasteJspecifyMark]
|
||||
val offset = fileLines[lineIndexToPasteJspecifyMark + 1].takeWhile { it == ' ' }.length
|
||||
|
||||
testServices.globalMetadataInfoHandler.addMetadataInfosForFile(
|
||||
testFile,
|
||||
listOf(JspecifyMarkerCodeMetaInfo(positionToPasteJspecifyMark, positionToPasteJspecifyMark, offset, jspecifyMark))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
|
||||
|
||||
companion object {
|
||||
val diagnosticsToJspecifyMarks = mapOf(
|
||||
ReportLevel.WARN to mapOf(
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
),
|
||||
ReportLevel.STRICT to mapOf(
|
||||
Errors.TYPE_MISMATCH to "jspecify_nullness_mismatch",
|
||||
Errors.NULL_FOR_NONNULL_TYPE to "jspecify_nullness_mismatch",
|
||||
Errors.NOTHING_TO_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.RETURN_TYPE_MISMATCH_ON_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.UPPER_BOUND_VIOLATED to "jspecify_nullness_mismatch",
|
||||
Errors.UNSAFE_CALL to "jspecify_nullness_mismatch",
|
||||
),
|
||||
ReportLevel.IGNORE to emptyMap()
|
||||
)
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.test.preprocessors
|
||||
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.JspecifyDiagnosticComplianceHandler.Companion.diagnosticsToJspecifyMarks
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
|
||||
class JspecifyMarksCleanupPreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
|
||||
override fun process(file: TestFile, content: String) = content.replace(regexToCleanup, "")
|
||||
|
||||
companion object {
|
||||
private val jspecifyMarks = diagnosticsToJspecifyMarks.values.map { it.values }.flatten().joinToString("|")
|
||||
private val regexToCleanup = Regex("""[ ]*// ($jspecifyMarks)(, ($jspecifyMarks))*${System.lineSeparator()}""")
|
||||
}
|
||||
}
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* 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.test.preprocessors
|
||||
|
||||
import org.jetbrains.kotlin.checkers.DiagnosedRange
|
||||
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.test.KtAssert
|
||||
import org.jetbrains.kotlin.test.directives.ForeignAnnotationsDirectives
|
||||
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JSPECIFY_MUTE
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
|
||||
import org.jetbrains.kotlin.utils.ReportLevel
|
||||
import java.util.*
|
||||
|
||||
class JspecifyTestsPreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
|
||||
val shouldAutoApplyChanges = System.getProperty("autoApply") == "true"
|
||||
|
||||
private fun getJspecifyMarkRegex(jspecifyMark: String) = Regex("""^\s*// $jspecifyMark$""")
|
||||
private fun checkIfAllJspecifyMarksByDiagnosticsArePresent(
|
||||
diagnosedRanges: List<DiagnosedRange>,
|
||||
lineIndexesByRanges: TreeMap<Int, Int>,
|
||||
textLines: List<String>,
|
||||
compilerDiagnosticsToJspecifyMarksMap: Map<String, String>
|
||||
) {
|
||||
for (diagnosticRange in diagnosedRanges) {
|
||||
val lineIndex = lineIndexesByRanges.floorEntry(diagnosticRange.start).value
|
||||
|
||||
for (diagnostic in diagnosticRange.getDiagnostics()) {
|
||||
val requiredJspecifyMark = compilerDiagnosticsToJspecifyMarksMap[diagnostic.name] ?: continue
|
||||
|
||||
fun getErrorMessage(lineIndex: Int) =
|
||||
"Jspecify mark '$requiredJspecifyMark' not found for diagnostic '${diagnostic}' at ${lineIndex + 1} line.\n" +
|
||||
"It should be located at the previous line as a comment."
|
||||
|
||||
assert(lineIndex != 0) { getErrorMessage(0) }
|
||||
|
||||
val previousLine = textLines[lineIndex - 1]
|
||||
|
||||
assert(getJspecifyMarkRegex(requiredJspecifyMark).matches(previousLine)) { getErrorMessage(lineIndex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIfAllDiagnosticsByJspecifyMarksArePresent(
|
||||
diagnosedRanges: List<DiagnosedRange>,
|
||||
lineIndexesByRanges: TreeMap<Int, Int>,
|
||||
textLines: List<String>,
|
||||
compilerDiagnosticsToJspecifyMarksMap: Map<String, List<String>>
|
||||
) {
|
||||
for ((jspecifyMark, possibleDiagnostics) in compilerDiagnosticsToJspecifyMarksMap) {
|
||||
val diagnosticRanges = diagnosedRanges.mapNotNull {
|
||||
val relevantDiagnostics = it.getDiagnostics().filter { it.name in possibleDiagnostics }
|
||||
if (relevantDiagnostics.isEmpty()) return@mapNotNull null
|
||||
it.start
|
||||
}
|
||||
|
||||
val lineIndexesWithJspecifyMarks =
|
||||
textLines.mapIndexedNotNull { index, it -> getJspecifyMarkRegex(jspecifyMark).find(it)?.let { index } }
|
||||
|
||||
if (diagnosticRanges.isEmpty()) {
|
||||
if (lineIndexesWithJspecifyMarks.isEmpty()) {
|
||||
continue
|
||||
} else {
|
||||
KtAssert.fail(
|
||||
"None of \"${possibleDiagnostics.joinToString(", ")}\" diagnostics not found " +
|
||||
"for jspecify mark '$jspecifyMark' at lines: ${lineIndexesWithJspecifyMarks.map { it + 1 }.joinToString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (lineIndex in lineIndexesWithJspecifyMarks) {
|
||||
val lineStartPosition = lineIndexesByRanges.entries.find { (_, index) -> index == lineIndex + 1 }?.key
|
||||
val errorMessage = "None of \"${possibleDiagnostics.joinToString()}\" diagnostics not found " +
|
||||
"for jspecify mark '$jspecifyMark' at ${lineIndex + 1} line"
|
||||
|
||||
KtAssert.assertTrue(errorMessage, lineStartPosition != null)
|
||||
|
||||
val lineEndPosition = lineStartPosition!! + textLines[lineIndex + 1].length
|
||||
val isCorrespondingDiagnosticPresent = diagnosticRanges.any { it in lineStartPosition..lineEndPosition }
|
||||
|
||||
KtAssert.assertTrue(errorMessage, isCorrespondingDiagnosticPresent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun process(file: TestFile, content: String): String {
|
||||
if (!file.relativePath.endsWith(".kt")) return content
|
||||
|
||||
val textWithDiagnostics = content.substringAfter(MAIN_KT_FILE_DIRECTIVE).removeSuffix("\n")
|
||||
val diagnosedRanges = mutableListOf<DiagnosedRange>()
|
||||
val textWithoutDiagnostics = CheckerTestUtil.parseDiagnosedRanges(textWithDiagnostics, diagnosedRanges)
|
||||
|
||||
val textLines = textWithoutDiagnostics.lines()
|
||||
val lineIndexesByRanges = TreeMap<Int, Int>().apply {
|
||||
textLines.scanIndexed(0) { index, position, line ->
|
||||
put(position, index)
|
||||
position + line.length + 1 // + new line symbol
|
||||
}
|
||||
}
|
||||
|
||||
val jspecifyMode = file.directives[ForeignAnnotationsDirectives.JSPECIFY_STATE].singleOrNull()
|
||||
?: JavaTypeEnhancementState.DEFAULT_REPORT_LEVEL_FOR_JSPECIFY
|
||||
val compilerDiagnosticsToJspecifyMarksMap = when (jspecifyMode) {
|
||||
ReportLevel.STRICT -> diagnosticsToJspecifyMarksMapForStrictMode
|
||||
ReportLevel.WARN -> diagnosticsToJspecifyMarksMapForWarnMode
|
||||
ReportLevel.IGNORE -> mapOf()
|
||||
}
|
||||
val jspecifyMarksToCompilerDiagnosticsMap = when (jspecifyMode) {
|
||||
ReportLevel.STRICT -> jspecifyMarksToPossibleDiagnosticsForStrictMode
|
||||
ReportLevel.WARN -> jspecifyMarksToPossibleDiagnosticsForWarnMode
|
||||
ReportLevel.IGNORE -> mapOf()
|
||||
}
|
||||
|
||||
if (shouldAutoApplyChanges || JSPECIFY_MUTE in testServices.moduleStructure.allDirectives) {
|
||||
return content
|
||||
}
|
||||
|
||||
checkIfAllJspecifyMarksByDiagnosticsArePresent(
|
||||
diagnosedRanges,
|
||||
lineIndexesByRanges,
|
||||
textLines,
|
||||
compilerDiagnosticsToJspecifyMarksMap
|
||||
)
|
||||
checkIfAllDiagnosticsByJspecifyMarksArePresent(
|
||||
diagnosedRanges,
|
||||
lineIndexesByRanges,
|
||||
textLines,
|
||||
jspecifyMarksToCompilerDiagnosticsMap
|
||||
)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAIN_KT_FILE_DIRECTIVE = "// FILE: main.kt\n"
|
||||
|
||||
val diagnosticsToJspecifyMarksMapForWarnMode = mapOf(
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.name to "jspecify_nullness_mismatch",
|
||||
Errors.TYPE_MISMATCH.name to "jspecify_nullness_mismatch",
|
||||
Errors.NULL_FOR_NONNULL_TYPE.name to "jspecify_nullness_mismatch",
|
||||
Errors.NOTHING_TO_OVERRIDE.name to "jspecify_nullness_mismatch",
|
||||
Errors.RETURN_TYPE_MISMATCH_ON_OVERRIDE.name to "jspecify_nullness_mismatch",
|
||||
Errors.UPPER_BOUND_VIOLATED.name to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.name to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.name to "jspecify_nullness_mismatch",
|
||||
Errors.UNSAFE_CALL.name to "jspecify_nullness_mismatch",
|
||||
)
|
||||
|
||||
val jspecifyMarksToPossibleDiagnosticsForWarnMode =
|
||||
diagnosticsToJspecifyMarksMapForWarnMode.entries.groupBy({ it.value }, { it.key })
|
||||
|
||||
val diagnosticsToJspecifyMarksMapForStrictMode = diagnosticsToJspecifyMarksMapForWarnMode
|
||||
|
||||
val jspecifyMarksToPossibleDiagnosticsForStrictMode =
|
||||
diagnosticsToJspecifyMarksMapForStrictMode.entries.groupBy({ it.value }, { it.key })
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -22,10 +22,11 @@ import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirective
|
||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.DeclarationsDumpHandler
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.JspecifyDiagnosticComplianceHandler
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.preprocessors.JspecifyTestsPreprocessor
|
||||
import org.jetbrains.kotlin.test.preprocessors.JspecifyMarksCleanupPreprocessor
|
||||
import org.jetbrains.kotlin.test.services.configuration.*
|
||||
import org.jetbrains.kotlin.test.services.jvm.ForeignAnnotationAgainstCompiledJavaTestSuppressor
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider
|
||||
@@ -89,7 +90,8 @@ abstract class AbstractForeignAnnotationsTestBase : AbstractKotlinCompilerTest()
|
||||
}
|
||||
|
||||
forTestsMatching("compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/*") {
|
||||
useSourcePreprocessor(::JspecifyTestsPreprocessor, needToPrepend = true)
|
||||
useFrontendHandlers(::JspecifyDiagnosticComplianceHandler)
|
||||
useSourcePreprocessor(::JspecifyMarksCleanupPreprocessor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user