Support decapitilized obsolete annotations in resolve
Annotations like `deprecated`, `jvmStatic`, etc. has been renamed to capitilized themselves. But we're going to support both versions. It's hard just to leave both versions of classes as their class-files can clash when compiled on register-independent file system. So here is solution (temporary hack): we just wrap JetScopes for package fragments of `kotlin.*` to make them search both versions of annotations if their names are contained in our hardcoded set.
This commit is contained in:
@@ -138,7 +138,7 @@ public class JvmCodegenUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinJvmBinaryClass binaryClass = ((LazyJavaPackageFragment) packageFragment).getMemberScope().getKotlinBinaryClass();
|
KotlinJvmBinaryClass binaryClass = ((LazyJavaPackageFragment) packageFragment).getScope().getKotlinBinaryClass();
|
||||||
if (binaryClass instanceof VirtualFileKotlinClass) {
|
if (binaryClass instanceof VirtualFileKotlinClass) {
|
||||||
VirtualFile file = ((VirtualFileKotlinClass) binaryClass).getFile();
|
VirtualFile file = ((VirtualFileKotlinClass) binaryClass).getFile();
|
||||||
if (file.getFileSystem().getProtocol() == StandardFileSystems.FILE_PROTOCOL) {
|
if (file.getFileSystem().getProtocol() == StandardFileSystems.FILE_PROTOCOL) {
|
||||||
|
|||||||
+2
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DecapitalizedAnnotationScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.serialization.PackageData
|
import org.jetbrains.kotlin.serialization.PackageData
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
@@ -105,7 +106,7 @@ public class IncrementalPackageFragmentProvider(
|
|||||||
JetScope.Empty
|
JetScope.Empty
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(packageDataBytes))
|
DecapitalizedAnnotationScope.wrapIfNeeded(IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(packageDataBytes)), fqName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.LazyEntity;
|
import org.jetbrains.kotlin.resolve.lazy.LazyEntity;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider;
|
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DecapitalizedAnnotationScope;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
|
|
||||||
public class LazyPackageDescriptor extends PackageFragmentDescriptorImpl implements LazyEntity {
|
public class LazyPackageDescriptor extends PackageFragmentDescriptorImpl implements LazyEntity {
|
||||||
@@ -41,7 +42,8 @@ public class LazyPackageDescriptor extends PackageFragmentDescriptorImpl impleme
|
|||||||
super(module, fqName);
|
super(module, fqName);
|
||||||
this.declarationProvider = declarationProvider;
|
this.declarationProvider = declarationProvider;
|
||||||
|
|
||||||
this.memberScope = new LazyPackageMemberScope(resolveSession, declarationProvider, this);
|
// Wrapping is just a temporary hack to inject deprecated decapitalized annotation
|
||||||
|
this.memberScope = DecapitalizedAnnotationScope.Companion.wrapIfNeeded(new LazyPackageMemberScope(resolveSession, declarationProvider, this), fqName);
|
||||||
|
|
||||||
for (JetFile file : declarationProvider.getPackageFiles()) {
|
for (JetFile file : declarationProvider.getPackageFiles()) {
|
||||||
resolveSession.getTrace().record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file, this);
|
resolveSession.getTrace().record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file, this);
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ public class LazyJavaPackageFragmentProvider(
|
|||||||
override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName))
|
override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName))
|
||||||
|
|
||||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean) =
|
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean) =
|
||||||
getPackageFragment(fqName)?.getMemberScope()?.getSubPackages().orEmpty()
|
getPackageFragment(fqName)?.scope?.getSubPackages().orEmpty()
|
||||||
|
|
||||||
fun getClass(javaClass: JavaClass): ClassDescriptor? = c.javaClassResolver.resolveClass(javaClass)
|
fun getClass(javaClass: JavaClass): ClassDescriptor? = c.javaClassResolver.resolveClass(javaClass)
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -22,12 +22,16 @@ import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
|||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DecapitalizedAnnotationScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
|
|
||||||
class LazyJavaPackageFragment(
|
class LazyJavaPackageFragment(
|
||||||
private val c: LazyJavaResolverContext,
|
private val c: LazyJavaResolverContext,
|
||||||
private val jPackage: JavaPackage
|
private val jPackage: JavaPackage
|
||||||
) : PackageFragmentDescriptorImpl(c.module, jPackage.getFqName()) {
|
) : PackageFragmentDescriptorImpl(c.module, jPackage.getFqName()) {
|
||||||
private val scope by lazy { LazyJavaPackageScope(c, jPackage, this) }
|
val scope: LazyJavaPackageScope by lazy { LazyJavaPackageScope(c, jPackage, this) }
|
||||||
|
// Just a temporary hack to inject deprecated decapitalized annotation
|
||||||
|
private val wrappedScope by lazy { DecapitalizedAnnotationScope.wrapIfNeeded(scope, jPackage.getFqName()) }
|
||||||
|
|
||||||
private val topLevelClasses = c.storageManager.createMemoizedFunctionWithNullableValues {
|
private val topLevelClasses = c.storageManager.createMemoizedFunctionWithNullableValues {
|
||||||
javaClass: JavaClass ->
|
javaClass: JavaClass ->
|
||||||
@@ -36,7 +40,7 @@ class LazyJavaPackageFragment(
|
|||||||
|
|
||||||
internal fun resolveTopLevelClass(javaClass: JavaClass) = topLevelClasses(javaClass)
|
internal fun resolveTopLevelClass(javaClass: JavaClass) = topLevelClasses(javaClass)
|
||||||
|
|
||||||
override fun getMemberScope() = scope
|
override fun getMemberScope(): JetScope = wrappedScope
|
||||||
|
|
||||||
override fun toString() = "lazy java package fragment: $fqName"
|
override fun toString() = "lazy java package fragment: $fqName"
|
||||||
|
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.scopes
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
|
||||||
|
val DECAPITALIZED_DEPRECATED_ANNOTATIONS = arrayOf(
|
||||||
|
"Deprecated", "Extension", "Suppress", "Throws",
|
||||||
|
"jvm.Volatile", "jvm.Transient", "jvm.Strictfp", "jvm.Synchronized",
|
||||||
|
"jvm.JvmOverloads", "jvm.JvmName", "jvm.JvmStatic"
|
||||||
|
).map { FqName("kotlin.$it") }.toSet()
|
||||||
|
|
||||||
|
val DECAPITALIZED_SHORT_NAMES = DECAPITALIZED_DEPRECATED_ANNOTATIONS.map { it.shortName().asString().decapitalize() }.toSet()
|
||||||
|
|
||||||
|
public class DecapitalizedAnnotationScope(override val workerScope: JetScope) : AbstractScopeAdapter() {
|
||||||
|
override fun getClassifier(name: Name, location: LookupLocation)
|
||||||
|
= super.getClassifier(name, location)
|
||||||
|
?: findDecapitalizedAnnotation(name, location)
|
||||||
|
|
||||||
|
private fun findDecapitalizedAnnotation(name: Name, location: LookupLocation): ClassifierDescriptor? {
|
||||||
|
val nameAsString = name.asString()
|
||||||
|
|
||||||
|
if (nameAsString[0].isUpperCase() || nameAsString !in DECAPITALIZED_SHORT_NAMES) return null
|
||||||
|
val capitalizedIdentifier = Name.identifier(nameAsString.capitalize())
|
||||||
|
|
||||||
|
val capitalizedClassifier = getClassifier(capitalizedIdentifier, location) ?: return null
|
||||||
|
|
||||||
|
return if (capitalizedClassifier.fqNameSafe in DECAPITALIZED_DEPRECATED_ANNOTATIONS)
|
||||||
|
capitalizedClassifier
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
public fun wrapIfNeeded(scope: JetScope, fqName: FqName): JetScope {
|
||||||
|
if (fqName.firstSegmentIs(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) {
|
||||||
|
return DecapitalizedAnnotationScope(scope)
|
||||||
|
}
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-2
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DecapitalizedAnnotationScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
import org.jetbrains.kotlin.serialization.SerializedResourcePaths
|
import org.jetbrains.kotlin.serialization.SerializedResourcePaths
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
@@ -56,10 +58,17 @@ public abstract class DeserializedPackageFragment(
|
|||||||
DeserializedPackageMemberScope(this, packageProto, nameResolver, components, classNames = { loadClassNames(packageProto) })
|
DeserializedPackageMemberScope(this, packageProto, nameResolver, components, classNames = { loadClassNames(packageProto) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMemberScope() = deserializedMemberScope
|
// Just a temporary hack to inject deprecated decapitalized annotation
|
||||||
|
internal val deserializedMemberScopeWrapped by storageManager.createLazyValue {
|
||||||
|
DecapitalizedAnnotationScope.wrapIfNeeded(deserializedMemberScope, fqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMemberScope(): JetScope {
|
||||||
|
return deserializedMemberScopeWrapped
|
||||||
|
}
|
||||||
|
|
||||||
internal fun hasTopLevelClass(name: Name): Boolean {
|
internal fun hasTopLevelClass(name: Name): Boolean {
|
||||||
return name in getMemberScope().classNames
|
return name in deserializedMemberScope.classNames
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun loadClassNames(packageProto: ProtoBuf.Package): Collection<Name>
|
protected abstract fun loadClassNames(packageProto: ProtoBuf.Package): Collection<Name>
|
||||||
|
|||||||
Reference in New Issue
Block a user