Compare commits

...

74 Commits

Author SHA1 Message Date
Ilya Gorbunov
8b3380dec0 ~ refactor test a bit 2020-12-04 12:06:50 +03:00
Ilya Gorbunov
fd70c33cc3 Revert using regex Pattern in String.replace
Use String.indexOf(..., ignoreCase) instead in all branches to preserve
compatibility with behavior before 1.4.20 that used String.split which
essentially relied on that String.indexOf
2020-12-04 11:52:23 +03:00
Ilmir Usmanov
19b16da183 Minor. Add test to check value classes 2020-12-04 09:19:05 +01:00
Ilmir Usmanov
0d55c9108d IC: Forbid inner classes inside inline classes
#KT-43067 Fixed
2020-12-04 05:45:53 +01:00
Ilmir Usmanov
15c325cf10 Value classes: Allow nested inline classes 2020-12-04 05:45:51 +01:00
Vyacheslav Gerasimov
235813736e Build: Set file access rights explicitly in kotlin-stdlib-js jar
Workaround for #KTI-401. Since gradle 6.6 ant.replaceregexp call sets
incorrect access rights `-rw-------` instead of `-rw-r--r--`
2020-12-04 01:47:18 +03:00
Mikhail Glukhikh
4626f21c58 Record type arguments for FirResolvedQualifier 2020-12-03 19:33:51 +03:00
Mikhail Glukhikh
68d271fc91 Move FirModifierList inside FirModifierChecker to reduce its scope 2020-12-03 19:33:51 +03:00
Mikhail Glukhikh
94ddb71213 [FIR] Simplify UnusedChecker & delete FirSourceChildren.kt 2020-12-03 19:33:51 +03:00
Mikhail Glukhikh
8abf27898d Simplify FirMemberDeclaration.implicitModality 2020-12-03 19:33:51 +03:00
Mikhail Glukhikh
5fbdc0af5e [FIR] Introduce & use MODALITY_MODIFIER positioning strategy 2020-12-03 19:33:50 +03:00
Mikhail Glukhikh
54f9edb597 Simplify RedundantVisibilityModifierChecker 2020-12-03 19:33:50 +03:00
Mikhail Glukhikh
b1c9d4b046 [FIR] Introduce & use VISIBILITY_MODIFIER positioning strategy 2020-12-03 19:33:50 +03:00
Mikhail Glukhikh
7f1b539011 [FIR] Simplify CanBeValChecker.getDestructuringChildrenCount 2020-12-03 19:33:50 +03:00
Mikhail Glukhikh
3877933913 [FIR] Adapt VAL_OR_VAR strategy & use it in CanBeValChecker 2020-12-03 19:33:50 +03:00
Mikhail Glukhikh
ea7d738ee1 [FIR] Introduce & use SourceElementPositioningStrategies.OPERATOR 2020-12-03 19:33:49 +03:00
Mikhail Glukhikh
c9806c5af9 [FIR] Simplify RedundantExplicitTypeChecker 2020-12-03 19:33:49 +03:00
Ilmir Usmanov
516fce37db Value classes: Allow unsigned arrays in annotations
including varargs, apparently.
So, we allow unsigned types and unsigned arrays in annotations,
but disallow user-defined inline classes.
 #KT-23816 Fixed
2020-12-03 17:22:08 +01:00
Alexander Udalov
a9c072f826 Regenerate compiler tests 2020-12-03 17:02:35 +01:00
Dmitry Petrov
caea0a9df0 JVM_IR KT-43721 coerce intrinsic result to corresponding unsigned type 2020-12-03 16:44:26 +03:00
Mads Ager
c776fcbd00 [JVM_IR] Fix incorrect name in inner class attributes. 2020-12-03 13:41:36 +01:00
Mads Ager
fae5b8da4b [JVM] Do not put the name of default lambda parameter in LVT.
If we do, the local variable table will not make sense. As as
example:

```
inline fun foo(getString: () -> String = { "OK" }) {
  println(getString())
}

inline fun bar() {
}

fun main() {
    bar()
    foo()
}
```

leads to the following bytecode:

