Disable JSR-305 annotations by default, introduce CLI argument

No package annotations are going to be loaded, and
TypeQualifierDefault/TypeQualifierNickname are no longer recognized by
default. Use the CLI argument "-Xload-jsr305-annotations" to enable this
behavior back

 #KT-10942
This commit is contained in:
Alexander Udalov
2017-07-07 13:33:42 +03:00
parent 522f67fda0
commit 127cd1295e
15 changed files with 119 additions and 76 deletions
@@ -157,6 +157,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
description = "Java compiler arguments")
public String[] javacArguments;
@Argument(value = "-Xload-jsr305-annotations", description = "Load JSR-305 nullability annotations")
public boolean loadJsr305annotations;
// Paths to output directories for friend modules.
public String[] friendPaths;
}
@@ -122,8 +122,8 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
}
}
private static void setupCommonArgumentsAndServices(
@NotNull CompilerConfiguration configuration, @NotNull CommonCompilerArguments arguments, @NotNull Services services
private void setupCommonArgumentsAndServices(
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
) {
if (arguments.noInline) {
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true);
@@ -143,9 +143,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
setupLanguageVersionSettings(configuration, arguments);
}
private static void setupLanguageVersionSettings(
@NotNull CompilerConfiguration configuration, @NotNull CommonCompilerArguments arguments
) {
private void setupLanguageVersionSettings(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
LanguageVersion languageVersion = parseVersion(configuration, arguments.languageVersion, "language");
LanguageVersion apiVersion = parseVersion(configuration, arguments.apiVersion, "API");
@@ -195,9 +193,13 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
new LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(apiVersion), extraLanguageFeatures);
settings.switchFlag(AnalysisFlags.getSkipMetadataVersionCheck(), arguments.skipMetadataVersionCheck);
settings.switchFlag(AnalysisFlags.getMultiPlatformDoNotCheckImpl(), arguments.noCheckImpl);
configureAnalysisFlags(settings, arguments);
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, settings);
}
protected void configureAnalysisFlags(@NotNull LanguageVersionSettingsImpl settings, @NotNull A arguments) {
}
@Nullable
private static LanguageFeature.State chooseCoroutinesApplicabilityLevel(
@NotNull CompilerConfiguration configuration,
@@ -310,6 +310,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
}
override fun configureAnalysisFlags(settings: LanguageVersionSettingsImpl, arguments: K2JVMCompilerArguments) {
settings.switchFlag(AnalysisFlags.loadJsr305Annotations, arguments.loadJsr305annotations)
}
override fun createArguments(): K2JVMCompilerArguments = K2JVMCompilerArguments().apply {
if (System.getenv("KOTLIN_REPORT_PERF") != null) {
reportPerf = true
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.frontend.java.di
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -28,9 +29,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.frontend.di.configureModule
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.components.*
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
import org.jetbrains.kotlin.load.java.sam.SamConversionResolverImpl
@@ -104,6 +103,13 @@ fun createContainerForLazyResolveWithJava(
useInstance(languageVersionSettings)
if (languageVersionSettings.isFlagEnabled(AnalysisFlags.loadJsr305Annotations)) {
useImpl<AnnotationTypeQualifierResolverImpl>()
}
else {
useInstance(AnnotationTypeQualifierResolver.Empty)
}
if (useBuiltInsProvider) {
useInstance((moduleContext.module.builtIns as JvmBuiltIns).settings)
useImpl<JvmBuiltInsPackageFragmentProvider>()
+1
View File
@@ -20,6 +20,7 @@ where advanced options include:
Script resolver environment in key-value pairs (the value could be quoted and escaped)
-Xuse-javac Use javac for Java source and class files analysis
-Xjavac-arguments=<option[,]> Java compiler arguments
-Xload-jsr305-annotations Load JSR-305 nullability annotations
-Xno-inline Disable method inlining
-Xrepeat=<count> Repeat compilation (for performance analysis)
-Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes)
@@ -203,7 +203,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
// To be overridden by diagnostic-like tests.
}
private fun loadLanguageVersionSettings(module: List<TestFile>): LanguageVersionSettings {
protected open fun loadLanguageVersionSettings(module: List<TestFile>): LanguageVersionSettings {
var result: LanguageVersionSettings? = null
for (file in module) {
val current = file.customLanguageVersionSettings
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.checkers
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.test.MockLibraryUtil
import java.io.File
@@ -27,4 +28,10 @@ abstract class AbstractForeignAnnotationsTest : AbstractDiagnosticsWithFullJdkTe
open protected val annotationsPath: String
get() = FOREIGN_ANNOTATIONS_SOURCES_PATH
override fun loadLanguageVersionSettings(module: List<TestFile>): LanguageVersionSettings {
return LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE).apply {
switchFlag(AnalysisFlags.loadJsr305Annotations, true)
}
}
}
@@ -20,8 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.name.FqName
@@ -41,26 +40,28 @@ class LoadJavaPackageAnnotationsTest : KtUsefulTestCase() {
}
private fun doTest(useJavac: Boolean, configurator: (CompilerConfiguration) -> Unit) {
val configuration = KotlinTestUtils.newConfiguration(
ConfigurationKind.ALL, TestJdkKind.FULL_JDK, KotlinTestUtils.getAnnotationsJar()
).apply {
if (useJavac) {
put(JVMConfigurationKeys.USE_JAVAC, true)
}
languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE).apply {
switchFlag(AnalysisFlags.loadJsr305Annotations, true)
}
configurator(this)
}
val environment =
KotlinCoreEnvironment.createForTests(
myTestRootDisposable,
KotlinTestUtils.newConfiguration(
ConfigurationKind.ALL, TestJdkKind.FULL_JDK, KotlinTestUtils.getAnnotationsJar()
).also {
if (useJavac) {
it.put(JVMConfigurationKeys.USE_JAVAC, true)
}
configurator(it)
},
configuration,
EnvironmentConfigFiles.JVM_CONFIG_FILES
).apply {
if (useJavac) {
registerJavac()
}
}
val moduleDescriptor = JvmResolveUtil.analyze(
environment
).moduleDescriptor
val moduleDescriptor = JvmResolveUtil.analyze(environment).moduleDescriptor
val packageFragmentDescriptor =
moduleDescriptor.getPackage(FqName("test")).fragments
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.jvm.compiler
import org.jetbrains.kotlin.checkers.FOREIGN_ANNOTATIONS_SOURCES_PATH
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -82,33 +83,27 @@ class TypeQualifierAnnotationResolverTest : KtUsefulTestCase() {
}
private fun buildTypeQualifierResolverAndFindClass(className: String): Pair<AnnotationTypeQualifierResolver, ClassDescriptor> {
val environment =
KotlinCoreEnvironment.createForTests(
myTestRootDisposable,
KotlinTestUtils.newConfiguration(
ConfigurationKind.ALL, TestJdkKind.FULL_JDK,
listOf(
KotlinTestUtils.getAnnotationsJar(),
MockLibraryUtil.compileJavaFilesLibraryToJar(
FOREIGN_ANNOTATIONS_SOURCES_PATH,
"foreign-annotations"
)
),
listOf(File(TEST_DATA_PATH))
),
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
val configuration = KotlinTestUtils.newConfiguration(
ConfigurationKind.ALL, TestJdkKind.FULL_JDK,
listOf(
KotlinTestUtils.getAnnotationsJar(),
MockLibraryUtil.compileJavaFilesLibraryToJar(
FOREIGN_ANNOTATIONS_SOURCES_PATH,
"foreign-annotations"
)
),
listOf(File(TEST_DATA_PATH))
).apply {
languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE).apply {
switchFlag(AnalysisFlags.loadJsr305Annotations, true)
}
}
val environment = KotlinCoreEnvironment.createForTests(myTestRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
val container = JvmResolveUtil.createContainer(environment)
val typeQualifierResolver = container.get<JavaResolverComponents>().annotationTypeQualifierResolver
val aClass =
container
.get<ModuleDescriptor>()
.resolveClassByFqName(FqName(className), NoLookupLocation.FROM_TEST)!!
val aClass = container.get<ModuleDescriptor>().resolveClassByFqName(FqName(className), NoLookupLocation.FROM_TEST)!!
return typeQualifierResolver to aClass
}
@@ -29,7 +29,7 @@ class AnalysisFlag internal constructor(private val name: String) {
companion object
}
private operator fun AnalysisFlag.Companion.provideDelegate(instance: Any?, property: KProperty<*>) =
private operator fun @Suppress("unused") AnalysisFlag.Companion.provideDelegate(instance: Any?, property: KProperty<*>) =
object : ReadOnlyProperty<Any?, AnalysisFlag> {
private val flag = AnalysisFlag(property.name)
@@ -42,4 +42,7 @@ object AnalysisFlags {
@JvmStatic
val multiPlatformDoNotCheckImpl by AnalysisFlag
@JvmStatic
val loadJsr305Annotations by AnalysisFlag
}
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver.QualifierApplicabilityType
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver.TypeQualifierWithApplicability
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
@@ -31,28 +33,10 @@ private val TYPE_QUALIFIER_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQ
private val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier")
private val TYPE_QUALIFIER_DEFAULT_FQNAME = FqName("javax.annotation.meta.TypeQualifierDefault")
class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
private val resolvedNicknames =
storageManager.createMemoizedFunctionWithNullableValues(this::computeTypeQualifierNickname)
interface AnnotationTypeQualifierResolver {
fun resolveTypeQualifierAnnotation(annotationDescriptor: AnnotationDescriptor): AnnotationDescriptor?
private fun computeTypeQualifierNickname(classDescriptor: ClassDescriptor): AnnotationDescriptor? {
if (!classDescriptor.annotations.hasAnnotation(TYPE_QUALIFIER_NICKNAME_FQNAME)) return null
return classDescriptor.annotations.firstNotNullResult(this::resolveTypeQualifierAnnotation)
}
private fun resolveTypeQualifierNickname(classDescriptor: ClassDescriptor): AnnotationDescriptor? {
if (classDescriptor.kind != ClassKind.ANNOTATION_CLASS) return null
return resolvedNicknames(classDescriptor)
}
fun resolveTypeQualifierAnnotation(annotationDescriptor: AnnotationDescriptor): AnnotationDescriptor? {
val annotationClass = annotationDescriptor.annotationClass ?: return null
if (annotationClass.isAnnotatedWithTypeQualifier) return annotationDescriptor
return resolveTypeQualifierNickname(annotationClass)
}
fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability?
enum class QualifierApplicabilityType {
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE
@@ -68,7 +52,37 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
operator fun component2() = QualifierApplicabilityType.values().filter(this::isApplicableTo)
}
fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? {
object Empty : AnnotationTypeQualifierResolver {
override fun resolveTypeQualifierAnnotation(annotationDescriptor: AnnotationDescriptor): AnnotationDescriptor? = null
override fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? = null
}
}
class AnnotationTypeQualifierResolverImpl(storageManager: StorageManager) : AnnotationTypeQualifierResolver {
private val resolvedNicknames =
storageManager.createMemoizedFunctionWithNullableValues(this::computeTypeQualifierNickname)
private fun computeTypeQualifierNickname(classDescriptor: ClassDescriptor): AnnotationDescriptor? {
if (!classDescriptor.annotations.hasAnnotation(TYPE_QUALIFIER_NICKNAME_FQNAME)) return null
return classDescriptor.annotations.firstNotNullResult(this::resolveTypeQualifierAnnotation)
}
private fun resolveTypeQualifierNickname(classDescriptor: ClassDescriptor): AnnotationDescriptor? {
if (classDescriptor.kind != ClassKind.ANNOTATION_CLASS) return null
return resolvedNicknames(classDescriptor)
}
override fun resolveTypeQualifierAnnotation(annotationDescriptor: AnnotationDescriptor): AnnotationDescriptor? {
val annotationClass = annotationDescriptor.annotationClass ?: return null
if (annotationClass.isAnnotatedWithTypeQualifier) return annotationDescriptor
return resolveTypeQualifierNickname(annotationClass)
}
override fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? {
val typeQualifierDefaultAnnotatedClass =
annotationDescriptor.annotationClass?.takeIf { it.annotations.hasAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME) }
?: return null
@@ -26,7 +26,7 @@ class LazyJavaPackageFragmentProvider(
components: JavaResolverComponents
) : PackageFragmentProvider {
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY, lazyOf(null))
private val packageFragments: MemoizedFunctionToNullable<FqName, LazyJavaPackageFragment> =
c.storageManager.createMemoizedFunctionWithNullableValues {
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
@@ -52,7 +54,10 @@ class LazyJavaPackageFragment(
onRecursiveCall = listOf()
)
override val annotations = c.resolveAnnotations(jPackage)
override val annotations =
// Do not resolve package annotations if JSR-305 is disabled
if (c.components.annotationTypeQualifierResolver == AnnotationTypeQualifierResolver.Empty) Annotations.EMPTY
else c.resolveAnnotations(jPackage)
internal fun getSubPackageFqNames(): List<FqName> = subPackages()
@@ -48,16 +48,18 @@ import java.util.*
class SignatureEnhancement(private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver) {
fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifier? {
when (annotationDescriptor.annotationClass?.fqNameSafe) {
val annotationFqName = annotationDescriptor.annotationClass?.fqNameSafe ?: return null
when (annotationFqName) {
in NULLABLE_ANNOTATIONS -> return NullabilityQualifier.NULLABLE
in NOT_NULL_ANNOTATIONS -> return NullabilityQualifier.NOT_NULL
}
val typeQualifier =
annotationTypeQualifierResolver
.resolveTypeQualifierAnnotation(annotationDescriptor)
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
?: return null
when {
annotationFqName == JAVAX_NONNULL_ANNOTATION -> annotationDescriptor
else -> annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor)
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
} ?: return null
val enumEntryDescriptor =
typeQualifier.allValueArguments.values.singleOrNull()?.value
@@ -58,7 +58,7 @@ class RuntimeModuleData private constructor(
val runtimePackagePartProvider = RuntimePackagePartProvider(classLoader)
val javaResolverCache = JavaResolverCache.EMPTY
val notFoundClasses = NotFoundClasses(storageManager, module)
val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver(storageManager)
val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver.Empty
val globalJavaResolverContext = JavaResolverComponents(
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
ExternalAnnotationResolver.EMPTY, SignaturePropagator.DO_NOTHING, RuntimeErrorReporter, javaResolverCache,