mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-10 08:31:32 +00:00
Compare commits
74 Commits
rr/ilmir/i
...
rr/stdlib/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b3380dec0 | ||
|
|
fd70c33cc3 | ||
|
|
19b16da183 | ||
|
|
0d55c9108d | ||
|
|
15c325cf10 | ||
|
|
235813736e | ||
|
|
4626f21c58 | ||
|
|
68d271fc91 | ||
|
|
94ddb71213 | ||
|
|
8abf27898d | ||
|
|
5fbdc0af5e | ||
|
|
54f9edb597 | ||
|
|
b1c9d4b046 | ||
|
|
7f1b539011 | ||
|
|
3877933913 | ||
|
|
ea7d738ee1 | ||
|
|
c9806c5af9 | ||
|
|
516fce37db | ||
|
|
a9c072f826 | ||
|
|
caea0a9df0 | ||
|
|
c776fcbd00 | ||
|
|
fae5b8da4b | ||
|
|
e5c46a86aa | ||
|
|
daf42c1ee6 | ||
|
|
984b3c2f30 | ||
|
|
68f8e88d8b | ||
|
|
dce3d4d1b7 | ||
|
|
b0ff3e7e5e | ||
|
|
9d749feb64 | ||
|
|
d25ad269e0 | ||
|
|
9f58e4bcfe | ||
|
|
1ccbb09029 | ||
|
|
8e5bcd349e | ||
|
|
6b649d02d3 | ||
|
|
8ce2e4654b | ||
|
|
e6a3e38c4d | ||
|
|
11673bd09c | ||
|
|
08a2b47c77 | ||
|
|
0522583602 | ||
|
|
05e47da458 | ||
|
|
c7e5beece5 | ||
|
|
d512158c25 | ||
|
|
a917ebd11e | ||
|
|
c7c793c724 | ||
|
|
d41d1bf64d | ||
|
|
be03bc477d | ||
|
|
988cc52174 | ||
|
|
697b2b02f1 | ||
|
|
6cb573cb45 | ||
|
|
4d7b6c022b | ||
|
|
842d31d04e | ||
|
|
7cbcde77dd | ||
|
|
a7d7aa123e | ||
|
|
a1603716ed | ||
|
|
5630667320 | ||
|
|
56c3faee00 | ||
|
|
18e5af37ff | ||
|
|
535aa1e9e0 | ||
|
|
229c6f97ac | ||
|
|
aff90b335c | ||
|
|
6aff96a401 | ||
|
|
3fc424246b | ||
|
|
2a8f783393 | ||
|
|
4c69043a15 | ||
|
|
3e3ec5fc69 | ||
|
|
fdaf31dbf3 | ||
|
|
aae0081f3f | ||
|
|
2429f429c5 | ||
|
|
eae8821dec | ||
|
|
2ffedd2731 | ||
|
|
8a969dab7d | ||
|
|
b23d7a79b0 | ||
|
|
c0cd9064d7 | ||
|
|
14b773c1fd |
@@ -136,9 +136,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
) {
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = createInlineMethodNode(
|
||||
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
|
||||
)
|
||||
nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
|
||||
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
|
||||
} catch (e: CompilationException) {
|
||||
throw e
|
||||
@@ -274,6 +272,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
|
||||
|
||||
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
@@ -512,38 +512,33 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun createInlineMethodNode(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
methodOwner: Type,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext,
|
||||
state: GenerationState,
|
||||
sourceCompilerForInline: SourceCompilerForInline
|
||||
): SMAPAndMethodNode {
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
|
||||
if (intrinsic != null) {
|
||||
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
|
||||
}
|
||||
|
||||
val asmMethod = if (callDefault)
|
||||
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||
else
|
||||
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DescriptorWithContainerSource) {
|
||||
val node = sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
return node
|
||||
}
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
|
||||
internal fun createInlineMethodNode(
|
||||
callDefault: Boolean,
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext
|
||||
): SMAPAndMethodNode {
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
|
||||
if (intrinsic != null) {
|
||||
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
|
||||
}
|
||||
|
||||
val asmMethod = if (callDefault)
|
||||
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
|
||||
else
|
||||
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
|
||||
val node = sourceCompiler.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
return node
|
||||
}
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
assert(directMember is DescriptorWithContainerSource) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -16,7 +15,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class InlineCodegenForDefaultBody(
|
||||
@@ -41,8 +39,10 @@ class InlineCodegenForDefaultBody(
|
||||
}
|
||||
|
||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
||||
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
|
||||
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
|
||||
val nodeAndSmap = PsiInlineCodegen(
|
||||
codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
|
||||
).createInlineMethodNode(
|
||||
callDefault, null, codegen.typeSystem
|
||||
)
|
||||
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpres
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -208,4 +210,7 @@ class PsiInlineCodegen(
|
||||
::PsiDefaultLambda
|
||||
)
|
||||
}
|
||||
|
||||
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
|
||||
memberDescriptor is DescriptorWithContainerSource
|
||||
}
|
||||
|
||||
@@ -130,7 +130,9 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
|
||||
node.instructions.insert(position, newInsn)
|
||||
}
|
||||
|
||||
node.localVariables.removeIf { it.start in toDelete && it.end in toDelete }
|
||||
node.localVariables.removeIf {
|
||||
(it.start in toDelete && it.end in toDelete) || defaultLambdas.contains(it.index)
|
||||
}
|
||||
|
||||
node.remove(toDelete)
|
||||
|
||||
|
||||
44
compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt
vendored
Normal file
44
compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
interface CommonBackendContext
|
||||
|
||||
interface PhaserState<Data> {
|
||||
var depth: Int
|
||||
}
|
||||
|
||||
interface PhaseConfig {
|
||||
val needProfiling: Boolean
|
||||
}
|
||||
|
||||
inline fun <R, D> PhaserState<D>.downlevel(nlevels: Int, block: () -> R): R {
|
||||
depth += nlevels
|
||||
val result = block()
|
||||
depth -= nlevels
|
||||
return result
|
||||
}
|
||||
|
||||
interface CompilerPhase<in Context : CommonBackendContext, Input, Output> {
|
||||
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output
|
||||
}
|
||||
|
||||
class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
|
||||
private val lower: CompilerPhase<Context, Data, Data>
|
||||
) : CompilerPhase<Context, Data, Data> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data): Data {
|
||||
// Expected: output: Data, Actual: output: Data?
|
||||
val output = if (phaseConfig.needProfiling) {
|
||||
runAndProfile(phaseConfig, phaserState, context, input)
|
||||
} else {
|
||||
phaserState.downlevel(1) {
|
||||
lower.invoke(phaseConfig, phaserState, context, input)
|
||||
}
|
||||
}
|
||||
runAfter(phaseConfig, phaserState, context, output)
|
||||
}
|
||||
|
||||
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, output: Data) {
|
||||
|
||||
}
|
||||
|
||||
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, source: Data): Data {
|
||||
|
||||
}
|
||||
}
|
||||
55
compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.txt
vendored
Normal file
55
compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.txt
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
FILE: compilerPhase.kt
|
||||
public abstract interface CommonBackendContext : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface PhaserState<Data> : R|kotlin/Any| {
|
||||
public abstract var depth: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface PhaseConfig : R|kotlin/Any| {
|
||||
public abstract val needProfiling: R|kotlin/Boolean|
|
||||
public get(): R|kotlin/Boolean|
|
||||
|
||||
}
|
||||
public final inline fun <R, D> R|PhaserState<D>|.downlevel(nlevels: R|kotlin/Int|, block: R|() -> R|): R|R| {
|
||||
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.plus|(R|<local>/nlevels|)
|
||||
lval result: R|R| = R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()
|
||||
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.minus|(R|<local>/nlevels|)
|
||||
^downlevel R|<local>/result|
|
||||
}
|
||||
public abstract interface CompilerPhase<in Context : R|CommonBackendContext|, Input, Output> : R|kotlin/Any| {
|
||||
public abstract fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Input>|, context: R|Context|, input: R|Input|): R|Output|
|
||||
|
||||
}
|
||||
public final class NamedCompilerPhase<in Context : R|CommonBackendContext|, Data> : R|CompilerPhase<Context, Data, Data>| {
|
||||
public constructor<in Context : R|CommonBackendContext|, Data>(lower: R|CompilerPhase<Context, Data, Data>|): R|NamedCompilerPhase<Context, Data>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
private final val lower: R|CompilerPhase<Context, Data, Data>| = R|<local>/lower|
|
||||
private get(): R|CompilerPhase<Context, Data, Data>|
|
||||
|
||||
public final override fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, input: R|Data|): R|Data| {
|
||||
lval output: R|Data| = when () {
|
||||
R|<local>/phaseConfig|.R|/PhaseConfig.needProfiling| -> {
|
||||
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAndProfile|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
|
||||
}
|
||||
else -> {
|
||||
R|<local>/phaserState|.R|/downlevel|<R|Data|, R|Data|>(Int(1), <L> = downlevel@fun <anonymous>(): R|Data| <kind=UNKNOWN> {
|
||||
^ this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.lower|.R|SubstitutionOverride</CompilerPhase.invoke: R|Data|>|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAfter|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/output|)
|
||||
}
|
||||
|
||||
private final fun runAfter(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, output: R|Data|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
private final fun runAndProfile(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, source: R|Data|): R|Data| {
|
||||
}
|
||||
|
||||
}
|
||||
20
compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt
vendored
Normal file
20
compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// FILE: AliasFor.java
|
||||
|
||||
public @interface AliasFor {
|
||||
@AliasFor(value = "attribute")
|
||||
String value() default "";
|
||||
|
||||
@AliasFor(value = "value")
|
||||
String attribute() default "";
|
||||
}
|
||||
|
||||
// FILE: Service.java
|
||||
public @interface Service {
|
||||
@AliasFor(value = "component")
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
// FILE: Annotated.kt
|
||||
|
||||
@Service(value = "Your")
|
||||
class My
|
||||
7
compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.txt
vendored
Normal file
7
compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
FILE: Annotated.kt
|
||||
@R|Service|(value = String(Your)) public final class My : R|kotlin/Any| {
|
||||
public constructor(): R|My| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2024,6 +2024,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compilerPhase.kt")
|
||||
public void testCompilerPhase() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
|
||||
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
|
||||
@@ -2079,6 +2084,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveNamedAnnotation.kt")
|
||||
public void testRecursiveNamedAnnotation() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallInvoke.kt")
|
||||
public void testSafeCallInvoke() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");
|
||||
|
||||
@@ -2024,6 +2024,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compilerPhase.kt")
|
||||
public void testCompilerPhase() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
|
||||
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
|
||||
@@ -2079,6 +2084,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveNamedAnnotation.kt")
|
||||
public void testRecursiveNamedAnnotation() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallInvoke.kt")
|
||||
public void testSafeCallInvoke() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");
|
||||
|
||||
@@ -10659,6 +10659,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedFlexibleIntersectionTypesWithDifferentBounds.kt")
|
||||
public void testCapturedFlexibleIntersectionTypesWithDifferentBounds() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentBounds.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedFlexibleIntersectionTypesWithDifferentConstructors.kt")
|
||||
public void testCapturedFlexibleIntersectionTypesWithDifferentConstructors() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedType.kt")
|
||||
public void testCapturedType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt");
|
||||
@@ -12907,6 +12917,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassInsideInlineClass.kt")
|
||||
public void testInnerClassInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lateinitInlineClasses.kt")
|
||||
public void testLateinitInlineClasses() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/lateinitInlineClasses.kt");
|
||||
|
||||
@@ -2024,6 +2024,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compilerPhase.kt")
|
||||
public void testCompilerPhase() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
|
||||
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
|
||||
@@ -2079,6 +2084,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveNamedAnnotation.kt")
|
||||
public void testRecursiveNamedAnnotation() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallInvoke.kt")
|
||||
public void testSafeCallInvoke() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis
|
||||
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
|
||||
fun FirSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1): FirSourceElement? {
|
||||
return getChild(setOf(type), index, depth)
|
||||
}
|
||||
|
||||
fun FirSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1): FirSourceElement? {
|
||||
return getChild(types.types.toSet(), index, depth)
|
||||
}
|
||||
|
||||
fun FirSourceElement.getChild(types: Set<IElementType>, index: Int = 0, depth: Int = -1): FirSourceElement? {
|
||||
return when (this) {
|
||||
is FirPsiSourceElement<*> -> {
|
||||
getChild(types, index, depth)
|
||||
}
|
||||
is FirLightSourceElement -> {
|
||||
getChild(types, index, depth)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirPsiSourceElement<*>.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
|
||||
val visitor = PsiElementFinderByType(types, index, depth)
|
||||
return visitor.find(psi)?.toFirPsiSourceElement()
|
||||
}
|
||||
|
||||
private fun FirLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
|
||||
val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth)
|
||||
|
||||
return visitor.find(lighterASTNode)?.toFirLightSourceElement(treeStructure)
|
||||
}
|
||||
@@ -12,6 +12,9 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
@@ -250,20 +253,21 @@ fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality {
|
||||
}
|
||||
|
||||
val klass = context.findClosestClassOrObject() ?: return Modality.FINAL
|
||||
val modifiers = this.modifierListOrNull() ?: return Modality.FINAL
|
||||
if (modifiers.contains(KtTokens.OVERRIDE_KEYWORD)) {
|
||||
val klassModifiers = klass.modifierListOrNull()
|
||||
if (klassModifiers != null && klassModifiers.run {
|
||||
contains(KtTokens.ABSTRACT_KEYWORD) || contains(KtTokens.OPEN_KEYWORD) || contains(KtTokens.SEALED_KEYWORD)
|
||||
}) {
|
||||
val source = source ?: return Modality.FINAL
|
||||
val tree = source.treeStructure
|
||||
if (tree.overrideModifier(source.lighterASTNode) != null) {
|
||||
val klassModalityTokenType = klass.source?.let { tree.modalityModifier(it.lighterASTNode)?.tokenType }
|
||||
if (klassModalityTokenType == KtTokens.ABSTRACT_KEYWORD ||
|
||||
klassModalityTokenType == KtTokens.OPEN_KEYWORD ||
|
||||
klassModalityTokenType == KtTokens.SEALED_KEYWORD
|
||||
) {
|
||||
return Modality.OPEN
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
klass is FirRegularClass
|
||||
if (klass is FirRegularClass
|
||||
&& klass.classKind == ClassKind.INTERFACE
|
||||
&& !modifiers.contains(KtTokens.PRIVATE_KEYWORD)
|
||||
&& tree.visibilityModifier(source.lighterASTNode)?.tokenType != KtTokens.PRIVATE_KEYWORD
|
||||
) {
|
||||
return if (this.hasBody()) Modality.OPEN else Modality.ABSTRACT
|
||||
}
|
||||
@@ -271,8 +275,6 @@ fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality {
|
||||
return Modality.FINAL
|
||||
}
|
||||
|
||||
private fun FirDeclaration.modifierListOrNull() = this.source.getModifierList()?.modifiers?.map { it.token }
|
||||
|
||||
private fun FirDeclaration.hasBody(): Boolean = when (this) {
|
||||
is FirSimpleFunction -> this.body != null && this.body !is FirEmptyExpressionBlock
|
||||
is FirProperty -> this.setter?.body !is FirEmptyExpressionBlock? || this.getter?.body !is FirEmptyExpressionBlock?
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
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.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtModifierList
|
||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||
|
||||
sealed class FirModifierList {
|
||||
abstract val modifiers: List<FirModifier<*>>
|
||||
}
|
||||
|
||||
fun FirSourceElement?.getModifierList(): FirModifierList? {
|
||||
return when (this) {
|
||||
null -> null
|
||||
is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) }
|
||||
is FirLightSourceElement -> {
|
||||
val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST }
|
||||
?: return null
|
||||
FirLightModifierList(modifierListNode, treeStructure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val MODIFIER_KEYWORD_SET = TokenSet.orSet(KtTokens.SOFT_KEYWORDS, TokenSet.create(KtTokens.IN_KEYWORD, KtTokens.FUN_KEYWORD))
|
||||
|
||||
class FirPsiModifierList(val modifierList: KtModifierList) : FirModifierList() {
|
||||
override val modifiers: List<FirPsiModifier>
|
||||
get() = modifierList.node.getChildren(MODIFIER_KEYWORD_SET).map { node ->
|
||||
FirPsiModifier(node, node.elementType as KtModifierKeywordToken)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FirLightModifierList(val modifierList: LighterASTNode, val tree: FlyweightCapableTreeStructure<LighterASTNode>) : FirModifierList() {
|
||||
override val modifiers: List<FirLightModifier>
|
||||
get() {
|
||||
val modifierNodes = modifierList.getChildren(tree)
|
||||
return modifierNodes.filterNotNull()
|
||||
.filter { it.tokenType is KtModifierKeywordToken }
|
||||
.map { FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class FirModifier<Node : Any>(val node: Node, val token: KtModifierKeywordToken)
|
||||
|
||||
class FirPsiModifier(
|
||||
node: ASTNode,
|
||||
token: KtModifierKeywordToken
|
||||
) : FirModifier<ASTNode>(node, token)
|
||||
|
||||
class FirLightModifier(
|
||||
node: LighterASTNode,
|
||||
token: KtModifierKeywordToken,
|
||||
val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
) : FirModifier<LighterASTNode>(node, token)
|
||||
|
||||
val FirModifier<*>.psi: PsiElement? get() = (this as? FirPsiModifier)?.node?.psi
|
||||
|
||||
val FirModifier<*>.lightNode: LighterASTNode? get() = (this as? FirLightModifier)?.node
|
||||
|
||||
val FirModifier<*>.source: FirSourceElement?
|
||||
get() = when (this) {
|
||||
is FirPsiModifier -> psi?.toFirPsiSourceElement()
|
||||
is FirLightModifier -> node.toFirLightSourceElement(tree)
|
||||
}
|
||||
@@ -5,19 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
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.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.source
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.psi.KtModifierList
|
||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||
|
||||
object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
|
||||
@@ -112,7 +115,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
val firstToken = firstModifier.token
|
||||
val secondToken = secondModifier.token
|
||||
when (val compatibilityType = deduceCompatibilityType(firstToken, secondToken)) {
|
||||
CompatibilityType.COMPATIBLE -> {}
|
||||
CompatibilityType.COMPATIBLE -> {
|
||||
}
|
||||
CompatibilityType.REPEATED ->
|
||||
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken)
|
||||
CompatibilityType.REDUNDANT_2_TO_1 ->
|
||||
@@ -170,35 +174,94 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
if (!isDeclarationMappedToSourceCorrectly(declaration, source)) return
|
||||
if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return
|
||||
|
||||
val modifierList = source.getModifierList()
|
||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||
modifierList?.let { checkModifiers(it, declaration, reporter) }
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportRepeatedModifier(
|
||||
modifier: FirModifier<*>, keyword: KtModifierKeywordToken
|
||||
) {
|
||||
val source = modifier.source
|
||||
source?.let { report(FirErrors.REPEATED_MODIFIER.on(it, keyword)) }
|
||||
report(FirErrors.REPEATED_MODIFIER.on(modifier.source, keyword))
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportRedundantModifier(
|
||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
||||
) {
|
||||
val source = modifier.source
|
||||
source?.let { report(FirErrors.REDUNDANT_MODIFIER.on(it, firstKeyword, secondKeyword)) }
|
||||
report(FirErrors.REDUNDANT_MODIFIER.on(modifier.source, firstKeyword, secondKeyword))
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportDeprecatedModifierPair(
|
||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
||||
) {
|
||||
val source = modifier.source
|
||||
source?.let { report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(it, firstKeyword, secondKeyword)) }
|
||||
report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(modifier.source, firstKeyword, secondKeyword))
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportIncompatibleModifiers(
|
||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
||||
) {
|
||||
val source = modifier.source
|
||||
source?.let { report(FirErrors.INCOMPATIBLE_MODIFIERS.on(it, firstKeyword, secondKeyword)) }
|
||||
report(FirErrors.INCOMPATIBLE_MODIFIERS.on(modifier.source, firstKeyword, secondKeyword))
|
||||
}
|
||||
|
||||
private sealed class FirModifierList {
|
||||
abstract val modifiers: List<FirModifier<*>>
|
||||
|
||||
class FirPsiModifierList(val modifierList: KtModifierList) : FirModifierList() {
|
||||
override val modifiers: List<FirModifier.FirPsiModifier>
|
||||
get() = modifierList.node.getChildren(MODIFIER_KEYWORD_SET).map { node ->
|
||||
FirModifier.FirPsiModifier(node, node.elementType as KtModifierKeywordToken)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FirLightModifierList(
|
||||
val modifierList: LighterASTNode,
|
||||
val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
) : FirModifierList() {
|
||||
override val modifiers: List<FirModifier.FirLightModifier>
|
||||
get() {
|
||||
val modifierNodes = modifierList.getChildren(tree)
|
||||
return modifierNodes.filterNotNull()
|
||||
.filter { it.tokenType is KtModifierKeywordToken }
|
||||
.map { FirModifier.FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun FirSourceElement?.getModifierList(): FirModifierList? {
|
||||
return when (this) {
|
||||
null -> null
|
||||
is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) }
|
||||
is FirLightSourceElement -> {
|
||||
val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST }
|
||||
?: return null
|
||||
FirLightModifierList(modifierListNode, treeStructure)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val MODIFIER_KEYWORD_SET = TokenSet.orSet(SOFT_KEYWORDS, TokenSet.create(IN_KEYWORD, FUN_KEYWORD))
|
||||
|
||||
sealed class FirModifier<Node : Any>(val node: Node, val token: KtModifierKeywordToken) {
|
||||
|
||||
class FirPsiModifier(
|
||||
node: ASTNode,
|
||||
token: KtModifierKeywordToken
|
||||
) : FirModifier<ASTNode>(node, token) {
|
||||
override val source: FirSourceElement
|
||||
get() = node.psi.toFirPsiSourceElement()
|
||||
}
|
||||
|
||||
class FirLightModifier(
|
||||
node: LighterASTNode,
|
||||
token: KtModifierKeywordToken,
|
||||
val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
) : FirModifier<LighterASTNode>(node, token) {
|
||||
override val source: FirSourceElement
|
||||
get() = node.toFirLightSourceElement(tree)
|
||||
}
|
||||
|
||||
abstract val source: FirSourceElement
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,22 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes.TYPE_ARGUMENT_LIST
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.psi.KtTypeArgumentList
|
||||
|
||||
object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -29,36 +19,13 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker()
|
||||
val explicitReceiver = expression.explicitReceiver
|
||||
|
||||
if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) {
|
||||
if (explicitReceiver.source?.hasAnyArguments() == true) {
|
||||
if (explicitReceiver.typeArguments.isNotEmpty()) {
|
||||
reporter.report(explicitReceiver.source)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirSourceElement.hasAnyArguments(): Boolean {
|
||||
val localPsi = this.psi
|
||||
val localLight = this.lighterASTNode
|
||||
|
||||
if (localPsi != null && localPsi !is PsiErrorElement) {
|
||||
return localPsi.hasAnyArguments()
|
||||
} else if (this is FirLightSourceElement) {
|
||||
return localLight.hasAnyArguments(this.treeStructure)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun PsiElement.hasAnyArguments(): Boolean {
|
||||
val children = this.children // this is a method call and it collects children
|
||||
return children.size > 1 && children[1] is KtTypeArgumentList
|
||||
}
|
||||
|
||||
private fun LighterASTNode.hasAnyArguments(tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
|
||||
val children = getChildren(tree)
|
||||
return children.count { it != null } > 1 && children[1]?.tokenType == TYPE_ARGUMENT_LIST
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let {
|
||||
report(FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.on(it))
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirOperation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
@@ -17,7 +16,6 @@ import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -29,7 +27,6 @@ object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
|
||||
if (left.typeRef.coneType.classId != StandardClassIds.Array) return
|
||||
if (right.typeRef.coneType.classId != StandardClassIds.Array) return
|
||||
|
||||
val source = expression.source?.getChild(setOf(KtTokens.EQEQ, KtTokens.EXCLEQ))
|
||||
reporter.report(source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS)
|
||||
reporter.report(expression.source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecke
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
@@ -59,8 +58,7 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker<FirVari
|
||||
}
|
||||
|
||||
if (needToReport) {
|
||||
val source = expression.source?.getChild(setOf(KtTokens.EQ))
|
||||
reporter.report(source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
|
||||
reporter.report(expression.source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,11 +12,9 @@ import org.jetbrains.kotlin.fir.analysis.cfa.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
||||
override fun analyze(
|
||||
@@ -42,7 +40,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
||||
var lastDestructuredVariables = 0
|
||||
|
||||
for ((symbol, value) in propertiesCharacteristics) {
|
||||
val source = symbol.fir.source?.getChild(setOf(KtTokens.VAL_KEYWORD, KtTokens.VAR_KEYWORD), depth = 1)
|
||||
val source = symbol.fir.source
|
||||
if (symbol.isDestructuring) {
|
||||
lastDestructuringSource = source
|
||||
lastDestructuredVariables = symbol.getDestructuringChildrenCount() ?: continue
|
||||
@@ -97,15 +95,11 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirPropertySymbol.getDestructuringChildrenCount(): Int? = when (fir.source) {
|
||||
is FirPsiSourceElement<*> -> fir.psi?.children?.size?.minus(1) // -1 cuz we don't need expression node after equals operator
|
||||
is FirLightSourceElement -> {
|
||||
val source = fir.source as FirLightSourceElement
|
||||
val tree = (fir.source as FirLightSourceElement).treeStructure
|
||||
val children = source.lighterASTNode.getChildren(tree)
|
||||
children.filter { it?.tokenType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY }.size
|
||||
private fun FirPropertySymbol.getDestructuringChildrenCount(): Int? {
|
||||
val source = fir.source ?: return null
|
||||
return source.lighterASTNode.getChildren(source.treeStructure).count {
|
||||
it?.tokenType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
private val FirPropertySymbol.isDestructuring
|
||||
|
||||
@@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
@@ -17,14 +15,11 @@ import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -71,10 +66,10 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
is FirNamedReference -> {
|
||||
if (typeReference.text != initializer.name.identifier) return
|
||||
if (!type.hasSameNameWithoutModifiers(initializer.name)) return
|
||||
}
|
||||
is FirFunctionCall -> {
|
||||
if (typeReference.text != initializer.calleeReference.name.asString()) return
|
||||
if (!type.hasSameNameWithoutModifiers(initializer.calleeReference.name)) return
|
||||
}
|
||||
is FirGetClassCall -> {
|
||||
return
|
||||
@@ -91,23 +86,12 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
||||
reporter.report(declaration.returnTypeRef.source, FirErrors.REDUNDANT_EXPLICIT_TYPE)
|
||||
}
|
||||
|
||||
private val FirTypeRef.text: String?
|
||||
get() {
|
||||
return when (source) {
|
||||
is FirPsiSourceElement<*> -> {
|
||||
source.psi?.text
|
||||
}
|
||||
is FirLightSourceElement -> {
|
||||
source?.lighterASTNode?.toString()
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isSame(other: ClassId?): Boolean {
|
||||
if (this.nullability.isNullable) return false
|
||||
if (this.type.classId == other) return true
|
||||
return false
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.hasSameNameWithoutModifiers(name: Name): Boolean =
|
||||
this is ConeClassLikeType && lookupTag.name == name && typeArguments.isEmpty() && !isMarkedNullable
|
||||
}
|
||||
@@ -11,17 +11,17 @@ 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.implicitModality
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toToken
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
|
||||
object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration.source?.kind is FirFakeSourceElementKind) return
|
||||
val source = declaration.source
|
||||
if (source?.kind is FirFakeSourceElementKind) return
|
||||
|
||||
val modality = declaration.modality ?: return
|
||||
if (
|
||||
@@ -29,11 +29,10 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
|
||||
&& (context.containingDeclarations.last() as? FirClass<*>)?.classKind == ClassKind.INTERFACE
|
||||
) return
|
||||
|
||||
if (source != null && source.treeStructure.modalityModifier(source.lighterASTNode) == null) return
|
||||
val implicitModality = declaration.implicitModality(context)
|
||||
|
||||
if (modality != implicitModality) return
|
||||
|
||||
val modalityModifierSource = declaration.source?.getChild(modality.toToken(), depth = 2)
|
||||
reporter.report(modalityModifierSource, REDUNDANT_MODALITY_MODIFIER)
|
||||
reporter.report(source, REDUNDANT_MODALITY_MODIFIER)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,34 +16,31 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirConstructor && declaration.source?.kind is FirFakeSourceElementKind) return
|
||||
if (declaration.source is FirFakeSourceElement<*>) return
|
||||
val source = declaration.source ?: return
|
||||
if (declaration is FirConstructor && source.kind is FirFakeSourceElementKind) return
|
||||
if (source is FirFakeSourceElement<*>) return
|
||||
if (
|
||||
declaration !is FirMemberDeclaration
|
||||
&& !(declaration is FirPropertyAccessor && declaration.visibility == context.containingPropertyVisibility)
|
||||
) return
|
||||
|
||||
val modifiers = declaration.source.getModifierList()
|
||||
val visibilityModifier = when (modifiers) {
|
||||
is FirPsiModifierList -> modifiers.modifierList.getVisibility()
|
||||
is FirLightModifierList -> modifiers.modifiers.visibilityOrNull()
|
||||
else -> null
|
||||
} ?: return
|
||||
val visibilityModifier = source.treeStructure.visibilityModifier(source.lighterASTNode)
|
||||
val explicitVisibility = (visibilityModifier?.tokenType as? KtModifierKeywordToken)?.toVisibilityOrNull()
|
||||
val implicitVisibility = declaration.implicitVisibility(context)
|
||||
val containingMemberDeclaration = context.findClosest<FirMemberDeclaration>()
|
||||
|
||||
val redundantVisibility = when {
|
||||
visibilityModifier == implicitVisibility -> implicitVisibility
|
||||
modifiers?.modifiers.hasModifier(KtTokens.INTERNAL_KEYWORD) &&
|
||||
explicitVisibility == implicitVisibility -> implicitVisibility
|
||||
explicitVisibility == Visibilities.Internal &&
|
||||
containingMemberDeclaration.let { decl ->
|
||||
decl != null && (decl.isLocalMember || modifiers?.modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD))
|
||||
decl != null && decl.isLocalMember
|
||||
} -> Visibilities.Internal
|
||||
else -> return
|
||||
}
|
||||
@@ -51,12 +48,12 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
|
||||
if (
|
||||
redundantVisibility == Visibilities.Public
|
||||
&& declaration is FirProperty
|
||||
&& modifiers?.modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||
&& source.treeStructure.overrideModifier(source.lighterASTNode) != null
|
||||
&& declaration.isVar
|
||||
&& declaration.setter?.visibility == Visibilities.Public
|
||||
) return
|
||||
|
||||
reporter.report(declaration.source?.getChild(KtTokens.VISIBILITY_MODIFIERS), FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
|
||||
reporter.report(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
|
||||
}
|
||||
|
||||
private fun FirDeclaration.implicitVisibility(context: CheckerContext): Visibility {
|
||||
@@ -126,10 +123,4 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
|
||||
|
||||
private val CheckerContext.containingPropertyVisibility
|
||||
get() = (this.containingDeclarations.last() as? FirProperty)?.visibility
|
||||
|
||||
private fun List<FirLightModifier>.visibilityOrNull() =
|
||||
firstOrNull { it.token.toVisibilityOrNull() != null }?.token?.toVisibilityOrNull()
|
||||
|
||||
private fun List<FirModifier<*>>?.hasModifier(token: KtModifierKeywordToken) = this != null && any { it.token == token }
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
@@ -17,16 +17,17 @@ import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isIterator
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object UnusedChecker : FirControlFlowChecker() {
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
|
||||
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf { !it.symbol.classId.isLocal }!= null) return
|
||||
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf {
|
||||
!it.symbol.classId.isLocal
|
||||
} != null
|
||||
) return
|
||||
val properties = LocalPropertyCollector.collect(graph)
|
||||
if (properties.isEmpty()) return
|
||||
|
||||
@@ -55,11 +56,11 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
if (variableSymbol.isLoopIterator) return
|
||||
val data = data[node]?.get(variableSymbol) ?: return
|
||||
|
||||
val variableSource = variableSymbol.fir.source.takeIf { it?.elementType != KtNodeTypes.DESTRUCTURING_DECLARATION }
|
||||
when {
|
||||
data == VariableStatus.UNUSED -> {
|
||||
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
|
||||
val source = variableSymbol.identifierSource
|
||||
reporter.report(source, FirErrors.UNUSED_VARIABLE)
|
||||
reporter.report(variableSource, FirErrors.UNUSED_VARIABLE)
|
||||
}
|
||||
}
|
||||
data.isRedundantInit -> {
|
||||
@@ -67,8 +68,7 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
reporter.report(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT)
|
||||
}
|
||||
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
|
||||
val source = variableSymbol.identifierSource
|
||||
reporter.report(source, FirErrors.VARIABLE_NEVER_READ)
|
||||
reporter.report(variableSource, FirErrors.VARIABLE_NEVER_READ)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
@@ -203,7 +203,4 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
|
||||
private val FirPropertySymbol.isLoopIterator
|
||||
get() = fir.initializer?.source?.kind == FirFakeSourceElementKind.DesugaredForLoop
|
||||
|
||||
private val FirPropertySymbol.identifierSource: FirSourceElement?
|
||||
get() = fir.source?.getChild(KtTokens.IDENTIFIER, 0, 1)
|
||||
}
|
||||
|
||||
@@ -154,20 +154,20 @@ object FirErrors {
|
||||
val WRONG_IMPLIES_CONDITION by error0<FirSourceElement, PsiElement>()
|
||||
|
||||
// Extended checkers group
|
||||
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, PsiElement>()
|
||||
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, PsiElement>()
|
||||
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
|
||||
val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>()
|
||||
val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>()
|
||||
val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>()
|
||||
val CAN_BE_VAL by warning0<FirSourceElement, PsiElement>()
|
||||
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, PsiElement>()
|
||||
val CAN_BE_VAL by warning0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning0<FirSourceElement, PsiElement>()
|
||||
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, PsiElement>()
|
||||
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val EMPTY_RANGE by warning0<FirSourceElement, PsiElement>()
|
||||
val REDUNDANT_SETTER_PARAMETER_TYPE by warning0<FirSourceElement, PsiElement>()
|
||||
val UNUSED_VARIABLE by warning0<FirSourceElement, PsiElement>()
|
||||
val UNUSED_VARIABLE by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val ASSIGNED_VALUE_IS_NEVER_READ by warning0<FirSourceElement, PsiElement>()
|
||||
val VARIABLE_INITIALIZER_IS_REDUNDANT by warning0<FirSourceElement, PsiElement>()
|
||||
val VARIABLE_NEVER_READ by warning0<FirSourceElement, PsiElement>()
|
||||
val VARIABLE_NEVER_READ by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val USELESS_CALL_ON_NOT_NULL by warning0<FirSourceElement, PsiElement>()
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
|
||||
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
||||
|
||||
object LightTreePositioningStrategies {
|
||||
@@ -142,6 +144,32 @@ object LightTreePositioningStrategies {
|
||||
return super.mark(node, tree)
|
||||
}
|
||||
}
|
||||
|
||||
private class ModifierSetBasedLightTreePositioningStrategy(private val modifierSet: TokenSet) : LightTreePositioningStrategy() {
|
||||
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
|
||||
tree.findChildByType(node, modifierSet)?.let { return markElement(it, tree) }
|
||||
tree.nameIdentifier(node)?.let { return markElement(it, tree) }
|
||||
return when (node.tokenType) {
|
||||
KtNodeTypes.OBJECT_DECLARATION -> {
|
||||
markElement(tree.objectKeyword(node)!!, tree)
|
||||
}
|
||||
KtNodeTypes.PROPERTY_ACCESSOR -> {
|
||||
markElement(tree.accessorNamePlaceholder(node), tree)
|
||||
}
|
||||
else -> markElement(node, tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val VISIBILITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(VISIBILITY_MODIFIERS)
|
||||
|
||||
val MODALITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(MODALITY_MODIFIERS)
|
||||
|
||||
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
|
||||
return markElement(tree.operationReference(node) ?: node, tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||
@@ -162,6 +190,9 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: Ligh
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.nameIdentifier(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.IDENTIFIER)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.operationReference(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtNodeTypes.OPERATION_REFERENCE)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.RPAR)
|
||||
|
||||
@@ -171,6 +202,15 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.objectKeyword(node: Li
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.valOrVarKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, VAL_VAR_TOKEN_SET)
|
||||
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.visibilityModifier(declaration: LighterASTNode): LighterASTNode? =
|
||||
modifierList(declaration)?.let { findChildByType(it, VISIBILITY_MODIFIERS) }
|
||||
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.modalityModifier(declaration: LighterASTNode): LighterASTNode? =
|
||||
modifierList(declaration)?.let { findChildByType(it, MODALITY_MODIFIERS) }
|
||||
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.overrideModifier(declaration: LighterASTNode): LighterASTNode? =
|
||||
modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) }
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode =
|
||||
findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!!
|
||||
|
||||
|
||||
@@ -32,4 +32,19 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.DECLARATION_SIGNATURE,
|
||||
PositioningStrategies.DECLARATION_SIGNATURE
|
||||
)
|
||||
|
||||
val VISIBILITY_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.VISIBILITY_MODIFIER,
|
||||
PositioningStrategies.VISIBILITY_MODIFIER
|
||||
)
|
||||
|
||||
val MODALITY_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.MODALITY_MODIFIER,
|
||||
PositioningStrategies.MODALITY_MODIFIER
|
||||
)
|
||||
|
||||
val OPERATOR = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.OPERATOR,
|
||||
PositioningStrategies.OPERATOR
|
||||
)
|
||||
}
|
||||
@@ -14,14 +14,14 @@ import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.*
|
||||
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.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
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.ir.util.*
|
||||
@@ -86,8 +86,17 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext<JvmSignatur
|
||||
typeContext.hasNothingInNonContravariantPosition(type)
|
||||
}
|
||||
|
||||
private fun FirClassLikeSymbol<*>.toRegularClassSymbol(): FirRegularClassSymbol? = when (this) {
|
||||
is FirRegularClassSymbol -> this
|
||||
is FirTypeAliasSymbol -> {
|
||||
val expandedType = fir.expandedTypeRef.coneType.fullyExpandedType(session) as? ConeClassLikeType
|
||||
expandedType?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun ConeClassLikeType.buildPossiblyInnerType(): PossiblyInnerConeType? =
|
||||
buildPossiblyInnerType(lookupTag.toSymbol(session) as? FirRegularClassSymbol?, 0)
|
||||
buildPossiblyInnerType(lookupTag.toSymbol(session)?.toRegularClassSymbol(), 0)
|
||||
|
||||
private fun ConeClassLikeType.parentClassOrNull(): FirRegularClassSymbol? {
|
||||
val parentClassId = classId?.outerClassId ?: return null
|
||||
|
||||
@@ -404,9 +404,7 @@ class Fir2IrDeclarationStorage(
|
||||
factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction
|
||||
): IrSimpleFunction {
|
||||
if (signature == null) {
|
||||
val descriptor =
|
||||
if (containerSource != null) WrappedFunctionDescriptorWithContainerSource()
|
||||
else WrappedSimpleFunctionDescriptor()
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
return symbolTable.declareSimpleFunction(descriptor, factory).apply { descriptor.bind(this) }
|
||||
}
|
||||
return symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature, containerSource) }, factory)
|
||||
@@ -687,9 +685,7 @@ class Fir2IrDeclarationStorage(
|
||||
factory: (IrPropertySymbol) -> IrProperty
|
||||
): IrProperty {
|
||||
if (signature == null) {
|
||||
val descriptor =
|
||||
if (containerSource != null) WrappedPropertyDescriptorWithContainerSource()
|
||||
else WrappedPropertyDescriptor()
|
||||
val descriptor = WrappedPropertyDescriptor()
|
||||
return symbolTable.declareProperty(0, 0, IrDeclarationOrigin.DEFINED, descriptor, isDelegated = false, factory).apply {
|
||||
descriptor.bind(this)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
package org.jetbrains.kotlin.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
@@ -42,8 +40,6 @@ abstract class Fir2IrBindableSymbol<out D : DeclarationDescriptor, B : IrSymbolO
|
||||
is IrClass -> WrappedClassDescriptor().apply { bind(owner) }
|
||||
is IrConstructor -> WrappedClassConstructorDescriptor().apply { bind(owner) }
|
||||
is IrSimpleFunction -> when {
|
||||
containerSource != null ->
|
||||
WrappedFunctionDescriptorWithContainerSource()
|
||||
owner.name.isSpecial && owner.name.asString().startsWith(GETTER_PREFIX) ->
|
||||
WrappedPropertyGetterDescriptor()
|
||||
owner.name.isSpecial && owner.name.asString().startsWith(SETTER_PREFIX) ->
|
||||
@@ -54,11 +50,7 @@ abstract class Fir2IrBindableSymbol<out D : DeclarationDescriptor, B : IrSymbolO
|
||||
is IrVariable -> WrappedVariableDescriptor().apply { bind(owner) }
|
||||
is IrValueParameter -> WrappedValueParameterDescriptor().apply { bind(owner) }
|
||||
is IrTypeParameter -> WrappedTypeParameterDescriptor().apply { bind(owner) }
|
||||
is IrProperty -> if (containerSource != null) {
|
||||
WrappedPropertyDescriptorWithContainerSource()
|
||||
} else {
|
||||
WrappedPropertyDescriptor()
|
||||
}.apply { bind(owner) }
|
||||
is IrProperty -> WrappedPropertyDescriptor().apply { bind(owner) }
|
||||
is IrField -> WrappedFieldDescriptor().apply { bind(owner) }
|
||||
is IrTypeAlias -> WrappedTypeAliasDescriptor().apply { bind(owner) }
|
||||
else -> throw IllegalStateException("Unsupported owner in Fir2IrBindableSymbol: $owner")
|
||||
|
||||
@@ -148,6 +148,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importCompanion.kt")
|
||||
public void testImportCompanion() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/importCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFromBinaryDependencies.kt")
|
||||
public void testInlineClassFromBinaryDependencies() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
|
||||
|
||||
@@ -3840,6 +3840,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/classes/exceptionConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionFunWithDefaultParam.kt")
|
||||
public void testExtensionFunWithDefaultParam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classes/extensionFunWithDefaultParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionOnNamedClassObject.kt")
|
||||
public void testExtensionOnNamedClassObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classes/extensionOnNamedClassObject.kt");
|
||||
@@ -9838,6 +9843,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/function/covariantOverrideGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultLambdaInline.kt")
|
||||
public void testDefaultLambdaInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/function/defaultLambdaInline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionFunctionManyArgs.kt")
|
||||
public void testExtensionFunctionManyArgs() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/function/extensionFunctionManyArgs.kt");
|
||||
@@ -14147,6 +14157,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/multifileClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedInlineClass.kt")
|
||||
public void testNestedInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/nestedInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
|
||||
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
|
||||
@@ -15159,6 +15174,59 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Jvm8DefaultInterfaceMethods extends AbstractFirBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJvm8DefaultInterfaceMethods() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaDefaultMethodOverriddenByKotlin.kt")
|
||||
public void testJavaDefaultMethodOverriddenByKotlin() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/javaDefaultMethodOverriddenByKotlin.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultAll.kt")
|
||||
public void testJvmDefaultAll() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultAll.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultAllPrimaryProperty.kt")
|
||||
public void testJvmDefaultAllPrimaryProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultAllPrimaryProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultAllProperty.kt")
|
||||
public void testJvmDefaultAllProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultAllProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultEnable.kt")
|
||||
public void testJvmDefaultEnable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultEnable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultEnablePrimaryProperty.kt")
|
||||
public void testJvmDefaultEnablePrimaryProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultEnablePrimaryProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmDefaultEnableProperty.kt")
|
||||
public void testJvmDefaultEnableProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/jvm8DefaultInterfaceMethods/jvmDefaultEnableProperty.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses/propertyDelegation")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -21468,6 +21536,31 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/properties/kt9603.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lazyInitialization.kt")
|
||||
public void testLazyInitialization() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/lazyInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lazyInitializationCyclicImports.kt")
|
||||
public void testLazyInitializationCyclicImports() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/lazyInitializationCyclicImports.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lazyInitializationMultiModule.kt")
|
||||
public void testLazyInitializationMultiModule() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/lazyInitializationMultiModule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lazyInitializationOrder.kt")
|
||||
public void testLazyInitializationOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/lazyInitializationOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lazyInitializationSplitPerModule.kt")
|
||||
public void testLazyInitializationSplitPerModule() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/lazyInitializationSplitPerModule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
|
||||
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");
|
||||
@@ -32041,6 +32134,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/equalsImplForInlineClassWrappingNullableInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("evaluateConstructorOfUnsignedArrayType.kt")
|
||||
public void testEvaluateConstructorOfUnsignedArrayType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("evaluateConstructorOfUnsignedType.kt")
|
||||
public void testEvaluateConstructorOfUnsignedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt");
|
||||
@@ -32220,6 +32318,77 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testWhenByUnsigned() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Jvm8Intrinsics extends AbstractFirBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntCompare_jvm8.kt")
|
||||
public void testUnsignedIntCompare_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntCompare_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntDivide_jvm8.kt")
|
||||
public void testUnsignedIntDivide_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntDivide_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntRemainder_jvm8.kt")
|
||||
public void testUnsignedIntRemainder_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntRemainder_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntToString_jvm8.kt")
|
||||
public void testUnsignedIntToString_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntToString_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLongCompare_jvm8.kt")
|
||||
public void testUnsignedLongCompare_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongCompare_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLongDivide_jvm8.kt")
|
||||
public void testUnsignedLongDivide_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongDivide_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLongRemainder_jvm8.kt")
|
||||
public void testUnsignedLongRemainder_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongRemainder_jvm8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLongToString_jvm8.kt")
|
||||
public void testUnsignedLongToString_jvm8() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongToString_jvm8.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/valueClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ValueClasses extends AbstractFirBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInValueClasses() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmInline.kt")
|
||||
public void testJvmInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/jvmInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/vararg")
|
||||
|
||||
@@ -168,6 +168,7 @@ class JavaSymbolProvider(
|
||||
javaTypeParameterStack.addStack(parentStack)
|
||||
}
|
||||
}
|
||||
val methodMap = mutableMapOf<JavaMethod, FirJavaMethod>()
|
||||
val firJavaClass = buildJavaClass {
|
||||
source = (javaClass as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
||||
session = this@JavaSymbolProvider.session
|
||||
@@ -219,7 +220,9 @@ class JavaSymbolProvider(
|
||||
classIsAnnotation,
|
||||
valueParametersForAnnotationConstructor,
|
||||
dispatchReceiver
|
||||
)
|
||||
).apply {
|
||||
methodMap[javaMethod] = this
|
||||
}
|
||||
}
|
||||
val javaClassDeclaredConstructors = javaClass.constructors
|
||||
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
|
||||
@@ -270,6 +273,10 @@ class JavaSymbolProvider(
|
||||
}
|
||||
)
|
||||
firJavaClass.addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack)
|
||||
// NB: this is done here to unbind possible annotation cycle
|
||||
for ((javaMethod, firJavaMethod) in methodMap) {
|
||||
firJavaMethod.annotations.addAnnotationsFrom(session, javaMethod, javaTypeParameterStack)
|
||||
}
|
||||
return firJavaClass
|
||||
}
|
||||
|
||||
@@ -364,7 +371,6 @@ class JavaSymbolProvider(
|
||||
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack)
|
||||
isStatic = javaMethod.isStatic
|
||||
typeParameters += javaMethod.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
||||
addAnnotationsFrom(this@JavaSymbolProvider.session, javaMethod, javaTypeParameterStack)
|
||||
for ((index, valueParameter) in javaMethod.valueParameters.withIndex()) {
|
||||
valueParameters += valueParameter.toFirValueParameter(
|
||||
this@JavaSymbolProvider.session, index, javaTypeParameterStack,
|
||||
|
||||
@@ -485,7 +485,7 @@ internal fun FirJavaClass.addAnnotationsFrom(
|
||||
annotations.addAnnotationsFrom(session, javaAnnotationOwner, javaTypeParameterStack)
|
||||
}
|
||||
|
||||
private fun MutableList<FirAnnotationCall>.addAnnotationsFrom(
|
||||
internal fun MutableList<FirAnnotationCall>.addAnnotationsFrom(
|
||||
session: FirSession,
|
||||
javaAnnotationOwner: JavaAnnotationOwner,
|
||||
javaTypeParameterStack: JavaTypeParameterStack
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.load.kotlin.*
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
@@ -300,6 +301,12 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
return loadAnnotation(annotationClassId, result)
|
||||
}
|
||||
|
||||
private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? {
|
||||
val outerClassId = classId.outerClassId ?: return null
|
||||
findAndDeserializeClass(outerClassId) ?: return null
|
||||
return classCache[classId]
|
||||
}
|
||||
|
||||
private fun findAndDeserializeClass(
|
||||
classId: ClassId,
|
||||
parentContext: FirDeserializationContext? = null
|
||||
@@ -314,7 +321,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
} catch (e: ProcessCanceledException) {
|
||||
return null
|
||||
}
|
||||
val kotlinClassWithContent = when (result) {
|
||||
val (kotlinJvmBinaryClass, byteContent) = when (result) {
|
||||
is KotlinClassFinder.Result.KotlinClass -> result
|
||||
is KotlinClassFinder.Result.ClassFileContent -> {
|
||||
handledByJava.add(classId)
|
||||
@@ -324,45 +331,39 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
null
|
||||
}
|
||||
}
|
||||
null -> null
|
||||
null -> return findAndDeserializeClassViaParent(classId)
|
||||
}
|
||||
if (kotlinClassWithContent == null) {
|
||||
val outerClassId = classId.outerClassId ?: return null
|
||||
findAndDeserializeClass(outerClassId) ?: return null
|
||||
} else {
|
||||
val (kotlinJvmBinaryClass, byteContent) = kotlinClassWithContent
|
||||
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
|
||||
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null
|
||||
|
||||
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
|
||||
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null
|
||||
|
||||
val symbol = FirRegularClassSymbol(classId)
|
||||
deserializeClassToSymbol(
|
||||
classId, classProto, symbol, nameResolver, session,
|
||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||
kotlinScopeProvider,
|
||||
parentContext, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass),
|
||||
this::findAndDeserializeClass
|
||||
)
|
||||
|
||||
classCache[classId] = symbol
|
||||
val annotations = mutableListOf<FirAnnotationCall>()
|
||||
kotlinJvmBinaryClass.loadClassAnnotations(
|
||||
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return loadAnnotationIfNotSpecial(classId, annotations)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
byteContent,
|
||||
)
|
||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||
if (parentContext == null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||
return findAndDeserializeClassViaParent(classId)
|
||||
}
|
||||
|
||||
return classCache[classId]
|
||||
val symbol = FirRegularClassSymbol(classId)
|
||||
deserializeClassToSymbol(
|
||||
classId, classProto, symbol, nameResolver, session,
|
||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||
kotlinScopeProvider,
|
||||
parentContext, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass),
|
||||
this::findAndDeserializeClass
|
||||
)
|
||||
|
||||
classCache[classId] = symbol
|
||||
val annotations = mutableListOf<FirAnnotationCall>()
|
||||
kotlinJvmBinaryClass.loadClassAnnotations(
|
||||
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return loadAnnotationIfNotSpecial(classId, annotations)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
}
|
||||
},
|
||||
byteContent,
|
||||
)
|
||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||
return symbol
|
||||
}
|
||||
|
||||
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirCallableSymbol<*>> {
|
||||
|
||||
@@ -168,7 +168,7 @@ class FirCallResolver(
|
||||
fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidate(qualifiedAccess: T): FirStatement {
|
||||
val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess
|
||||
|
||||
qualifiedResolver.initProcessingQualifiedAccess(callee)
|
||||
qualifiedResolver.initProcessingQualifiedAccess(callee, qualifiedAccess.typeArguments)
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver<FirQualifiedAccess>()
|
||||
|
||||
@@ -16,14 +16,17 @@ import org.jetbrains.kotlin.fir.resolve.transformers.PackageOrClass
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass
|
||||
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirQualifiedNameResolver(private val components: BodyResolveComponents) {
|
||||
private val session = components.session
|
||||
private var qualifierStack = mutableListOf<Name>()
|
||||
private var qualifierStack = mutableListOf<NameWithTypeArguments>()
|
||||
private var qualifierPartsToDrop = 0
|
||||
|
||||
private class NameWithTypeArguments(val name: Name, val typeArguments: List<FirTypeProjection>)
|
||||
|
||||
fun reset() {
|
||||
qualifierStack.clear()
|
||||
qualifierPartsToDrop = 0
|
||||
@@ -41,11 +44,11 @@ class FirQualifiedNameResolver(private val components: BodyResolveComponents) {
|
||||
*/
|
||||
fun isPotentialQualifierPartPosition() = qualifierStack.size > 1
|
||||
|
||||
fun initProcessingQualifiedAccess(callee: FirSimpleNamedReference) {
|
||||
fun initProcessingQualifiedAccess(callee: FirSimpleNamedReference, typeArguments: List<FirTypeProjection>) {
|
||||
if (callee.name.isSpecial) {
|
||||
qualifierStack.clear()
|
||||
} else {
|
||||
qualifierStack.add(callee.name)
|
||||
qualifierStack.add(NameWithTypeArguments(callee.name, typeArguments))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +65,7 @@ class FirQualifiedNameResolver(private val components: BodyResolveComponents) {
|
||||
return null
|
||||
}
|
||||
val symbolProvider = session.firSymbolProvider
|
||||
var qualifierParts = qualifierStack.asReversed().map { it.asString() }
|
||||
var qualifierParts = qualifierStack.asReversed().map { it.name.asString() }
|
||||
var resolved: PackageOrClass?
|
||||
do {
|
||||
resolved = resolveToPackageOrClass(
|
||||
@@ -80,6 +83,7 @@ class FirQualifiedNameResolver(private val components: BodyResolveComponents) {
|
||||
packageFqName = resolved.packageFqName
|
||||
relativeClassFqName = resolved.relativeClassFqName
|
||||
symbol = resolved.classSymbol
|
||||
typeArguments.addAll(qualifierStack.take(qualifierParts.size).flatMap { it.typeArguments })
|
||||
}.apply {
|
||||
resultType = components.typeForQualifier(this)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||
|
||||
@NoMutableState
|
||||
class InferenceComponents(val session: FirSession) : FirSessionComponent {
|
||||
val ctx: ConeTypeCheckerContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session)
|
||||
val ctx: ConeTypeCheckerContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session)
|
||||
|
||||
val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {}
|
||||
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)
|
||||
|
||||
@@ -584,7 +584,7 @@ class ConeTypeCheckerContext(
|
||||
errorTypesEqualToAnything: Boolean,
|
||||
stubTypesEqualToAnything: Boolean
|
||||
): AbstractTypeCheckerContext =
|
||||
if (this.isErrorTypeEqualsToAnything == errorTypesEqualToAnything)
|
||||
if (this.isErrorTypeEqualsToAnything == errorTypesEqualToAnything && this.isStubTypeEqualsToAnything == stubTypesEqualToAnything)
|
||||
this
|
||||
else
|
||||
ConeTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, session)
|
||||
|
||||
@@ -34,7 +34,7 @@ fun ConeClassLikeType.isByte(): Boolean = lookupTag.classId == StandardClassIds.
|
||||
fun ConeClassLikeType.isBoolean(): Boolean = lookupTag.classId == StandardClassIds.Boolean
|
||||
fun ConeClassLikeType.isChar(): Boolean = lookupTag.classId == StandardClassIds.Char
|
||||
|
||||
fun ConeClassLikeType.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort()
|
||||
fun ConeClassLikeType.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
||||
fun ConeClassLikeType.isPrimitiveNumberType(): Boolean = lookupTag.classId in PRIMITIVE_NUMBER_CLASS_IDS
|
||||
fun ConeClassLikeType.isPrimitiveUnsignedNumberType(): Boolean = lookupTag.classId in PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS
|
||||
fun ConeClassLikeType.isPrimitiveNumberOrUnsignedNumberType(): Boolean = isPrimitiveNumberType() || isPrimitiveUnsignedNumberType()
|
||||
|
||||
@@ -362,6 +362,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtTypeReference> INLINE_CLASS_CANNOT_BE_RECURSIVE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> RESERVED_MEMBER_INSIDE_INLINE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INNER_CLASS_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Result class
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.diagnostics.Errors.ACTUAL_WITHOUT_EXPECT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
||||
@@ -402,15 +404,12 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = object : PositioningStrategy<KtModifierListOwner>() {
|
||||
private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
|
||||
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
||||
val visibilityTokens =
|
||||
listOf(KtTokens.PRIVATE_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PUBLIC_KEYWORD, KtTokens.INTERNAL_KEYWORD)
|
||||
val modifierList = element.modifierList
|
||||
|
||||
val result = visibilityTokens.mapNotNull { modifierList?.getModifier(it)?.textRange }
|
||||
if (!result.isEmpty()) return result
|
||||
val result = modifierSet.types.mapNotNull { modifierList?.getModifier(it as KtModifierKeywordToken)?.textRange }
|
||||
if (result.isNotEmpty()) return result
|
||||
|
||||
// Try to resolve situation when there's no visibility modifiers written before element
|
||||
if (element is PsiNameIdentifierOwner) {
|
||||
@@ -432,6 +431,12 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = ModifierSetBasedPositioningStrategy(VISIBILITY_MODIFIERS)
|
||||
|
||||
@JvmField
|
||||
val MODALITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = ModifierSetBasedPositioningStrategy(MODALITY_MODIFIERS)
|
||||
|
||||
@JvmField
|
||||
val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
|
||||
override fun mark(element: KtTypeProjection): List<TextRange> {
|
||||
@@ -477,11 +482,12 @@ object PositioningStrategies {
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val VAL_OR_VAR_NODE: PositioningStrategy<KtNamedDeclaration> = object : PositioningStrategy<KtNamedDeclaration>() {
|
||||
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
||||
val VAL_OR_VAR_NODE: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
||||
override fun mark(element: KtDeclaration): List<TextRange> {
|
||||
return when (element) {
|
||||
is KtParameter -> markElement(element.valOrVarKeyword ?: element)
|
||||
is KtProperty -> markElement(element.valOrVarKeyword)
|
||||
is KtDestructuringDeclaration -> markElement(element.valOrVarKeyword ?: element)
|
||||
else -> error("Declaration is neither a parameter nor a property: " + element.getElementTextWithContext())
|
||||
}
|
||||
}
|
||||
@@ -687,4 +693,14 @@ object PositioningStrategies {
|
||||
return DEFAULT.mark(element)
|
||||
}
|
||||
}
|
||||
|
||||
val OPERATOR: PositioningStrategy<KtExpression> = object : PositioningStrategy<KtExpression>() {
|
||||
override fun mark(element: KtExpression): List<TextRange> {
|
||||
return when (element) {
|
||||
is KtBinaryExpression -> mark(element.operationReference)
|
||||
is KtUnaryExpression -> mark(element.operationReference)
|
||||
else -> super.mark(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,7 +704,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(NON_PRIVATE_CONSTRUCTOR_IN_ENUM, "Constructor must be private in enum class");
|
||||
MAP.put(NON_PRIVATE_CONSTRUCTOR_IN_SEALED, "Constructor must be private in sealed class");
|
||||
|
||||
MAP.put(INLINE_CLASS_NOT_TOP_LEVEL, "Inline classes are only allowed on top level");
|
||||
MAP.put(INLINE_CLASS_NOT_TOP_LEVEL, "Inline classes cannot be local or inner");
|
||||
MAP.put(INLINE_CLASS_NOT_FINAL, "Inline classes can be only final");
|
||||
MAP.put(ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS, "Primary constructor is required for inline class");
|
||||
MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter");
|
||||
@@ -717,6 +717,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(INLINE_CLASS_CANNOT_BE_RECURSIVE, "Inline class cannot be recursive");
|
||||
MAP.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING);
|
||||
MAP.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS, "Secondary constructors with bodies are reserved for for future releases");
|
||||
MAP.put(INNER_CLASS_INSIDE_INLINE_CLASS, "Inline class cannot have inner classes");
|
||||
|
||||
MAP.put(RESULT_CLASS_IN_RETURN_TYPE, "'kotlin.Result' cannot be used as a return type");
|
||||
MAP.put(RESULT_CLASS_WITH_NULLABLE_OPERATOR, "Expression of type 'kotlin.Result' cannot be used as a left operand of ''{0}''", STRING);
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -93,12 +94,16 @@ class CollectionLiteralResolver(
|
||||
}
|
||||
|
||||
private fun getArrayFunctionCallName(expectedType: KotlinType): Name {
|
||||
if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) {
|
||||
if (NO_EXPECTED_TYPE === expectedType ||
|
||||
!(KotlinBuiltIns.isPrimitiveArray(expectedType) || KotlinBuiltIns.isUnsignedArrayType(expectedType))
|
||||
) {
|
||||
return ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
}
|
||||
|
||||
val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
|
||||
return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)]
|
||||
?: UnsignedTypes.unsignedArrayTypeToArrayCall[UnsignedTypes.toUnsignedArrayType(descriptor)]
|
||||
?: ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,11 @@ public class CompileTimeConstantUtils {
|
||||
"kotlin.shortArrayOf",
|
||||
"kotlin.byteArrayOf",
|
||||
"kotlin.booleanArrayOf",
|
||||
"kotlin.emptyArray"
|
||||
"kotlin.emptyArray",
|
||||
"kotlin.ubyteArrayOf",
|
||||
"kotlin.ushortArrayOf",
|
||||
"kotlin.uintArrayOf",
|
||||
"kotlin.ulongArrayOf"
|
||||
);
|
||||
|
||||
public static void checkConstructorParametersType(@NotNull List<KtParameter> parameters, @NotNull BindingTrace trace) {
|
||||
@@ -91,7 +95,8 @@ public class CompileTimeConstantUtils {
|
||||
KotlinBuiltIns.isPrimitiveArray(parameterType) ||
|
||||
KotlinBuiltIns.isPrimitiveType(parameterType) ||
|
||||
KotlinBuiltIns.isString(parameterType) ||
|
||||
UnsignedTypes.INSTANCE.isUnsignedType(parameterType)) {
|
||||
UnsignedTypes.isUnsignedType(parameterType) ||
|
||||
UnsignedTypes.isUnsignedArrayType(parameterType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
SuspendLimitationsChecker,
|
||||
InlineClassDeclarationChecker,
|
||||
PropertiesWithBackingFieldsInsideInlineClass(),
|
||||
InnerClassInsideInlineClass(),
|
||||
AnnotationClassTargetAndRetentionChecker(),
|
||||
ReservedMembersAndConstructsForInlineClass(),
|
||||
ResultClassInReturnTypeChecker(),
|
||||
|
||||
@@ -29,7 +29,7 @@ object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
require(inlineOrValueKeyword != null) { "Declaration of inline class must have 'inline' keyword" }
|
||||
|
||||
val trace = context.trace
|
||||
if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||
if (descriptor.isInner || DescriptorUtils.isLocal(descriptor)) {
|
||||
trace.report(Errors.INLINE_CLASS_NOT_TOP_LEVEL.on(inlineOrValueKeyword))
|
||||
return
|
||||
}
|
||||
@@ -124,6 +124,18 @@ class PropertiesWithBackingFieldsInsideInlineClass : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
class InnerClassInsideInlineClass : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration !is KtClass) return
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
if (!descriptor.isInner) return
|
||||
|
||||
if (!descriptor.containingDeclaration.isInlineClass()) return
|
||||
|
||||
context.trace.report(Errors.INNER_CLASS_INSIDE_INLINE_CLASS.on(declaration.modifierList!!.getModifier(KtTokens.INNER_KEYWORD)!!))
|
||||
}
|
||||
}
|
||||
|
||||
class ReservedMembersAndConstructsForInlineClass : DeclarationChecker {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -397,7 +397,7 @@ fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
|
||||
|
||||
fun IrSimpleFunction.isMethodOfAny() =
|
||||
fun IrFunction.isMethodOfAny() =
|
||||
((valueParameters.size == 0 && name.asString().let { it == "hashCode" || it == "toString" }) ||
|
||||
(valueParameters.size == 1 && name.asString() == "equals" && valueParameters[0].type.isNullableAny()))
|
||||
|
||||
@@ -497,9 +497,7 @@ fun IrFactory.createStaticFunctionWithReceivers(
|
||||
copyMetadata: Boolean = true,
|
||||
typeParametersFromContext: List<IrTypeParameter> = listOf()
|
||||
): IrSimpleFunction {
|
||||
val descriptor = (oldFunction.descriptor as? DescriptorWithContainerSource)?.let {
|
||||
WrappedFunctionDescriptorWithContainerSource()
|
||||
} ?: WrappedSimpleFunctionDescriptor()
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
return createFunction(
|
||||
oldFunction.startOffset, oldFunction.endOffset,
|
||||
origin,
|
||||
|
||||
@@ -11,8 +11,6 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyProperty
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
@@ -77,9 +75,7 @@ fun IrClass.addField(fieldName: String, fieldType: IrType, fieldVisibility: Desc
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildProperty(builder: IrPropertyBuilder): IrProperty = with(builder) {
|
||||
val wrappedDescriptor = if (originalDeclaration is IrLazyProperty || containerSource != null)
|
||||
WrappedPropertyDescriptorWithContainerSource()
|
||||
else WrappedPropertyDescriptor()
|
||||
val wrappedDescriptor = WrappedPropertyDescriptor()
|
||||
|
||||
createProperty(
|
||||
startOffset, endOffset, origin,
|
||||
@@ -117,9 +113,7 @@ inline fun IrProperty.addGetter(builder: IrFunctionBuilder.() -> Unit = {}): IrS
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildFunction(builder: IrFunctionBuilder): IrSimpleFunction = with(builder) {
|
||||
val wrappedDescriptor = if (originalDeclaration is IrLazyFunction || containerSource != null)
|
||||
WrappedFunctionDescriptorWithContainerSource()
|
||||
else WrappedSimpleFunctionDescriptor()
|
||||
val wrappedDescriptor = WrappedSimpleFunctionDescriptor()
|
||||
createFunction(
|
||||
startOffset, endOffset, origin,
|
||||
IrSimpleFunctionSymbolImpl(wrappedDescriptor),
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
@@ -118,7 +118,7 @@ abstract class BridgesConstruction(val context: JsCommonBackendContext) : Declar
|
||||
): IrFunction {
|
||||
|
||||
val origin =
|
||||
if (bridge.isEffectivelyExternal() || bridge.getJsName() != null)
|
||||
if (bridge.hasStableJsName())
|
||||
JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION
|
||||
else
|
||||
IrDeclarationOrigin.BRIDGE
|
||||
|
||||
@@ -37,11 +37,12 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
|
||||
): IrExpression {
|
||||
val paramCount = oldIrFunction.valueParameters.size
|
||||
val invokeFunctionN = resolveInvoke(paramCount)
|
||||
// NOTE: currently we do not have a syntax to perform super extension call
|
||||
// but in case we have such functionality in the future the logic bellow should be fixed
|
||||
|
||||
return irCall(invokeFunctionN, IrStatementOrigin.INVOKE).apply {
|
||||
dispatchReceiver = irImplicitCast(irGet(handlerDeclaration), invokeFunctionN.dispatchReceiverParameter!!.type)
|
||||
assert(newIrFunction.extensionReceiverParameter == null)
|
||||
// NOTE: currently we do not have a syntax to perform super extension call
|
||||
// that's why we've used to just fail with an exception in case we have extension function in for JS IR compilation
|
||||
// TODO: that was overkill, however, we still need to revisit this issue later on
|
||||
params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +47,11 @@ class PropertyLazyInitLowering(
|
||||
return
|
||||
}
|
||||
|
||||
if (container !is IrSimpleFunction && container !is IrField && container !is IrProperty)
|
||||
if (container !is IrField && container !is IrSimpleFunction && container !is IrProperty)
|
||||
return
|
||||
|
||||
if (container.origin !in compatibleOrigins) return
|
||||
|
||||
val file = container.parent as? IrFile
|
||||
?: return
|
||||
|
||||
@@ -224,6 +226,8 @@ class RemoveInitializersForLazyProperties(
|
||||
|
||||
if (declaration !is IrField) return null
|
||||
|
||||
if (!declaration.isCompatibleDeclaration()) return null
|
||||
|
||||
val file = declaration.parent as? IrFile ?: return null
|
||||
|
||||
if (fileToInitializerPureness[file] == true) return null
|
||||
@@ -257,6 +261,7 @@ class RemoveInitializersForLazyProperties(
|
||||
private fun calculateFieldToExpression(declarations: Collection<IrDeclaration>): Map<IrField, IrExpression> =
|
||||
declarations
|
||||
.asSequence()
|
||||
.filter { it.isCompatibleDeclaration() }
|
||||
.map { it.correspondingProperty }
|
||||
.filterNotNull()
|
||||
.filter { it.isForLazyInit() }
|
||||
@@ -288,4 +293,14 @@ private val IrDeclaration.correspondingProperty: IrProperty?
|
||||
private fun IrDeclaration.propertyWithPersistentSafe(transform: IrDeclaration.() -> IrProperty?): IrProperty? =
|
||||
if (((this as? PersistentIrElementBase<*>)?.createdOn ?: 0) <= stageController.currentStage) {
|
||||
transform()
|
||||
} else null
|
||||
} else null
|
||||
|
||||
private fun IrDeclaration.isCompatibleDeclaration() =
|
||||
origin in compatibleOrigins
|
||||
|
||||
private val compatibleOrigins = listOf(
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
||||
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
|
||||
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||
)
|
||||
@@ -109,20 +109,13 @@ fun jsFunctionSignature(declaration: IrFunction): Signature {
|
||||
require(declaration.dispatchReceiverParameter != null)
|
||||
|
||||
val declarationName = declaration.getJsNameOrKotlinName().asString()
|
||||
val stableName = StableNameSignature(declarationName)
|
||||
|
||||
if (declaration.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION) {
|
||||
return stableName
|
||||
}
|
||||
if (declaration.isEffectivelyExternal()) {
|
||||
return stableName
|
||||
}
|
||||
if (declaration.getJsName() != null) {
|
||||
return stableName
|
||||
}
|
||||
// Handle names for special functions
|
||||
if (declaration is IrSimpleFunction && declaration.isMethodOfAny()) {
|
||||
return stableName
|
||||
val needsStableName = declaration.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION ||
|
||||
declaration.hasStableJsName() ||
|
||||
(declaration as? IrSimpleFunction)?.isMethodOfAny() == true // Handle names for special functions
|
||||
|
||||
if (needsStableName) {
|
||||
return StableNameSignature(declarationName)
|
||||
}
|
||||
|
||||
val nameBuilder = StringBuilder()
|
||||
|
||||
@@ -15,11 +15,29 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
fun TODO(element: IrElement): Nothing = TODO(element::class.java.simpleName + " is not supported yet here")
|
||||
|
||||
fun IrFunction.hasStableJsName(): Boolean {
|
||||
val namedOrMissingGetter = when (this) {
|
||||
is IrSimpleFunction -> {
|
||||
val owner = correspondingPropertySymbol?.owner
|
||||
if (owner == null) {
|
||||
true
|
||||
} else {
|
||||
owner.getter?.getJsName() != null
|
||||
}
|
||||
}
|
||||
else -> true
|
||||
}
|
||||
|
||||
return (isEffectivelyExternal() || getJsName() != null || parentClassOrNull?.isJsExport() == true) && namedOrMissingGetter
|
||||
}
|
||||
|
||||
fun IrFunction.isEqualsInheritedFromAny() =
|
||||
name == Name.identifier("equals") &&
|
||||
dispatchReceiverParameter != null &&
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.AnnotationCodegen.Companion.annotationClass
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.copyCorrespondingPropertyFrom
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||
@@ -156,27 +157,9 @@ class JvmCachedDeclarations(
|
||||
//
|
||||
// is supposed to allow using `I2.DefaultImpls.f` as if it was inherited from `I1.DefaultImpls`.
|
||||
// The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge.
|
||||
val defaultImplsOrigin = when {
|
||||
!forCompatibilityMode && !interfaceFun.isFakeOverride ->
|
||||
when {
|
||||
interfaceFun.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ->
|
||||
interfaceFun.origin
|
||||
interfaceFun.origin.isSynthetic ->
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS_SYNTHETIC
|
||||
else ->
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS
|
||||
}
|
||||
interfaceFun.resolveFakeOverride()!!.origin.isSynthetic ->
|
||||
if (forCompatibilityMode)
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
else
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
|
||||
else ->
|
||||
if (forCompatibilityMode)
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
|
||||
else
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE
|
||||
}
|
||||
val defaultImplsOrigin =
|
||||
if (!forCompatibilityMode && !interfaceFun.isFakeOverride) interfaceFun.origin
|
||||
else interfaceFun.resolveFakeOverride()!!.origin
|
||||
|
||||
// Interface functions are public or private, with one exception: clone in Cloneable, which is protected.
|
||||
// However, Cloneable has no DefaultImpls, so this merely replicates the incorrect behavior of the old backend.
|
||||
@@ -198,11 +181,12 @@ class JvmCachedDeclarations(
|
||||
typeParametersFromContext = parent.typeParameters
|
||||
).also {
|
||||
it.copyCorrespondingPropertyFrom(interfaceFun)
|
||||
if (it.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY &&
|
||||
!it.annotations.hasAnnotation(DeprecationResolver.JAVA_DEPRECATED)
|
||||
) {
|
||||
|
||||
if (forCompatibilityMode && !interfaceFun.resolveFakeOverride()!!.origin.isSynthetic) {
|
||||
context.createJvmIrBuilder(it.symbol).run {
|
||||
it.annotations += irCall(irSymbols.javaLangDeprecatedConstructorWithDeprecatedFlag)
|
||||
it.annotations = it.annotations
|
||||
.filterNot { it.annotationClass.hasEqualFqName(DeprecationResolver.JAVA_DEPRECATED) }
|
||||
.plus(irCall(irSymbols.javaLangDeprecatedConstructorWithDeprecatedFlag))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +216,7 @@ class JvmCachedDeclarations(
|
||||
assert(fakeOverride.isFakeOverride)
|
||||
val irClass = fakeOverride.parentAsClass
|
||||
context.irFactory.buildFun {
|
||||
origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE
|
||||
origin = JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE
|
||||
name = fakeOverride.name
|
||||
visibility = fakeOverride.visibility
|
||||
modality = fakeOverride.modality
|
||||
|
||||
@@ -11,13 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
||||
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPLS")
|
||||
object DEFAULT_IMPLS_WITH_MOVED_RECEIVERS : IrDeclarationOriginImpl("STATIC_WITH_MOVED_RECEIVERS")
|
||||
object DEFAULT_IMPLS_WITH_MOVED_RECEIVERS_SYNTHETIC :
|
||||
IrDeclarationOriginImpl("STATIC_WITH_MOVED_RECEIVERS_SYNTHETIC", isSynthetic = true)
|
||||
object DEFAULT_IMPLS_BRIDGE : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE")
|
||||
object DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY")
|
||||
object DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC", isSynthetic = true)
|
||||
object DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC", isSynthetic = true)
|
||||
object SUPER_INTERFACE_METHOD_BRIDGE : IrDeclarationOriginImpl("SUPER_INTERFACE_METHOD_BRIDGE")
|
||||
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL")
|
||||
object FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL", isSynthetic = true)
|
||||
@@ -28,10 +22,8 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
object JVM_STATIC_WRAPPER : IrDeclarationOriginImpl("JVM_STATIC_WRAPPER")
|
||||
object JVM_OVERLOADS_WRAPPER : IrDeclarationOriginImpl("JVM_OVERLOADS_WRAPPER")
|
||||
object SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS :
|
||||
IrDeclarationOriginImpl("SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS", isSynthetic = true)
|
||||
object SYNTHETIC_METHOD_FOR_TYPEALIAS_ANNOTATIONS :
|
||||
IrDeclarationOriginImpl("SYNTHETIC_METHOD_FOR_TYPEALIAS_ANNOTATIONS", isSynthetic = true)
|
||||
object SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS :
|
||||
IrDeclarationOriginImpl("SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS", isSynthetic = true)
|
||||
object GENERATED_PROPERTY_REFERENCE : IrDeclarationOriginImpl("GENERATED_PROPERTY_REFERENCE", isSynthetic = true)
|
||||
object GENERATED_MEMBER_IN_CALLABLE_REFERENCE : IrDeclarationOriginImpl("GENERATED_MEMBER_IN_CALLABLE_REFERENCE", isSynthetic = false)
|
||||
object ENUM_MAPPINGS_FOR_WHEN : IrDeclarationOriginImpl("ENUM_MAPPINGS_FOR_WHEN", isSynthetic = true)
|
||||
@@ -365,7 +365,7 @@ class ClassCodegen private constructor(
|
||||
|
||||
when (val metadata = method.metadata) {
|
||||
is MetadataSource.Property -> {
|
||||
assert(method.isSyntheticMethodForProperty) {
|
||||
assert(method.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS) {
|
||||
"MetadataSource.Property on IrFunction should only be used for synthetic \$annotations methods: ${method.render()}"
|
||||
}
|
||||
metadataSerializer.bindMethodMetadata(metadata, Method(node.name, node.desc))
|
||||
@@ -457,9 +457,8 @@ private val IrClass.flags: Int
|
||||
|
||||
private fun IrField.computeFieldFlags(context: JvmBackendContext, languageVersionSettings: LanguageVersionSettings): Int =
|
||||
origin.flags or visibility.flags or
|
||||
(if (isDeprecatedCallable ||
|
||||
correspondingPropertySymbol?.owner?.isDeprecatedCallable == true ||
|
||||
shouldHaveSpecialDeprecationFlag(context)
|
||||
(if (isDeprecatedCallable(context) ||
|
||||
correspondingPropertySymbol?.owner?.isDeprecatedCallable(context) == true
|
||||
) Opcodes.ACC_DEPRECATED else 0) or
|
||||
(if (isFinal) Opcodes.ACC_FINAL else 0) or
|
||||
(if (isStatic) Opcodes.ACC_STATIC else 0) or
|
||||
@@ -475,10 +474,6 @@ private fun IrField.isPrivateCompanionFieldInInterface(languageVersionSettings:
|
||||
parentAsClass.isJvmInterface &&
|
||||
DescriptorVisibilities.isPrivate(parentAsClass.companionObject()!!.visibility)
|
||||
|
||||
fun IrField.shouldHaveSpecialDeprecationFlag(context: JvmBackendContext): Boolean {
|
||||
return annotations.any { it.symbol == context.ir.symbols.javaLangDeprecatedConstructorWithDeprecatedFlag }
|
||||
}
|
||||
|
||||
private val IrDeclarationOrigin.flags: Int
|
||||
get() = (if (isSynthetic) Opcodes.ACC_SYNTHETIC else 0) or
|
||||
(if (this == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) Opcodes.ACC_ENUM else 0)
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||
@@ -146,10 +145,7 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen
|
||||
origin != JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC &&
|
||||
origin != JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE &&
|
||||
origin != IrDeclarationOrigin.BRIDGE &&
|
||||
origin != IrDeclarationOrigin.BRIDGE_SPECIAL &&
|
||||
origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
|
||||
|
||||
@@ -293,7 +293,7 @@ class ExpressionCodegen(
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD ||
|
||||
// Although these are accessible from Java, the functions they bridge to already have the assertions.
|
||||
irFunction.origin == IrDeclarationOrigin.BRIDGE_SPECIAL ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER ||
|
||||
irFunction.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ||
|
||||
irFunction.parentAsClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS ||
|
||||
|
||||
@@ -118,7 +118,7 @@ class FunctionCodegen(
|
||||
|
||||
private fun shouldGenerateAnnotationsOnValueParameters(): Boolean =
|
||||
when {
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS ->
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS ->
|
||||
false
|
||||
irFunction is IrConstructor && irFunction.parentAsClass.shouldNotGenerateConstructorParameterAnnotations() ->
|
||||
// Not generating parameter annotations for default stubs fixes KT-7892, though
|
||||
@@ -146,7 +146,7 @@ class FunctionCodegen(
|
||||
private fun IrFunction.calculateMethodFlags(): Int {
|
||||
if (origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||
return getVisibilityForDefaultArgumentStub() or Opcodes.ACC_SYNTHETIC or
|
||||
(if (isDeprecatedFunction) Opcodes.ACC_DEPRECATED else 0) or
|
||||
(if (isDeprecatedFunction(context)) Opcodes.ACC_DEPRECATED else 0) or
|
||||
(if (this is IrConstructor) 0 else Opcodes.ACC_STATIC)
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ class FunctionCodegen(
|
||||
val isSynchronized = hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
|
||||
|
||||
return getVisibilityAccessFlag() or modalityFlag or
|
||||
(if (isDeprecatedFunction) Opcodes.ACC_DEPRECATED else 0) or
|
||||
(if (isDeprecatedFunction(context)) Opcodes.ACC_DEPRECATED else 0) or
|
||||
(if (isStatic) Opcodes.ACC_STATIC else 0) or
|
||||
(if (isVararg) Opcodes.ACC_VARARGS else 0) or
|
||||
(if (isExternal) Opcodes.ACC_NATIVE else 0) or
|
||||
|
||||
@@ -13,11 +13,11 @@ import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.ValueKind
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
@@ -161,6 +161,9 @@ class IrInlineCodegen(
|
||||
::IrDefaultLambda
|
||||
)
|
||||
}
|
||||
|
||||
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
|
||||
((memberDescriptor as IrBasedDeclarationDescriptor<*>).owner as IrMemberWithContainerSource).parentClassId != null
|
||||
}
|
||||
|
||||
class IrExpressionLambdaImpl(
|
||||
|
||||
@@ -53,6 +53,10 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
||||
}
|
||||
|
||||
private fun computeClassInternalName(irClass: IrClass): StringBuilder {
|
||||
context.getLocalClassType(irClass)?.internalName?.let {
|
||||
return StringBuilder(it)
|
||||
}
|
||||
|
||||
val shortName = SpecialNames.safeIdentifier(irClass.name).identifier
|
||||
|
||||
when (val parent = irClass.parent) {
|
||||
@@ -73,11 +77,6 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
||||
}
|
||||
}
|
||||
|
||||
val localClassType = context.getLocalClassType(irClass)
|
||||
if (localClassType != null) {
|
||||
return StringBuilder(localClassType.internalName)
|
||||
}
|
||||
|
||||
error(
|
||||
"Local class should have its name computed in InventNamesForLocalClasses: ${irClass.fqNameWhenAvailable}\n" +
|
||||
"Ensure that any lowering that transforms elements with local class info (classes, function references) " +
|
||||
|
||||
@@ -187,10 +187,7 @@ class JvmSignatureClashDetector(
|
||||
IrDeclarationOrigin.BRIDGE_SPECIAL,
|
||||
IrDeclarationOrigin.IR_BUILTINS_STUB,
|
||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE,
|
||||
)
|
||||
|
||||
val PREDEFINED_SIGNATURES = listOf(
|
||||
|
||||
@@ -127,10 +127,10 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
originalForDefaultAdapter?.isInvisibleInMultifilePart() == true)
|
||||
|
||||
private fun IrSimpleFunction.getInternalFunctionForManglingIfNeeded(): IrSimpleFunction? {
|
||||
if (origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR &&
|
||||
visibility == DescriptorVisibilities.INTERNAL &&
|
||||
!isPublishedApi() &&
|
||||
!isSyntheticMethodForProperty
|
||||
if (visibility == DescriptorVisibilities.INTERNAL &&
|
||||
origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS &&
|
||||
!isPublishedApi()
|
||||
) {
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -14,14 +14,13 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.FrameMapBase
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
||||
import org.jetbrains.kotlin.codegen.classFileContainsMethod
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
@@ -34,7 +33,6 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -346,20 +344,16 @@ fun IrClass.isOptionalAnnotationClass(): Boolean =
|
||||
val IrDeclaration.isAnnotatedWithDeprecated: Boolean
|
||||
get() = annotations.hasAnnotation(FqNames.deprecated)
|
||||
|
||||
val IrDeclaration.isDeprecatedCallable: Boolean
|
||||
get() = isAnnotatedWithDeprecated || origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
|
||||
internal fun IrDeclaration.isDeprecatedCallable(context: JvmBackendContext): Boolean =
|
||||
isAnnotatedWithDeprecated ||
|
||||
annotations.any { it.symbol == context.ir.symbols.javaLangDeprecatedConstructorWithDeprecatedFlag }
|
||||
|
||||
// We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods
|
||||
// moved to DefaultImpls, origin is changed to DEFAULT_IMPLS
|
||||
// TODO: Fix origin somehow
|
||||
val IrFunction.isSyntheticMethodForProperty: Boolean
|
||||
get() = name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)
|
||||
|
||||
val IrFunction.isDeprecatedFunction: Boolean
|
||||
get() = isSyntheticMethodForProperty || isDeprecatedCallable ||
|
||||
(this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isDeprecatedCallable == true ||
|
||||
internal fun IrFunction.isDeprecatedFunction(context: JvmBackendContext): Boolean =
|
||||
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS ||
|
||||
isDeprecatedCallable(context) ||
|
||||
(this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isDeprecatedCallable(context) == true ||
|
||||
isAccessorForDeprecatedPropertyImplementedByDelegation ||
|
||||
isAccessorForDeprecatedJvmStaticProperty
|
||||
isAccessorForDeprecatedJvmStaticProperty(context)
|
||||
|
||||
private val IrFunction.isAccessorForDeprecatedPropertyImplementedByDelegation: Boolean
|
||||
get() =
|
||||
@@ -367,20 +361,19 @@ private val IrFunction.isAccessorForDeprecatedPropertyImplementedByDelegation: B
|
||||
this is IrSimpleFunction &&
|
||||
correspondingPropertySymbol != null &&
|
||||
overriddenSymbols.any {
|
||||
it.owner.correspondingPropertySymbol?.owner?.isDeprecatedCallable == true
|
||||
it.owner.correspondingPropertySymbol?.owner?.isAnnotatedWithDeprecated == true
|
||||
}
|
||||
|
||||
private val IrFunction.isAccessorForDeprecatedJvmStaticProperty: Boolean
|
||||
get() {
|
||||
if (origin != JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER) return false
|
||||
val irExpressionBody = this.body as? IrExpressionBody
|
||||
?: throw AssertionError("IrExpressionBody expected for JvmStatic wrapper:\n${this.dump()}")
|
||||
val irCall = irExpressionBody.expression as? IrCall
|
||||
?: throw AssertionError("IrCall expected inside JvmStatic wrapper:\n${this.dump()}")
|
||||
val callee = irCall.symbol.owner
|
||||
val property = callee.correspondingPropertySymbol?.owner ?: return false
|
||||
return property.isDeprecatedCallable
|
||||
}
|
||||
private fun IrFunction.isAccessorForDeprecatedJvmStaticProperty(context: JvmBackendContext): Boolean {
|
||||
if (origin != JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER) return false
|
||||
val irExpressionBody = this.body as? IrExpressionBody
|
||||
?: throw AssertionError("IrExpressionBody expected for JvmStatic wrapper:\n${this.dump()}")
|
||||
val irCall = irExpressionBody.expression as? IrCall
|
||||
?: throw AssertionError("IrCall expected inside JvmStatic wrapper:\n${this.dump()}")
|
||||
val callee = irCall.symbol.owner
|
||||
val property = callee.correspondingPropertySymbol?.owner ?: return false
|
||||
return property.isDeprecatedCallable(context)
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
val IrDeclaration.psiElement: PsiElement?
|
||||
@@ -394,7 +387,7 @@ fun IrSimpleType.isRawType(): Boolean =
|
||||
hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME)
|
||||
|
||||
internal fun classFileContainsMethod(function: IrFunction, context: JvmBackendContext, name: String): Boolean? {
|
||||
val classId = (function.containerSource as? JvmPackagePartSource)?.classId ?: (function.parent as? IrClass)?.classId ?: return null
|
||||
val classId = function.parentClassId ?: return null
|
||||
val originalDescriptor = context.methodSignatureMapper.mapSignatureWithGeneric(function).asmMethod.descriptor
|
||||
val descriptor = if (function.isSuspend)
|
||||
listOf(*Type.getArgumentTypes(originalDescriptor), Type.getObjectType("kotlin/coroutines/Continuation"))
|
||||
@@ -403,6 +396,9 @@ internal fun classFileContainsMethod(function: IrFunction, context: JvmBackendCo
|
||||
return classFileContainsMethod(classId, context.state, Method(name, descriptor))
|
||||
}
|
||||
|
||||
val IrMemberWithContainerSource.parentClassId: ClassId?
|
||||
get() = (containerSource as? JvmPackagePartSource)?.classId ?: (parent as? IrClass)?.classId
|
||||
|
||||
// Translated into IR-based terms from classifierDescriptor?.classId
|
||||
val IrClass.classId: ClassId?
|
||||
get() = when (val parent = parent) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.jvm.localDeclarationsPhase
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -208,10 +209,8 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
}
|
||||
}
|
||||
|
||||
private fun Name.toSuspendImplementationName() = when {
|
||||
isSpecial -> Name.special(asString() + SUSPEND_IMPL_NAME_SUFFIX)
|
||||
else -> Name.identifier(asString() + SUSPEND_IMPL_NAME_SUFFIX)
|
||||
}
|
||||
private fun Name.toSuspendImplementationName(): Name =
|
||||
Name.guessByFirstCharacter(asString() + SUSPEND_IMPL_NAME_SUFFIX)
|
||||
|
||||
private fun createStaticSuspendImpl(irFunction: IrSimpleFunction): IrSimpleFunction {
|
||||
// Create static suspend impl method.
|
||||
@@ -220,6 +219,8 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
irFunction.name.toSuspendImplementationName(),
|
||||
irFunction,
|
||||
origin = JvmLoweredDeclarationOrigin.SUSPEND_IMPL_STATIC_FUNCTION,
|
||||
modality = Modality.OPEN,
|
||||
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY,
|
||||
isFakeOverride = false,
|
||||
copyMetadata = false
|
||||
)
|
||||
@@ -341,7 +342,7 @@ internal fun IrFunction.suspendFunctionOriginal(): IrFunction =
|
||||
if (this is IrSimpleFunction && isSuspend &&
|
||||
!isStaticInlineClassReplacement &&
|
||||
!isOrOverridesDefaultParameterStub() &&
|
||||
!isDefaultImplsFunction
|
||||
parentAsClass.origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS
|
||||
)
|
||||
attributeOwnerId as IrFunction
|
||||
else this
|
||||
@@ -354,19 +355,6 @@ private fun IrSimpleFunction.isOrOverridesDefaultParameterStub(): Boolean =
|
||||
{ it.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER }
|
||||
)
|
||||
|
||||
private val defaultImplsOrigins = setOf(
|
||||
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS_SYNTHETIC,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC,
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
)
|
||||
|
||||
private val IrSimpleFunction.isDefaultImplsFunction: Boolean
|
||||
get() = origin in defaultImplsOrigins
|
||||
|
||||
private fun IrFunction.createSuspendFunctionStub(context: JvmBackendContext): IrFunction {
|
||||
require(this.isSuspend && this is IrSimpleFunction)
|
||||
return factory.buildFun {
|
||||
@@ -385,7 +373,7 @@ private fun IrFunction.createSuspendFunctionStub(context: JvmBackendContext): Ir
|
||||
val substitutionMap = makeTypeParameterSubstitutionMap(this, function)
|
||||
function.copyReceiverParametersFrom(this, substitutionMap)
|
||||
|
||||
if (origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE) {
|
||||
if (origin != JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE) {
|
||||
function.overriddenSymbols +=
|
||||
overriddenSymbols.map { it.owner.suspendFunctionViewOrStub(context).symbol as IrSimpleFunctionSymbol }
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.backend.common.phaser.makeCustomPhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isSyntheticMethodForProperty
|
||||
import org.jetbrains.kotlin.config.JvmAnalysisFlags
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -223,7 +222,8 @@ private fun IrSimpleFunction.createMultifileDelegateIfNeeded(
|
||||
name == StaticInitializersLowering.clinitName ||
|
||||
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
||||
// $annotations methods in the facade are only needed for const properties.
|
||||
(isSyntheticMethodForProperty && (metadata as? MetadataSource.Property)?.isConst != true)
|
||||
(origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS &&
|
||||
(metadata as? MetadataSource.Property)?.isConst != true)
|
||||
) return null
|
||||
|
||||
val function = context.irFactory.buildFun {
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
@@ -260,24 +259,18 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE
|
||||
* interface implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
||||
* override of any interface implementation or such method was already generated into the superclass or is a method from Any.
|
||||
*/
|
||||
private fun isDefaultImplsBridge(f: IrSimpleFunction) =
|
||||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
||||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY ||
|
||||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC ||
|
||||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
|
||||
internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDefaultMode): IrSimpleFunction? {
|
||||
if (!isFakeOverride) return null
|
||||
parent.let { if (it is IrClass && it.isJvmInterface) return null }
|
||||
|
||||
val implementation = resolveFakeOverride(toSkip = ::isDefaultImplsBridge) ?: return null
|
||||
val implementation = resolveFakeOverride() ?: return null
|
||||
|
||||
// Only generate interface delegation for functions immediately inherited from an interface.
|
||||
// (Otherwise, delegation will be present in the parent class)
|
||||
if (overriddenSymbols.any {
|
||||
!it.owner.parentAsClass.isInterface &&
|
||||
it.owner.modality != Modality.ABSTRACT &&
|
||||
it.owner.resolveFakeOverride(toSkip = ::isDefaultImplsBridge) == implementation
|
||||
it.owner.resolveFakeOverride() == implementation
|
||||
}) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
*/
|
||||
(DescriptorVisibilities.isPrivate(function.visibility) && !function.isCompiledToJvmDefault(jvmDefaultMode))
|
||||
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.isCompiledToJvmDefault(jvmDefaultMode))
|
||||
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> {
|
||||
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.body = function.moveBodyTo(defaultImpl)
|
||||
removedFunctions[function.symbol] = defaultImpl.symbol
|
||||
@@ -175,7 +175,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
private fun handleAnnotationClass(irClass: IrClass) {
|
||||
// We produce $DefaultImpls for annotation classes only to move $annotations methods (for property annotations) there.
|
||||
val annotationsMethods =
|
||||
irClass.functions.filter { it.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS }
|
||||
irClass.functions.filter { it.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS }
|
||||
if (annotationsMethods.none()) return
|
||||
|
||||
for (function in annotationsMethods) {
|
||||
|
||||
@@ -129,7 +129,7 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
|
||||
|
||||
private fun createSyntheticMethodForAnnotations(declaration: IrProperty): IrSimpleFunction =
|
||||
backendContext.irFactory.buildFun {
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS
|
||||
name = Name.identifier(computeSyntheticMethodName(declaration))
|
||||
visibility = declaration.visibility
|
||||
modality = Modality.OPEN
|
||||
|
||||
@@ -14,8 +14,9 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
|
||||
internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase(
|
||||
@@ -60,11 +61,14 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
|
||||
// Originals are so far only instance methods, and the replacements are
|
||||
// statics, so we copy dispatch receivers to a value argument if needed.
|
||||
// If we can't coerce arguments to required types, keep original expression (see below).
|
||||
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrCall =
|
||||
IrCallImpl.fromSymbolOwner(
|
||||
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrExpression {
|
||||
val expectedType = this.type
|
||||
val intrinsicCallType = replacement.owner.returnType
|
||||
|
||||
val intrinsicCall = IrCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
intrinsicCallType,
|
||||
replacement
|
||||
).also { newCall ->
|
||||
var valueArgumentOffset = 0
|
||||
@@ -81,6 +85,15 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
|
||||
}
|
||||
}
|
||||
|
||||
// Coerce intrinsic call result from JVM 'int' or 'long' to corresponding unsigned type if required.
|
||||
return if (intrinsicCallType.isInt() || intrinsicCallType.isLong()) {
|
||||
intrinsicCall.coerceIfPossible(expectedType)
|
||||
?: throw AssertionError("Can't coerce '${intrinsicCallType.render()}' to '${expectedType.render()}'")
|
||||
} else {
|
||||
intrinsicCall
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.coerceIfPossible(toType: IrType): IrExpression? {
|
||||
// TODO maybe UnsafeCoerce could handle types with different, but coercible underlying representations.
|
||||
// See KT-43286 and related tests for details.
|
||||
|
||||
@@ -63,7 +63,7 @@ private class JvmStaticInCompanionLowering(val context: JvmBackendContext) : IrE
|
||||
.filter {
|
||||
it.isJvmStaticDeclaration() &&
|
||||
it.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER &&
|
||||
it.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
|
||||
it.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS
|
||||
}
|
||||
.forEach { declaration ->
|
||||
val jvmStaticFunction = declaration as IrSimpleFunction
|
||||
|
||||
@@ -588,7 +588,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
if (!withSuper && !declaration.visibility.isPrivate && !declaration.visibility.isProtected) return true
|
||||
|
||||
// `toArray` is always accessible cause mapped to public functions
|
||||
if (symbolOwner is IrSimpleFunction && (symbolOwner.isNonGenericToArray(context) || symbolOwner.isGenericToArray(context))) {
|
||||
if (symbolOwner is IrSimpleFunction && (symbolOwner.isNonGenericToArray() || symbolOwner.isGenericToArray(context))) {
|
||||
if (symbolOwner.parentAsClass.isCollectionSubClass) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addDispatchReceiver
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addTypeParameter
|
||||
@@ -75,7 +75,7 @@ private class ToArrayLowering(private val context: JvmBackendContext) : ClassLow
|
||||
}
|
||||
}
|
||||
|
||||
irClass.findOrCreate(indirectCollectionSubClass, { it.isNonGenericToArray(context) }) {
|
||||
irClass.findOrCreate(indirectCollectionSubClass, IrSimpleFunction::isNonGenericToArray) {
|
||||
irClass.addFunction {
|
||||
name = Name.identifier("toArray")
|
||||
origin = JvmLoweredDeclarationOrigin.TO_ARRAY
|
||||
@@ -132,7 +132,12 @@ internal fun IrSimpleFunction.isGenericToArray(context: JvmBackendContext): Bool
|
||||
returnType.isArrayOrNullableArrayOf(context, typeParameters[0].symbol) &&
|
||||
valueParameters[0].type.isArrayOrNullableArrayOf(context, typeParameters[0].symbol)
|
||||
|
||||
// Match `fun toArray(): Array<Any?>`
|
||||
internal fun IrSimpleFunction.isNonGenericToArray(context: JvmBackendContext): Boolean =
|
||||
// Match `fun toArray(): Array<...>`.
|
||||
// It would be more correct to check that the return type is erased to `Object[]`, however the old backend doesn't do that
|
||||
// (see `FunctionDescriptor.isNonGenericToArray` and KT-43111).
|
||||
internal fun IrSimpleFunction.isNonGenericToArray(): Boolean =
|
||||
name.asString() == "toArray" && typeParameters.isEmpty() && valueParameters.isEmpty() &&
|
||||
extensionReceiverParameter == null && returnType.isArrayOrNullableArrayOf(context, context.irBuiltIns.anyClass)
|
||||
extensionReceiverParameter == null && returnType.isArrayOrNullableArray()
|
||||
|
||||
private fun IrType.isArrayOrNullableArray(): Boolean =
|
||||
this is IrSimpleType && (isArray() || isNullableArray())
|
||||
|
||||
@@ -45,7 +45,7 @@ class TypeAliasAnnotationMethodsLowering(val context: CommonBackendContext) :
|
||||
visibility = alias.visibility
|
||||
returnType = context.irBuiltIns.unitType
|
||||
modality = Modality.OPEN
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_TYPEALIAS_ANNOTATIONS
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS
|
||||
}.apply {
|
||||
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
annotations += alias.annotations
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isFromJava
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
||||
@@ -71,7 +72,7 @@ class MemoizedInlineClassReplacements(
|
||||
when {
|
||||
it.isRemoveAtSpecialBuiltinStub() ->
|
||||
null
|
||||
it.isInlineClassMemberFakeOverriddenFromDefaultJavaInterfaceMethod() ->
|
||||
it.isInlineClassMemberFakeOverriddenFromJvmDefaultInterfaceMethod() ->
|
||||
null
|
||||
it.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||
createMethodReplacement(it)
|
||||
@@ -97,14 +98,21 @@ class MemoizedInlineClassReplacements(
|
||||
valueParameters.size == 1 &&
|
||||
valueParameters[0].type.isInt()
|
||||
|
||||
private fun IrFunction.isInlineClassMemberFakeOverriddenFromDefaultJavaInterfaceMethod(): Boolean {
|
||||
private fun IrFunction.isInlineClassMemberFakeOverriddenFromJvmDefaultInterfaceMethod(): Boolean {
|
||||
if (this !is IrSimpleFunction) return false
|
||||
if (!this.isFakeOverride) return false
|
||||
val parentClass = parentClassOrNull ?: return false
|
||||
if (!parentClass.isInline) return false
|
||||
|
||||
val overridden = resolveFakeOverride() ?: return false
|
||||
return overridden.isFromJava() && overridden.modality != Modality.ABSTRACT && overridden.parentAsClass.isJvmInterface
|
||||
if (!overridden.parentAsClass.isJvmInterface) return false
|
||||
if (overridden.modality == Modality.ABSTRACT) return false
|
||||
|
||||
// We have a non-abstract interface member.
|
||||
// It is a JVM default interface method if one of the following conditions are true:
|
||||
// - it is a Java method,
|
||||
// - it is a Kotlin function compiled to JVM default interface method.
|
||||
return overridden.isFromJava() || overridden.isCompiledToJvmDefault(context.state.jvmDefaultMode)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
interface IrSymbolOwner : IrElement {
|
||||
val symbol: IrSymbol
|
||||
@@ -66,3 +67,7 @@ interface IrDeclarationWithName : IrDeclaration {
|
||||
interface IrOverridableMember : IrDeclarationWithVisibility, IrDeclarationWithName, IrSymbolOwner {
|
||||
val modality: Modality
|
||||
}
|
||||
|
||||
interface IrMemberWithContainerSource : IrDeclarationWithName {
|
||||
val containerSource: DeserializedContainerSource?
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
abstract class IrFunction :
|
||||
IrDeclarationBase(),
|
||||
IrDeclarationWithName, IrDeclarationWithVisibility, IrTypeParametersContainer, IrSymbolOwner, IrDeclarationParent, IrReturnTarget,
|
||||
IrMemberWithContainerSource,
|
||||
IrMetadataSourceOwner {
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
@@ -49,8 +50,6 @@ abstract class IrFunction :
|
||||
|
||||
abstract var body: IrBody?
|
||||
|
||||
abstract val containerSource: DeserializedContainerSource?
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
abstract class IrProperty : IrDeclarationBase(), IrOverridableMember, IrMetadataSourceOwner, IrAttributeContainer {
|
||||
abstract class IrProperty :
|
||||
IrDeclarationBase(), IrOverridableMember, IrMetadataSourceOwner, IrAttributeContainer, IrMemberWithContainerSource {
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
abstract override val descriptor: PropertyDescriptor
|
||||
abstract override val symbol: IrPropertySymbol
|
||||
@@ -40,8 +41,6 @@ abstract class IrProperty : IrDeclarationBase(), IrOverridableMember, IrMetadata
|
||||
abstract var getter: IrSimpleFunction?
|
||||
abstract var setter: IrSimpleFunction?
|
||||
|
||||
abstract val containerSource: DeserializedContainerSource?
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitProperty(this, data)
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
@@ -371,7 +369,9 @@ open class IrBasedVariableDescriptorWithAccessor(owner: IrLocalDelegatedProperty
|
||||
|
||||
fun IrLocalDelegatedProperty.toIrBasedDescriptor() = IrBasedVariableDescriptorWithAccessor(this)
|
||||
|
||||
open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunctionDescriptor,
|
||||
// We make all IR-based function descriptors instances of DescriptorWithContainerSource, and use .parentClassId to
|
||||
// check whether declaration is deserialized. See IrInlineCodegen.descriptorIsDeserialized
|
||||
open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunctionDescriptor, DescriptorWithContainerSource,
|
||||
IrBasedCallableDescriptor<IrSimpleFunction>(owner) {
|
||||
|
||||
override fun getOverriddenDescriptors(): List<FunctionDescriptor> = owner.overriddenSymbols.map { it.owner.toIrBasedDescriptor() }
|
||||
@@ -402,6 +402,9 @@ open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunc
|
||||
override fun isInfix() = false
|
||||
override fun isOperator() = false
|
||||
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
get() = owner.containerSource
|
||||
|
||||
override fun getOriginal() = this
|
||||
override fun substitute(substitutor: TypeSubstitutor): SimpleFunctionDescriptor {
|
||||
TODO("")
|
||||
@@ -444,19 +447,8 @@ open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunc
|
||||
}
|
||||
}
|
||||
|
||||
class IrBasedFunctionDescriptorWithContainerSource(owner: IrSimpleFunction) : IrBasedSimpleFunctionDescriptor(owner),
|
||||
DescriptorWithContainerSource {
|
||||
override val containerSource: DeserializedContainerSource? get() = owner.containerSource
|
||||
}
|
||||
|
||||
fun IrSimpleFunction.toIrBasedDescriptor() =
|
||||
if (originalFunction is IrLazyFunction || containerSource != null)
|
||||
when {
|
||||
isGetter -> IrBasedPropertyGetterDescriptorWithContainerSource(this)
|
||||
isSetter -> IrBasedPropertySetterDescriptorWithContainerSource(this)
|
||||
else -> IrBasedFunctionDescriptorWithContainerSource(this)
|
||||
}
|
||||
else when {
|
||||
when {
|
||||
isGetter -> IrBasedPropertyGetterDescriptor(this)
|
||||
isSetter -> IrBasedPropertySetterDescriptor(this)
|
||||
else -> IrBasedSimpleFunctionDescriptor(this)
|
||||
@@ -759,7 +751,8 @@ open class IrBasedEnumEntryDescriptor(owner: IrEnumEntry) : ClassDescriptor, IrB
|
||||
|
||||
fun IrEnumEntry.toIrBasedDescriptor() = IrBasedEnumEntryDescriptor(this)
|
||||
|
||||
open class IrBasedPropertyDescriptor(owner: IrProperty) : PropertyDescriptor, IrBasedDeclarationDescriptor<IrProperty>(owner) {
|
||||
open class IrBasedPropertyDescriptor(owner: IrProperty) :
|
||||
PropertyDescriptor, DescriptorWithContainerSource, IrBasedDeclarationDescriptor<IrProperty>(owner) {
|
||||
override fun getModality() = owner.modality
|
||||
|
||||
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) {
|
||||
@@ -806,6 +799,8 @@ open class IrBasedPropertyDescriptor(owner: IrProperty) : PropertyDescriptor, Ir
|
||||
|
||||
override val setter: PropertySetterDescriptor? get() = owner.setter?.toIrBasedDescriptor() as? PropertySetterDescriptor
|
||||
|
||||
override val containerSource: DeserializedContainerSource? = owner.containerSource
|
||||
|
||||
override fun getOriginal() = this
|
||||
|
||||
override fun isExpect() = false
|
||||
@@ -861,16 +856,7 @@ open class IrBasedPropertyDescriptor(owner: IrProperty) : PropertyDescriptor, Ir
|
||||
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
|
||||
}
|
||||
|
||||
class IrBasedPropertyDescriptorWithContainerSource(
|
||||
owner: IrProperty
|
||||
) : IrBasedPropertyDescriptor(owner), DescriptorWithContainerSource {
|
||||
override val containerSource: DeserializedContainerSource? = owner.containerSource
|
||||
}
|
||||
|
||||
fun IrProperty.toIrBasedDescriptor() = if (originalProperty is IrLazyProperty || containerSource != null)
|
||||
IrBasedPropertyDescriptorWithContainerSource(this)
|
||||
else
|
||||
IrBasedPropertyDescriptor(this)
|
||||
fun IrProperty.toIrBasedDescriptor() = IrBasedPropertyDescriptor(this)
|
||||
|
||||
abstract class IrBasedPropertyAccessorDescriptor(owner: IrSimpleFunction) : IrBasedSimpleFunctionDescriptor(owner),
|
||||
PropertyAccessorDescriptor {
|
||||
@@ -891,22 +877,12 @@ open class IrBasedPropertyGetterDescriptor(owner: IrSimpleFunction) : IrBasedPro
|
||||
override fun getOriginal(): IrBasedPropertyGetterDescriptor = this
|
||||
}
|
||||
|
||||
class IrBasedPropertyGetterDescriptorWithContainerSource(owner: IrSimpleFunction) : IrBasedPropertyGetterDescriptor(owner),
|
||||
DescriptorWithContainerSource {
|
||||
override val containerSource: DeserializedContainerSource? get() = owner.containerSource
|
||||
}
|
||||
|
||||
open class IrBasedPropertySetterDescriptor(owner: IrSimpleFunction) : IrBasedPropertyAccessorDescriptor(owner), PropertySetterDescriptor {
|
||||
override fun getOverriddenDescriptors() = super.getOverriddenDescriptors().map { it as PropertySetterDescriptor }
|
||||
|
||||
override fun getOriginal(): IrBasedPropertySetterDescriptor = this
|
||||
}
|
||||
|
||||
class IrBasedPropertySetterDescriptorWithContainerSource(owner: IrSimpleFunction) : IrBasedPropertySetterDescriptor(owner),
|
||||
DescriptorWithContainerSource {
|
||||
override val containerSource: DeserializedContainerSource? get() = owner.containerSource
|
||||
}
|
||||
|
||||
open class IrBasedTypeAliasDescriptor(owner: IrTypeAlias) : IrBasedDeclarationDescriptor<IrTypeAlias>(owner), TypeAliasDescriptor {
|
||||
|
||||
override val underlyingType: SimpleType
|
||||
|
||||
@@ -365,8 +365,11 @@ open class WrappedVariableDescriptorWithAccessor : VariableDescriptorWithAccesso
|
||||
|
||||
}
|
||||
|
||||
// We make all wrapped function descriptors instances of DescriptorWithContainerSource, and use .parentClassId to
|
||||
// check whether declaration is deserialized. See IrInlineCodegen.descriptorIsDeserialized
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
open class WrappedSimpleFunctionDescriptor : SimpleFunctionDescriptor, WrappedCallableDescriptor<IrSimpleFunction>() {
|
||||
open class WrappedSimpleFunctionDescriptor :
|
||||
SimpleFunctionDescriptor, DescriptorWithContainerSource, WrappedCallableDescriptor<IrSimpleFunction>() {
|
||||
|
||||
override fun getOverriddenDescriptors() = owner.overriddenSymbols.map { it.descriptor }
|
||||
|
||||
@@ -402,6 +405,9 @@ open class WrappedSimpleFunctionDescriptor : SimpleFunctionDescriptor, WrappedCa
|
||||
override fun isInfix() = false
|
||||
override fun isOperator() = false
|
||||
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
get() = owner.containerSource
|
||||
|
||||
override fun getOriginal() = this
|
||||
override fun substitute(substitutor: TypeSubstitutor): SimpleFunctionDescriptor {
|
||||
TODO("")
|
||||
@@ -444,12 +450,6 @@ open class WrappedSimpleFunctionDescriptor : SimpleFunctionDescriptor, WrappedCa
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class WrappedFunctionDescriptorWithContainerSource : WrappedSimpleFunctionDescriptor(), DescriptorWithContainerSource {
|
||||
override val containerSource
|
||||
get() = owner.containerSource
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
open class WrappedClassConstructorDescriptor : ClassConstructorDescriptor, WrappedCallableDescriptor<IrConstructor>() {
|
||||
override fun getContainingDeclaration() = (owner.parent as IrClass).descriptor
|
||||
@@ -877,7 +877,8 @@ open class WrappedEnumEntryDescriptor : ClassDescriptor, WrappedDeclarationDescr
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
open class WrappedPropertyDescriptor : PropertyDescriptor, WrappedDeclarationDescriptor<IrProperty>() {
|
||||
open class WrappedPropertyDescriptor :
|
||||
PropertyDescriptor, DescriptorWithContainerSource, WrappedDeclarationDescriptor<IrProperty>() {
|
||||
override fun getModality() = owner.modality
|
||||
|
||||
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) {
|
||||
@@ -924,6 +925,9 @@ open class WrappedPropertyDescriptor : PropertyDescriptor, WrappedDeclarationDes
|
||||
|
||||
override val setter: PropertySetterDescriptor? get() = owner.setter?.descriptor as? PropertySetterDescriptor
|
||||
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
get() = owner.containerSource
|
||||
|
||||
override fun getOriginal() = this
|
||||
|
||||
override fun isExpect() = false
|
||||
@@ -979,11 +983,6 @@ open class WrappedPropertyDescriptor : PropertyDescriptor, WrappedDeclarationDes
|
||||
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
|
||||
}
|
||||
|
||||
class WrappedPropertyDescriptorWithContainerSource : WrappedPropertyDescriptor(), DescriptorWithContainerSource {
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
get() = owner.containerSource
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
abstract class WrappedPropertyAccessorDescriptor : WrappedSimpleFunctionDescriptor(), PropertyAccessorDescriptor {
|
||||
override fun isDefault(): Boolean = false
|
||||
|
||||
@@ -24,36 +24,26 @@ val IrSimpleFunction.target: IrSimpleFunction
|
||||
else
|
||||
resolveFakeOverride() ?: error("Could not resolveFakeOverride() for ${this.render()}")
|
||||
|
||||
val IrFunction.target: IrFunction get() = when (this) {
|
||||
is IrSimpleFunction -> this.target
|
||||
is IrConstructor -> this
|
||||
else -> error(this)
|
||||
}
|
||||
val IrFunction.target: IrFunction
|
||||
get() = when (this) {
|
||||
is IrSimpleFunction -> this.target
|
||||
is IrConstructor -> this
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
fun IrSimpleFunction.collectRealOverrides(
|
||||
toSkip: (IrSimpleFunction) -> Boolean = { false },
|
||||
filter: (IrOverridableMember) -> Boolean = { false }
|
||||
): Set<IrSimpleFunction> {
|
||||
if (isReal && !toSkip(this)) return setOf(this)
|
||||
fun IrSimpleFunction.collectRealOverrides(filter: (IrOverridableMember) -> Boolean = { false }): Set<IrSimpleFunction> {
|
||||
if (isReal) return setOf(this)
|
||||
|
||||
return this.overriddenSymbols
|
||||
.map { it.owner }
|
||||
.collectAndFilterRealOverrides(
|
||||
{
|
||||
require(it is IrSimpleFunction) { "Expected IrSimpleFunction: ${it.render()}" }
|
||||
toSkip(it)
|
||||
},
|
||||
filter
|
||||
)
|
||||
.collectAndFilterRealOverrides(filter)
|
||||
.map { it as IrSimpleFunction }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
|
||||
toSkip: (IrOverridableMember) -> Boolean = { false },
|
||||
filter: (IrOverridableMember) -> Boolean = { false }
|
||||
): Set<IrOverridableMember> {
|
||||
|
||||
val visited = mutableSetOf<IrOverridableMember>()
|
||||
val realOverrides = mutableSetOf<IrOverridableMember>()
|
||||
|
||||
@@ -68,7 +58,7 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
|
||||
fun collectRealOverrides(member: IrOverridableMember) {
|
||||
if (!visited.add(member) || filter(member)) return
|
||||
|
||||
if (member.isReal && !toSkip(member)) {
|
||||
if (member.isReal) {
|
||||
realOverrides += member
|
||||
} else {
|
||||
overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) }
|
||||
@@ -93,13 +83,13 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
|
||||
}
|
||||
|
||||
// TODO: use this implementation instead of any other
|
||||
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false, toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? {
|
||||
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction? {
|
||||
return if (allowAbstract) {
|
||||
val reals = collectRealOverrides(toSkip)
|
||||
val reals = collectRealOverrides()
|
||||
if (reals.isEmpty()) error("No real overrides for ${this.render()}")
|
||||
reals.first()
|
||||
} else {
|
||||
collectRealOverrides(toSkip, { it.modality == Modality.ABSTRACT })
|
||||
collectRealOverrides { it.modality == Modality.ABSTRACT }
|
||||
.let { realOverrides ->
|
||||
// Kotlin forbids conflicts between overrides, but they may trickle down from Java.
|
||||
realOverrides.singleOrNull { it.parent.safeAs<IrClass>()?.isInterface != true }
|
||||
|
||||
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrScriptImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazySymbolTable
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedFunctionDescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
@@ -1025,24 +1025,24 @@ class SymbolTable(
|
||||
fun wrappedTopLevelCallableDescriptors(): Set<DescriptorWithContainerSource> {
|
||||
val result = mutableSetOf<DescriptorWithContainerSource>()
|
||||
for (descriptor in simpleFunctionSymbolTable.descriptorToSymbol.keys) {
|
||||
if (descriptor is WrappedFunctionDescriptorWithContainerSource && descriptor.owner.parent !is IrClass) {
|
||||
if (descriptor is WrappedSimpleFunctionDescriptor && descriptor.owner.parent is IrPackageFragment) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
}
|
||||
for (symbol in simpleFunctionSymbolTable.idSigToSymbol.values) {
|
||||
val descriptor = symbol.descriptor
|
||||
if (descriptor is WrappedFunctionDescriptorWithContainerSource && symbol.owner.parent !is IrClass) {
|
||||
if (descriptor is WrappedSimpleFunctionDescriptor && symbol.owner.parent is IrPackageFragment) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
}
|
||||
for (descriptor in propertySymbolTable.descriptorToSymbol.keys) {
|
||||
if (descriptor is WrappedPropertyDescriptorWithContainerSource && descriptor.owner.parent !is IrClass) {
|
||||
if (descriptor is WrappedPropertyDescriptor && descriptor.owner.parent is IrPackageFragment) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
}
|
||||
for (symbol in propertySymbolTable.idSigToSymbol.values) {
|
||||
val descriptor = symbol.descriptor
|
||||
if (descriptor is WrappedPropertyDescriptorWithContainerSource && symbol.owner.parent !is IrClass) {
|
||||
if (descriptor is WrappedPropertyDescriptor && symbol.owner.parent is IrPackageFragment) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,6 @@ enum class E {
|
||||
Entry2,
|
||||
@Deprecated("b")
|
||||
Entry3
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -7,3 +7,5 @@ abstract class A<T : A<T>> : B<Collection<T>>(), C<T> {
|
||||
|
||||
inner class Inner2<X> : Inner<X>(), C<X>
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -9,3 +9,5 @@ interface Bar : Foo {
|
||||
}
|
||||
|
||||
enum class EnumNameOverride : Bar
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -13,3 +13,5 @@ class A {
|
||||
private val j: String = { "a" }()
|
||||
private val j: String = { "b" }()
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -8,3 +8,5 @@ package p
|
||||
private fun f(): Int = 3
|
||||
|
||||
private fun g(p: String): String = "p"
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -8,3 +8,5 @@ package test
|
||||
val foo = 42
|
||||
|
||||
typealias A = String
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -44,4 +44,6 @@ class Container {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -13,4 +13,5 @@ class C : A(), I {
|
||||
override fun if() = 5
|
||||
}
|
||||
|
||||
// LAZINESS:NoLaziness
|
||||
// LAZINESS:NoLaziness
|
||||
// FIR_COMPARISON
|
||||
@@ -6,3 +6,5 @@ class C {
|
||||
return "a"
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -1,3 +1,5 @@
|
||||
// NullableUnitReturnKt
|
||||
|
||||
fun foo(): Unit? = null
|
||||
fun foo(): Unit? = null
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -20,4 +20,6 @@ interface Primitives {
|
||||
val long: Long
|
||||
val float: Float
|
||||
val double: Double
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -17,4 +17,6 @@ interface Trait {
|
||||
var nullableVar: String?
|
||||
val notNullVal: String
|
||||
var notNullVar: String
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -6,3 +6,5 @@ class C {
|
||||
@[kotlin.jvm.JvmField] public val foo: String = { "A" }()
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -12,4 +12,6 @@ class Foo {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -29,3 +29,5 @@ private class Private {
|
||||
override val overridesNothing: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -3,3 +3,5 @@ typealias JO = JvmOverloads
|
||||
object O {
|
||||
@JO fun foo(a: Int = 1, b: String = "") {}
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
@@ -2,3 +2,5 @@
|
||||
val a: Collection<*> = emptyList()
|
||||
@JvmField
|
||||
var b: Int = 1
|
||||
|
||||
// FIR_COMPARISON
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user