mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-05 08:31:29 +00:00
Compare commits
93 Commits
rr/pdn_byt
...
build-1.5.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5b9b6d962 | ||
|
|
d6e3cd8926 | ||
|
|
320aa586e2 | ||
|
|
b2f6218857 | ||
|
|
9ec4f503fb | ||
|
|
ea1859809d | ||
|
|
7dc80cd57f | ||
|
|
c7902eee64 | ||
|
|
6de79570e8 | ||
|
|
1641e8d97e | ||
|
|
241d4f973d | ||
|
|
0ff28e00c8 | ||
|
|
39111bd33c | ||
|
|
87a1a9de10 | ||
|
|
da07980f0c | ||
|
|
b8ad5b8c56 | ||
|
|
504e172f29 | ||
|
|
6844b9047a | ||
|
|
88b4914b2e | ||
|
|
0294a3f1a1 | ||
|
|
72761a9255 | ||
|
|
5aba18ad15 | ||
|
|
b20a7efdb5 | ||
|
|
2832137461 | ||
|
|
85eef93f1d | ||
|
|
8db78e45b0 | ||
|
|
8d959dc8ef | ||
|
|
c7092b1e1d | ||
|
|
b8ae6d607d | ||
|
|
01e1e512fb | ||
|
|
eccd2c389e | ||
|
|
9d937f96ce | ||
|
|
125e229dcf | ||
|
|
b3a664ce13 | ||
|
|
f7bd9285c1 | ||
|
|
330c801957 | ||
|
|
50cb6a5308 | ||
|
|
5be8b728f1 | ||
|
|
19cc7866b3 | ||
|
|
1fd3575d57 | ||
|
|
d9dc51549f | ||
|
|
77e9a8ae13 | ||
|
|
9d98d93c9d | ||
|
|
3e69bcba47 | ||
|
|
47a7a28446 | ||
|
|
7573f73d9b | ||
|
|
fd55fcfca0 | ||
|
|
beba85a848 | ||
|
|
f7fdffefd6 | ||
|
|
b34e2c1474 | ||
|
|
72849a3dc3 | ||
|
|
bdf914e8d5 | ||
|
|
07b15f9de6 | ||
|
|
32c3f85679 | ||
|
|
7e052c1eb1 | ||
|
|
2a08923c51 | ||
|
|
8925b8c922 | ||
|
|
1afb844e1a | ||
|
|
12331cb10c | ||
|
|
d54808e33f | ||
|
|
f2f2df90aa | ||
|
|
660208740e | ||
|
|
704b5a0e13 | ||
|
|
ea2d9f7c0c | ||
|
|
cc4adb798f | ||
|
|
0c6066db74 | ||
|
|
0c0710bb79 | ||
|
|
71365d2452 | ||
|
|
dfc6d85aee | ||
|
|
dc2485ae71 | ||
|
|
37ccd82b6c | ||
|
|
19a5c2f1c8 | ||
|
|
e5128a8772 | ||
|
|
ccc27b6a0c | ||
|
|
6f2af740cb | ||
|
|
ed3542cdf5 | ||
|
|
666ad1f9d5 | ||
|
|
ea7ea979ee | ||
|
|
e2acc507d4 | ||
|
|
9cb740bfdb | ||
|
|
a1c1a32515 | ||
|
|
af2d0ad36f | ||
|
|
1835185b16 | ||
|
|
edb6b337dc | ||
|
|
e69b729e21 | ||
|
|
4282d17467 | ||
|
|
b88913af1d | ||
|
|
9a4742c08d | ||
|
|
9cf5ac1fbd | ||
|
|
a9cc046ec9 | ||
|
|
2c29957cb8 | ||
|
|
e96f64e6c9 | ||
|
|
b59f668a50 |
@@ -18,6 +18,7 @@ interface TypeMappingContext<Writer : JvmDescriptorTypeWriter<Type>> {
|
||||
val typeContext: TypeSystemCommonBackendContextForTypeMapping
|
||||
|
||||
fun getClassInternalName(typeConstructor: TypeConstructorMarker): String
|
||||
fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String
|
||||
fun Writer.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode)
|
||||
}
|
||||
|
||||
@@ -117,9 +118,7 @@ object AbstractTypeMapper {
|
||||
}
|
||||
|
||||
typeConstructor.isScript() -> {
|
||||
val asmType = AsmTypes.JAVA_CLASS_TYPE
|
||||
with(context) { sw?.writeGenericType(type, asmType, mode) }
|
||||
return asmType
|
||||
return Type.getObjectType(context.getScriptInternalName(typeConstructor))
|
||||
}
|
||||
|
||||
typeConstructor.isTypeParameter() -> {
|
||||
|
||||
@@ -265,13 +265,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
);
|
||||
}
|
||||
|
||||
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) {
|
||||
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen<?> member, @NotNull ClassDescriptor descriptor) {
|
||||
for (KotlinType type : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
for (TypeProjection supertypeArgument : type.getArguments()) {
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
|
||||
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
|
||||
processTypeArguments(member, type);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processTypeArguments(@NotNull MemberCodegen<?> member, KotlinType type) {
|
||||
for (TypeProjection supertypeArgument : type.getArguments()) {
|
||||
if (supertypeArgument.isStarProjection()) continue;
|
||||
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
|
||||
if (parameterDescriptor != null) {
|
||||
if (parameterDescriptor.isReified()) {
|
||||
member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString());
|
||||
}
|
||||
} else {
|
||||
processTypeArguments(member, supertypeArgument.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,12 @@ class JvmRuntimeTypes(
|
||||
else -> if (isMutable) mutablePropertyReferences else propertyReferences
|
||||
}
|
||||
|
||||
return classes[arity].defaultType
|
||||
return if (arity >= 0) {
|
||||
classes[arity].defaultType
|
||||
} else {
|
||||
//in case of ErrorUtils.ERROR_PROPERTY there would be no dispatchReceiverParameter and arity becomes negative
|
||||
//so we just take zero argument reference class (because it is incorrect anyway)
|
||||
classes[0].defaultType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,8 +320,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
|
||||
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
|
||||
|
||||
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
|
||||
processor.localVarsMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true);
|
||||
|
||||
mark.dropTo()
|
||||
}
|
||||
@@ -330,8 +329,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
}
|
||||
|
||||
processor.substituteTryBlockNodes(intoNode)
|
||||
|
||||
//processor.substituteLocalVarTable(intoNode);
|
||||
processor.substituteLocalVarTable(intoNode);
|
||||
}
|
||||
|
||||
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)
|
||||
|
||||
@@ -39,7 +39,7 @@ class RedundantBoxingMethodTransformer(private val generationState: GenerationSt
|
||||
|
||||
override fun transform(internalClassName: String, node: MethodNode) {
|
||||
val interpreter = RedundantBoxingInterpreter(node.instructions, generationState)
|
||||
val frames = MethodTransformer.analyze(internalClassName, node, interpreter)
|
||||
val frames = analyze(internalClassName, node, interpreter)
|
||||
|
||||
interpretPopInstructionsForBoxedValues(interpreter, node, frames)
|
||||
|
||||
@@ -168,7 +168,8 @@ class RedundantBoxingMethodTransformer(private val generationState: GenerationSt
|
||||
val frame = frames[i] ?: continue
|
||||
val insn = insnList[i]
|
||||
if ((insn.opcode == Opcodes.ASTORE || insn.opcode == Opcodes.ALOAD) &&
|
||||
(insn as VarInsnNode).`var` == localVariableNode.index) {
|
||||
(insn as VarInsnNode).`var` == localVariableNode.index
|
||||
) {
|
||||
if (insn.getOpcode() == Opcodes.ASTORE) {
|
||||
values.add(frame.top()!!)
|
||||
} else {
|
||||
|
||||
@@ -245,6 +245,7 @@ class GenerationState private constructor(
|
||||
this.moduleName,
|
||||
languageVersionSettings,
|
||||
useOldManglingSchemeForFunctionsWithInlineClassesInSignatures,
|
||||
IncompatibleClassTracker.DoNothing,
|
||||
target,
|
||||
isIrBackend
|
||||
)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
|
||||
interface IncompatibleClassTracker {
|
||||
fun record(binaryClass: KotlinJvmBinaryClass)
|
||||
|
||||
object DoNothing : IncompatibleClassTracker {
|
||||
override fun record(binaryClass: KotlinJvmBinaryClass) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
private val moduleName: String,
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
private val useOldInlineClassesManglingScheme: Boolean,
|
||||
// temporary returned to preserve binary compatibility with Dagger in IDE
|
||||
// https://android.googlesource.com/platform/tools/adt/idea/+/refs/heads/mirror-goog-studio-master-dev/dagger/src/com/android/tools/idea/dagger/DaggerAnnotatedElementsSearch.kt
|
||||
private val incompatibleClassTracker: IncompatibleClassTracker = IncompatibleClassTracker.DoNothing,
|
||||
val jvmTarget: JvmTarget = JvmTarget.DEFAULT,
|
||||
private val isIrBackend: Boolean = false,
|
||||
private val typePreprocessor: ((KotlinType) -> KotlinType?)? = null,
|
||||
|
||||
@@ -377,7 +377,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise"""
|
||||
|
||||
)
|
||||
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)
|
||||
var stringConcat: String? by NullableStringFreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-Xsam-conversions",
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiJavaModule
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.impl.light.LightJavaModule
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.cli.common.config.ContentRoot
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleGraph
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.isValidJavaFqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME
|
||||
@@ -52,10 +54,13 @@ class ClasspathRootsResolver(
|
||||
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
|
||||
private val javaModuleFinder: CliJavaModuleFinder,
|
||||
private val requireStdlibModule: Boolean,
|
||||
private val outputDirectory: VirtualFile?
|
||||
private val outputDirectory: VirtualFile?,
|
||||
private val javaFileManager: KotlinCliJavaFileManager
|
||||
) {
|
||||
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
|
||||
|
||||
private val searchScope = GlobalSearchScope.allScope(psiManager.project)
|
||||
|
||||
data class RootsAndModules(val roots: List<JavaRoot>, val modules: List<JavaModule>)
|
||||
|
||||
private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?)
|
||||
@@ -160,7 +165,7 @@ class ClasspathRootsResolver(
|
||||
}
|
||||
|
||||
if (moduleInfoFile != null) {
|
||||
val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
|
||||
val moduleInfo = JavaModuleInfo.read(moduleInfoFile, javaFileManager, searchScope) ?: return null
|
||||
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ class CliVirtualFileFinder(
|
||||
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? =
|
||||
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
|
||||
|
||||
override fun findSourceOrBinaryVirtualFile(classId: ClassId) =
|
||||
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
|
||||
?: findSourceClass(classId, classId.relativeClassName.asString() + ".java")
|
||||
|
||||
override fun findMetadata(classId: ClassId): InputStream? {
|
||||
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
|
||||
|
||||
@@ -61,8 +65,11 @@ class CliVirtualFileFinder(
|
||||
return findBinaryClass(classId, BuiltInSerializerProtocol.getBuiltInsFileName(packageFqName))?.inputStream
|
||||
}
|
||||
|
||||
private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? =
|
||||
index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
|
||||
private fun findClass(classId: ClassId, fileName: String, rootType: Set<JavaRoot.RootType>) =
|
||||
index.findClass(classId, acceptedRootTypes = rootType) { dir, _ ->
|
||||
dir.findChild(fileName)?.takeIf(VirtualFile::isValid)
|
||||
}?.takeIf { it in scope }
|
||||
|
||||
private fun findBinaryClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlyBinary)
|
||||
private fun findSourceClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlySource)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
|
||||
private val signatureParsingComponent = BinaryClassSignatureParser()
|
||||
|
||||
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
|
||||
fun findClass(classId: ClassId, searchScope: GlobalSearchScope) = findClass(JavaClassFinder.Request(classId), searchScope)
|
||||
|
||||
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
|
||||
val (classId, classFileContentFromRequest, outerClassFromRequest) = request
|
||||
|
||||
@@ -190,11 +190,17 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
sourceFiles.sortBy { it.virtualFile.path }
|
||||
|
||||
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
|
||||
|
||||
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
|
||||
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
|
||||
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
|
||||
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
|
||||
})
|
||||
val javaModuleFinder = CliJavaModuleFinder(
|
||||
jdkHome?.path?.let { path ->
|
||||
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
|
||||
},
|
||||
javaFileManager,
|
||||
project
|
||||
)
|
||||
|
||||
val outputDirectory =
|
||||
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
|
||||
@@ -207,7 +213,8 @@ class KotlinCoreEnvironment private constructor(
|
||||
this::contentRootToVirtualFile,
|
||||
javaModuleFinder,
|
||||
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
|
||||
outputDirectory?.let(this::findLocalFile)
|
||||
outputDirectory?.let(this::findLocalFile),
|
||||
javaFileManager
|
||||
)
|
||||
|
||||
val (initialRoots, javaModules) =
|
||||
@@ -231,7 +238,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
updateClasspathFromRootsIndex(this)
|
||||
}
|
||||
|
||||
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
|
||||
javaFileManager.initialize(
|
||||
rootsIndex,
|
||||
packagePartProviders,
|
||||
SingleJavaFileRootsIndex(singleJavaFileRoots),
|
||||
@@ -240,7 +247,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
project.registerService(
|
||||
JavaModuleResolver::class.java,
|
||||
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
|
||||
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
|
||||
)
|
||||
|
||||
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
|
||||
|
||||
@@ -78,10 +78,7 @@ import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
|
||||
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.extensions.*
|
||||
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
|
||||
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
|
||||
@@ -193,11 +190,16 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
sourceFiles.sortBy { it.virtualFile.path }
|
||||
|
||||
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
|
||||
|
||||
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
|
||||
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
|
||||
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
|
||||
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
|
||||
})
|
||||
val javaModuleFinder = CliJavaModuleFinder(
|
||||
jdkHome?.path?.let { path ->
|
||||
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
|
||||
},
|
||||
javaFileManager
|
||||
)
|
||||
|
||||
val outputDirectory =
|
||||
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
|
||||
@@ -210,7 +212,8 @@ class KotlinCoreEnvironment private constructor(
|
||||
this::contentRootToVirtualFile,
|
||||
javaModuleFinder,
|
||||
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
|
||||
outputDirectory?.let(this::findLocalFile)
|
||||
outputDirectory?.let(this::findLocalFile),
|
||||
javaFileManager
|
||||
)
|
||||
|
||||
val (initialRoots, javaModules) =
|
||||
@@ -234,7 +237,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
updateClasspathFromRootsIndex(this)
|
||||
}
|
||||
|
||||
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
|
||||
javaFileManager.initialize(
|
||||
rootsIndex,
|
||||
packagePartProviders,
|
||||
SingleJavaFileRootsIndex(singleJavaFileRoots),
|
||||
@@ -243,7 +246,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
project.registerService(
|
||||
JavaModuleResolver::class.java,
|
||||
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
|
||||
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
|
||||
)
|
||||
|
||||
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
|
||||
|
||||
@@ -49,6 +49,9 @@ fun CompilerConfiguration.addJvmSdkRoots(files: List<File>) {
|
||||
val CompilerConfiguration.jvmClasspathRoots: List<File>
|
||||
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmClasspathRoot>().map(JvmContentRoot::file)
|
||||
|
||||
val CompilerConfiguration.jvmModularRoots: List<File>
|
||||
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmModulePathRoot>().map(JvmContentRoot::file)
|
||||
|
||||
@JvmOverloads
|
||||
fun CompilerConfiguration.addJavaSourceRoot(file: File, packagePrefix: String? = null) {
|
||||
add(CLIConfigurationKeys.CONTENT_ROOTS, JavaSourceRoot(file, packagePrefix))
|
||||
|
||||
@@ -45,6 +45,7 @@ data class JavaRoot(val file: VirtualFile, val type: RootType, val prefixFqName:
|
||||
|
||||
companion object RootTypes {
|
||||
val OnlyBinary: Set<RootType> = EnumSet.of(RootType.BINARY)
|
||||
val OnlySource: Set<RootType> = EnumSet.of(RootType.SOURCE)
|
||||
val SourceAndBinary: Set<RootType> = EnumSet.of(RootType.BINARY, RootType.SOURCE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,19 +54,20 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.stringConcat != null) {
|
||||
val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!)
|
||||
val stringConcat = arguments.stringConcat
|
||||
if (stringConcat != null) {
|
||||
val runtimeStringConcat = JvmStringConcat.fromString(stringConcat)
|
||||
if (runtimeStringConcat != null) {
|
||||
put(JVMConfigurationKeys.STRING_CONCAT, runtimeStringConcat)
|
||||
if (jvmTarget.majorVersion < JvmTarget.JVM_9.majorVersion && runtimeStringConcat != JvmStringConcat.INLINE) {
|
||||
messageCollector.report(
|
||||
WARNING,
|
||||
"`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`."
|
||||
"`-Xstring-concat=$stringConcat` does nothing with JVM target `${jvmTarget.description}`."
|
||||
)
|
||||
}
|
||||
} else {
|
||||
messageCollector.report(
|
||||
ERROR, "Unknown `-Xstring-concat` mode: ${arguments.stringConcat}\n" +
|
||||
ERROR, "Unknown `-Xstring-concat` mode: $stringConcat\n" +
|
||||
"Supported modes: ${JvmStringConcat.values().joinToString { it.description }}"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,16 +16,25 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.modules
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiJavaModule
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
|
||||
|
||||
class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
|
||||
class CliJavaModuleFinder(
|
||||
jrtFileSystemRoot: VirtualFile?,
|
||||
private val javaFileManager: KotlinCliJavaFileManager,
|
||||
project: Project
|
||||
) : JavaModuleFinder {
|
||||
private val modulesRoot = jrtFileSystemRoot?.findChild("modules")
|
||||
private val userModules = linkedMapOf<String, JavaModule>()
|
||||
|
||||
private val allScope = GlobalSearchScope.allScope(project)
|
||||
|
||||
fun addUserModule(module: JavaModule) {
|
||||
userModules.putIfAbsent(module.name, module)
|
||||
}
|
||||
@@ -41,7 +50,7 @@ class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
|
||||
|
||||
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
|
||||
val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null
|
||||
val moduleInfo = JavaModuleInfo.read(file) ?: return null
|
||||
val moduleInfo = JavaModuleInfo.read(file, javaFileManager, allScope) ?: return null
|
||||
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,18 +18,24 @@ package org.jetbrains.kotlin.cli.jvm.modules
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class CliJavaModuleResolver(
|
||||
private val moduleGraph: JavaModuleGraph,
|
||||
private val userModules: List<JavaModule>,
|
||||
private val systemModules: List<JavaModule.Explicit>
|
||||
private val systemModules: List<JavaModule.Explicit>,
|
||||
private val project: Project
|
||||
) : JavaModuleResolver {
|
||||
init {
|
||||
assert(userModules.count(JavaModule::isSourceModule) <= 1) {
|
||||
@@ -37,6 +43,14 @@ class CliJavaModuleResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private val virtualFileFinder by lazy { VirtualFileFinder.getInstance(project) }
|
||||
|
||||
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? {
|
||||
val virtualFile = virtualFileFinder.findSourceOrBinaryVirtualFile(classId) ?: return null
|
||||
|
||||
return (findJavaModule(virtualFile) as? JavaModule.Explicit)?.moduleInfo?.annotations
|
||||
}
|
||||
|
||||
private val sourceModule: JavaModule? = userModules.firstOrNull(JavaModule::isSourceModule)
|
||||
|
||||
private fun findJavaModule(file: VirtualFile): JavaModule? {
|
||||
@@ -77,4 +91,8 @@ class CliJavaModuleResolver(
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MODULE_ANNOTATIONS_CACHE_SIZE = 10000
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,11 @@ object KotlinCompilerClient {
|
||||
fun CompileService.leaseImpl(): CompileServiceSession? {
|
||||
// the newJVMOptions could be checked here for additional parameters, if needed
|
||||
registerClient(clientAliveFlagFile.absolutePath)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
|
||||
val javaExecutablePath = compilerId.javaExecutable?.absolutePath ?: "'user jvm'"
|
||||
reportingTargets.report(
|
||||
DaemonReportCategory.DEBUG,
|
||||
"connected to the daemon. Daemon is using following 'java' executable to run itself: $javaExecutablePath"
|
||||
)
|
||||
|
||||
if (!leaseSession) return CompileServiceSession(this, CompileService.NO_SESSION)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public open class MethodWithFunctionTypes : R|kotlin/Any| {
|
||||
public open fun foo(f: R|(kotlin/String?) -> kotlin/String|): R|kotlin/String.() -> kotlin/String?|
|
||||
public open fun foo(f: R|(kotlin/String?) -> kotlin/String|): R|(kotlin/String.() -> kotlin/String?)?|
|
||||
|
||||
public constructor(): R|test/MethodWithFunctionTypes|
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
public final fun test1(): R|suspend () -> kotlin/Unit|
|
||||
|
||||
public final fun test1N(): R|(suspend () -> kotlin/Unit)?|
|
||||
|
||||
public final fun test2(): R|suspend kotlin/Int.() -> kotlin/Int|
|
||||
|
||||
public final fun test2N(): R|(suspend kotlin/Int.() -> kotlin/Int)?|
|
||||
|
||||
public final fun test3(): R|kotlin/collections/List<kotlin/coroutines/SuspendFunction0<kotlin/Unit>>|
|
||||
|
||||
public final fun test3N(): R|kotlin/collections/List<kotlin/coroutines/SuspendFunction0<kotlin/Unit>?>|
|
||||
|
||||
public final fun test4(): R|suspend () -> kotlin/coroutines/SuspendFunction0<kotlin/Unit>|
|
||||
|
||||
public final fun test4N(): R|(suspend () -> kotlin/coroutines/SuspendFunction0<kotlin/Unit>?)?|
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
FILE: safeCallOnTypeAlias.kt
|
||||
public final typealias MyTypeAlias = R|() -> kotlin/String?|
|
||||
public final typealias MyTypeAlias = R|(() -> kotlin/String?)?|
|
||||
public final fun foo(x: R|MyTypeAlias|): R|kotlin/Unit| {
|
||||
R|<local>/x|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/String?|, R|kotlin/String?|>(<L> = let@fun <anonymous>(y: R|() -> kotlin/String?|): R|kotlin/String?| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
^ R|<local>/y|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/String?|>|()?.{ $subj$.R|kotlin/let|<R|kotlin/String|, R|kotlin/String|>(<L> = let@fun <anonymous>(result: R|kotlin/String|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
|
||||
@@ -18,7 +18,7 @@ FILE: kt41982.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final fun <Type : R|Base|, Base : R|DelegateProvider<Base>|> R|Type|.long(initializer: R|() -> kotlin/Long?| = Null(null)): R|Delegate<Type, kotlin/Long>| {
|
||||
public final fun <Type : R|Base|, Base : R|DelegateProvider<Base>|> R|Type|.long(initializer: R|(() -> kotlin/Long?)?| = Null(null)): R|Delegate<Type, kotlin/Long>| {
|
||||
^long Null(null)!!
|
||||
}
|
||||
public final class Test : R|DelegateProvider<kotlin/Any>| {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
FILE: propertyWithExtensionType.kt
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/String.() -> kotlin/Unit|, y: R|kotlin/String.() -> kotlin/Int|): R|A| {
|
||||
public constructor(x: R|(kotlin/String.() -> kotlin/Unit)?|, y: R|kotlin/String.() -> kotlin/Int|): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|kotlin/String.() -> kotlin/Unit| = R|<local>/x|
|
||||
public get(): R|kotlin/String.() -> kotlin/Unit|
|
||||
public final val x: R|(kotlin/String.() -> kotlin/Unit)?| = R|<local>/x|
|
||||
public get(): R|(kotlin/String.() -> kotlin/Unit)?|
|
||||
|
||||
public final val y: R|kotlin/String.() -> kotlin/Int| = R|<local>/y|
|
||||
public get(): R|kotlin/String.() -> kotlin/Int|
|
||||
@@ -14,7 +14,7 @@ FILE: propertyWithExtensionType.kt
|
||||
public final fun test(a: R|A|): R|kotlin/Unit| {
|
||||
when () {
|
||||
!=(R|<local>/a|.R|/A.x|, Null(null)) -> {
|
||||
lval b: R|kotlin/String.() -> kotlin/Unit| = R|<local>/a|.R|/A.x|
|
||||
lval b: R|(kotlin/String.() -> kotlin/Unit)?| = R|<local>/a|.R|/A.x|
|
||||
R|<local>/b|.R|SubstitutionOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ interface I {
|
||||
}
|
||||
|
||||
class A {
|
||||
fun too(): <!NOT_AN_ANNOTATION_CLASS, NOT_AN_ANNOTATION_CLASS!>@Annotation<!> Unit {}
|
||||
fun too(): <!NOT_AN_ANNOTATION_CLASS!>@Annotation<!> Unit {}
|
||||
|
||||
fun foo(): <!REDUNDANT_RETURN_UNIT_TYPE!>Unit<!>
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@ FILE: kt41989.kt
|
||||
|
||||
}
|
||||
public abstract interface C : R|B| {
|
||||
public open val lineCellStyle: R|A.() -> kotlin/Unit|
|
||||
public get(): R|A.() -> kotlin/Unit| {
|
||||
public open val lineCellStyle: R|(A.() -> kotlin/Unit)?|
|
||||
public get(): R|(A.() -> kotlin/Unit)?| {
|
||||
^ when () {
|
||||
R|/cond|() -> {
|
||||
fun R|A|.<anonymous>(): R|kotlin/Unit| <inline=Unknown> {
|
||||
|
||||
@@ -21,14 +21,14 @@ FILE: lambdaArgInScopeFunction.kt
|
||||
this@R|special/anonymous|.R|/_|<R|KotlinClass?|>()
|
||||
}
|
||||
)
|
||||
lval lambda: R|() -> KotlinClass| = R|<local>/kotlinClass|?.{ $subj$.R|kotlin/let|<R|KotlinClass|, R|() -> KotlinClass|>(<L> = let@fun <anonymous>(it: R|KotlinClass|): R|() -> KotlinClass| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
lval lambda: R|(() -> KotlinClass)?| = R|<local>/kotlinClass|?.{ $subj$.R|kotlin/let|<R|KotlinClass|, R|() -> KotlinClass|>(<L> = let@fun <anonymous>(it: R|KotlinClass|): R|() -> KotlinClass| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
^ let@fun <anonymous>(): R|KotlinClass| <inline=Unknown> {
|
||||
^ R|<local>/it|
|
||||
}
|
||||
|
||||
}
|
||||
) }
|
||||
R|<local>/lambda|.R|/checkType|<R|() -> KotlinClass|>(<L> = checkType@fun R|CheckTypeInv<kotlin/Function0<KotlinClass>?>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
|
||||
R|<local>/lambda|.R|/checkType|<R|(() -> KotlinClass)?|>(<L> = checkType@fun R|CheckTypeInv<kotlin/Function0<KotlinClass>?>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
|
||||
this@R|special/anonymous|.<Inapplicable(INAPPLICABLE_WRONG_RECEIVER): /_>#<R|(kotlin/Unit) -> KotlinClass?|>()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
FILE: smartcastOnLambda.kt
|
||||
public final fun test(func: R|() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
public final fun test(func: R|(() -> kotlin/Unit)?|): R|kotlin/Unit| {
|
||||
when () {
|
||||
!=(R|<local>/func|, Null(null)) -> {
|
||||
R|<local>/func|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
|
||||
|
||||
@@ -5680,6 +5680,136 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SuspendFunctionAsSupertype {
|
||||
@Test
|
||||
public void testAllFilesPresentInSuspendFunctionAsSupertype() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class KSuspendFunctionN {
|
||||
@Test
|
||||
public void testAllFilesPresentInKSuspendFunctionN() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Simple {
|
||||
@Test
|
||||
public void testAllFilesPresentInSimple() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SuspendFunctionN {
|
||||
@Test
|
||||
public void testAllFilesPresentInSuspendFunctionN() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/simple.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -12457,6 +12587,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("violatingUpperBoundForSelfTypeError.kt")
|
||||
public void testViolatingUpperBoundForSelfTypeError() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -21000,6 +21136,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("errorType.kt")
|
||||
public void testErrorType() throws Exception {
|
||||
@@ -21090,6 +21238,30 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
|
||||
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
|
||||
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeEnhancement.kt")
|
||||
public void testTypeEnhancement() throws Exception {
|
||||
@@ -29017,6 +29189,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42042Error.kt")
|
||||
public void testKt42042Error() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42396.kt")
|
||||
public void testKt42396() throws Exception {
|
||||
|
||||
@@ -5680,6 +5680,136 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SuspendFunctionAsSupertype {
|
||||
@Test
|
||||
public void testAllFilesPresentInSuspendFunctionAsSupertype() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class KSuspendFunctionN {
|
||||
@Test
|
||||
public void testAllFilesPresentInKSuspendFunctionN() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Simple {
|
||||
@Test
|
||||
public void testAllFilesPresentInSimple() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SuspendFunctionN {
|
||||
@Test
|
||||
public void testAllFilesPresentInSuspendFunctionN() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
|
||||
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/simple.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -12457,6 +12587,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("violatingUpperBoundForSelfTypeError.kt")
|
||||
public void testViolatingUpperBoundForSelfTypeError() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -21000,6 +21136,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("errorType.kt")
|
||||
public void testErrorType() throws Exception {
|
||||
@@ -21090,6 +21238,30 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
|
||||
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
|
||||
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeEnhancement.kt")
|
||||
public void testTypeEnhancement() throws Exception {
|
||||
@@ -29017,6 +29189,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42042Error.kt")
|
||||
public void testKt42042Error() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42396.kt")
|
||||
public void testKt42396() throws Exception {
|
||||
|
||||
@@ -9,11 +9,17 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DIAGNOSTICS_LIST
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.generateDiagnostics
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import java.io.File
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/fir/checkers/gen").absoluteFile
|
||||
|
||||
val typePackage = "org.jetbrains.kotlin.fir.analysis.checkers.type"
|
||||
generateCheckersComponents(generationPath, typePackage, "FirTypeChecker") {
|
||||
alias<FirTypeRef>("TypeRefChecker")
|
||||
}
|
||||
|
||||
val expressionPackage = "org.jetbrains.kotlin.fir.analysis.checkers.expression"
|
||||
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
|
||||
alias<FirStatement>("BasicExpressionChecker")
|
||||
|
||||
@@ -67,6 +67,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
FUN_MODIFIER,
|
||||
SUSPEND_MODIFIER,
|
||||
FUN_INTERFACE,
|
||||
RESERVED_UNDERSCORE,
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val NO_THIS by error<PsiElement>()
|
||||
}
|
||||
|
||||
val CALL_RESOLUTION by object : DiagnosticGroup("Call resolution") {
|
||||
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error<KtExpression>()
|
||||
}
|
||||
|
||||
val SUPER by object : DiagnosticGroup("Super") {
|
||||
val SUPER_IS_NOT_AN_EXPRESSION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val SUPER_NOT_AVAILABLE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
@@ -696,6 +700,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
parameter<String>("expectedFunctionSignature")
|
||||
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
|
||||
}
|
||||
val UNDERSCORE_IS_RESERVED by error<KtExpression>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<KtExpression>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
}
|
||||
|
||||
val TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
|
||||
@@ -725,6 +731,49 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val RETURN_NOT_ALLOWED by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
|
||||
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
|
||||
}
|
||||
|
||||
val INLINE by object : DiagnosticGroup("Inline") {
|
||||
val USAGE_IS_NOT_INLINABLE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("parameter")
|
||||
}
|
||||
|
||||
val NON_LOCAL_RETURN_NOT_ALLOWED by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("parameter")
|
||||
}
|
||||
|
||||
val RECURSION_IN_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("symbol")
|
||||
}
|
||||
|
||||
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("inlineDeclaration")
|
||||
parameter<Symbol>("referencedDeclaration")
|
||||
}
|
||||
|
||||
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("inlineDeclaration")
|
||||
parameter<Symbol>("referencedDeclaration")
|
||||
}
|
||||
|
||||
val PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("inlineDeclaration")
|
||||
parameter<Symbol>("referencedDeclaration")
|
||||
}
|
||||
|
||||
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("inlineDeclaration")
|
||||
parameter<Symbol>("referencedDeclaration")
|
||||
}
|
||||
|
||||
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("inlineDeclaration")
|
||||
parameter<Symbol>("referencedDeclaration")
|
||||
}
|
||||
|
||||
val SUPER_CALL_FROM_PUBLIC_INLINE by warning<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("symbol")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val exposedVisibilityDiagnosticInit: DiagnosticBuilder.() -> Unit = {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
internal class ComposedTypeCheckers : TypeCheckers() {
|
||||
override val typeRefCheckers: Set<FirTypeRefChecker>
|
||||
get() = _typeRefCheckers
|
||||
|
||||
private val _typeRefCheckers: MutableSet<FirTypeRefChecker> = mutableSetOf()
|
||||
|
||||
@CheckersComponentInternal
|
||||
internal fun register(checkers: TypeCheckers) {
|
||||
_typeRefCheckers += checkers.typeRefCheckers
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
typealias FirTypeRefChecker = FirTypeChecker<FirTypeRef>
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class TypeCheckers {
|
||||
companion object {
|
||||
val EMPTY: TypeCheckers = object : TypeCheckers() {}
|
||||
}
|
||||
|
||||
open val typeRefCheckers: Set<FirTypeRefChecker> = emptySet()
|
||||
|
||||
@CheckersComponentInternal internal val allTypeRefCheckers: Set<FirTypeRefChecker> get() = typeRefCheckers
|
||||
}
|
||||
@@ -105,6 +105,9 @@ object FirErrors {
|
||||
val MISSING_STDLIB_CLASS by error0<PsiElement>()
|
||||
val NO_THIS by error0<PsiElement>()
|
||||
|
||||
// Call resolution
|
||||
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error0<KtExpression>()
|
||||
|
||||
// Super
|
||||
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val SUPER_NOT_AVAILABLE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
@@ -409,6 +412,8 @@ object FirErrors {
|
||||
val DELEGATE_SPECIAL_FUNCTION_MISSING by error3<KtExpression, String, ConeKotlinType, String>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_AMBIGUITY by error2<KtExpression, String, Collection<AbstractFirBasedSymbol<*>>>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE by error2<KtExpression, String, Collection<AbstractFirBasedSymbol<*>>>()
|
||||
val UNDERSCORE_IS_RESERVED by error0<KtExpression>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<KtExpression>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
|
||||
// Type alias
|
||||
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
|
||||
@@ -435,4 +440,15 @@ object FirErrors {
|
||||
val RETURN_NOT_ALLOWED by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
|
||||
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
|
||||
|
||||
// Inline
|
||||
val USAGE_IS_NOT_INLINABLE by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val NON_LOCAL_RETURN_NOT_ALLOWED by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val RECURSION_IN_INLINE by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val SUPER_CALL_FROM_PUBLIC_INLINE by warning1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.ComposedDeclaratio
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ComposedExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.ComposedTypeCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
||||
|
||||
@RequiresOptIn
|
||||
@@ -26,6 +28,9 @@ class CheckersComponent : FirSessionComponent {
|
||||
val expressionCheckers: ExpressionCheckers get() = _expressionCheckers
|
||||
private val _expressionCheckers = ComposedExpressionCheckers()
|
||||
|
||||
val typeCheckers: TypeCheckers get() = _typeCheckers
|
||||
private val _typeCheckers = ComposedTypeCheckers()
|
||||
|
||||
@SessionConfiguration
|
||||
@OptIn(CheckersComponentInternal::class)
|
||||
fun register(checkers: DeclarationCheckers) {
|
||||
@@ -38,10 +43,17 @@ class CheckersComponent : FirSessionComponent {
|
||||
_expressionCheckers.register(checkers)
|
||||
}
|
||||
|
||||
@SessionConfiguration
|
||||
@OptIn(CheckersComponentInternal::class)
|
||||
fun register(checkers: TypeCheckers) {
|
||||
_typeCheckers.register(checkers)
|
||||
}
|
||||
|
||||
@SessionConfiguration
|
||||
fun register(checkers: FirAdditionalCheckersExtension) {
|
||||
register(checkers.declarationCheckers)
|
||||
register(checkers.expressionCheckers)
|
||||
register(checkers.typeCheckers)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.LighterASTNode
|
||||
@@ -11,8 +11,6 @@ import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtModifierList
|
||||
@@ -95,6 +93,6 @@ internal fun FirSourceElement?.getModifierList(): FirModifierList? {
|
||||
|
||||
internal operator fun FirModifierList?.contains(token: KtModifierKeywordToken): Boolean = this?.contains(token) == true
|
||||
|
||||
internal fun FirDeclaration.getModifier(token: KtModifierKeywordToken): FirModifier<*>? = source.getModifierList()?.get(token)
|
||||
internal fun FirElement.getModifier(token: KtModifierKeywordToken): FirModifier<*>? = source.getModifierList()?.get(token)
|
||||
|
||||
internal fun FirDeclaration.hasModifier(token: KtModifierKeywordToken): Boolean = token in source.getModifierList()
|
||||
internal fun FirElement.hasModifier(token: KtModifierKeywordToken): Boolean = token in source.getModifierList()
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.canBeUsedForConstVal
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -9,7 +9,10 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.contains
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -183,7 +186,8 @@ internal val FirDeclaration.isEnumEntryInitializer: Boolean
|
||||
return (containingClassAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.fir?.classKind == ClassKind.ENUM_ENTRY
|
||||
}
|
||||
|
||||
internal val FirMemberDeclaration.isLocalMember: Boolean
|
||||
// contract: returns(true) implies (this is FirMemberDeclaration)
|
||||
internal val FirDeclaration.isLocalMember: Boolean
|
||||
get() = when (this) {
|
||||
is FirProperty -> this.isLocal
|
||||
is FirRegularClass -> this.isLocal
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.util.checkChildrenWithCustomVisitor
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isMarkedNullable
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FirInlineDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.isInline) return
|
||||
// local inline functions are prohibited
|
||||
if (declaration.isLocalMember) return
|
||||
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
|
||||
|
||||
val effectiveVisibility = declaration.effectiveVisibility
|
||||
val function = declaration as FirFunction<*>
|
||||
checkInlineFunctionBody(function, effectiveVisibility, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkInlineFunctionBody(
|
||||
function: FirFunction<*>,
|
||||
effectiveVisibility: EffectiveVisibility,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val body = function.body ?: return
|
||||
val inlinableParameters = function.valueParameters.filter {
|
||||
if (it.isNoinline) return@filter false
|
||||
val type = it.returnTypeRef.coneType
|
||||
!type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType }
|
||||
}
|
||||
|
||||
val visitor = Visitor(
|
||||
function,
|
||||
effectiveVisibility,
|
||||
inlinableParameters,
|
||||
context.session,
|
||||
reporter
|
||||
)
|
||||
body.checkChildrenWithCustomVisitor(context, visitor)
|
||||
}
|
||||
|
||||
private class Visitor(
|
||||
val inlineFunction: FirFunction<*>,
|
||||
val inlineFunEffectiveVisibility: EffectiveVisibility,
|
||||
val inlinableParameters: List<FirValueParameter>,
|
||||
val session: FirSession,
|
||||
val reporter: DiagnosticReporter
|
||||
) : FirDefaultVisitor<Unit, CheckerContext>() {
|
||||
private val isEffectivelyPrivateApiFunction: Boolean = inlineFunEffectiveVisibility.privateApi
|
||||
|
||||
private val prohibitProtectedCallFromInline: Boolean =
|
||||
session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitProtectedCallFromInline)
|
||||
|
||||
override fun visitElement(element: FirElement, data: CheckerContext) {}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: CheckerContext) {
|
||||
val targetSymbol = functionCall.toResolvedCallableSymbol()
|
||||
checkReceiversOfQualifiedAccessExpression(functionCall, targetSymbol, data)
|
||||
checkArgumentsOfCall(functionCall, targetSymbol, data)
|
||||
checkQualifiedAccess(functionCall, targetSymbol, data)
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
|
||||
val targetSymbol = qualifiedAccessExpression.toResolvedCallableSymbol()
|
||||
checkQualifiedAccess(qualifiedAccessExpression, targetSymbol, data)
|
||||
checkReceiversOfQualifiedAccessExpression(qualifiedAccessExpression, targetSymbol, data)
|
||||
}
|
||||
|
||||
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
|
||||
val propertySymbol = variableAssignment.calleeReference.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
|
||||
val setterSymbol = propertySymbol.fir.setter?.symbol ?: return
|
||||
checkQualifiedAccess(variableAssignment, setterSymbol, data)
|
||||
}
|
||||
|
||||
private fun checkReceiversOfQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
targetSymbol: AbstractFirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
) {
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.dispatchReceiver, targetSymbol, context)
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.extensionReceiver, targetSymbol, context)
|
||||
}
|
||||
|
||||
private fun checkArgumentsOfCall(
|
||||
functionCall: FirFunctionCall,
|
||||
targetSymbol: AbstractFirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val calledFunction = (targetSymbol as? FirNamedFunctionSymbol)?.fir ?: return
|
||||
val argumentMapping = functionCall.resolvedArgumentMapping ?: return
|
||||
for ((wrappedArgument, valueParameter) in argumentMapping) {
|
||||
val argument = wrappedArgument.unwrapArgument()
|
||||
val resolvedArgumentSymbol = argument.toResolvedCallableSymbol() as? FirVariableSymbol<*> ?: continue
|
||||
|
||||
val valueParameterOfOriginalInlineFunction = inlinableParameters.firstOrNull { it == resolvedArgumentSymbol.fir }
|
||||
if (valueParameterOfOriginalInlineFunction != null) {
|
||||
val factory = when {
|
||||
calledFunction.isInline -> when {
|
||||
valueParameter.isNoinline -> FirErrors.USAGE_IS_NOT_INLINABLE
|
||||
valueParameter.isCrossinline && !valueParameterOfOriginalInlineFunction.isCrossinline
|
||||
-> FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
|
||||
else -> continue
|
||||
}
|
||||
else -> FirErrors.USAGE_IS_NOT_INLINABLE
|
||||
}
|
||||
reporter.reportOn(argument.source, factory, valueParameterOfOriginalInlineFunction.symbol, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReceiver(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
receiverExpression: FirExpression,
|
||||
targetSymbol: AbstractFirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val receiverSymbol = receiverExpression.toResolvedCallableSymbol() ?: return
|
||||
if (receiverSymbol.fir in inlinableParameters) {
|
||||
val valueParameter = receiverSymbol.fir as FirValueParameter
|
||||
if (!isInvokeOrInlineExtension(targetSymbol)) {
|
||||
reporter.reportOn(
|
||||
qualifiedAccessExpression.source,
|
||||
FirErrors.USAGE_IS_NOT_INLINABLE,
|
||||
valueParameter.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInvokeOrInlineExtension(targetSymbol: AbstractFirBasedSymbol<*>?): Boolean {
|
||||
if (targetSymbol !is FirNamedFunctionSymbol) return false
|
||||
val function = targetSymbol.fir
|
||||
if (function.isInline) return true
|
||||
return function.name == OperatorNameConventions.INVOKE &&
|
||||
function.dispatchReceiverType?.isBuiltinFunctionalType(session) == true
|
||||
}
|
||||
|
||||
private fun checkQualifiedAccess(
|
||||
qualifiedAccess: FirQualifiedAccess,
|
||||
targetSymbol: AbstractFirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val source = qualifiedAccess.source ?: return
|
||||
if (targetSymbol == null) return
|
||||
val targetFir = targetSymbol.fir as? FirCallableMemberDeclaration<*>
|
||||
|
||||
if (targetSymbol.fir in inlinableParameters) {
|
||||
if (!qualifiedAccess.partOfCall(context)) {
|
||||
val valueParameter = targetSymbol.fir as FirValueParameter
|
||||
reporter.reportOn(source, FirErrors.USAGE_IS_NOT_INLINABLE, valueParameter.symbol, context)
|
||||
}
|
||||
}
|
||||
checkVisibilityAndAccess(qualifiedAccess, targetFir, source, context)
|
||||
checkRecursion(targetSymbol, source, context)
|
||||
}
|
||||
|
||||
private fun FirQualifiedAccess.partOfCall(context: CheckerContext): Boolean {
|
||||
if (this !is FirExpression) return false
|
||||
val containingQualifiedAccess = context.qualifiedAccesses.getOrNull(context.qualifiedAccesses.size - 2) ?: return false
|
||||
if (this == containingQualifiedAccess.explicitReceiver) return true
|
||||
val call = containingQualifiedAccess as? FirCall ?: return false
|
||||
return call.arguments.any { it.unwrapArgument() == this }
|
||||
}
|
||||
|
||||
private fun checkVisibilityAndAccess(
|
||||
accessExpression: FirQualifiedAccess,
|
||||
calledDeclaration: FirCallableMemberDeclaration<*>?,
|
||||
source: FirSourceElement,
|
||||
context: CheckerContext
|
||||
) {
|
||||
if (calledDeclaration == null) return
|
||||
val recordedEffectiveVisibility = calledDeclaration.publishedApiEffectiveVisibility ?: calledDeclaration.effectiveVisibility
|
||||
val calledFunEffectiveVisibility = recordedEffectiveVisibility.let {
|
||||
if (it == EffectiveVisibility.Local) {
|
||||
EffectiveVisibility.Public
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
val isCalledFunPublicOrPublishedApi = calledFunEffectiveVisibility.publicApi
|
||||
val isInlineFunPublicOrPublishedApi = inlineFunEffectiveVisibility.publicApi
|
||||
if (isInlineFunPublicOrPublishedApi &&
|
||||
!isCalledFunPublicOrPublishedApi &&
|
||||
calledDeclaration.visibility !== Visibilities.Local
|
||||
) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE,
|
||||
calledDeclaration.symbol,
|
||||
inlineFunction.symbol,
|
||||
context
|
||||
)
|
||||
} else {
|
||||
checkPrivateClassMemberAccess(calledDeclaration, source, context)
|
||||
if (isInlineFunPublicOrPublishedApi) {
|
||||
checkSuperCalls(calledDeclaration, accessExpression, context)
|
||||
}
|
||||
}
|
||||
|
||||
val isConstructorCall = calledDeclaration is FirConstructor
|
||||
if (
|
||||
isInlineFunPublicOrPublishedApi &&
|
||||
inlineFunEffectiveVisibility.toVisibility() !== Visibilities.Protected &&
|
||||
calledFunEffectiveVisibility.toVisibility() === Visibilities.Protected
|
||||
) {
|
||||
val factory = when {
|
||||
isConstructorCall -> FirErrors.PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE
|
||||
prohibitProtectedCallFromInline -> FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR
|
||||
else -> FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE
|
||||
}
|
||||
reporter.reportOn(source, factory, calledDeclaration.symbol, inlineFunction.symbol, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPrivateClassMemberAccess(
|
||||
calledDeclaration: FirCallableMemberDeclaration<*>,
|
||||
source: FirSourceElement,
|
||||
context: CheckerContext
|
||||
) {
|
||||
if (!isEffectivelyPrivateApiFunction) {
|
||||
if (calledDeclaration.isInsidePrivateClass()) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.PRIVATE_CLASS_MEMBER_FROM_INLINE,
|
||||
calledDeclaration.symbol,
|
||||
inlineFunction.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSuperCalls(
|
||||
calledDeclaration: FirCallableMemberDeclaration<*>,
|
||||
callExpression: FirQualifiedAccess,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val receiver = callExpression.dispatchReceiver as? FirQualifiedAccessExpression ?: return
|
||||
if (receiver.calleeReference is FirSuperReference) {
|
||||
val dispatchReceiverType = receiver.dispatchReceiver.typeRef.coneType
|
||||
val classSymbol = dispatchReceiverType.toSymbol(session) ?: return
|
||||
if (!classSymbol.isDefinedInInlineFunction()) {
|
||||
reporter.reportOn(
|
||||
callExpression.dispatchReceiver.source,
|
||||
FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE,
|
||||
calledDeclaration.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractFirBasedSymbol<*>.isDefinedInInlineFunction(): Boolean {
|
||||
return when (val fir = this.fir) {
|
||||
is FirAnonymousFunction -> true
|
||||
is FirMemberDeclaration -> fir.isLocalMember
|
||||
is FirAnonymousObject -> true
|
||||
is FirRegularClass -> fir.classId.isLocal
|
||||
else -> error("Unknown callable declaration type: ${fir.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRecursion(
|
||||
targetSymbol: AbstractFirBasedSymbol<*>,
|
||||
source: FirSourceElement,
|
||||
context: CheckerContext
|
||||
) {
|
||||
if (targetSymbol == inlineFunction.symbol) {
|
||||
reporter.reportOn(source, FirErrors.RECURSION_IN_INLINE, targetSymbol, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCallableMemberDeclaration<*>.isInsidePrivateClass(): Boolean {
|
||||
val containingClass = this.containingClass()?.toSymbol(session)?.fir ?: return false
|
||||
|
||||
val containingClassVisibility = when (containingClass) {
|
||||
is FirAnonymousObject -> return false
|
||||
is FirRegularClass -> containingClass.visibility
|
||||
is FirTypeAlias -> containingClass.visibility
|
||||
}
|
||||
return containingClassVisibility == Visibilities.Private || containingClassVisibility == Visibilities.PrivateToThis
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.contains
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -12,7 +12,9 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfo
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfoCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.contains
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
|
||||
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration.jvm
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.isAbstract
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
|
||||
object FirConstructorCallChecker : FirFunctionCallChecker() {
|
||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val constructorSymbol =
|
||||
(expression.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol ?: return
|
||||
val declarationClass = constructorSymbol.fir.returnTypeRef.coneType.toRegularClass(context.session)
|
||||
|
||||
if (declarationClass != null && declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
|
||||
reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtDotQualifiedExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtParameterElementType
|
||||
|
||||
object FirReservedUnderscoreExpressionChecker : FirBasicExpressionChecker() {
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = expression.source
|
||||
|
||||
if (expression is FirFunctionCall) {
|
||||
val calleeReferenceSource = expression.calleeReference.source
|
||||
if (calleeReferenceSource is FirLightSourceElement && calleeReferenceSource.lighterASTNode.tokenType == KtNodeTypes.OPERATION_REFERENCE) {
|
||||
return
|
||||
}
|
||||
|
||||
reportIfUnderscore(
|
||||
expression.calleeReference.source.text, expression.calleeReference.source, context, reporter,
|
||||
isExpression = true
|
||||
)
|
||||
} else if (expression is FirQualifiedAccess) {
|
||||
if (source is FirPsiSourceElement<*>) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
} else if (source is FirLightSourceElement) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
}
|
||||
} else if (expression is FirGetClassCall) {
|
||||
for (argument in expression.argumentList.arguments) {
|
||||
reportIfUnderscore(argument.source.text, expression.source, context, reporter, isExpression = true)
|
||||
}
|
||||
} else if (expression is FirReturnExpression) {
|
||||
var labelName: String? = null
|
||||
if (source is FirPsiSourceElement<*>) {
|
||||
labelName = (source.psi.parent as? KtLabeledExpression)?.getLabelName()
|
||||
} else if (source is FirLightSourceElement) {
|
||||
val parent = source.treeStructure.getParent(source.lighterASTNode)
|
||||
if (parent != null && parent.tokenType == KtNodeTypes.LABELED_EXPRESSION) {
|
||||
labelName = source.treeStructure.findDescendantByType(parent, KtNodeTypes.LABEL).toString()
|
||||
labelName = labelName.substring(0, labelName.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
reportIfUnderscore(labelName, expression.source, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirPsiSourceElement<*>,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(psi: PsiElement?) {
|
||||
if (psi is KtNameReferenceExpression) {
|
||||
reportIfUnderscore(psi.text, expression.source, context, reporter, isExpression = true)
|
||||
} else if (psi is KtDotQualifiedExpression || psi is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi.firstChild)
|
||||
processQualifiedAccess(psi.lastChild)
|
||||
}
|
||||
}
|
||||
|
||||
val psi = source.psi
|
||||
if (psi.parent !is KtDotQualifiedExpression && psi.parent !is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirLightSourceElement,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(lightSourceElement: LighterASTNode?) {
|
||||
val tokenType = lightSourceElement?.tokenType
|
||||
if (tokenType is KtNameReferenceExpressionElementType) {
|
||||
reportIfUnderscore(lightSourceElement.toString(), expression.source, context, reporter, isExpression = true)
|
||||
} else if (lightSourceElement != null && (tokenType is KtDotQualifiedExpressionElementType || tokenType == KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION)) {
|
||||
val children = lightSourceElement.getChildren(source.treeStructure)
|
||||
processQualifiedAccess(children.first())
|
||||
processQualifiedAccess(children.last())
|
||||
}
|
||||
}
|
||||
|
||||
val astNode = source.lighterASTNode
|
||||
val parent = source.treeStructure.getParent(astNode)
|
||||
if (parent?.tokenType !is KtDotQualifiedExpressionElementType && parent?.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION) {
|
||||
processQualifiedAccess(astNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (
|
||||
declaration is FirClass<*> ||
|
||||
declaration is FirFunction<*> ||
|
||||
declaration is FirTypeParameter ||
|
||||
declaration is FirProperty ||
|
||||
declaration is FirTypeAlias
|
||||
) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
|
||||
if (declaration is FirFunction<*>) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
reportIfUnderscore(
|
||||
parameter,
|
||||
context,
|
||||
reporter,
|
||||
isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (declaration is FirFile) {
|
||||
for (import in declaration.imports) {
|
||||
reportIfUnderscore(import.aliasName?.asString(), import.source, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
declaration: FirDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false
|
||||
) {
|
||||
val source = declaration.source
|
||||
val rawIdentifier = when (source) {
|
||||
is FirPsiSourceElement<*> ->
|
||||
(source.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||
is FirLightSourceElement ->
|
||||
source.treeStructure.nameIdentifier(source.lighterASTNode)?.toString()
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
reportIfUnderscore(rawIdentifier, source, context, reporter, isSingleUnderscoreAllowed)
|
||||
|
||||
fun reportIfAnyDescendantIsUnderscore(typeRefSource: FirSourceElement?) {
|
||||
if (typeRefSource == null) return
|
||||
|
||||
val isReport = when (typeRefSource) {
|
||||
is FirPsiSourceElement<*> -> {
|
||||
val psi = typeRefSource.psi
|
||||
psi !is KtFunctionLiteral && psi.anyDescendantOfType<LeafPsiElement> { isUnderscore(it.text) }
|
||||
}
|
||||
is FirLightSourceElement ->
|
||||
source?.treeStructure?.findFirstDescendant(typeRefSource.lighterASTNode) { node -> isUnderscore(node.toString()) } != null
|
||||
else ->
|
||||
false
|
||||
}
|
||||
|
||||
if (isReport) {
|
||||
reporter.reportOn(
|
||||
typeRefSource,
|
||||
FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is FirValueParameter) {
|
||||
val isReport = when (val returnTypeRefSource = declaration.returnTypeRef.source) {
|
||||
is FirPsiSourceElement<*> -> {
|
||||
val psi = returnTypeRefSource.psi
|
||||
psi !is KtFunctionLiteral && psi !is KtParameter
|
||||
}
|
||||
is FirLightSourceElement -> {
|
||||
val tokenType = returnTypeRefSource.lighterASTNode.tokenType
|
||||
tokenType !is KtParameterElementType && tokenType != KtNodeTypes.CLASS
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
if (isReport) {
|
||||
reportIfAnyDescendantIsUnderscore(declaration.returnTypeRef.source)
|
||||
}
|
||||
} else if (declaration is FirFunction<*>) {
|
||||
reportIfAnyDescendantIsUnderscore(declaration.receiverTypeRef?.source)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
text: CharSequence?,
|
||||
source: FirSourceElement?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false,
|
||||
isExpression: Boolean = false
|
||||
) {
|
||||
if (text == null || isSingleUnderscoreAllowed && text == "_") {
|
||||
return
|
||||
}
|
||||
|
||||
if (isUnderscore(text)) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUnderscore(text: CharSequence) = text.all { it == '_' }
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRefWithNullability
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object FirSuspendModifierChecker : FirTypeRefChecker() {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// We are only interested in source type refs (i.e., Fir(Dynamic|User|Function)TypeRef).
|
||||
if (typeRef !is FirTypeRefWithNullability) return
|
||||
|
||||
val suspendModifier = typeRef.getModifier(KtTokens.SUSPEND_KEYWORD) ?: return
|
||||
|
||||
// `suspend` is invalid for non-function types (i.e., FirDynamicTypeRef or FirUserTypeRef).
|
||||
//
|
||||
// It is also invalid for nullable function types, e.g., `suspend (() -> Int)?`.
|
||||
// The correct way to denote a nullable suspend function type is `(suspend () -> Int)?`.
|
||||
// (To clarify: You can "mark nullable" a suspend function type, but you cannot "mark suspend" a nullable function type.)
|
||||
//
|
||||
// In both invalid and correct cases, the source for the FirFunctionTypeRef is the TYPE_REFERENCE element.
|
||||
// In the invalid case, the `suspend` modifier is in the source TYPE_REFERENCE element.
|
||||
// But in the correct case, the `suspend` modifier is in the child NULLABLE_TYPE element, i.e., the source TYPE_REFERENCE element
|
||||
// will not have the `suspend` modifier.
|
||||
//
|
||||
// In both cases, the FirFunctionTypeRef is marked nullable. But it is invalid to have the `suspend` modifier on the source element.
|
||||
if (typeRef !is FirFunctionTypeRef || typeRef.isMarkedNullable) {
|
||||
reporter.reportOn(
|
||||
suspendModifier.source,
|
||||
FirErrors.WRONG_MODIFIER_TARGET,
|
||||
suspendModifier.token,
|
||||
"non-functional type",
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
abstract class FirTypeChecker<in T : FirTypeRef> {
|
||||
/**
|
||||
* [FirTypeChecker] should only be used when the check can be performed independent of the context of the type refs. That is,
|
||||
* you should NOT be examining containing declarations, qualified accesses, etc. when writing a FirTypeChecker.
|
||||
*
|
||||
* If the check is dependent on context, or if it is specific to type refs in a certain kind of declaration or expression,
|
||||
* please write a [org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker] or
|
||||
* [org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker] instead.
|
||||
*/
|
||||
abstract fun check(typeRef: T, context: CheckerContext, reporter: DiagnosticReporter)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.util
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
fun FirElement.checkChildrenWithCustomVisitor(
|
||||
parentContext: CheckerContext,
|
||||
visitorVoid: FirVisitor<Unit, CheckerContext>
|
||||
) {
|
||||
val collectingVisitor = object : AbstractDiagnosticCollectorVisitor(parentContext as PersistentCheckerContext) {
|
||||
override fun checkElement(element: FirElement) {
|
||||
element.accept(visitorVoid, context)
|
||||
}
|
||||
}
|
||||
this.accept(collectingVisitor, null)
|
||||
}
|
||||
@@ -72,6 +72,7 @@ fun AbstractDiagnosticCollector.registerAllComponents() {
|
||||
initializeComponents(
|
||||
DeclarationCheckersDiagnosticComponent(this),
|
||||
ExpressionCheckersDiagnosticComponent(this),
|
||||
TypeCheckersDiagnosticComponent(this),
|
||||
ErrorNodeDiagnosticCollectorComponent(this),
|
||||
ControlFlowAnalysisDiagnosticComponent(this),
|
||||
)
|
||||
|
||||
@@ -15,11 +15,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -30,7 +27,10 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
protected open fun shouldVisitDeclaration(declaration: FirDeclaration) = true
|
||||
protected open fun onDeclarationExit(declaration: FirDeclaration) {}
|
||||
|
||||
protected abstract fun visitNestedElements(element: FirElement)
|
||||
protected open fun visitNestedElements(element: FirElement) {
|
||||
element.acceptChildren(this, null)
|
||||
}
|
||||
|
||||
protected abstract fun checkElement(element: FirElement)
|
||||
|
||||
override fun visitElement(element: FirElement, data: Nothing?) {
|
||||
@@ -165,7 +165,12 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
}
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?) {
|
||||
super.visitResolvedTypeRef(resolvedTypeRef, data)
|
||||
// Assuming no errors, the children of FirResolvedTypeRef (currently this can be FirAnnotationCalls) will also be present
|
||||
// as children in delegatedTypeRef. We should make sure those elements are only visited once, otherwise diagnostics will be
|
||||
// collected twice: once through resolvedTypeRef's children and another through resolvedTypeRef.delegatedTypeRef's children.
|
||||
if (resolvedTypeRef.type is ConeClassErrorType) {
|
||||
super.visitResolvedTypeRef(resolvedTypeRef, data)
|
||||
}
|
||||
resolvedTypeRef.delegatedTypeRef?.accept(this, data)
|
||||
}
|
||||
|
||||
@@ -208,15 +213,13 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
|
||||
private fun visitWithQualifiedAccess(qualifiedAccess: FirQualifiedAccess) {
|
||||
return withQualifiedAccess(qualifiedAccess) {
|
||||
checkElement(qualifiedAccess)
|
||||
visitNestedElements(qualifiedAccess)
|
||||
visitElement(qualifiedAccess, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitWithGetClassCall(getClassCall: FirGetClassCall) {
|
||||
return withGetClassCall(getClassCall) {
|
||||
checkElement(getClassCall)
|
||||
visitNestedElements(getClassCall)
|
||||
visitElement(getClassCall, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,4 +304,4 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
allErrorsSuppressed = AbstractDiagnosticCollector.SUPPRESS_ALL_ERRORS in arguments
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ open class CheckerRunningDiagnosticCollectorVisitor(
|
||||
protected val components: List<AbstractDiagnosticCollectorComponent>
|
||||
) : AbstractDiagnosticCollectorVisitor(context) {
|
||||
|
||||
override fun visitNestedElements(element: FirElement) {
|
||||
element.acceptChildren(this, null)
|
||||
}
|
||||
|
||||
override fun checkElement(element: FirElement) {
|
||||
components.forEach {
|
||||
element.accept(it, context)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
@OptIn(CheckersComponentInternal::class)
|
||||
class TypeCheckersDiagnosticComponent(
|
||||
collector: AbstractDiagnosticCollector,
|
||||
private val checkers: TypeCheckers = collector.session.checkersComponent.typeCheckers,
|
||||
) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
|
||||
override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(dynamicTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(functionTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(userTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(resolvedTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(errorTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(typeRefWithNullability, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(implicitTypeRef, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitTypeRef(typeRef: FirTypeRef, data: CheckerContext) {
|
||||
checkers.allTypeRefCheckers.check(typeRef, data, reporter)
|
||||
}
|
||||
|
||||
private fun <T : FirTypeRef> Collection<FirTypeChecker<T>>.check(
|
||||
typeRef: T,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
for (checker in this) {
|
||||
checker.check(typeRef, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITHOUT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DELEGATE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
|
||||
@@ -169,9 +170,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||
@@ -192,6 +195,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_CLASS_MEMBER_FROM_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_FUNCTION_WITH_NO_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_PROPERTY_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY
|
||||
@@ -202,8 +206,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD
|
||||
@@ -234,6 +242,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_NOT_INITIALIZED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_IS_NOT_AN_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_NOT_AVAILABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX
|
||||
@@ -268,6 +277,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATU
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USAGE_IS_NOT_INLINABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIGHT_IS_NULL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
|
||||
@@ -345,6 +355,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
"Cannot access ''{0}'' before superclass constructor has been called",
|
||||
TO_STRING
|
||||
)
|
||||
map.put(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, "Cannot create an instance of an abstract class")
|
||||
|
||||
// Supertypes
|
||||
map.put(ENUM_AS_SUPERTYPE, "Enum as supertype")
|
||||
@@ -903,6 +914,45 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
"Returns are not allowed for functions with expression body. Use block body in '{...}'"
|
||||
)
|
||||
|
||||
// Inline
|
||||
map.put(
|
||||
USAGE_IS_NOT_INLINABLE,
|
||||
"Illegal usage of inline-parameter ''{0}''. Add ''noinline'' modifier to the parameter declaration",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
NON_LOCAL_RETURN_NOT_ALLOWED,
|
||||
"Can''t inline ''{0}'' here: it may contain non-local returns. Add ''crossinline'' modifier to parameter declaration ''{0}''",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(RECURSION_IN_INLINE, "Inline function ''{0}'' cannot be recursive", SYMBOL)
|
||||
map.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{1}''", SYMBOL, SYMBOL)
|
||||
map.put(
|
||||
PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE,
|
||||
"Protected constructor call from public-API inline function is deprecated",
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
PROTECTED_CALL_FROM_PUBLIC_INLINE,
|
||||
"Protected function call from public-API inline function is deprecated",
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR,
|
||||
"Protected function call from public-API inline function is prohibited",
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
PRIVATE_CLASS_MEMBER_FROM_INLINE,
|
||||
"Non-private inline function cannot access members of private classes: ''{1}''",
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
|
||||
|
||||
// Extended checkers group
|
||||
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
|
||||
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")
|
||||
|
||||
@@ -642,6 +642,31 @@ object LightTreePositioningStrategies {
|
||||
return markElement(tree.typeParametersList(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
|
||||
val RESERVED_UNDERSCORE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
if (node.tokenType == KtNodeTypes.RETURN) {
|
||||
val parent = tree.getParent(node)
|
||||
if (parent != null) {
|
||||
val label = tree.findDescendantByType(parent, KtNodeTypes.LABEL)
|
||||
if (label != null) {
|
||||
return markElement(label, startOffset, endOffset - 1, tree, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val descendants =
|
||||
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } };
|
||||
if (descendants.isNotEmpty())
|
||||
return descendants.map { markSingleElement(it, it, startOffset, endOffset, tree, node) }
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||
@@ -855,6 +880,35 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.findFirstDescendant(
|
||||
?: childrenRef.get()?.firstNotNullResult { child -> child?.let { findFirstDescendant(it, predicate) } }
|
||||
}
|
||||
|
||||
fun FlyweightCapableTreeStructure<LighterASTNode>.collectDescendantsOfType(
|
||||
node: LighterASTNode, type: IElementType,
|
||||
predicate: (LighterASTNode) -> Boolean = { true }
|
||||
): List<LighterASTNode> {
|
||||
val result = mutableListOf<LighterASTNode>()
|
||||
|
||||
fun FlyweightCapableTreeStructure<LighterASTNode>.collectDescendantByType(node: LighterASTNode) {
|
||||
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||
getChildren(node, childrenRef)
|
||||
|
||||
val childrenRefGet = childrenRef.get()
|
||||
if (childrenRefGet != null) {
|
||||
for (child in childrenRefGet) {
|
||||
if (child?.tokenType == type && predicate(child)) {
|
||||
result.add(child)
|
||||
}
|
||||
|
||||
if (child != null) {
|
||||
collectDescendantByType(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectDescendantByType(node)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: TokenSet): LighterASTNode? {
|
||||
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||
getChildren(node, childrenRef)
|
||||
|
||||
@@ -46,11 +46,22 @@ fun markRange(
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||
originalNode: LighterASTNode
|
||||
): List<TextRange> {
|
||||
return listOf(markSingleElement(from, to, startOffset, endOffset, tree, originalNode))
|
||||
}
|
||||
|
||||
fun markSingleElement(
|
||||
from: LighterASTNode,
|
||||
to: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||
originalNode: LighterASTNode
|
||||
): TextRange {
|
||||
val betterFrom = from.nonFillerFirstChildOrSelf(tree)
|
||||
val betterTo = to.nonFillerLastChildOrSelf(tree)
|
||||
val startDelta = tree.getStartOffset(betterFrom) - tree.getStartOffset(originalNode)
|
||||
val endDelta = tree.getEndOffset(betterTo) - tree.getEndOffset(originalNode)
|
||||
return listOf(TextRange(startDelta + startOffset, endDelta + endOffset))
|
||||
return TextRange(startDelta + startOffset, endDelta + endOffset)
|
||||
}
|
||||
|
||||
private val DOC_AND_COMMENT_TOKENS = setOf(
|
||||
|
||||
@@ -228,4 +228,9 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.TYPE_PARAMETERS_LIST,
|
||||
PositioningStrategies.TYPE_PARAMETERS_LIST
|
||||
)
|
||||
|
||||
val RESERVED_UNDERSCORE = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.RESERVED_UNDERSCORE,
|
||||
PositioningStrategies.RESERVED_UNDERSCORE
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.extensions
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||
import org.jetbrains.kotlin.fir.extensions.AbstractFirAdditionalCheckersExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionPointName
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionService
|
||||
@@ -19,6 +20,7 @@ abstract class FirAdditionalCheckersExtension(session: FirSession) : AbstractFir
|
||||
|
||||
open val declarationCheckers: DeclarationCheckers = DeclarationCheckers.EMPTY
|
||||
open val expressionCheckers: ExpressionCheckers = ExpressionCheckers.EMPTY
|
||||
open val typeCheckers: TypeCheckers = TypeCheckers.EMPTY
|
||||
|
||||
final override val name: FirExtensionPointName
|
||||
get() = NAME
|
||||
|
||||
@@ -69,7 +69,7 @@ fun ConeKotlinType.renderFunctionType(
|
||||
kind: FunctionClassKind?, isExtension: Boolean, renderType: ConeTypeProjection.() -> String = { render() }
|
||||
): String {
|
||||
if (!kind.withPrettyRender()) return renderType()
|
||||
return buildString {
|
||||
val renderedType = buildString {
|
||||
if (kind == FunctionClassKind.SuspendFunction) {
|
||||
append("suspend ")
|
||||
}
|
||||
@@ -88,6 +88,7 @@ fun ConeKotlinType.renderFunctionType(
|
||||
append(" -> ")
|
||||
append(returnType.renderType())
|
||||
}
|
||||
return if (isMarkedNullable) "($renderedType)?" else renderedType
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.session.FirSessionFactory
|
||||
fun FirSessionFactory.FirSessionConfigurator.registerCommonCheckers() {
|
||||
useCheckers(CommonDeclarationCheckers)
|
||||
useCheckers(CommonExpressionCheckers)
|
||||
useCheckers(CommonTypeCheckers)
|
||||
}
|
||||
|
||||
fun FirSessionFactory.FirSessionConfigurator.registerExtendedCommonCheckers() {
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirReservedUnderscoreDeclarationChecker
|
||||
|
||||
object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||
@@ -20,6 +21,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirConflictsChecker,
|
||||
FirConflictingProjectionChecker,
|
||||
FirTypeConstraintsChecker,
|
||||
FirReservedUnderscoreDeclarationChecker
|
||||
)
|
||||
|
||||
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
||||
@@ -29,6 +31,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirSealedSupertypeChecker,
|
||||
FirTypeAliasChecker,
|
||||
FirCyclicTypeBoundsChecker,
|
||||
FirInlineDeclarationChecker,
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
@@ -15,6 +15,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
|
||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||
get() = setOf(
|
||||
FirReservedUnderscoreExpressionChecker
|
||||
)
|
||||
|
||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
||||
@@ -31,13 +32,14 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirTypeParameterInQualifiedAccessChecker,
|
||||
FirSealedClassConstructorCallChecker,
|
||||
FirUninitializedEnumChecker,
|
||||
FirFunInterfaceConstructorReferenceChecker,
|
||||
FirFunInterfaceConstructorReferenceChecker
|
||||
)
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||
get() = setOf(
|
||||
FirConventionFunctionCallChecker,
|
||||
FirDivisionByZeroChecker
|
||||
FirDivisionByZeroChecker,
|
||||
FirConstructorCallChecker
|
||||
)
|
||||
|
||||
override val tryExpressionCheckers: Set<FirTryExpressionChecker>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirCallsEffectAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirSuspendModifierChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||
|
||||
object CommonTypeCheckers : TypeCheckers() {
|
||||
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
|
||||
FirSuspendModifierChecker
|
||||
)
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
|
||||
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
|
||||
@@ -53,6 +54,10 @@ object FirSessionFactory {
|
||||
session.checkersComponent.register(checkers)
|
||||
}
|
||||
|
||||
fun useCheckers(checkers: TypeCheckers) {
|
||||
session.checkersComponent.register(checkers)
|
||||
}
|
||||
|
||||
@SessionConfiguration
|
||||
fun configure() {
|
||||
session.extensionService.registerExtensions(registeredExtensions.reduce(BunchOfRegisteredExtensions::plus))
|
||||
|
||||
@@ -234,6 +234,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags
|
||||
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags))
|
||||
val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
|
||||
if (Flags.IS_NOT_DEFAULT.get(getterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
declarationSiteSession = c.session
|
||||
@@ -244,7 +245,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
visibility,
|
||||
modality,
|
||||
visibility.toEffectiveVisibility(classSymbol)
|
||||
effectiveVisibility
|
||||
).apply {
|
||||
isInline = Flags.IS_INLINE_ACCESSOR.get(getterFlags)
|
||||
isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags)
|
||||
@@ -255,7 +256,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
versionRequirementsTable = c.versionRequirementTable
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility, effectiveVisibility)
|
||||
}.apply {
|
||||
(annotations as MutableList<FirAnnotationCall>) +=
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(
|
||||
@@ -270,6 +271,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags
|
||||
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags))
|
||||
val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
|
||||
if (Flags.IS_NOT_DEFAULT.get(setterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
declarationSiteSession = c.session
|
||||
@@ -280,7 +282,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
visibility,
|
||||
modality,
|
||||
visibility.toEffectiveVisibility(classSymbol)
|
||||
effectiveVisibility
|
||||
).apply {
|
||||
isInline = Flags.IS_INLINE_ACCESSOR.get(setterFlags)
|
||||
isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags)
|
||||
@@ -297,7 +299,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
versionRequirementsTable = c.versionRequirementTable
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility, effectiveVisibility)
|
||||
}.apply {
|
||||
(annotations as MutableList<FirAnnotationCall>) +=
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(
|
||||
|
||||
@@ -13,19 +13,19 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.*
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.types.AbstractTypeMapper
|
||||
import org.jetbrains.kotlin.types.TypeMappingContext
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
@@ -50,6 +50,9 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext<JvmSignatur
|
||||
return typeConstructor.classId.asString().replace(".", "$").replace("/", ".")
|
||||
}
|
||||
|
||||
override fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String =
|
||||
TODO("Not yet implemented")
|
||||
|
||||
override fun JvmSignatureWriter.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode) {
|
||||
if (type !is ConeClassLikeType) return
|
||||
if (skipGenericSignature() || hasNothingInNonContravariantPosition(type) || type.typeArguments.isEmpty()) {
|
||||
|
||||
@@ -55,10 +55,11 @@ class Fir2IrConverter(
|
||||
processClassMembers(regularClass, irClass)
|
||||
}
|
||||
|
||||
fun registerFileAndClasses(file: FirFile): IrFile {
|
||||
fun registerFileAndClasses(file: FirFile, moduleFragment: IrModuleFragment) {
|
||||
val irFile = IrFileImpl(
|
||||
PsiIrFileEntry(file.psi as KtFile),
|
||||
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
|
||||
moduleDescriptor.getPackage(file.packageFqName).fragments.first(),
|
||||
moduleFragment
|
||||
)
|
||||
declarationStorage.registerFile(file, irFile)
|
||||
file.declarations.forEach {
|
||||
@@ -66,7 +67,7 @@ class Fir2IrConverter(
|
||||
registerClassAndNestedClasses(it, irFile)
|
||||
}
|
||||
}
|
||||
return irFile
|
||||
moduleFragment.files += irFile
|
||||
}
|
||||
|
||||
fun processClassHeaders(file: FirFile) {
|
||||
@@ -279,12 +280,11 @@ class Fir2IrConverter(
|
||||
components.visibilityConverter = visibilityConverter
|
||||
components.builtIns = builtIns
|
||||
components.annotationGenerator = annotationGenerator
|
||||
val irFiles = mutableListOf<IrFile>()
|
||||
|
||||
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
|
||||
for (firFile in firFiles) {
|
||||
irFiles += converter.registerFileAndClasses(firFile)
|
||||
converter.registerFileAndClasses(firFile, irModuleFragment)
|
||||
}
|
||||
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns, irFiles)
|
||||
val irProviders =
|
||||
generateTypicalIrProviderList(irModuleFragment.descriptor, irBuiltIns, symbolTable, extensions = generatorExtensions)
|
||||
val externalDependenciesGenerator = ExternalDependenciesGenerator(
|
||||
|
||||
@@ -529,7 +529,7 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
private fun IrMemberAccessExpression<*>.applyArgumentsWithReorderingIfNeeded(
|
||||
argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>,
|
||||
argumentMapping: Map<FirExpression, FirValueParameter>,
|
||||
valueParameters: List<FirValueParameter>,
|
||||
substitutor: ConeSubstitutor,
|
||||
annotationMode: Boolean
|
||||
|
||||
@@ -2794,6 +2794,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/isAs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableParameter.kt")
|
||||
public void testNullableParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/nullableParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
@@ -8653,6 +8659,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
@@ -9252,6 +9264,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableSuspendFunctionType.kt")
|
||||
public void testNullableSuspendFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/nullableSuspendFunctionType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overrideDefaultArgument.kt")
|
||||
public void testOverrideDefaultArgument() throws Exception {
|
||||
@@ -9354,6 +9372,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/suspendFunImportedFromObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunctionAsSupertype.kt")
|
||||
public void testSuspendFunctionAsSupertype() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/suspendFunctionAsSupertype.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunctionMethodReference.kt")
|
||||
public void testSuspendFunctionMethodReference() throws Exception {
|
||||
@@ -9777,6 +9801,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overrideInInnerClass.kt")
|
||||
public void testOverrideInInnerClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("safeCallOnTwoReceivers.kt")
|
||||
public void testSafeCallOnTwoReceivers() throws Exception {
|
||||
@@ -17160,6 +17190,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/kt39824.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42042.kt")
|
||||
public void testKt42042() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/kt42042.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt42130.kt")
|
||||
public void testKt42130() throws Exception {
|
||||
@@ -17184,6 +17220,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt")
|
||||
public void testManyConstraintsDueToFlexibleRawTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
|
||||
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
|
||||
@@ -17268,6 +17310,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("violatingUpperBoundForSelfType.kt")
|
||||
public void testViolatingUpperBoundForSelfType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/inference/builderInference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -38591,6 +38639,22 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/script")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Script {
|
||||
@Test
|
||||
public void testAllFilesPresentInScript() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/script"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classReference.kt")
|
||||
public void testClassReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/script/classReference.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sealed")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -41086,6 +41150,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsForMaxLongValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsInApiVersion14.kt")
|
||||
public void testUnsignedLiteralsInApiVersion14() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsInApiVersion14.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||
|
||||
@@ -3702,6 +3702,18 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44770.kt")
|
||||
public void testKt44770() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt44770.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44770_2.kt")
|
||||
public void testKt44770_2() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt6988.kt")
|
||||
public void testKt6988() throws Exception {
|
||||
|
||||
@@ -238,6 +238,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
||||
runTest("compiler/testData/ir/irText/classes/kt43217.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt44013.kt")
|
||||
public void testKt44013() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/classes/kt44013.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt45853.kt")
|
||||
public void testKt45853() throws Exception {
|
||||
|
||||
@@ -916,7 +916,8 @@ class DeclarationsConverter(
|
||||
}
|
||||
constructedTypeRef = delegatedType.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
|
||||
this.isThis = isThis
|
||||
val calleeKind = if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
|
||||
val calleeKind =
|
||||
if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
|
||||
val calleeSource = constructorDelegationCall.getChildNodeByType(CONSTRUCTOR_DELEGATION_REFERENCE)
|
||||
?.toFirSourceElement(calleeKind)
|
||||
?: this@buildDelegatedConstructorCall.source?.fakeElement(calleeKind)
|
||||
@@ -1281,7 +1282,8 @@ class DeclarationsConverter(
|
||||
CONTRACT_EFFECT -> {
|
||||
val effect = it.getFirstChild()
|
||||
if (effect == null) {
|
||||
val errorExpression = buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected))
|
||||
val errorExpression =
|
||||
buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected))
|
||||
destination.add(errorExpression)
|
||||
} else {
|
||||
val expression = expressionConverter.convertExpression(effect, errorReason)
|
||||
@@ -1671,33 +1673,62 @@ class DeclarationsConverter(
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
|
||||
*/
|
||||
fun convertType(type: LighterASTNode): FirTypeRef {
|
||||
val typeRefSource = type.toFirSourceElement()
|
||||
if (type.asText.isEmpty()) {
|
||||
return buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax) }
|
||||
}
|
||||
var typeModifiers = TypeModifier()
|
||||
var firType: FirTypeRef = buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) }
|
||||
var afterLPar = false
|
||||
type.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LPAR -> afterLPar = true
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
MODIFIER_LIST -> if (!afterLPar || typeModifiers.hasNoAnnotations()) typeModifiers = convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(it)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(it)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(it, isSuspend = typeModifiers.hasSuspend)
|
||||
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
|
||||
source = type.toFirSourceElement()
|
||||
isMarkedNullable = false
|
||||
}
|
||||
TokenType.ERROR_ELEMENT -> firType =
|
||||
buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax) }
|
||||
return buildErrorTypeRef {
|
||||
source = typeRefSource
|
||||
diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax)
|
||||
}
|
||||
}
|
||||
|
||||
return firType.also { (it.annotations as MutableList<FirAnnotationCall>) += typeModifiers.annotations }
|
||||
// There can be MODIFIER_LIST children on the TYPE_REFERENCE node AND the descendant NULLABLE_TYPE nodes.
|
||||
// We aggregate them to get modifiers and annotations. Not only that, there could be multiple modifier lists on each. Examples:
|
||||
//
|
||||
// `@A() (@B Int)` -> Has 2 modifier lists (@A and @B) in TYPE_REFERENCE
|
||||
// `(@A() (@B Int))? -> No modifier list on TYPE_REFERENCE, but 2 modifier lists (@A and @B) on child NULLABLE_TYPE
|
||||
// `@A() (@B Int)? -> Has 1 modifier list (@A) on TYPE_REFERENCE, and 1 modifier list (@B) on child NULLABLE_TYPE
|
||||
// `@A (@B() (@C() (@Bar D)?)?)?` -> Has 1 modifier list (@A) on B and 1 modifier list on each of the
|
||||
// 3 descendant NULLABLE_TYPE (@B, @C, @D)
|
||||
//
|
||||
// We need to examine all modifier lists for some cases:
|
||||
// 1. `@A Int?` and `(@A Int)?` are effectively the same, but in the latter, the modifier list is on the child NULLABLE_TYPE
|
||||
// 2. `(suspend @A () -> Int)?` is a nullable suspend function type but the modifier list is on the child NULLABLE_TYPE
|
||||
//
|
||||
// TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them?
|
||||
val allTypeModifiers = mutableListOf<TypeModifier>()
|
||||
|
||||
var firType: FirTypeRef = buildErrorTypeRef {
|
||||
source = typeRefSource
|
||||
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax)
|
||||
}
|
||||
type.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(typeRefSource, it)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isSuspend = allTypeModifiers.hasSuspend())
|
||||
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
|
||||
source = typeRefSource
|
||||
isMarkedNullable = false
|
||||
}
|
||||
TokenType.ERROR_ELEMENT -> firType =
|
||||
buildErrorTypeRef {
|
||||
source = typeRefSource
|
||||
diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (modifierList in allTypeModifiers) {
|
||||
(firType.annotations as MutableList<FirAnnotationCall>) += modifierList.annotations
|
||||
}
|
||||
return firType
|
||||
}
|
||||
|
||||
private fun Collection<TypeModifier>.hasSuspend() = any { it.hasSuspend }
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRefContents
|
||||
*/
|
||||
@@ -1715,17 +1746,23 @@ class DeclarationsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseNullableTypeSuffix
|
||||
*/
|
||||
private fun convertNullableType(nullableType: LighterASTNode): FirTypeRef {
|
||||
private fun convertNullableType(
|
||||
typeRefSource: FirSourceElement,
|
||||
nullableType: LighterASTNode,
|
||||
allTypeModifiers: MutableList<TypeModifier>,
|
||||
isNullable: Boolean = true
|
||||
): FirTypeRef {
|
||||
lateinit var firType: FirTypeRef
|
||||
nullableType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> firType =
|
||||
convertUserType(it, true)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(it, true)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(it)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it, nullable = true)
|
||||
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(typeRefSource, it, isNullable)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isNullable, isSuspend = allTypeModifiers.hasSuspend())
|
||||
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType =
|
||||
unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers, isNullable = true)
|
||||
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
|
||||
source = nullableType.toFirSourceElement()
|
||||
source = typeRefSource
|
||||
isMarkedNullable = true
|
||||
}
|
||||
}
|
||||
@@ -1734,18 +1771,23 @@ class DeclarationsConverter(
|
||||
return firType
|
||||
}
|
||||
|
||||
private fun unwrapDefinitelyNotNullableType(definitelyNotNullType: LighterASTNode, nullable: Boolean = false): FirTypeRef {
|
||||
private fun unwrapDefinitelyNotNullableType(
|
||||
typeRefSource: FirSourceElement,
|
||||
definitelyNotNullType: LighterASTNode,
|
||||
allTypeModifiers: MutableList<TypeModifier>,
|
||||
isNullable: Boolean = false
|
||||
): FirTypeRef {
|
||||
lateinit var firType: FirTypeRef
|
||||
// TODO: Support proper DefinitelyNotNullableType
|
||||
definitelyNotNullType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> firType =
|
||||
convertUserType(it, nullable)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(it, nullable)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(it)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it, nullable)
|
||||
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(typeRefSource, it, isNullable)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isNullable, isSuspend = allTypeModifiers.hasSuspend())
|
||||
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers, isNullable = false)
|
||||
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers, isNullable)
|
||||
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
|
||||
source = definitelyNotNullType.toFirSourceElement()
|
||||
source = typeRefSource
|
||||
isMarkedNullable = false
|
||||
}
|
||||
}
|
||||
@@ -1757,32 +1799,37 @@ class DeclarationsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseUserType
|
||||
*/
|
||||
private fun convertUserType(userType: LighterASTNode, isNullable: Boolean = false): FirTypeRef {
|
||||
private fun convertUserType(
|
||||
typeRefSource: FirSourceElement,
|
||||
userType: LighterASTNode,
|
||||
isNullable: Boolean = false
|
||||
): FirTypeRef {
|
||||
var simpleFirUserType: FirUserTypeRef? = null
|
||||
var identifier: String? = null
|
||||
val firTypeArguments = mutableListOf<FirTypeProjection>()
|
||||
userType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type
|
||||
USER_TYPE -> simpleFirUserType = convertUserType(typeRefSource, it) as? FirUserTypeRef //simple user type
|
||||
REFERENCE_EXPRESSION -> identifier = it.asText
|
||||
TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (identifier == null)
|
||||
return buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax) }
|
||||
return buildErrorTypeRef {
|
||||
source = typeRefSource
|
||||
diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax)
|
||||
}
|
||||
|
||||
// Note: we take TYPE_REFERENCE, not USER_TYPE, as the source (to be consistent with RawFirBuilder)
|
||||
val theSource = tree.getParent(userType)!!.toFirSourceElement()
|
||||
val qualifierPart = FirQualifierPartImpl(
|
||||
identifier.nameAsSafeName(),
|
||||
FirTypeArgumentListImpl(theSource).apply {
|
||||
FirTypeArgumentListImpl(typeRefSource).apply {
|
||||
typeArguments += firTypeArguments
|
||||
}
|
||||
)
|
||||
|
||||
return buildUserTypeRef {
|
||||
source = theSource
|
||||
source = typeRefSource
|
||||
isMarkedNullable = isNullable
|
||||
qualifier.add(qualifierPart)
|
||||
simpleFirUserType?.qualifier?.let { this.qualifier.addAll(0, it) }
|
||||
@@ -1827,7 +1874,12 @@ class DeclarationsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunctionType
|
||||
*/
|
||||
private fun convertFunctionType(functionType: LighterASTNode, isNullable: Boolean = false, isSuspend: Boolean = false): FirTypeRef {
|
||||
private fun convertFunctionType(
|
||||
typeRefSource: FirSourceElement,
|
||||
functionType: LighterASTNode,
|
||||
isNullable: Boolean = false,
|
||||
isSuspend: Boolean = false
|
||||
): FirTypeRef {
|
||||
var receiverTypeReference: FirTypeRef? = null
|
||||
lateinit var returnTypeReference: FirTypeRef
|
||||
val valueParametersList = mutableListOf<ValueParameter>()
|
||||
@@ -1840,7 +1892,7 @@ class DeclarationsConverter(
|
||||
}
|
||||
|
||||
return buildFunctionTypeRef {
|
||||
source = functionType.toFirSourceElement()
|
||||
source = typeRefSource
|
||||
isMarkedNullable = isNullable
|
||||
receiverTypeRef = receiverTypeReference
|
||||
returnTypeRef = returnTypeReference
|
||||
|
||||
@@ -46,6 +46,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexTypes.kt")
|
||||
public void testComplexTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
|
||||
@@ -156,6 +166,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitModifierList.kt")
|
||||
public void testSplitModifierList() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendFunctionTypes.kt")
|
||||
public void testSuspendFunctionTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeAliasWithGeneric.kt")
|
||||
public void testTypeAliasWithGeneric() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.name.LocalCallableIdConstructor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
@@ -1354,11 +1355,37 @@ open class RawFirBuilder(
|
||||
val source = typeReference.toFirSourceElement()
|
||||
val isNullable = typeElement is KtNullableType
|
||||
|
||||
// There can be KtDeclarationModifierLists in the KtTypeReference AND the descendant KtNullableTypes.
|
||||
// We aggregate them to get modifiers and annotations. Not only that, there could be multiple modifier lists on each. Examples:
|
||||
//
|
||||
// `@A() (@B Int)` -> Has 2 modifier lists (@A and @B) on KtTypeReference
|
||||
// `(@A() (@B Int))? -> No modifier list on KtTypeReference, but 2 modifier lists (@A and @B) on child KtNullableType
|
||||
// `@A() (@B Int)? -> Has 1 modifier list (@A) on KtTypeReference, and 1 modifier list (@B) on child KtNullableType
|
||||
// `@A (@B() (@C() (@Bar D)?)?)?` -> Has 1 modifier list (@A) on KtTypeReference and 1 modifier list on each of the
|
||||
// 3 descendant KtNullableTypes (@B, @C, @D)
|
||||
//
|
||||
// We need to examine all modifier lists for some cases:
|
||||
// 1. `@A Int?` and `(@A Int)?` are effectively the same, but in the latter, the modifier list is on the child KtNullableType
|
||||
// 2. `(suspend @A () -> Int)?` is a nullable suspend function type but the modifier list is on the child KtNullableType
|
||||
//
|
||||
// `getModifierList()` only returns the first one so we have to get all modifier list children.
|
||||
// TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them?
|
||||
fun KtElementImplStub<*>.getAllModifierLists(): Array<out KtDeclarationModifierList> =
|
||||
getStubOrPsiChildren(KtStubElementTypes.MODIFIER_LIST, KtStubElementTypes.MODIFIER_LIST.arrayFactory)
|
||||
|
||||
val allModifierLists = mutableListOf<KtModifierList>(*typeReference.getAllModifierLists())
|
||||
|
||||
fun KtTypeElement?.unwrapNullable(): KtTypeElement? =
|
||||
when (this) {
|
||||
is KtNullableType -> this.innerType.unwrapNullable()
|
||||
is KtNullableType -> {
|
||||
allModifierLists += getAllModifierLists()
|
||||
this.innerType.unwrapNullable()
|
||||
}
|
||||
// TODO: Support explicit definitely not null type
|
||||
is KtDefinitelyNotNullType -> this.innerType.unwrapNullable()
|
||||
is KtDefinitelyNotNullType -> {
|
||||
allModifierLists += getAllModifierLists()
|
||||
this.innerType.unwrapNullable()
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
|
||||
@@ -1403,7 +1430,7 @@ open class RawFirBuilder(
|
||||
FirFunctionTypeRefBuilder().apply {
|
||||
this.source = source
|
||||
isMarkedNullable = isNullable
|
||||
isSuspend = typeReference.hasModifier(SUSPEND_KEYWORD)
|
||||
isSuspend = allModifierLists.any { it.hasSuspendModifier() }
|
||||
receiverTypeRef = unwrappedElement.receiverTypeReference.convertSafe()
|
||||
// TODO: probably implicit type should not be here
|
||||
returnTypeRef = unwrappedElement.returnTypeReference.toFirOrErrorType()
|
||||
@@ -1422,8 +1449,10 @@ open class RawFirBuilder(
|
||||
else -> throw AssertionError("Unexpected type element: ${unwrappedElement.text}")
|
||||
}
|
||||
|
||||
for (annotationEntry in typeReference.annotationEntries) {
|
||||
firTypeBuilder.annotations += annotationEntry.convert<FirAnnotationCall>()
|
||||
for (modifierList in allModifierLists) {
|
||||
for (annotationEntry in modifierList.annotationEntries) {
|
||||
firTypeBuilder.annotations += annotationEntry.convert<FirAnnotationCall>()
|
||||
}
|
||||
}
|
||||
return firTypeBuilder.build()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
interface AnnotationsOnNullableParenthesizedTypes {
|
||||
fun B<(@A C)?>.receiverArgument() {}
|
||||
|
||||
fun parameter(a: (@A C)?) {}
|
||||
|
||||
fun parameterArgument(a: B<(@A C)?>) {}
|
||||
|
||||
fun returnValue(): (@A C)?
|
||||
|
||||
fun <T> returnTypeParameterValue(): (@A T)?
|
||||
|
||||
fun returnArgument(): B<(@A C)?>
|
||||
|
||||
val lambdaType: (@A() (() -> C))?
|
||||
|
||||
val lambdaParameter: ((@A C)?) -> C
|
||||
|
||||
val lambdaReturnValue: () -> (@A C)?
|
||||
|
||||
val lambdaReceiver: (@A C)?.() -> C
|
||||
}
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A
|
||||
|
||||
interface B<T>
|
||||
interface C
|
||||
@@ -0,0 +1,37 @@
|
||||
FILE: annotationsOnNullableParenthesizedTypes.kt
|
||||
public? final? interface AnnotationsOnNullableParenthesizedTypes : R|kotlin/Any| {
|
||||
public? final? fun B<@A() C?>.receiverArgument(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun parameter(a: @A() C?): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun parameterArgument(a: B<@A() C?>): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun returnValue(): @A() C?
|
||||
|
||||
public? final? fun <T> returnTypeParameterValue(): @A() T?
|
||||
|
||||
public? final? fun returnArgument(): B<@A() C?>
|
||||
|
||||
public? final? val lambdaType: @A() ( () -> C )?
|
||||
public? get(): @A() ( () -> C )?
|
||||
|
||||
public? final? val lambdaParameter: ( (@A() C?) -> C )
|
||||
public? get(): ( (@A() C?) -> C )
|
||||
|
||||
public? final? val lambdaReturnValue: ( () -> @A() C? )
|
||||
public? get(): ( () -> @A() C? )
|
||||
|
||||
public? final? val lambdaReceiver: ( @A() C?.() -> C )
|
||||
public? get(): ( @A() C?.() -> C )
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final? interface B<T> : R|kotlin/Any| {
|
||||
}
|
||||
public? final? interface C : R|kotlin/Any| {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
FILE: annotationsOnNullableParenthesizedTypes.kt
|
||||
public? final? interface AnnotationsOnNullableParenthesizedTypes : R|kotlin/Any| {
|
||||
public? final? fun B<@A() C?>.receiverArgument(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun parameter(a: @A() C?): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun parameterArgument(a: B<@A() C?>): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun returnValue(): @A() C?
|
||||
|
||||
public? final? fun <T> returnTypeParameterValue(): @A() T?
|
||||
|
||||
public? final? fun returnArgument(): B<@A() C?>
|
||||
|
||||
public? final? val lambdaType: @A() ( () -> C )?
|
||||
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): @A() ( () -> C )?
|
||||
|
||||
public? final? val lambdaParameter: ( (@A() C?) -> C )
|
||||
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( (@A() C?) -> C )
|
||||
|
||||
public? final? val lambdaReturnValue: ( () -> @A() C? )
|
||||
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( () -> @A() C? )
|
||||
|
||||
public? final? val lambdaReceiver: ( @A() C?.() -> C )
|
||||
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( @A() C?.() -> C )
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? [ContainingClassKey=A] constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final? interface B<T> : R|kotlin/Any| {
|
||||
}
|
||||
public? final? interface C : R|kotlin/Any| {
|
||||
}
|
||||
29
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt
vendored
Normal file
29
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
interface AnnotationsOnParenthesizedTypes {
|
||||
fun B<(@A C)>.receiverArgument() {}
|
||||
|
||||
fun parameter(a: (@A C)) {}
|
||||
|
||||
fun parameterArgument(a: B<(@A C)>) {}
|
||||
|
||||
fun returnValue(): (@A C)
|
||||
|
||||
fun <T> returnTypeParameterValue(): (@A T)
|
||||
|
||||
fun returnArgument(): B<(@A C)>
|
||||
|
||||
val lambdaType: (@A() (() -> C))
|
||||
|
||||
val lambdaParameter: ((@A C)) -> C
|
||||
|
||||
val lambdaReturnValue: () -> (@A C)
|
||||
|
||||
val lambdaReceiver: (@A C).() -> C
|
||||
|
||||
val lambdaParameterNP: (@A C) -> C
|
||||
}
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A
|
||||
|
||||
interface B<T>
|
||||
interface C
|
||||
@@ -0,0 +1,40 @@
|
||||
FILE: annotationsOnParenthesizedTypes.kt
|
||||
public? final? interface AnnotationsOnParenthesizedTypes : R|kotlin/Any| {
|
||||
public? final? fun B<@A() C>.receiverArgument(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun parameter(a: @A() C): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun parameterArgument(a: B<@A() C>): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
|
||||
public? final? fun returnValue(): @A() C
|
||||
|
||||
public? final? fun <T> returnTypeParameterValue(): @A() T
|
||||
|
||||
public? final? fun returnArgument(): B<@A() C>
|
||||
|
||||
public? final? val lambdaType: @A() ( () -> C )
|
||||
public? get(): @A() ( () -> C )
|
||||
|
||||
public? final? val lambdaParameter: ( (@A() C) -> C )
|
||||
public? get(): ( (@A() C) -> C )
|
||||
|
||||
public? final? val lambdaReturnValue: ( () -> @A() C )
|
||||
public? get(): ( () -> @A() C )
|
||||
|
||||
public? final? val lambdaReceiver: ( @A() C.() -> C )
|
||||
public? get(): ( @A() C.() -> C )
|
||||
|
||||
public? final? val lambdaParameterNP: ( (@A() C) -> C )
|
||||
public? get(): ( (@A() C) -> C )
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final? interface B<T> : R|kotlin/Any| {
|
||||
}
|
||||
public? final? interface C : R|kotlin/Any| {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
FILE: annotationsOnParenthesizedTypes.kt
|
||||
public? final? interface AnnotationsOnParenthesizedTypes : R|kotlin/Any| {
|
||||
public? final? fun B<@A() C>.receiverArgument(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun parameter(a: @A() C): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun parameterArgument(a: B<@A() C>): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public? final? fun returnValue(): @A() C
|
||||
|
||||
public? final? fun <T> returnTypeParameterValue(): @A() T
|
||||
|
||||
public? final? fun returnArgument(): B<@A() C>
|
||||
|
||||
public? final? val lambdaType: @A() ( () -> C )
|
||||
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): @A() ( () -> C )
|
||||
|
||||
public? final? val lambdaParameter: ( (@A() C) -> C )
|
||||
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( (@A() C) -> C )
|
||||
|
||||
public? final? val lambdaReturnValue: ( () -> @A() C )
|
||||
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( () -> @A() C )
|
||||
|
||||
public? final? val lambdaReceiver: ( @A() C.() -> C )
|
||||
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( @A() C.() -> C )
|
||||
|
||||
public? final? val lambdaParameterNP: ( (@A() C) -> C )
|
||||
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( (@A() C) -> C )
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? [ContainingClassKey=A] constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final? interface B<T> : R|kotlin/Any| {
|
||||
}
|
||||
public? final? interface C : R|kotlin/Any| {
|
||||
}
|
||||
16
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt
vendored
Normal file
16
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class B
|
||||
|
||||
typealias Test0 = @A @B Int
|
||||
typealias Test1 = @A() (@A Int)
|
||||
typealias Test2 = @A() (@B Int)
|
||||
typealias Test3 = @A() (@A Int) -> Int
|
||||
typealias Test4 = @A() (@B Int)?
|
||||
typealias Test5 = @A() ( (@B Int)? )
|
||||
typealias Test6 = (@A @B Int)
|
||||
typealias Test7 = (@A @B Int)?
|
||||
typealias Test8 = (@A() (@B Int)? )
|
||||
typealias Test9 = (@A() (@B Int) )?
|
||||
23
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.lazyBodies.txt
vendored
Normal file
23
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.lazyBodies.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
FILE: splitModifierList.kt
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class B : R|kotlin/Annotation| {
|
||||
public? constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final typealias Test0 = @A() @B() Int
|
||||
public? final typealias Test1 = @A() @A() Int
|
||||
public? final typealias Test2 = @A() @B() Int
|
||||
public? final typealias Test3 = @A() ( (@A() Int) -> Int )
|
||||
public? final typealias Test4 = @A() @B() Int?
|
||||
public? final typealias Test5 = @A() @B() Int?
|
||||
public? final typealias Test6 = @A() @B() Int
|
||||
public? final typealias Test7 = @A() @B() Int?
|
||||
public? final typealias Test8 = @A() @B() Int?
|
||||
public? final typealias Test9 = @A() @B() Int?
|
||||
23
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.txt
vendored
Normal file
23
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
FILE: splitModifierList.kt
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
|
||||
public? [ContainingClassKey=A] constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class B : R|kotlin/Annotation| {
|
||||
public? [ContainingClassKey=B] constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final typealias Test0 = @A() @B() Int
|
||||
public? final typealias Test1 = @A() @A() Int
|
||||
public? final typealias Test2 = @A() @B() Int
|
||||
public? final typealias Test3 = @A() ( (@A() Int) -> Int )
|
||||
public? final typealias Test4 = @A() @B() Int?
|
||||
public? final typealias Test5 = @A() @B() Int?
|
||||
public? final typealias Test6 = @A() @B() Int
|
||||
public? final typealias Test7 = @A() @B() Int?
|
||||
public? final typealias Test8 = @A() @B() Int?
|
||||
public? final typealias Test9 = @A() @B() Int?
|
||||
8
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt
vendored
Normal file
8
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
suspend fun <T> simpleRun(f: suspend () -> T): T = f()
|
||||
|
||||
suspend fun <T, R> List<T>.simpleMap(f: suspend (T) -> R): R {
|
||||
|
||||
}
|
||||
|
||||
suspend fun <T> simpleWith(t: T, f: suspend T.() -> Unit): Unit = t.f()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
FILE: suspendFunctionTypes.kt
|
||||
public? final? suspend fun <T> simpleRun(f: ( suspend () -> T )): T { LAZY_BLOCK }
|
||||
public? final? suspend fun <T, R> List<T>.simpleMap(f: ( suspend (T) -> R )): R { LAZY_BLOCK }
|
||||
public? final? suspend fun <T> simpleWith(t: T, f: ( suspend T.() -> Unit )): Unit { LAZY_BLOCK }
|
||||
9
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.txt
vendored
Normal file
9
compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.txt
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
FILE: suspendFunctionTypes.kt
|
||||
public? final? suspend fun <T> simpleRun(f: ( suspend () -> T )): T {
|
||||
^simpleRun f#()
|
||||
}
|
||||
public? final? suspend fun <T, R> List<T>.simpleMap(f: ( suspend (T) -> R )): R {
|
||||
}
|
||||
public? final? suspend fun <T> simpleWith(t: T, f: ( suspend T.() -> Unit )): Unit {
|
||||
^simpleWith t#.f#()
|
||||
}
|
||||
@@ -46,6 +46,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexTypes.kt")
|
||||
public void testComplexTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
|
||||
@@ -156,6 +166,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitModifierList.kt")
|
||||
public void testSplitModifierList() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendFunctionTypes.kt")
|
||||
public void testSuspendFunctionTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeAliasWithGeneric.kt")
|
||||
public void testTypeAliasWithGeneric() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");
|
||||
|
||||
@@ -46,6 +46,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsOnParenthesizedTypes.kt")
|
||||
public void testAnnotationsOnParenthesizedTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexTypes.kt")
|
||||
public void testComplexTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
|
||||
@@ -156,6 +166,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitModifierList.kt")
|
||||
public void testSplitModifierList() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendFunctionTypes.kt")
|
||||
public void testSuspendFunctionTypes() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeAliasWithGeneric.kt")
|
||||
public void testTypeAliasWithGeneric() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");
|
||||
|
||||
@@ -22,16 +22,16 @@ fun Visibility.toEffectiveVisibility(
|
||||
fun Visibility.toEffectiveVisibility(
|
||||
owner: ConeClassLikeLookupTag?,
|
||||
forClass: Boolean = false,
|
||||
checkPublishedApi: Boolean = false
|
||||
ownerIsPublishedApi: Boolean = false
|
||||
): EffectiveVisibility {
|
||||
customEffectiveVisibility()?.let { return it }
|
||||
return when (this.normalize()) {
|
||||
Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass
|
||||
Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass
|
||||
Visibilities.Protected -> EffectiveVisibility.Protected(owner)
|
||||
Visibilities.Internal -> when (!checkPublishedApi /*|| !owner.isPublishedApi()*/) { // TODO
|
||||
true -> EffectiveVisibility.Internal
|
||||
false -> EffectiveVisibility.Public
|
||||
Visibilities.Internal -> when (ownerIsPublishedApi) {
|
||||
true -> EffectiveVisibility.Public
|
||||
false -> EffectiveVisibility.Internal
|
||||
}
|
||||
Visibilities.Public -> EffectiveVisibility.Public
|
||||
Visibilities.Local -> EffectiveVisibility.Local
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassAttr
|
||||
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
@@ -167,7 +169,12 @@ class FirSamResolverImpl(
|
||||
source = firRegularClass.source
|
||||
name = classId.shortClassName
|
||||
origin = FirDeclarationOrigin.SamConstructor
|
||||
status = FirDeclarationStatusImpl(firRegularClass.visibility, Modality.FINAL).apply {
|
||||
val visibility = firRegularClass.visibility
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
visibility,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.Local
|
||||
).apply {
|
||||
isExpect = firRegularClass.isExpect
|
||||
isActual = firRegularClass.isActual
|
||||
isOverride = false
|
||||
|
||||
@@ -47,7 +47,7 @@ fun ConeKotlinType.isKMutableProperty(session: FirSession): Boolean {
|
||||
classId.shortClassName.identifier.startsWith("KMutableProperty")
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
|
||||
fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
|
||||
return classId(session)?.toFunctionClassKind()
|
||||
}
|
||||
|
||||
@@ -55,29 +55,34 @@ private fun ClassId.toFunctionClassKind(): FunctionClassKind? {
|
||||
return FunctionClassKind.byClassNamePrefix(packageFqName, relativeClassName.asString())
|
||||
}
|
||||
|
||||
// Function, SuspendFunction, KFunction, KSuspendFunction
|
||||
fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean {
|
||||
return functionClassKind(session) != null
|
||||
}
|
||||
|
||||
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
|
||||
val kind = functionClassKind(session) ?: return false
|
||||
return kind == FunctionClassKind.Function
|
||||
}
|
||||
|
||||
// Function, SuspendFunction, KFunction, KSuspendFunction
|
||||
fun ConeClassLikeLookupTag.isBuiltinFunctionalType(): Boolean {
|
||||
return classId.toFunctionClassKind() != null
|
||||
}
|
||||
|
||||
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
|
||||
inline fun ConeKotlinType.isFunctionalType(session: FirSession, predicate: (FunctionClassKind) -> Boolean): Boolean {
|
||||
val kind = functionClassKind(session) ?: return false
|
||||
return kind == FunctionClassKind.SuspendFunction ||
|
||||
kind == FunctionClassKind.KSuspendFunction
|
||||
return predicate(kind)
|
||||
}
|
||||
|
||||
// Function
|
||||
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
|
||||
return isFunctionalType(session) { it == FunctionClassKind.Function }
|
||||
}
|
||||
|
||||
// SuspendFunction, KSuspendFunction
|
||||
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
|
||||
return isFunctionalType(session) { it.isSuspendType }
|
||||
}
|
||||
|
||||
// KFunction, KSuspendFunction
|
||||
fun ConeKotlinType.isKFunctionType(session: FirSession): Boolean {
|
||||
val kind = functionClassKind(session) ?: return false
|
||||
return kind == FunctionClassKind.KFunction ||
|
||||
kind == FunctionClassKind.KSuspendFunction
|
||||
return isFunctionalType(session) { it.isReflectType }
|
||||
}
|
||||
|
||||
fun ConeKotlinType.kFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType {
|
||||
|
||||
@@ -16,6 +16,9 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
class FirStatusResolver(
|
||||
val session: FirSession,
|
||||
@@ -172,6 +175,22 @@ class FirStatusResolver(
|
||||
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>
|
||||
)
|
||||
val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext)
|
||||
val annotations = ((containingProperty ?: declaration) as? FirAnnotatedDeclaration)?.annotations ?: emptyList()
|
||||
if (annotations.any { it.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == StandardClassIds.PublishedApi }) {
|
||||
val publishedApiSelfEffectiveVisibility = visibility.toEffectiveVisibility(
|
||||
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>, ownerIsPublishedApi = true
|
||||
)
|
||||
val parentPublishedEffectiveVisibility = when {
|
||||
containingProperty != null -> containingProperty.publishedApiEffectiveVisibility
|
||||
containingClass is FirRegularClass -> containingClass.publishedApiEffectiveVisibility
|
||||
else -> null
|
||||
} ?: parentEffectiveVisibility
|
||||
declaration.publishedApiEffectiveVisibility = parentPublishedEffectiveVisibility.lowerBound(
|
||||
publishedApiSelfEffectiveVisibility,
|
||||
session.typeContext
|
||||
)
|
||||
}
|
||||
|
||||
return status.resolved(visibility, modality, effectiveVisibility)
|
||||
}
|
||||
|
||||
@@ -243,3 +262,6 @@ private fun FirDeclaration.hasOwnBodyOrAccessorBody(): Boolean {
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private object PublishedApiEffectiveVisibilityKey : FirDeclarationDataKey()
|
||||
var FirDeclaration.publishedApiEffectiveVisibility: EffectiveVisibility? by FirDeclarationDataRegistry.data(PublishedApiEffectiveVisibilityKey)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user