```
  public static final void main();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=4, args_size=0
         0: iconst_0
         1: istore_0
         2: nop
         3: nop
         4: iconst_0
         5: istore_1
         6: nop
         7: ldc           #53                 // String OK
         9: astore_2
        10: iconst_0
        11: istore_3
        12: getstatic     #30                 // Field java/lang/System.out:Ljava/io/PrintStream;
        15: aload_2
        16: invokevirtual #36                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        19: nop
        20: return
      LineNumberTable:
        line 9: 0
        line 13: 2
        line 10: 3
        line 14: 4
        line 15: 6
        line 16: 7
        line 17: 19
        line 11: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2       1     0 $i$f$bar   I
            6      14     1 $i$f$foo   I
            4      16     0 getString$iv   Lkotlin/jvm/functions/Function0;
```

The `getString$iv` local should not be there. It has been inlined away.
Leaving it in the local variable table leads to inconsistent locals
info. Local 0 contains an int but we declare a local of type
Function0.
2020-12-03 13:41:36 +01:00
Dmitriy Dolovov
e5c46a86aa [Commonizer] Minor. Rename file 2020-12-03 15:33:26 +03:00
Dmitriy Dolovov
daf42c1ee6 [Commonizer] Remove unnecessary nullability at CirKnownClassifiers.commonDependeeLibraries 2020-12-03 15:33:20 +03:00
Vladimir Dolzhenko
984b3c2f30 Fix to address platform expectation for project path
Project path has to be absolute
2020-12-03 12:35:31 +01:00
Dmitriy Dolovov
68f8e88d8b [Commonizer] Introduce various types of classifier caches
- New CirCommonizedClassifiers and CirForwardDeclarations caches
- New CirProvidedClassifiers cache with classifier names loaded from arbitrary modules
- CirClassifiersCache is replaced by CirKnownClassifiers umbrella
- Replace the remaining usages of 'isUnderStandardKotlinPackages' by delegation to
  CirKnownClassifiers.commonDependeeLibraries
2020-12-03 13:11:40 +03:00
Dmitriy Dolovov
dce3d4d1b7 [Commonizer] Rename InputTarget and OutputTarget
Rename target classes to better reflect their meaning:
- InputTarget -> LeafTarget
- OutputTarget -> SharedTarget
2020-12-03 13:11:33 +03:00
Dmitriy Dolovov
b0ff3e7e5e [Commonizer] More fine-grained control of commonized module dependencies
- Reduce usage of 'isUnderStandardKotlinPackages' check in commonizer source code
- Rely on common module dependencies supplied via commonizer Parameters which not only
  Kotlin standard library but may also include common fragments of other libraries
