Support compiler flag -Xcodeanalysis-annotations

This commit is contained in:
Denis Zharkov
2019-08-15 12:17:29 +03:00
committed by Victor Petukhov
parent c734bac676
commit f3a490ee16
45 changed files with 1031 additions and 35 deletions
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.utils.ReportLevel
class JavaTypeEnhancementStateParser(private val collector: MessageCollector) { class JavaTypeEnhancementStateParser(private val collector: MessageCollector) {
fun parse( fun parse(
jsr305Args: Array<String>?, supportCompatqualCheckerFrameworkAnnotations: String? jsr305Args: Array<String>?,
supportCompatqualCheckerFrameworkAnnotations: String?,
codeAnalysisState: String?
): JavaTypeEnhancementState { ): JavaTypeEnhancementState {
val jsr305State = parseJsr305State(jsr305Args) val jsr305State = parseJsr305State(jsr305Args)
@@ -40,15 +42,34 @@ class JavaTypeEnhancementStateParser(private val collector: MessageCollector) {
} }
} }
val codeAnalysisReportLevel = parseCodeAnalysisReportLevel(codeAnalysisState)
val state = JavaTypeEnhancementState( val state = JavaTypeEnhancementState(
jsr305State.global ?: ReportLevel.WARN, jsr305State.migration, jsr305State.usedDefined, jsr305State.global ?: ReportLevel.WARN, jsr305State.migration, jsr305State.usedDefined,
enableCompatqualCheckerFrameworkAnnotations = enableCompatqualCheckerFrameworkAnnotations =
enableCompatqualCheckerFrameworkAnnotations enableCompatqualCheckerFrameworkAnnotations
?: JavaTypeEnhancementState.COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE ?: JavaTypeEnhancementState.COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE,
jspecifyReportLevel = codeAnalysisReportLevel
) )
return if (state == JavaTypeEnhancementState.DISABLED_JSR_305) JavaTypeEnhancementState.DISABLED_JSR_305 else state return if (state == JavaTypeEnhancementState.DISABLED_JSR_305) JavaTypeEnhancementState.DISABLED_JSR_305 else state
} }
private fun parseCodeAnalysisReportLevel(codeAnalysisState: String?): ReportLevel {
if (codeAnalysisState == null) return JavaTypeEnhancementState.DEFAULT_REPORT_LEVEL_FOR_CODE_ANALYSIS
val reportLevel = ReportLevel.findByDescription(codeAnalysisState)
if (reportLevel == null) {
collector.report(
CompilerMessageSeverity.ERROR,
"Unrecognized -Xcodeanalysis-annotations option: $codeAnalysisState. Possible values are 'disable'/'warn'/'strict'"
)
return JavaTypeEnhancementState.DEFAULT_REPORT_LEVEL_FOR_CODE_ANALYSIS
}
return reportLevel
}
private data class Jsr305State( private data class Jsr305State(
val global: ReportLevel?, val global: ReportLevel?,
val migration: ReportLevel?, val migration: ReportLevel?,
@@ -263,6 +263,14 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var supportCompatqualCheckerFrameworkAnnotations: String? by NullableStringFreezableVar(null) var supportCompatqualCheckerFrameworkAnnotations: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xjspecify-annotations",
valueDescription = "ignore|strict|warn",
description = "Specify behavior for jspecify annotations.\n" +
"Default value is 'warn'"
)
var jspecifyAnnotations: String? by FreezableVar(null)
@Argument( @Argument(
value = "-Xno-exception-on-explicit-equals-for-boxed-null", value = "-Xno-exception-on-explicit-equals-for-boxed-null",
description = "Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type" description = "Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type"
@@ -397,7 +405,8 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
result[JvmAnalysisFlags.javaTypeEnhancementState] = JavaTypeEnhancementStateParser(collector).parse( result[JvmAnalysisFlags.javaTypeEnhancementState] = JavaTypeEnhancementStateParser(collector).parse(
jsr305, jsr305,
supportCompatqualCheckerFrameworkAnnotations supportCompatqualCheckerFrameworkAnnotations,
jspecifyAnnotations
) )
result[AnalysisFlags.ignoreDataFlowInAssert] = JVMAssertionsMode.fromString(assertionsMode) != JVMAssertionsMode.LEGACY result[AnalysisFlags.ignoreDataFlowInAssert] = JVMAssertionsMode.fromString(assertionsMode) != JVMAssertionsMode.LEGACY
JvmDefaultMode.fromStringOrNull(jvmDefault)?.let { JvmDefaultMode.fromStringOrNull(jvmDefault)?.let {
+7
View File
@@ -0,0 +1,7 @@
@codeanalysis.experimental.annotations.DefaultNotNull
public class A {
public void foo(String x) {}
@codeanalysis.experimental.annotations.Nullable
public String bar() { return null; }
}
+5
View File
@@ -0,0 +1,5 @@
$TESTDATA_DIR$/jspecifyUsage.kt
$TESTDATA_DIR$/jspecify
$FOREIGN_ANNOTATIONS_DIR$
-d
$TEMP_DIR$
+7
View File
@@ -0,0 +1,7 @@
compiler/testData/cli/jvm/codeanalysisUsage.kt:2:11: warning: type mismatch: inferred type is Nothing? but String was expected
a.foo(null)
^
compiler/testData/cli/jvm/codeanalysisUsage.kt:3:5: warning: unsafe use of a nullable receiver of type String?
a.bar().hashCode()
^
OK
+6
View File
@@ -0,0 +1,6 @@
-Xcodeanalysis-annotations=ignore
$TESTDATA_DIR$/codeanalysisUsage.kt
$TESTDATA_DIR$/codeanalysis
$FOREIGN_ANNOTATIONS_DIR$
-d
$TEMP_DIR$
+1
View File
@@ -0,0 +1 @@
OK
+6
View File
@@ -0,0 +1,6 @@
-Xcodeanalysis-annotations=strict
$TESTDATA_DIR$/codeanalysisUsage.kt
$TESTDATA_DIR$/codeanalysis
$FOREIGN_ANNOTATIONS_DIR$
-d
$TEMP_DIR$
+4
View File
@@ -0,0 +1,4 @@
compiler/testData/cli/jvm/jspecifyUsage.kt:2:11: error: null can not be a value of a non-null type String
a.foo(null)
^
COMPILATION_ERROR
+4
View File
@@ -0,0 +1,4 @@
fun bar(a: A) {
a.foo(null)
a.bar().hashCode()
}
+6
View File
@@ -0,0 +1,6 @@
-Xjspecify-annotations=warn
$TESTDATA_DIR$/codeanalysisUsage.kt
$TESTDATA_DIR$/codeanalysis
$FOREIGN_ANNOTATIONS_DIR$
-d
$TEMP_DIR$
+7
View File
@@ -0,0 +1,7 @@
compiler/testData/cli/jvm/jspecifyUsage.kt:2:11: warning: type mismatch: inferred type is Nothing? but String was expected
a.foo(null)
^
compiler/testData/cli/jvm/jspecifyUsage.kt:3:5: warning: unsafe use of a nullable receiver of type String?
a.bar().hashCode()
^
OK
+3
View File
@@ -12,6 +12,9 @@ where advanced options include:
-Xassertions=legacy: calculate condition on each call, check depends on jvm assertion settings in the kotlin package; -Xassertions=legacy: calculate condition on each call, check depends on jvm assertion settings in the kotlin package;
default: legacy default: legacy
-Xbuild-file=<path> Path to the .xml build file to compile -Xbuild-file=<path> Path to the .xml build file to compile
-Xcodeanalysis-annotations=ignore|strict|warn
Specify behavior for Codeanalysis annotations.
Default value is 'warn'
-Xcompile-java Reuse javac analysis and compile Java source files -Xcompile-java Reuse javac analysis and compile Java source files
-Xnormalize-constructor-calls={disable|enable} -Xnormalize-constructor-calls={disable|enable}
Normalize constructor calls (disable: don't normalize; enable: normalize), Normalize constructor calls (disable: don't normalize; enable: normalize),
@@ -0,0 +1,52 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE ignore
// FILE: A.java
import jspecify.annotations.*;
public class A {
@Nullable public String field = null;
@Nullable
public String foo(@NotNull String x, @UnknownNullness CharSequence y) {
return "";
}
@NotNull
public String bar() {
return "";
}
@DefaultNotNull
public String everythingNotNullable(String x) { return ""; }
@DefaultNullable
public String everythingNullable(String x) { return ""; }
@DefaultNullnessUnknown
public String everythingUnknown(String x) { return ""; }
}
// FILE: main.kt
fun main(a: A) {
a.foo("", null)?.length
a.foo("", null).length
a.foo(null, "").length
a.bar().length
a.bar()!!.length
a.field?.length
a.field.length
a.everythingNotNullable(null)?.length
a.everythingNotNullable(null).length
a.everythingNotNullable("").length
a.everythingNullable(null).length
a.everythingNullable(null)?.length
a.everythingUnknown(null).length
a.everythingUnknown(null)?.length
}
@@ -0,0 +1,16 @@
package
public fun main(/*0*/ a: A): kotlin.Unit
public open class A {
public constructor A()
@jspecify.annotations.Nullable public final var field: kotlin.String!
@jspecify.annotations.NotNull public open fun bar(): kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@jspecify.annotations.DefaultNotNull public open fun everythingNotNullable(/*0*/ x: kotlin.String!): kotlin.String!
@jspecify.annotations.DefaultNullable public open fun everythingNullable(/*0*/ x: kotlin.String!): kotlin.String!
@jspecify.annotations.DefaultNullnessUnknown public open fun everythingUnknown(/*0*/ x: kotlin.String!): kotlin.String!
@jspecify.annotations.Nullable public open fun foo(/*0*/ @jspecify.annotations.NotNull x: kotlin.String!, /*1*/ @jspecify.annotations.UnknownNullness y: kotlin.CharSequence!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,81 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A<T extends @NotNull Object, E extends @Nullable Object, F extends @UnknownNullness Object> {
}
// FILE: B.java
import jspecify.annotations.*;
public class B {
public void superAsIs(A<? super CharSequence, ? super CharSequence, ? super CharSequence> a) {}
public void superNotNull(A<? super @NotNull CharSequence, ? super @NotNull CharSequence, ? super @NotNull CharSequence> a) {}
public void superNullable(A<? super @Nullable CharSequence, ? super @Nullable CharSequence, ? super @Nullable CharSequence> a) {}
public void extendsAsIs(A<? extends CharSequence, ? extends CharSequence, ? extends CharSequence> a) {}
public void extendsNotNull(A<? extends @NotNull CharSequence, ? extends @NotNull CharSequence, ? extends @NotNull CharSequence> a) {}
public void extendsNullable(A<? extends @Nullable CharSequence, ? extends @Nullable CharSequence, ? extends @Nullable CharSequence> a) {}
public void noBounds(A<?, ?, ?> a) {}
}
// FILE: main.kt
fun main(
aNotNullNotNullNotNull: A<String, String, String>,
aNotNullNotNullNull: A<String, String, String?>,
aNotNullNullNotNull: A<String, String?, String>,
aNotNullNullNull: A<String, String?, String?>,
aAnyNotNullNotNullNotNull: A<Any, Any, Any>,
aAnyNotNullNotNullNull: A<Any, Any, Any?>,
aAnyNotNullNullNotNull: A<Any, Any?, Any>,
aAnyNotNullNullNull: A<Any, Any?, Any?>,
b: B
) {
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.superAsIs(aAnyNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.superAsIs(aAnyNotNullNotNullNull)
b.superAsIs(aAnyNotNullNullNotNull)
b.superAsIs(aAnyNotNullNullNull)
b.superNotNull(aAnyNotNullNotNullNotNull)
b.superNotNull(aAnyNotNullNotNullNull)
b.superNotNull(aAnyNotNullNullNotNull)
b.superNotNull(aAnyNotNullNullNull)
// TODO: Bound for the first argument in "superNullable" contradicts to declared nullability of the parameter
// Do we need to ignore such arguments' nullability?
b.superNullable(aAnyNotNullNotNullNotNull)
b.superNullable(aAnyNotNullNotNullNull)
b.superNullable(aAnyNotNullNullNotNull)
b.superNullable(aAnyNotNullNullNull)
b.extendsAsIs(aNotNullNotNullNotNull)
b.extendsAsIs(aNotNullNotNullNull)
b.extendsAsIs(aNotNullNullNotNull)
b.extendsAsIs(aNotNullNullNull)
b.extendsNotNull(aNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.extendsNotNull(aNotNullNotNullNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.extendsNotNull(aNotNullNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.extendsNotNull(aNotNullNullNull)
b.extendsNullable(aNotNullNotNullNotNull)
b.extendsNullable(aNotNullNotNullNull)
b.extendsNullable(aNotNullNullNotNull)
b.extendsNullable(aNotNullNullNull)
b.noBounds(aNotNullNotNullNotNull)
b.noBounds(aNotNullNotNullNull)
b.noBounds(aNotNullNullNotNull)
b.noBounds(aNotNullNullNull)
}
@@ -0,0 +1,24 @@
package
public fun main(/*0*/ aNotNullNotNullNotNull: A<kotlin.String, kotlin.String, kotlin.String>, /*1*/ aNotNullNotNullNull: A<kotlin.String, kotlin.String, kotlin.String?>, /*2*/ aNotNullNullNotNull: A<kotlin.String, kotlin.String?, kotlin.String>, /*3*/ aNotNullNullNull: A<kotlin.String, kotlin.String?, kotlin.String?>, /*4*/ aAnyNotNullNotNullNotNull: A<kotlin.Any, kotlin.Any, kotlin.Any>, /*5*/ aAnyNotNullNotNullNull: A<kotlin.Any, kotlin.Any, kotlin.Any?>, /*6*/ aAnyNotNullNullNotNull: A<kotlin.Any, kotlin.Any?, kotlin.Any>, /*7*/ aAnyNotNullNullNull: A<kotlin.Any, kotlin.Any?, kotlin.Any?>, /*8*/ b: B): kotlin.Unit
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!> {
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class B {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun extendsAsIs(/*0*/ a: A<out kotlin.CharSequence!, out kotlin.CharSequence!, out kotlin.CharSequence!>!): kotlin.Unit
public open fun extendsNotNull(/*0*/ a: A<out @jspecify.annotations.NotNull kotlin.CharSequence!, out @jspecify.annotations.NotNull kotlin.CharSequence!, out @jspecify.annotations.NotNull kotlin.CharSequence!>!): kotlin.Unit
public open fun extendsNullable(/*0*/ a: A<out @jspecify.annotations.Nullable kotlin.CharSequence!, out @jspecify.annotations.Nullable kotlin.CharSequence!, out @jspecify.annotations.Nullable kotlin.CharSequence!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open fun noBounds(/*0*/ a: A<*, *, *>!): kotlin.Unit
public open fun superAsIs(/*0*/ a: A<in kotlin.CharSequence!, in kotlin.CharSequence!, in kotlin.CharSequence!>!): kotlin.Unit
public open fun superNotNull(/*0*/ a: A<in @jspecify.annotations.NotNull kotlin.CharSequence!, in @jspecify.annotations.NotNull kotlin.CharSequence!, in @jspecify.annotations.NotNull kotlin.CharSequence!>!): kotlin.Unit
public open fun superNullable(/*0*/ a: A<in @jspecify.annotations.Nullable kotlin.CharSequence!, in @jspecify.annotations.Nullable kotlin.CharSequence!, in @jspecify.annotations.Nullable kotlin.CharSequence!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,46 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
@DefaultNotNull
public class A {
public String defaultField = "";
@Nullable public String field = null;
public String everythingNotNullable(String x) { return ""; }
@DefaultNullable
public String everythingNullable(String x) { return ""; }
@DefaultNullnessUnknown
public String everythingUnknown(String x) { return ""; }
@DefaultNullable
public String mixed(@NotNull String x) { return ""; }
}
// FILE: main.kt
fun main(a: A) {
a.everythingNotNullable(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!UNNECESSARY_SAFE_CALL!>?.<!>length
a.everythingNotNullable(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
a.everythingNotNullable("").length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.everythingNullable(null)<!>.length
a.everythingNullable(null)?.length
a.everythingUnknown(null).length
a.everythingUnknown(null)?.length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.mixed(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.length
a.mixed(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)?.length
a.mixed("")?.length
a.defaultField<!UNNECESSARY_SAFE_CALL!>?.<!>length
a.defaultField.length
a.field?.length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
}
@@ -0,0 +1,16 @@
package
public fun main(/*0*/ a: A): kotlin.Unit
@jspecify.annotations.DefaultNotNull public open class A {
public constructor A()
public final var defaultField: kotlin.String!
@jspecify.annotations.Nullable public final var field: kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun everythingNotNullable(/*0*/ x: kotlin.String!): kotlin.String!
@jspecify.annotations.DefaultNullable public open fun everythingNullable(/*0*/ x: kotlin.String!): kotlin.String!
@jspecify.annotations.DefaultNullnessUnknown public open fun everythingUnknown(/*0*/ x: kotlin.String!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@jspecify.annotations.DefaultNullable public open fun mixed(/*0*/ @jspecify.annotations.NotNull x: kotlin.String!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,50 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A<T extends @Nullable Object> {
public void foo(T t) {}
public <E extends @Nullable Object> void bar(E e) {}
}
// FILE: B.java
import jspecify.annotations.*;
@DefaultNullable
public class B<T> {
public void foo(T t) {}
public <E> void bar(E e) {}
}
// FILE: main.kt
fun main(a1: A<Any?>, a2: A<String>, b1: B<Any?>, b2: B<String>) {
a1.foo(null)
a1.bar<String?>(null)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
a1.bar<String>(null)
a1.bar<String>("")
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
a2.foo(null)
a2.bar<String?>(null)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
a2.bar<String>(null)
a2.bar<String>("")
b1.foo(null)
b1.bar<String?>(null)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b1.bar<String>(null)
b1.bar<String>("")
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b2.foo(null)
b2.bar<String?>(null)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b2.bar<String>(null)
b2.bar<String>("")
}
@@ -0,0 +1,21 @@
package
public fun main(/*0*/ a1: A<kotlin.Any?>, /*1*/ a2: A<kotlin.String>, /*2*/ b1: B<kotlin.Any?>, /*3*/ b2: B<kotlin.String>): kotlin.Unit
public open class A</*0*/ T : @jspecify.annotations.Nullable kotlin.Any!> {
public constructor A</*0*/ T : @jspecify.annotations.Nullable kotlin.Any!>()
public open fun </*0*/ E : @jspecify.annotations.Nullable kotlin.Any!> bar(/*0*/ e: E!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@jspecify.annotations.DefaultNullable public open class B</*0*/ T : kotlin.Any!> {
public constructor B</*0*/ T : kotlin.Any!>()
public open fun </*0*/ E : kotlin.Any!> bar(/*0*/ e: E!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,34 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A {
@Nullable public String field = null;
@Nullable
public String foo(@NotNull String x, @UnknownNullness CharSequence y) {
return "";
}
@NotNull
public String bar() {
return "";
}
}
// FILE: main.kt
fun main(a: A) {
a.foo("", null)?.length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
a.bar().length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a.field?.length
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
}
@@ -0,0 +1,13 @@
package
public fun main(/*0*/ a: A): kotlin.Unit
public open class A {
public constructor A()
@jspecify.annotations.Nullable public final var field: kotlin.String!
@jspecify.annotations.NotNull public open fun bar(): kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@jspecify.annotations.Nullable public open fun foo(/*0*/ @jspecify.annotations.NotNull x: kotlin.String!, /*1*/ @jspecify.annotations.UnknownNullness y: kotlin.CharSequence!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,68 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A<T extends @NotNull Object, E extends @Nullable Object, F extends @UnknownNullness Object> {
}
// FILE: B.java
import jspecify.annotations.*;
@DefaultNullable
public class B {
public void bar(A<String, String, String> a) {}
}
// FILE: C.java
import jspecify.annotations.*;
@DefaultNotNull
public class C {
public void bar(A<String, String, String> a) {}
}
// FILE: D.java
import jspecify.annotations.*;
@DefaultUnknownNullness
public class D {
public void bar(A<String, String, String> a) {}
}
// FILE: main.kt
fun main(
aNotNullNotNullNotNull: A<String, String, String>,
aNotNullNotNullNull: A<String, String, String?>,
aNotNullNullNotNull: A<String, String?, String>,
aNotNullNullNull: A<String, String?, String?>,
b: B, c: C, d: D
) {
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.bar(aNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.bar(aNotNullNotNullNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.bar(aNotNullNullNotNull)
b.bar(aNotNullNullNull)
c.bar(aNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
c.bar(aNotNullNotNullNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
c.bar(aNotNullNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
c.bar(aNotNullNullNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
d.bar(aNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
d.bar(aNotNullNotNullNull)
d.bar(aNotNullNullNotNull)
d.bar(aNotNullNullNull)
}
@@ -0,0 +1,34 @@
package
public fun main(/*0*/ aNotNullNotNullNotNull: A<kotlin.String, kotlin.String, kotlin.String>, /*1*/ aNotNullNotNullNull: A<kotlin.String, kotlin.String, kotlin.String?>, /*2*/ aNotNullNullNotNull: A<kotlin.String, kotlin.String?, kotlin.String>, /*3*/ aNotNullNullNull: A<kotlin.String, kotlin.String?, kotlin.String?>, /*4*/ b: B, /*5*/ c: C, /*6*/ d: D): kotlin.Unit
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!> {
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@jspecify.annotations.DefaultNullable public open class B {
public constructor B()
public open fun bar(/*0*/ a: A<kotlin.String!, kotlin.String!, kotlin.String!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@jspecify.annotations.DefaultNotNull public open class C {
public constructor C()
public open fun bar(/*0*/ a: A<kotlin.String!, kotlin.String!, kotlin.String!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@DefaultUnknownNullness /* annotation class not found */ public open class D {
public constructor D()
public open fun bar(/*0*/ a: A<kotlin.String!, kotlin.String!, kotlin.String!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,49 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A<T extends @NotNull Object> {
public void foo(T t) {}
public <E extends @NotNull Object> void bar(E e) {}
}
// FILE: B.java
import jspecify.annotations.*;
@DefaultNotNull
public class B<T> {
public void foo(T t) {}
public <E> void bar(E e) {}
}
// FILE: main.kt
// TODO: UPPER_BOUND_VIOLATED_WARNING should be reported
fun main(a1: A<Any?>, a2: A<String>, b1: B<Any?>, b2: B<String>) {
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
a1.foo(null)
// TODO: UPPER_BOUND_VIOLATED_WARNING should be reported
a1.bar<String?>(null)
a1.bar<String>("")
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
a2.foo(null)
// TODO: UPPER_BOUND_VIOLATED_WARNING should be reported
a2.bar<String?>(null)
a2.bar<String>("")
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b1.foo(null)
// TODO: UPPER_BOUND_VIOLATED_WARNING should be reported
b1.bar<String?>(null)
b1.bar<String>("")
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b2.foo(null)
// TODO: UPPER_BOUND_VIOLATED_WARNING should be reported
b2.bar<String?>(null)
b2.bar<String>("")
}
@@ -0,0 +1,21 @@
package
public fun main(/*0*/ a1: A<kotlin.Any?>, /*1*/ a2: A<kotlin.String>, /*2*/ b1: B<kotlin.Any?>, /*3*/ b2: B<kotlin.String>): kotlin.Unit
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!> {
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!>()
public open fun </*0*/ E : @jspecify.annotations.NotNull kotlin.Any!> bar(/*0*/ e: E!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@jspecify.annotations.DefaultNotNull public open class B</*0*/ T : kotlin.Any!> {
public constructor B</*0*/ T : kotlin.Any!>()
public open fun </*0*/ E : kotlin.Any!> bar(/*0*/ e: E!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,30 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import codeanalysis.annotations.*;
public class A<T> {
public void foo(T t) {}
@DefaultNotNull
public void bar(String s, T t) {} // t should not become not nullable
}
// FILE: main.kt
fun main(a1: A<Int>, a2: A<Int?>) {
a1.foo(null)
a1.foo(1)
a2.foo(null)
a2.foo(1)
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
a1.bar("", null)
a1.bar("", 1)
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
a2.bar("", null)
a2.bar("", 1)
}
@@ -0,0 +1,12 @@
package
public fun main(/*0*/ a1: A<kotlin.Int>, /*1*/ a2: A<kotlin.Int?>): kotlin.Unit
public open class A</*0*/ T : kotlin.Any!> {
public constructor A</*0*/ T : kotlin.Any!>()
@codeanalysis.annotations.DefaultNotNull public open fun bar(/*0*/ s: kotlin.String!, /*1*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(/*0*/ t: T!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,42 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// CODE_ANALYSIS_STATE warn
// FILE: A.java
import jspecify.annotations.*;
public class A<T extends @NotNull Object, E extends @Nullable Object, F extends @UnknownNullness Object> {
}
// FILE: B.java
import jspecify.annotations.*;
public class B {
@DefaultNotNull
public void noBoundsNotNull(A<?, ?, ?> a) {}
@DefaultNullable
public void noBoundsNullable(A<?, ?, ?> a) {}
}
// FILE: main.kt
fun main(
aNotNullNotNullNotNull: A<String, String, String>,
aNotNullNotNullNull: A<String, String, String?>,
aNotNullNullNotNull: A<String, String?, String>,
aNotNullNullNull: A<String, String?, String?>,
b: B
) {
b.noBoundsNotNull(aNotNullNotNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.noBoundsNotNull(aNotNullNotNullNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.noBoundsNotNull(aNotNullNullNotNull)
// TODO: NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS should be reported
b.noBoundsNotNull(aNotNullNullNull)
b.noBoundsNullable(aNotNullNotNullNotNull)
b.noBoundsNullable(aNotNullNotNullNull)
b.noBoundsNullable(aNotNullNullNotNull)
b.noBoundsNullable(aNotNullNullNull)
}
@@ -0,0 +1,19 @@
package
public fun main(/*0*/ aNotNullNotNullNotNull: A<kotlin.String, kotlin.String, kotlin.String>, /*1*/ aNotNullNotNullNull: A<kotlin.String, kotlin.String, kotlin.String?>, /*2*/ aNotNullNullNotNull: A<kotlin.String, kotlin.String?, kotlin.String>, /*3*/ aNotNullNullNull: A<kotlin.String, kotlin.String?, kotlin.String?>, /*4*/ b: B): kotlin.Unit
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!> {
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any!, /*1*/ E : @jspecify.annotations.Nullable kotlin.Any!, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class B {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@jspecify.annotations.DefaultNotNull public open fun noBoundsNotNull(/*0*/ a: A<*, *, *>!): kotlin.Unit
@jspecify.annotations.DefaultNullable public open fun noBoundsNullable(/*0*/ a: A<*, *, *>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -18,10 +18,8 @@ package org.jetbrains.kotlin.checkers
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.MockLibraryUtil import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
import org.jetbrains.kotlin.utils.ReportLevel import org.jetbrains.kotlin.utils.ReportLevel
import java.io.File import java.io.File
@@ -33,6 +31,7 @@ abstract class AbstractForeignAnnotationsTest : AbstractDiagnosticsTest() {
private val JSR305_GLOBAL_DIRECTIVE = "JSR305_GLOBAL_REPORT" private val JSR305_GLOBAL_DIRECTIVE = "JSR305_GLOBAL_REPORT"
private val JSR305_MIGRATION_DIRECTIVE = "JSR305_MIGRATION_REPORT" private val JSR305_MIGRATION_DIRECTIVE = "JSR305_MIGRATION_REPORT"
private val JSR305_SPECIAL_DIRECTIVE = "JSR305_SPECIAL_REPORT" private val JSR305_SPECIAL_DIRECTIVE = "JSR305_SPECIAL_REPORT"
private val CODE_ANALYSIS_STATE_SPECIAL_DIRECTIVE = "CODE_ANALYSIS_STATE"
override fun getExtraClasspath(): List<File> { override fun getExtraClasspath(): List<File> {
val foreignAnnotations = createJarWithForeignAnnotations() val foreignAnnotations = createJarWithForeignAnnotations()
@@ -78,11 +77,14 @@ abstract class AbstractForeignAnnotationsTest : AbstractDiagnosticsTest() {
name to state name to state
}.toMap() }.toMap()
val codeAnalysisReportLevel = module.getDirectiveValue(CODE_ANALYSIS_STATE_SPECIAL_DIRECTIVE) ?: ReportLevel.STRICT
return mapOf( return mapOf(
JvmAnalysisFlags.javaTypeEnhancementState to JavaTypeEnhancementState( JvmAnalysisFlags.javaTypeEnhancementState to JavaTypeEnhancementState(
globalState, globalState,
migrationState, migrationState,
userAnnotationsState userAnnotationsState,
jspecifyReportLevel = codeAnalysisReportLevel
) )
) )
} }
@@ -60,10 +60,68 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated extends
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
} }
@TestMetadata("ignoreAnnotations.kt")
public void testIgnoreAnnotations() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/ignoreAnnotations.kt");
}
@TestMetadata("wildcardsWithDefault.kt") @TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception { public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Warnings extends AbstractForeignJava8AnnotationsNoAnnotationInClasspathTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWarnings() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("annotatedWildcards.kt")
public void testAnnotatedWildcards() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/annotatedWildcards.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/defaults.kt");
}
@TestMetadata("nonPlatformTypeParameter.kt")
public void testNonPlatformTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/nonPlatformTypeParameter.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/simple.kt");
}
@TestMetadata("typeArgumentsFromParameterBounds.kt")
public void testTypeArgumentsFromParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeArgumentsFromParameterBounds.kt");
}
@TestMetadata("typeParameterBounds.kt")
public void testTypeParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeParameterBounds.kt");
}
@TestMetadata("unknownNullnessTypeParameter.kt")
public void testUnknownNullnessTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/unknownNullnessTypeParameter.kt");
}
@TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/wildcardsWithDefault.kt");
}
}
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify") @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
@@ -60,10 +60,68 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathWithPsiClassReadingTe
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
} }
@TestMetadata("ignoreAnnotations.kt")
public void testIgnoreAnnotations() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/ignoreAnnotations.kt");
}
@TestMetadata("wildcardsWithDefault.kt") @TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception { public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Warnings extends AbstractForeignJava8AnnotationsNoAnnotationInClasspathWithPsiClassReadingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWarnings() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("annotatedWildcards.kt")
public void testAnnotatedWildcards() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/annotatedWildcards.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/defaults.kt");
}
@TestMetadata("nonPlatformTypeParameter.kt")
public void testNonPlatformTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/nonPlatformTypeParameter.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/simple.kt");
}
@TestMetadata("typeArgumentsFromParameterBounds.kt")
public void testTypeArgumentsFromParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeArgumentsFromParameterBounds.kt");
}
@TestMetadata("typeParameterBounds.kt")
public void testTypeParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeParameterBounds.kt");
}
@TestMetadata("unknownNullnessTypeParameter.kt")
public void testUnknownNullnessTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/unknownNullnessTypeParameter.kt");
}
@TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/wildcardsWithDefault.kt");
}
}
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify") @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
@@ -60,10 +60,68 @@ public class ForeignJava8AnnotationsTestGenerated extends AbstractForeignJava8An
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
} }
@TestMetadata("ignoreAnnotations.kt")
public void testIgnoreAnnotations() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/ignoreAnnotations.kt");
}
@TestMetadata("wildcardsWithDefault.kt") @TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception { public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Warnings extends AbstractForeignJava8AnnotationsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWarnings() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("annotatedWildcards.kt")
public void testAnnotatedWildcards() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/annotatedWildcards.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/defaults.kt");
}
@TestMetadata("nonPlatformTypeParameter.kt")
public void testNonPlatformTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/nonPlatformTypeParameter.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/simple.kt");
}
@TestMetadata("typeArgumentsFromParameterBounds.kt")
public void testTypeArgumentsFromParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeArgumentsFromParameterBounds.kt");
}
@TestMetadata("typeParameterBounds.kt")
public void testTypeParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeParameterBounds.kt");
}
@TestMetadata("unknownNullnessTypeParameter.kt")
public void testUnknownNullnessTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/unknownNullnessTypeParameter.kt");
}
@TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/wildcardsWithDefault.kt");
}
}
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify") @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
@@ -60,10 +60,68 @@ public class JavacForeignJava8AnnotationsTestGenerated extends AbstractJavacFore
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
} }
@TestMetadata("ignoreAnnotations.kt")
public void testIgnoreAnnotations() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/ignoreAnnotations.kt");
}
@TestMetadata("wildcardsWithDefault.kt") @TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception { public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt"); runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Warnings extends AbstractJavacForeignJava8AnnotationsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWarnings() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("annotatedWildcards.kt")
public void testAnnotatedWildcards() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/annotatedWildcards.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/defaults.kt");
}
@TestMetadata("nonPlatformTypeParameter.kt")
public void testNonPlatformTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/nonPlatformTypeParameter.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/simple.kt");
}
@TestMetadata("typeArgumentsFromParameterBounds.kt")
public void testTypeArgumentsFromParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeArgumentsFromParameterBounds.kt");
}
@TestMetadata("typeParameterBounds.kt")
public void testTypeParameterBounds() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/typeParameterBounds.kt");
}
@TestMetadata("unknownNullnessTypeParameter.kt")
public void testUnknownNullnessTypeParameter() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/unknownNullnessTypeParameter.kt");
}
@TestMetadata("wildcardsWithDefault.kt")
public void testWildcardsWithDefault() throws Exception {
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/warnings/wildcardsWithDefault.kt");
}
}
} }
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify") @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
@@ -115,6 +115,26 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/classpath.args"); runTest("compiler/testData/cli/jvm/classpath.args");
} }
@TestMetadata("codeanalysisDefault.args")
public void testCodeanalysisDefault() throws Exception {
runTest("compiler/testData/cli/jvm/codeanalysisDefault.args");
}
@TestMetadata("codeanalysisIgnore.args")
public void testCodeanalysisIgnore() throws Exception {
runTest("compiler/testData/cli/jvm/codeanalysisIgnore.args");
}
@TestMetadata("codeanalysisStrict.args")
public void testCodeanalysisStrict() throws Exception {
runTest("compiler/testData/cli/jvm/codeanalysisStrict.args");
}
@TestMetadata("codeanalysisWarn.args")
public void testCodeanalysisWarn() throws Exception {
runTest("compiler/testData/cli/jvm/codeanalysisWarn.args");
}
@TestMetadata("compatqualDefault.args") @TestMetadata("compatqualDefault.args")
public void testCompatqualDefault() throws Exception { public void testCompatqualDefault() throws Exception {
runTest("compiler/testData/cli/jvm/compatqualDefault.args"); runTest("compiler/testData/cli/jvm/compatqualDefault.args");
@@ -31,18 +31,7 @@ val DEFAULT_JSPECIFY_APPLICABILITY = listOf(
AnnotationQualifierApplicabilityType.TYPE_USE AnnotationQualifierApplicabilityType.TYPE_USE
) )
val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf( val CODE_ANALYSIS_DEFAULT_ANNOTATIONS = mapOf(
FqName("javax.annotation.ParametersAreNullableByDefault") to
JavaDefaultQualifiers(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
),
FqName("javax.annotation.ParametersAreNonnullByDefault") to
JavaDefaultQualifiers(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
),
JSPECIFY_DEFAULT_NULLABLE to JavaDefaultQualifiers( JSPECIFY_DEFAULT_NULLABLE to JavaDefaultQualifiers(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE), NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE),
DEFAULT_JSPECIFY_APPLICABILITY DEFAULT_JSPECIFY_APPLICABILITY
@@ -58,4 +47,17 @@ val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf(
) )
) )
val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf(
FqName("javax.annotation.ParametersAreNullableByDefault") to
JavaDefaultQualifiers(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
),
FqName("javax.annotation.ParametersAreNonnullByDefault") to
JavaDefaultQualifiers(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
)
) + CODE_ANALYSIS_DEFAULT_ANNOTATIONS
val BUILT_IN_TYPE_QUALIFIER_FQ_NAMES = setOf(JAVAX_NONNULL_ANNOTATION, JAVAX_CHECKFORNULL_ANNOTATION) val BUILT_IN_TYPE_QUALIFIER_FQ_NAMES = setOf(JAVAX_NONNULL_ANNOTATION, JAVAX_CHECKFORNULL_ANNOTATION)
@@ -79,18 +79,26 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
} }
fun resolveQualifierBuiltInDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): JavaDefaultQualifiers? { fun resolveQualifierBuiltInDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): JavaDefaultQualifiers? {
if (javaTypeEnhancementState.disabledJsr305) { if (javaTypeEnhancementState.disabledDefaultAnnotations) {
return null return null
} }
return BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS[annotationDescriptor.fqName]?.let { qualifierForDefaultingAnnotation -> return BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS[annotationDescriptor.fqName]?.let { qualifierForDefaultingAnnotation ->
val state = resolveJsr305AnnotationState(annotationDescriptor).takeIf { it != ReportLevel.IGNORE } ?: return null val state = resolveDefaultAnnotationState(annotationDescriptor).takeIf { it != ReportLevel.IGNORE } ?: return null
return qualifierForDefaultingAnnotation.copy( return qualifierForDefaultingAnnotation.copy(
nullabilityQualifier = qualifierForDefaultingAnnotation.nullabilityQualifier.copy(isForWarningOnly = state.isWarning) nullabilityQualifier = qualifierForDefaultingAnnotation.nullabilityQualifier.copy(isForWarningOnly = state.isWarning)
) )
} }
} }
private fun resolveDefaultAnnotationState(annotationDescriptor: AnnotationDescriptor): ReportLevel {
if (annotationDescriptor.fqName in CODE_ANALYSIS_DEFAULT_ANNOTATIONS) {
return javaTypeEnhancementState.jspecifyReportLevel
}
return resolveJsr305AnnotationState(annotationDescriptor)
}
fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? { fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? {
if (javaTypeEnhancementState.disabledJsr305) { if (javaTypeEnhancementState.disabledJsr305) {
return null return null
@@ -156,8 +164,6 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
) )
else -> emptyList() else -> emptyList()
} }
val disabled: Boolean = javaTypeEnhancementState.disabledJsr305
} }
private val ClassDescriptor.isAnnotatedWithTypeQualifier: Boolean private val ClassDescriptor.isAnnotatedWithTypeQualifier: Boolean
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
import java.util.* import java.util.*
class JavaResolverComponents( class JavaResolverComponents(
@@ -64,7 +65,8 @@ class JavaResolverComponents(
val signatureEnhancement: SignatureEnhancement, val signatureEnhancement: SignatureEnhancement,
val javaClassesTracker: JavaClassesTracker, val javaClassesTracker: JavaClassesTracker,
val settings: JavaResolverSettings, val settings: JavaResolverSettings,
val kotlinTypeChecker: NewKotlinTypeChecker val kotlinTypeChecker: NewKotlinTypeChecker,
val javaTypeEnhancementState: JavaTypeEnhancementState
) { ) {
fun replace( fun replace(
javaResolverCache: JavaResolverCache = this.javaResolverCache javaResolverCache: JavaResolverCache = this.javaResolverCache
@@ -74,7 +76,8 @@ class JavaResolverComponents(
javaPropertyInitializerEvaluator, samConversionResolver, sourceElementFactory, javaPropertyInitializerEvaluator, samConversionResolver, sourceElementFactory,
moduleClassResolver, packagePartProvider, supertypeLoopChecker, lookupTracker, module, reflectionTypes, moduleClassResolver, packagePartProvider, supertypeLoopChecker, lookupTracker, module, reflectionTypes,
annotationTypeQualifierResolver, signatureEnhancement, javaClassesTracker, settings, annotationTypeQualifierResolver, signatureEnhancement, javaClassesTracker, settings,
kotlinTypeChecker kotlinTypeChecker,
javaTypeEnhancementState
) )
} }
@@ -130,7 +133,7 @@ fun LazyJavaResolverContext.child(
fun LazyJavaResolverContext.computeNewDefaultTypeQualifiers( fun LazyJavaResolverContext.computeNewDefaultTypeQualifiers(
additionalAnnotations: Annotations additionalAnnotations: Annotations
): JavaTypeQualifiersByElementType? { ): JavaTypeQualifiersByElementType? {
if (components.annotationTypeQualifierResolver.disabled) return defaultTypeQualifiers if (components.javaTypeEnhancementState.disabledDefaultAnnotations) return defaultTypeQualifiers
val defaultQualifiers = val defaultQualifiers =
additionalAnnotations.mapNotNull(this::extractDefaultNullabilityQualifier) additionalAnnotations.mapNotNull(this::extractDefaultNullabilityQualifier)
@@ -56,7 +56,7 @@ class LazyJavaPackageFragment(
override val annotations = override val annotations =
// Do not resolve package annotations if JSR-305 is disabled // Do not resolve package annotations if JSR-305 is disabled
if (c.components.annotationTypeQualifierResolver.disabled) Annotations.EMPTY if (c.components.javaTypeEnhancementState.disabledDefaultAnnotations) Annotations.EMPTY
else c.resolveAnnotations(jPackage) else c.resolveAnnotations(jPackage)
internal fun getSubPackageFqNames(): List<FqName> = subPackages() internal fun getSubPackageFqNames(): List<FqName> = subPackages()
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
import org.jetbrains.kotlin.utils.ReportLevel
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -102,11 +103,16 @@ class SignatureEnhancement(
private fun jspecifyMigrationStatus( private fun jspecifyMigrationStatus(
annotationFqName: FqName annotationFqName: FqName
): NullabilityQualifierWithMigrationStatus? = when (annotationFqName) { ): NullabilityQualifierWithMigrationStatus? {
JSPECIFY_NOT_NULL -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) if (javaTypeEnhancementState.jspecifyReportLevel == ReportLevel.IGNORE) return null
JSPECIFY_NULLABLE -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) val isForWarningOnly = javaTypeEnhancementState.jspecifyReportLevel == ReportLevel.WARN
JSPECIFY_NULLNESS_UNKNOWN -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY) return when (annotationFqName) {
else -> null JSPECIFY_NOT_NULL -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly)
JSPECIFY_NULLABLE -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarningOnly)
JSPECIFY_NULLNESS_UNKNOWN ->
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY, isForWarningOnly)
else -> null
}
} }
private fun commonMigrationStatus( private fun commonMigrationStatus(
@@ -111,6 +111,7 @@ fun makeLazyJavaPackageFragmentFromClassLoaderProvider(
packagePartProvider: PackagePartProvider = PackagePartProvider.Empty packagePartProvider: PackagePartProvider = PackagePartProvider.Empty
): LazyJavaPackageFragmentProvider { ): LazyJavaPackageFragmentProvider {
val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver(storageManager, JavaTypeEnhancementState.DISABLED_JSR_305) val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver(storageManager, JavaTypeEnhancementState.DISABLED_JSR_305)
val javaTypeEnhancementState = JavaTypeEnhancementState.DISABLED_JSR_305
val javaResolverComponents = JavaResolverComponents( val javaResolverComponents = JavaResolverComponents(
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver, storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
SignaturePropagator.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY, SignaturePropagator.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY,
@@ -118,7 +119,7 @@ fun makeLazyJavaPackageFragmentFromClassLoaderProvider(
singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module, singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver, ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
SignatureEnhancement(annotationTypeQualifierResolver, JavaTypeEnhancementState.DISABLED_JSR_305, JavaTypeEnhancement(JavaResolverSettings.Default)), SignatureEnhancement(annotationTypeQualifierResolver, JavaTypeEnhancementState.DISABLED_JSR_305, JavaTypeEnhancement(JavaResolverSettings.Default)),
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default, javaTypeEnhancementState
) )
return LazyJavaPackageFragmentProvider(javaResolverComponents) return LazyJavaPackageFragmentProvider(javaResolverComponents)
@@ -34,7 +34,8 @@ class JavaTypeEnhancementState(
val globalJsr305Level: ReportLevel, val globalJsr305Level: ReportLevel,
val migrationLevelForJsr305: ReportLevel?, val migrationLevelForJsr305: ReportLevel?,
val userDefinedLevelForSpecificJsr305Annotation: Map<String, ReportLevel>, val userDefinedLevelForSpecificJsr305Annotation: Map<String, ReportLevel>,
val enableCompatqualCheckerFrameworkAnnotations: Boolean = COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE val enableCompatqualCheckerFrameworkAnnotations: Boolean = COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE,
val jspecifyReportLevel: ReportLevel = DEFAULT_REPORT_LEVEL_FOR_CODE_ANALYSIS
) { ) {
val description: Array<String> by lazy { val description: Array<String> by lazy {
val result = mutableListOf<String>() val result = mutableListOf<String>()
@@ -49,11 +50,19 @@ class JavaTypeEnhancementState(
result.toTypedArray() result.toTypedArray()
} }
val disabledJsr305: Boolean get() = this === DISABLED_JSR_305 val disabledJsr305: Boolean =
globalJsr305Level == ReportLevel.IGNORE &&
migrationLevelForJsr305 == ReportLevel.IGNORE &&
userDefinedLevelForSpecificJsr305Annotation.isEmpty()
val disabledDefaultAnnotations = disabledJsr305 || jspecifyReportLevel == ReportLevel.IGNORE
companion object { companion object {
const val COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE = true const val COMPATQUAL_CHECKER_FRAMEWORK_ANNOTATIONS_SUPPORT_DEFAULT_VALUE = true
@JvmField
val DEFAULT_REPORT_LEVEL_FOR_CODE_ANALYSIS = ReportLevel.WARN
@JvmField @JvmField
val DEFAULT: JavaTypeEnhancementState = JavaTypeEnhancementState(ReportLevel.WARN, null, emptyMap()) val DEFAULT: JavaTypeEnhancementState = JavaTypeEnhancementState(ReportLevel.WARN, null, emptyMap())
@@ -79,7 +79,8 @@ object IDELanguageSettingsProvider : LanguageSettingsProvider {
result = JavaTypeEnhancementStateParser(MessageCollector.NONE).parse( result = JavaTypeEnhancementStateParser(MessageCollector.NONE).parse(
compilerArguments.jsr305, compilerArguments.jsr305,
compilerArguments.supportCompatqualCheckerFrameworkAnnotations compilerArguments.supportCompatqualCheckerFrameworkAnnotations,
compilerArguments.jspecifyAnnotations
) )
} }