2020-12-03 13:11:27 +03:00
LepilkinaElena
9d749feb64 Fix gradle test for endorsed libraries in K/N (#3953) 2020-12-03 12:57:02 +03:00
Victor Petukhov
d25ad269e0 Reuse captured arguments for flexible type's bounds properly, by equality of type constructors modulo mutability and type argument
^KT-43630 Fixed
2020-12-03 11:13:41 +03:00
Victor Petukhov
9f58e4bcfe Add FlexibleTypeBoundsChecker which can answer the question: "can two types be different bounds of the same flexible type?"; and provide the base bound for the given bound.
For instance: `MutableList` and `List` may be within the same flexible type.
2020-12-03 11:13:39 +03:00
Victor Petukhov
1ccbb09029 Fix formatting in flexibleTypes.kt 2020-12-03 11:13:38 +03:00
Shagen Ogandzhanian
8e5bcd349e [JS IR] Respect JsExport while assigning stable names
see https://youtrack.jetbrains.com/issue/KT-43404
2020-12-02 22:21:16 +01:00
Alexander Udalov
6b649d02d3 JVM IR: fix visibility/modality of $suspendImpl methods
#KT-43614 Fixed
2020-12-02 20:53:55 +01:00
Alexander Udalov
8ce2e4654b JVM IR: allow custom toArray to have any array type
To avoid breaking Java source compatibility. This problem can be fixed
later once JVM IR is stabilized.

 #KT-43111 Fixed
2020-12-02 20:53:47 +01:00
Dmitry Petrov
e6a3e38c4d JVM_IR no static inline class members for Kotlin JvmDefault methods
KT-43698 KT-43051
2020-12-02 20:04:13 +03:00
Ivan Gavrilovic
11673bd09c KAPT: add tests for processed types, remove dead code, simplify logic
Add integration test which checks if only types can be
reprocessed in an incremental round. Also, remove unused
`invalidateTypesForFiles` method.

Furthermore, clarify that types that are reprocessed
(i.e types from .class files) are not necessarily
aggregating types, but simply types that should be reprocessed.

Test: KaptIncrementalWithIsolatingApt.testClasspathChangesCauseTypesToBeReprocessed
2020-12-02 16:55:50 +01:00
Ivan Gavrilovic
08a2b47c77 Incremental KAPT: fix typo and do check processed sources on
clean build
2020-12-02 16:55:49 +01:00
Ivan Gavrilovic
0522583602 Incremental KAPT: add test for isolating AP with classpath origin
Add a regression test for KT-34340 that allows APs to have
classpath types as origins.
2020-12-02 16:55:49 +01:00
Ivan Gavrilovic
05e47da458 Incremental KAPT: simplify impacted types computation
Process aggregating types first, and when computing impacted types
compute isolating generated impacted by classpath changes first.
2020-12-02 16:55:49 +01:00
Ivan Gavrilovic
c7e5beece5 Use types are origins for incremental KAPT and track generated source
This change introduces tracking of generated sources structure in order
to e.g track classpath changes impacting generated sources. This fixes KT-42182.

Also, origin tracking for isolating processors is now using types, allowing
for origin elements from classpath. This fixes KT-34340. However, classpath
origin is used only to invalidate generated files when the type changes and
processing will not be requested for that type. This is in line with the
incap spec.
2020-12-02 16:55:49 +01:00
Shagen Ogandzhanian
d512158c25 [JS IR] Remove redundant guard assertion for extension funs with default params
Introduce corresponding test
See https://youtrack.jetbrains.com/issue/KT-41076
2020-12-02 16:45:12 +01:00
Alexander Udalov
a917ebd11e JVM IR: use origin to detect property/typealias $annotations methods
Now that DEFAULT_IMPLS origins for methods do not exist after previous
commits, the name heuristic is no longer needed.
2020-12-02 15:54:15 +01:00
Alexander Udalov
c7c793c724 JVM IR: do not use origin DEFAULT_IMPLS_BRIDGE(_TO_SYNTHETIC)
Instead, check that origin of the parent class is DEFAULT_IMPLS. Also,
add a separate origin SUPER_INTERFACE_METHOD_BRIDGE for interface
methods with bodies that are copied to classes.
2020-12-02 15:54:14 +01:00
Alexander Udalov
d41d1bf64d JVM IR: remove obsolete isDefaultImplsBridge in findInterfaceImplementation 2020-12-02 15:54:14 +01:00
Alexander Udalov
be03bc477d JVM IR: do not use origin DEFAULT_IMPLS_WITH_MOVED_RECEIVERS(_SYNTHETIC)
Instead, check that origin of the parent class is DEFAULT_IMPLS.
2020-12-02 15:54:14 +01:00
Alexander Udalov
988cc52174 JVM IR: do not use origin DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY(_SYNTHETIC)
It was only used to generate deprecation in codegen, but it's annotated
with `javaLangDeprecatedConstructorWithDeprecatedFlag`, and a similar
annotation for IrField results in ACC_DEPRECATED. Adapt codegen to
generate this flag for functions too.
2020-12-02 15:54:13 +01:00
Ilya Goncharov
697b2b02f1 [JS IR] Add properties lazy initialization with multiple modules
[JS IR] Move tests into compiler/testData

[JS IR] Add cyclic dependencies with lazy property initialization

[JS IR] Add test on not initialization in case of call non properties (classed, objects, enum classes, const vals)

[JS IR] Add initialization through top level

[JS IR] Ignore enum getInstance function in property lazy initialization

[JS IR] Use let function with useful result instead of pure apply and also

[JS IR] Remove duplicated tests in js.translator
2020-12-02 17:35:30 +03:00
pyos
6cb573cb45 [FIR] Import parents of companion objects first
Otherwise, information about members moved from companion objects to the
parent class (e.g. on JVM, companion object fields -> static fields in
parent class) will be incorrect.
2020-12-02 15:29:42 +03:00
Igor Yakovlev
4d7b6c022b [FIR IDE] LC Anonymous to SuperClass type substitution 2020-12-02 15:13:09 +03:00
Igor Yakovlev
842d31d04e [FIR IDE] Fix HL API test data
Ignore failed tests
Set passing test to comparison mode
Fix testdata for symbols
Fix invalid LAZINESS parameter reading from testdata
2020-12-02 15:13:09 +03:00
Igor Yakovlev
7cbcde77dd [FIR IDE] LC More accurate fields visibility and modality 2020-12-02 15:13:08 +03:00
Igor Yakovlev
a7d7aa123e [FIR IDE] LC minor refactorings 2020-12-02 15:13:08 +03:00
Igor Yakovlev
a1603716ed [FIR IDE] LC Add anonymous objects support
+minor fixes
2020-12-02 15:13:08 +03:00
Igor Yakovlev
5630667320 [FIR IDE] LC better support for JvmMultiFileClass annotation 2020-12-02 15:13:08 +03:00
Igor Yakovlev
56c3faee00 [FIR IDE] LC Fix generating unique field names 2020-12-02 15:13:08 +03:00
Igor Yakovlev
18e5af37ff [FIR IDE] LC Fixed incorrect JvmOverloads 2020-12-02 15:13:07 +03:00
Igor Yakovlev
535aa1e9e0 [FIR IDE] LC expand typealiases for applied annotations 2020-12-02 15:13:07 +03:00
Igor Yakovlev
229c6f97ac [FIR IDE] LC Fixed nullability for getters 2020-12-02 15:13:07 +03:00
Igor Yakovlev
aff90b335c [FIR IDE] LC Implement special keywords like transient, volatile, synchronized, strictfp 2020-12-02 15:13:07 +03:00
Igor Yakovlev
6aff96a401 [FIR IDE] Remove extra analyzing for local declarations 2020-12-02 15:13:07 +03:00
Igor Yakovlev
3fc424246b [FIR IDE] LC basic support for type arguments
+ small fixes for deprecation, etc.
2020-12-02 15:13:06 +03:00
Igor Yakovlev
2a8f783393 [FIR IDE] HL API Better support of nullability and modality 2020-12-02 15:13:06 +03:00
Igor Yakovlev
4c69043a15 [FIR IDE] Move refactoring and minor bugfixing for modality, jvmname, etc. 2020-12-02 15:13:06 +03:00
Igor Yakovlev
3e3ec5fc69 [FIR IDE] Supporting member scopes in EnumEntries 2020-12-02 15:13:06 +03:00
Igor Yakovlev
fdaf31dbf3 [FIR IDE] Fix typemapping for FirTypeAliasSymbol 2020-12-02 15:13:05 +03:00
Igor Yakovlev
aae0081f3f [FIR IDE] Fixed invalid HL API getters request 2020-12-02 15:13:05 +03:00
Mikhail Glukhikh
2429f429c5 [FIR] Set isStubTypeEqualsToAnything = true for inference as in FE 1.0
#KT-43616 Fixed
2020-12-02 14:49:08 +03:00
Mikhail Glukhikh
eae8821dec FIR Java: unbind possible named annotation cycle 2020-12-02 14:48:46 +03:00
Nikolay Krasko
2ffedd2731 Fix Daemon compiler tests on Windows
In 202 platform tearDown tries to remove temporary directory, but this
fails on Windows, because while Daemon is active directory can't be
deleted.
2020-12-02 14:23:32 +03:00
Georgy Bronnikov
8a969dab7d Bugfix for FIR 2020-12-02 09:47:34 +03:00
Georgy Bronnikov
b23d7a79b0 IR: get rid of WrappedDescriptorWithContainerSource 2020-12-02 09:47:34 +03:00
Georgy Bronnikov
c0cd9064d7 IR: IrMemberWithContainerSource 2020-12-02 09:47:34 +03:00
Georgy Bronnikov
14b773c1fd JVM_IR: do not rely on DescriptorWithContainerSource in InlineCodegen 2020-12-02 09:47:34 +03:00
377 changed files with 9435 additions and 2975 deletions

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)

View 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 {
}
}

View 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| {
}
}

View 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

View 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|>()
}
}

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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)
}

View File

@@ -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?

View File

@@ -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)
}

View File

@@ -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
}
}

View File

@@ -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))

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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 }
}

View File

@@ -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)
}

View File

@@ -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>()
}

View File

@@ -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)!!

View File

@@ -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
)
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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")

View File

@@ -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");

View File

@@ -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")

View File

@@ -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,

View File

@@ -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

View File

@@ -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<*>> {

View File

@@ -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>()

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -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

View File

@@ -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)
}
}
}
}

View File

@@ -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);

View File

@@ -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
}
}

View File

@@ -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;
}

View File

@@ -28,6 +28,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
SuspendLimitationsChecker,
InlineClassDeclarationChecker,
PropertiesWithBackingFieldsInsideInlineClass(),
InnerClassInsideInlineClass(),
AnnotationClassTargetAndRetentionChecker(),
ReservedMembersAndConstructsForInlineClass(),
ResultClassInReturnTypeChecker(),

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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),

View File

@@ -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

View File

@@ -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)) }
}
}

View File

@@ -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,
)

View File

@@ -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()

View File

@@ -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 &&

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 &&

View File

@@ -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 ||

View File

@@ -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

View File

@@ -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(

View File

@@ -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) " +

View File

@@ -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(

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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 }
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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
}

View File

@@ -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())

View File

@@ -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

View File

@@ -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)
}
/**

View File

@@ -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?
}

View File

@@ -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) }

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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 }

View File

@@ -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)
}
}

View File

@@ -9,4 +9,6 @@ enum class E {
Entry2,
@Deprecated("b")
Entry3
}
}
// FIR_COMPARISON

View File

@@ -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

View File

@@ -9,3 +9,5 @@ interface Bar : Foo {
}
enum class EnumNameOverride : Bar
// FIR_COMPARISON

View File

@@ -13,3 +13,5 @@ class A {
private val j: String = { "a" }()
private val j: String = { "b" }()
}
// FIR_COMPARISON

View File

@@ -8,3 +8,5 @@ package p
private fun f(): Int = 3
private fun g(p: String): String = "p"
// FIR_COMPARISON

View File

@@ -8,3 +8,5 @@ package test
val foo = 42
typealias A = String
// FIR_COMPARISON

View File

@@ -44,4 +44,6 @@ class Container {
TODO("not implemented")
}
}
}
}
// FIR_COMPARISON

View File

@@ -13,4 +13,5 @@ class C : A(), I {
override fun if() = 5
}
// LAZINESS:NoLaziness
// LAZINESS:NoLaziness
// FIR_COMPARISON

View File

@@ -6,3 +6,5 @@ class C {
return "a"
}
}
// FIR_COMPARISON

View File

@@ -1,3 +1,5 @@
// NullableUnitReturnKt
fun foo(): Unit? = null
fun foo(): Unit? = null
// FIR_COMPARISON

View File

@@ -20,4 +20,6 @@ interface Primitives {
val long: Long
val float: Float
val double: Double
}
}
// FIR_COMPARISON

View File

@@ -17,4 +17,6 @@ interface Trait {
var nullableVar: String?
val notNullVal: String
var notNullVar: String
}
}
// FIR_COMPARISON

View File

@@ -6,3 +6,5 @@ class C {
@[kotlin.jvm.JvmField] public val foo: String = { "A" }()
}
}
// FIR_COMPARISON

View File

@@ -12,4 +12,6 @@ class Foo {
}
}
}
}
}
// FIR_COMPARISON

View File

@@ -29,3 +29,5 @@ private class Private {
override val overridesNothing: Boolean
get() = false
}
// FIR_COMPARISON

View File

@@ -3,3 +3,5 @@ typealias JO = JvmOverloads
object O {
@JO fun foo(a: Int = 1, b: String = "") {}
}
// FIR_COMPARISON

View File

@@ -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