Compare commits

...

93 Commits

Author SHA1 Message Date
Alexander Udalov
d5b9b6d962 IR: fix capturing of type parameters in local functions
collectPotentiallyCapturedTypeParameters no longer stops on the first
class when going through parents. This is needed because otherwise type
parameters of the containing class, and its outer classes, were never
considered "captured", and thus not duplicated/remapped later in
LocalDeclarationsLowering.

This led to the IR where a local function referenced generic type
parameters of the outer class. On JVM, local function is generated into
a private static function in that container class, and static functions
can't use generic type parameters, which crashed some bytecode
processing tools.

Also, add another explicit call to `seeType` to cover references to
generic type parameters in function return types.

 #KT-45941 Fixed

(cherry picked from commit c14a890e7e)
2021-05-04 21:11:20 +02:00
Alexander Udalov
d6e3cd8926 JVM IR: fix ::class reference and type mapping for scripts
#KT-46284 Fixed

(cherry picked from commit 276ffd5a4b)
2021-05-04 16:03:10 +02:00
sebastian.sellmair
320aa586e2 [Commonizer] Logging: NativeDistributionCommonizationCache: Log in level 'quite' on cache misses
^KT-36679 Verification Pending

(cherry picked from commit a1ed81146e)
2021-05-04 11:25:02 +02:00
sebastian.sellmair
b2f6218857 [Commonizer] Logging: Implement CommonizerLogLevel and hide verbose output by default
^KT-36679 Fixed

(cherry picked from commit b48850c993)
2021-05-04 11:25:01 +02:00
sebastian.sellmair
9ec4f503fb [Commonizer] Logging: Implement ProgressLogger.fork
^KT-36679

(cherry picked from commit 7349ec8f2f)
2021-05-04 11:24:59 +02:00
sebastian.sellmair
ea1859809d [Commonizer] Logging: Remove 'COMMONIZATION' prologue
^KT-36679

(cherry picked from commit ec440aecf6)
2021-05-04 11:24:58 +02:00
sebastian.sellmair
7dc80cd57f [Commonizer] Logging: 'Preparing commonized Kotlin/Native libraries': show outputTarget instead of flat list of targets
^KT-36679

(cherry picked from commit 9d9e11d6d8)
2021-05-04 11:24:57 +02:00
sebastian.sellmair
c7902eee64 [Commonizer] Logging: Show [Step x of y] only when more than one task is scheduled
^KT-36679

(cherry picked from commit 0d9e32f963)
2021-05-04 11:24:56 +02:00
Mads Ager
6de79570e8 JVM_IR: Add more local variable tests for finally code.
(cherry picked from commit 0c77565104)
2021-05-03 11:00:33 +02:00
Mads Ager
1641e8d97e [JVM] Split the variable range for external finally blocks in inliner
When external finally blocks are inlined none of the current locals
are in scope of the finally block.

(cherry picked from commit 6095d8a7fa)
2021-05-03 11:00:33 +02:00
Mads Ager
241d4f973d [JVM_IR] Fix range of locals in connection with finally blocks.
For code such as:

```
try {
  var y = "y"
  for (i in 0 until 1) {
    return y
  }
} finally {
  println("finally")
}
```

The local variables `y` and `i` ended up covering the finally block as
well in the debugger.

This change splits the range of the locals so that they do
not cover the finally block.

This change does not change the inliner to do similar transformations,
so the range of locals is still wrong win finally blocks when inlined
into an inline function. Added a failing test to that effect.

(cherry picked from commit 6d9f02cfc6)
2021-05-03 11:00:32 +02:00
Mikhael Bogdanov
0ff28e00c8 Mute test on JDK 6
(cherry picked from commit 84e67da2af)
2021-05-03 07:50:38 +02:00
Mikhael Bogdanov
39111bd33c Put reification markers came from super object signature
#KT-44770 Fixed
  #KT-30696 Open

(cherry picked from commit 95d95f9a9b)
2021-05-03 07:50:37 +02:00
Victor Petukhov
87a1a9de10 Use platform-independent line separator in jspecify tests handler
(cherry picked from commit 9eaec8d919)
2021-05-01 13:42:50 +03:00
Simon Ogorodnik
da07980f0c FIR: Fix gradle integration tests broken by c6fa3634
(cherry picked from commit 6365164c21)
2021-04-30 22:20:28 +03:00
Stanislav Erokhin
b8ad5b8c56 Fix binary compatibility with AS Arctic Fox C14 and AS 4.2 2021-04-30 19:26:43 +02:00
Sergey Shanshin
504e172f29 Fix IR compilation of external serializers in native
(cherry picked from commit 8dd307573a)
2021-04-30 19:23:54 +03:00
Victor Petukhov
6844b9047a Temporary disable failing jspecify tests on Windows
(cherry picked from commit 4fb78fab93)
2021-04-30 17:54:52 +03:00
Victor Petukhov
88b4914b2e Fix FIR tests 2021-04-30 16:49:16 +03:00
Victor Petukhov
0294a3f1a1 Introduce warnings reporting by missed constraints because of incorrect optimization in the constraints processor
(cherry picked from commit 7c62e9aecd)
2021-04-30 15:46:46 +03:00
Victor Petukhov
72761a9255 Revert "Don't stop constraints processing if all type variables have proper equality constraints"
This reverts commit b87c2a15

(cherry picked from commit e110b49cab)
2021-04-30 15:46:44 +03:00
Victor Petukhov
5aba18ad15 Mute foreign annotations tests with compiled java through psi class files reading
(cherry picked from commit f330d67740)
2021-04-30 14:50:10 +03:00
Victor Petukhov
b20a7efdb5 Add jspecify license
(cherry picked from commit 78ffefe107)
2021-04-30 14:50:09 +03:00
Victor Petukhov
2832137461 Implement caching module annotations per class id
(cherry picked from commit 909f0d8bdb)
2021-04-30 14:50:09 +03:00
Victor Petukhov
85eef93f1d Leave KotlinCliJavaFileManager::findClass only passing JavaClassFinder.Request
(cherry picked from commit 2e57ff25ee)
2021-04-30 14:50:08 +03:00
Victor Petukhov
8db78e45b0 Move foreign annotations logic into the corresponding configurator for the tests
(cherry picked from commit 072bba109f)
2021-04-30 14:50:07 +03:00
Victor Petukhov
8d959dc8ef Implement jspecify marks processing in the tests properly, by adding specific handler and cleanuper
(cherry picked from commit e93133a28f)
2021-04-30 14:50:06 +03:00
Victor Petukhov
c7092b1e1d Support type enhancement on freshly supported module level annotations
^KT-45189 Fixed

(cherry picked from commit b9536a25d6)
2021-04-30 14:49:57 +03:00
Victor Petukhov
b8ae6d607d Support reading annotations on java 9 module on sources and binaries
(cherry picked from commit bc5e92033b)
2021-04-30 14:49:56 +03:00
Victor Petukhov
01e1e512fb Add directive ALL_JAVA_AS_BINARIES and use it explicitly for foreign annotations tests with compiled java
(cherry picked from commit 24685ee9d6)
2021-04-30 14:49:52 +03:00
Victor Petukhov
eccd2c389e Update some third-party annotations
(cherry picked from commit 89270399db)
2021-04-30 14:49:45 +03:00
Victor Petukhov
9d937f96ce Add basic Java 9 module tests
(cherry picked from commit cdcde634e8)
2021-04-30 14:49:44 +03:00
Victor Petukhov
125e229dcf Add Java 9 jspecify annotations including module level ones
(cherry picked from commit 757fdb2b32)
2021-04-30 14:49:43 +03:00
Victor Petukhov
b3a664ce13 Support java 9 modules in the diagnostic tests both in sources and binaries
(cherry picked from commit 71755b7a5e)
2021-04-30 14:49:39 +03:00
Victor Petukhov
f7bd9285c1 Introduce special common directives for tests based on foreign annotation tests
(cherry picked from commit 1f0616439c)
2021-04-30 14:49:35 +03:00
Victor Petukhov
330c801957 [Jspecify] Move diagnostic tests against compiled java under the new tests infrastructure
(cherry picked from commit 6065f0e2d0)
2021-04-30 14:49:31 +03:00
Victor Petukhov
50cb6a5308 [Jspecify] Move jspecify test runner under the new tests infrastructure
(cherry picked from commit 8f097b14cc)
2021-04-30 14:49:28 +03:00
Victor Petukhov
5be8b728f1 Move foreign annotation tests into diagnostics folder
(cherry picked from commit 6f9694174f)
2021-04-30 14:49:14 +03:00
Victor Petukhov
19cc7866b3 [Jspecify] Remove Kotlin use sites generator: consider manually picking changes from the jspecify repo
(cherry picked from commit 57bd4d3a98)
2021-04-30 14:49:13 +03:00
Victor Petukhov
1fd3575d57 Clean-up JavaModuleInfo.kt
(cherry picked from commit 49e838781c)
2021-04-30 14:49:12 +03:00
Victor Petukhov
d9dc51549f Build recursive raw types and raw types which contain type parameters properly
1) Substitute erasure of other type parameters
2) Use star projection at top level for recursive raw types

^KT-46126 Fixed

(cherry picked from commit 8dd71ec5c8)
2021-04-30 10:54:35 +03:00
Yahor Berdnikau
77e9a8ae13 Made GradleCompileTaskProvder compative with configuration cache.
After moving compilerRunner() method evaluation into execution phase,
creation of GradleCompileTaskProvider class started to violate
configuration cache.

^KT-45611 In Progress
2021-04-29 20:20:28 +02:00
Yahor Berdnikau
9d98d93c9d Introduce KotlinJavaToolchain compile tasks input.
This task input provides a way to set different from current Gradle
JDK and use it for Kotlin files compilation. By default it provides
current Gradle JDK.

Provided JDK major version is used as task input, so on providing
different JDK user will see cache miss.

All required interfaces are located inside api module.

^KT-45611 In Progress
2021-04-29 20:20:17 +02:00
Yahor Berdnikau
3e69bcba47 Print path to java executable Kotlin daemon was started with.
Useful for tests to validate toolchain correct behaviour.

^KT-45611 In Progress
2021-04-29 20:20:08 +02:00
Yahor Berdnikau
47a7a28446 Add helper methods simplifying working with lazy properties from Kotlin.
Just allow to write Kotlin code easier and nicer when using Gradle
lazy properties.

^KT-45611 In Progress
2021-04-29 20:19:57 +02:00
Yahor Berdnikau
7573f73d9b Add initial test setup to enable and test Gradle build cache.
This will allow to write JUnit5 tests to verify tasks are re-using
build cache on rebuilding same project from clean state.

^KT-45611 In Progress
2021-04-29 20:19:45 +02:00
Ivan Gavrilovic
fd55fcfca0 [Gradle] Simplify Parcelize Gradle plugin
Do not iterate over all configurations, just
add the dependency to the compile and runtime classpath.
2021-04-29 16:41:19 +02:00
sebastian.sellmair
beba85a848 [Commonizer] Calculate 'commonModuleNames' in hierarchical context
^KT-46330 Verification Pending
2021-04-28 02:03:20 +03:00
Nikolay Krasko
f7fdffefd6 Add an explicit dependency on dist for UAST tests 2021-04-27 22:00:18 +03:00
Dmitry Petrov
b34e2c1474 JVM_IR KT-36646 fuze primitive equality with safe call 2021-04-27 19:41:31 +03:00
Dmitry Petrov
72849a3dc3 JVM_IR update test for KT-36637 2021-04-27 19:41:29 +03:00
Dmitry Petrov
bdf914e8d5 JVM_IR use static 'hashCode' for boxed primitives on JVM 1.8+ 2021-04-27 19:41:28 +03:00
Dmitriy Novozhilov
07b15f9de6 [FIR] Support effective visibility with @PublishedApi
#KT-46270 Fixed
2021-04-27 18:39:10 +03:00
Dmitriy Novozhilov
32c3f85679 [FIR] Add inline checker for bodies of inline functions
This checker doesn't support `@PublishedAPI` yet, so some BB tests for it
 were muted. #KT-46270
2021-04-27 18:39:09 +03:00
Dmitriy Novozhilov
7e052c1eb1 [FIR] Fix suppressing diagnostics for some expressions 2021-04-27 18:39:07 +03:00
Dmitriy Novozhilov
2a08923c51 [FIR] Add more utilities for builtin functional types 2021-04-27 18:39:06 +03:00
Dmitriy Novozhilov
8925b8c922 [FIR] Fix leaking mutable map type of resolved argument mapping 2021-04-27 18:39:05 +03:00
Dmitriy Novozhilov
1afb844e1a [FIR] Fix FirExpressionWithSmartcastImpl.acceptChildren 2021-04-27 18:39:03 +03:00
Dmitriy Novozhilov
12331cb10c [FIR] Build resolved declaration status for all non-raw declarations 2021-04-27 18:39:02 +03:00
Ivan Kochurkin
d54808e33f [FIR] Implement CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS diagnostics, fix tests 2021-04-27 18:27:39 +03:00
Alexander Likhachev
f2f2df90aa [Gradle] Prevent early resolve of compiler classpath
#KT-45834 Fixed
2021-04-27 18:21:19 +03:00
Dmitry Petrov
660208740e PSI2IR KT-44013 WA: function interface constructor call accepted by FE 2021-04-27 17:35:37 +03:00
Ivan Kochurkin
704b5a0e13 [FIR] Implement UNDERSCORE_IS_RESERVED, UNDERSCORE_USAGE_WITHOUT_BACKTICKS diagnostics (lighttree) 2021-04-27 17:03:53 +03:00
Ivan Kochurkin
ea2d9f7c0c [FIR] Implement UNDERSCORE_IS_RESERVED, UNDERSCORE_USAGE_WITHOUT_BACKTICKS diagnostics (psi only) 2021-04-27 17:03:52 +03:00
Sergey Bogolepov
cc4adb798f Add cacheable targets for macos_arm64 host. 2021-04-27 13:47:20 +00:00
Andrey Zinovyev
0c6066db74 [KAPT] Don't fail on illegal delegate
Kapt ignores error diagnostics, but backend can't
 compile such code at all
This is workaround so backend won't fail.
#KT-46176 Fixed
2021-04-27 16:18:44 +03:00
Ilmir Usmanov
0c0710bb79 Fix outer class accesses inside suspendImpl functions
We need to generate this$0 fields to get to the outer class and generate
accesses to these fields inside suspendImpl function.
 #KT-46214 Fixed
2021-04-27 10:44:18 +02:00
Pavel Kirpichenkov
71365d2452 [IDE] Move library dependency filtering to dependencies cache
The primary client of LibraryDependenciesCache is LibraryInfo,
but it is also used for maintaining modification trackers of
source-dependent libraries. Moving dependency filtering to
cache allows keeping all client in sync.

^KT-45908 In Progress
2021-04-27 10:14:13 +03:00
Mikhael Bogdanov
dfc6d85aee Enable runtime string concatenation by default (for -Xjvm-target=9 or greater)
#KT-42522 Fixed
2021-04-27 09:08:28 +02:00
Ilmir Usmanov
dc2485ae71 Support suspend functions as superinterfaces
Forbid mixing suspend and non-suspend functional supertypes.
Since JVM BE generates suspend functional types as non-suspend ones
with SuspendFunction marker interface, there is not way to distinguish
non-suspend functional type from suspend one if they are mixed.
 #KT-18707 Fixed
2021-04-26 22:14:32 +02:00
Alexander Udalov
37ccd82b6c Fix some warnings in kotlin-gradle-plugin 2021-04-26 22:02:26 +03:00
Alexander Udalov
19a5c2f1c8 Fix warnings related to appendln in kotlin-gradle-plugin
`appendln` is deprecated, but its replacement `appendLine` can't be used
yet in kotlin-gradle-plugin because it's compiled with API version 1.3.
2021-04-26 22:02:25 +03:00
Alexander Udalov
e5128a8772 Improve generated code for Gradle properties
Fix warnings about double nullability and useless elvis.
2021-04-26 22:02:24 +03:00
Svyatoslav Kuzmich
ccc27b6a0c [IR] Add module property to IrFile 2021-04-26 18:52:42 +03:00
Vasily Levchenko
6f2af740cb [kotlin-native][tests][lldb] adds possibility to run simple lldb scenarious with simulator 2021-04-26 14:46:51 +00:00
Ilya Gorbunov
ed3542cdf5 Support covariant MutableMap.entries.remove in JS/IR
Workaround for KT-43321
Follow up to KT-41278
2021-04-26 17:45:27 +03:00
Anton Yalyshev
666ad1f9d5 1.5.0 Change-notes correction. Restore excessively removed items 2021-04-26 16:23:11 +03:00
Anton Yalyshev
ea7ea979ee 1.5.0 Change-notes correction according to KT-42522 2021-04-26 16:01:00 +03:00
Ilya Kirillov
e2acc507d4 FIR IDE: fix inconsistency in element collecting in DiagnosticTraversalCounterTest 2021-04-26 15:11:47 +03:00
Dmitriy Novozhilov
9cb740bfdb Fix tests broken in c6fa3634 2021-04-26 15:11:46 +03:00
Steven Schäfer
a1c1a32515 JVM: Fix unsigned literals in API version < 1.5 2021-04-26 15:11:45 +03:00
Mark Punzalan
af2d0ad36f FIR: Properly set light-tree source for all nested types (e.g.,
nullable function type) and error type refs.
2021-04-26 15:11:44 +03:00
Mark Punzalan
1835185b16 FIR: Remove duplicated diagnostics on annotations on types. 2021-04-26 15:11:43 +03:00
Mark Punzalan
edb6b337dc FIR: Resolve anonymous function bodies during
IMPLICIT_TYPES_BODY_RESOLVE phase.

This fixes an issue where some FirAnnotationCalls can be left with some
implicit type refs if they have anonymous functions in the arguments.
2021-04-26 15:11:42 +03:00
Mark Punzalan
e69b729e21 FIR checker: Create a new kind of checker FirTypeChecker and add
FirSuspendModifierChecker to report WRONG_MODIFIER_TARGET for `suspend`
on  non-functional types.
2021-04-26 15:11:41 +03:00
Dmitriy Novozhilov
4282d17467 [FIR] Optimize imports 2021-04-26 15:11:40 +03:00
Mark Punzalan
b88913af1d FIR checker: Report WRONG_MODIFIER_TARGET for suspend on
non-functional types.
2021-04-26 15:11:39 +03:00
Mark Punzalan
9a4742c08d FIR: Properly build nullable suspend function types, and aggregate
modifiers and annotations within KtTypeReference/REFERENCE_TYPE nodes.
2021-04-26 15:11:38 +03:00
Mark Punzalan
9cf5ac1fbd FIR: Render "?" on nullable function types. 2021-04-26 15:11:37 +03:00
Ilya Gorbunov
a9cc046ec9 Add missing constructor for expect annotation class JvmRecord
KT-46280
2021-04-26 10:41:49 +00:00
Alexander Dudinsky
2c29957cb8 Move tests from GradleImportingTestCase to MultiplePluginVersionGradleImportingTestCase 2021-04-26 13:20:00 +03:00
Alexander Dudinsky
e96f64e6c9 Refactor MultiplePluginVersionGradleImportingTestCase
By this commit:
- Used `isTeamcityBuild` flag for a separating local run of the tests from CI
  For local run by default uses master version of gradle-plugin and
  LATEST_SUPPORTED_GRADLE_VERSION of the Gradle.
  But you can specify versions for local run by overriding sysenv
  `IMPORTING_TESTS_LOCAL_RUN_PARAMS`.
  For example: export IMPORTING_TESTS_LOCAL_RUN_PARAMS=6.7.1:1.4.30
- Moved main logic from `GradleImportingTestCase` to
  `MultiplePluginVersionGradleImportingTestCase` for removing the first one later
- Removed `AbstractModelBuilderTest` as useless only
 `DistributionLocator` left from this class.
2021-04-26 13:19:59 +03:00
Ilya Gorbunov
b59f668a50 Change the way kotlin.js source map paths are postprocessed
The idea is that we do no longer use `sourceMapBaseDirs` parameter
of `compileKotlin2Js` task to remove prefix from source paths,
but instead preserve the full paths relative to the output directory.
This allows us to avoid duplicate file names and to identify
source files more reliably.
Then, after sources have been embedded in the source map, we remove
several relative prefixes from source paths.
2021-04-26 13:13:21 +03:00
1076 changed files with 19013 additions and 6838 deletions

View File

@@ -18,6 +18,7 @@ interface TypeMappingContext<Writer : JvmDescriptorTypeWriter<Type>> {
val typeContext: TypeSystemCommonBackendContextForTypeMapping
fun getClassInternalName(typeConstructor: TypeConstructorMarker): String
fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String
fun Writer.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode)
}
@@ -117,9 +118,7 @@ object AbstractTypeMapper {
}
typeConstructor.isScript() -> {
val asmType = AsmTypes.JAVA_CLASS_TYPE
with(context) { sw?.writeGenericType(type, asmType, mode) }
return asmType
return Type.getObjectType(context.getScriptInternalName(typeConstructor))
}
typeConstructor.isTypeParameter() -> {

View File

@@ -265,13 +265,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
}
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) {
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen<?> member, @NotNull ClassDescriptor descriptor) {
for (KotlinType type : descriptor.getTypeConstructor().getSupertypes()) {
for (TypeProjection supertypeArgument : type.getArguments()) {
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
processTypeArguments(member, type);
}
}
private static void processTypeArguments(@NotNull MemberCodegen<?> member, KotlinType type) {
for (TypeProjection supertypeArgument : type.getArguments()) {
if (supertypeArgument.isStarProjection()) continue;
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
if (parameterDescriptor != null) {
if (parameterDescriptor.isReified()) {
member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString());
}
} else {
processTypeArguments(member, supertypeArgument.getType());
}
}
}

View File

@@ -188,6 +188,12 @@ class JvmRuntimeTypes(
else -> if (isMutable) mutablePropertyReferences else propertyReferences
}
return classes[arity].defaultType
return if (arity >= 0) {
classes[arity].defaultType
} else {
//in case of ErrorUtils.ERROR_PROPERTY there would be no dispatchReceiverParameter and arity becomes negative
//so we just take zero argument reference class (because it is incorrect anyway)
classes[0].defaultType
}
}
}

View File

@@ -320,8 +320,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
processor.localVarsMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true);
mark.dropTo()
}
@@ -330,8 +329,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
processor.substituteTryBlockNodes(intoNode)
//processor.substituteLocalVarTable(intoNode);
processor.substituteLocalVarTable(intoNode);
}
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)

View File

@@ -39,7 +39,7 @@ class RedundantBoxingMethodTransformer(private val generationState: GenerationSt
override fun transform(internalClassName: String, node: MethodNode) {
val interpreter = RedundantBoxingInterpreter(node.instructions, generationState)
val frames = MethodTransformer.analyze(internalClassName, node, interpreter)
val frames = analyze(internalClassName, node, interpreter)
interpretPopInstructionsForBoxedValues(interpreter, node, frames)
@@ -168,7 +168,8 @@ class RedundantBoxingMethodTransformer(private val generationState: GenerationSt
val frame = frames[i] ?: continue
val insn = insnList[i]
if ((insn.opcode == Opcodes.ASTORE || insn.opcode == Opcodes.ALOAD) &&
(insn as VarInsnNode).`var` == localVariableNode.index) {
(insn as VarInsnNode).`var` == localVariableNode.index
) {
if (insn.getOpcode() == Opcodes.ASTORE) {
values.add(frame.top()!!)
} else {

View File

@@ -245,6 +245,7 @@ class GenerationState private constructor(
this.moduleName,
languageVersionSettings,
useOldManglingSchemeForFunctionsWithInlineClassesInSignatures,
IncompatibleClassTracker.DoNothing,
target,
isIrBackend
)

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
interface IncompatibleClassTracker {
fun record(binaryClass: KotlinJvmBinaryClass)
object DoNothing : IncompatibleClassTracker {
override fun record(binaryClass: KotlinJvmBinaryClass) {
}
}
}

View File

@@ -87,6 +87,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
private val moduleName: String,
val languageVersionSettings: LanguageVersionSettings,
private val useOldInlineClassesManglingScheme: Boolean,
// temporary returned to preserve binary compatibility with Dagger in IDE
// https://android.googlesource.com/platform/tools/adt/idea/+/refs/heads/mirror-goog-studio-master-dev/dagger/src/com/android/tools/idea/dagger/DaggerAnnotatedElementsSearch.kt
private val incompatibleClassTracker: IncompatibleClassTracker = IncompatibleClassTracker.DoNothing,
val jvmTarget: JvmTarget = JvmTarget.DEFAULT,
private val isIrBackend: Boolean = false,
private val typePreprocessor: ((KotlinType) -> KotlinType?)? = null,

View File

@@ -377,7 +377,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise"""
)
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)
var stringConcat: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xsam-conversions",

View File

@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleGraph
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.isValidJavaFqName
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME
@@ -52,10 +54,13 @@ class ClasspathRootsResolver(
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
private val outputDirectory: VirtualFile?,
private val javaFileManager: KotlinCliJavaFileManager
) {
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
private val searchScope = GlobalSearchScope.allScope(psiManager.project)
data class RootsAndModules(val roots: List<JavaRoot>, val modules: List<JavaModule>)
private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?)
@@ -160,7 +165,7 @@ class ClasspathRootsResolver(
}
if (moduleInfoFile != null) {
val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
val moduleInfo = JavaModuleInfo.read(moduleInfoFile, javaFileManager, searchScope) ?: return null
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile)
}

View File

@@ -35,6 +35,10 @@ class CliVirtualFileFinder(
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? =
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
override fun findSourceOrBinaryVirtualFile(classId: ClassId) =
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
?: findSourceClass(classId, classId.relativeClassName.asString() + ".java")
override fun findMetadata(classId: ClassId): InputStream? {
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
@@ -61,8 +65,11 @@ class CliVirtualFileFinder(
return findBinaryClass(classId, BuiltInSerializerProtocol.getBuiltInsFileName(packageFqName))?.inputStream
}
private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? =
index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
private fun findClass(classId: ClassId, fileName: String, rootType: Set<JavaRoot.RootType>) =
index.findClass(classId, acceptedRootTypes = rootType) { dir, _ ->
dir.findChild(fileName)?.takeIf(VirtualFile::isValid)
}?.takeIf { it in scope }
private fun findBinaryClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlyBinary)
private fun findSourceClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlySource)
}

View File

@@ -82,7 +82,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = BinaryClassSignatureParser()
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
fun findClass(classId: ClassId, searchScope: GlobalSearchScope) = findClass(JavaClassFinder.Request(classId), searchScope)
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
val (classId, classFileContentFromRequest, outerClassFromRequest) = request

View File

@@ -190,11 +190,17 @@ class KotlinCoreEnvironment private constructor(
sourceFiles.sortBy { it.virtualFile.path }
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val javaModuleFinder = CliJavaModuleFinder(
jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
},
javaFileManager,
project
)
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
@@ -207,7 +213,8 @@ class KotlinCoreEnvironment private constructor(
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile)
outputDirectory?.let(this::findLocalFile),
javaFileManager
)
val (initialRoots, javaModules) =
@@ -231,7 +238,7 @@ class KotlinCoreEnvironment private constructor(
updateClasspathFromRootsIndex(this)
}
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
javaFileManager.initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
@@ -240,7 +247,7 @@ class KotlinCoreEnvironment private constructor(
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)

View File

@@ -78,10 +78,7 @@ import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
@@ -193,11 +190,16 @@ class KotlinCoreEnvironment private constructor(
sourceFiles.sortBy { it.virtualFile.path }
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val javaModuleFinder = CliJavaModuleFinder(
jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
},
javaFileManager
)
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
@@ -210,7 +212,8 @@ class KotlinCoreEnvironment private constructor(
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile)
outputDirectory?.let(this::findLocalFile),
javaFileManager
)
val (initialRoots, javaModules) =
@@ -234,7 +237,7 @@ class KotlinCoreEnvironment private constructor(
updateClasspathFromRootsIndex(this)
}
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
javaFileManager.initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
@@ -243,7 +246,7 @@ class KotlinCoreEnvironment private constructor(
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)

View File

@@ -49,6 +49,9 @@ fun CompilerConfiguration.addJvmSdkRoots(files: List<File>) {
val CompilerConfiguration.jvmClasspathRoots: List<File>
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmClasspathRoot>().map(JvmContentRoot::file)
val CompilerConfiguration.jvmModularRoots: List<File>
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmModulePathRoot>().map(JvmContentRoot::file)
@JvmOverloads
fun CompilerConfiguration.addJavaSourceRoot(file: File, packagePrefix: String? = null) {
add(CLIConfigurationKeys.CONTENT_ROOTS, JavaSourceRoot(file, packagePrefix))

View File

@@ -45,6 +45,7 @@ data class JavaRoot(val file: VirtualFile, val type: RootType, val prefixFqName:
companion object RootTypes {
val OnlyBinary: Set<RootType> = EnumSet.of(RootType.BINARY)
val OnlySource: Set<RootType> = EnumSet.of(RootType.SOURCE)
val SourceAndBinary: Set<RootType> = EnumSet.of(RootType.BINARY, RootType.SOURCE)
}
}

View File

@@ -54,19 +54,20 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
}
if (arguments.stringConcat != null) {
val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!)
val stringConcat = arguments.stringConcat
if (stringConcat != null) {
val runtimeStringConcat = JvmStringConcat.fromString(stringConcat)
if (runtimeStringConcat != null) {
put(JVMConfigurationKeys.STRING_CONCAT, runtimeStringConcat)
if (jvmTarget.majorVersion < JvmTarget.JVM_9.majorVersion && runtimeStringConcat != JvmStringConcat.INLINE) {
messageCollector.report(
WARNING,
"`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`."
"`-Xstring-concat=$stringConcat` does nothing with JVM target `${jvmTarget.description}`."
)
}
} else {
messageCollector.report(
ERROR, "Unknown `-Xstring-concat` mode: ${arguments.stringConcat}\n" +
ERROR, "Unknown `-Xstring-concat` mode: $stringConcat\n" +
"Supported modes: ${JvmStringConcat.values().joinToString { it.description }}"
)
}

View File

@@ -16,16 +16,25 @@
package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
class CliJavaModuleFinder(
jrtFileSystemRoot: VirtualFile?,
private val javaFileManager: KotlinCliJavaFileManager,
project: Project
) : JavaModuleFinder {
private val modulesRoot = jrtFileSystemRoot?.findChild("modules")
private val userModules = linkedMapOf<String, JavaModule>()
private val allScope = GlobalSearchScope.allScope(project)
fun addUserModule(module: JavaModule) {
userModules.putIfAbsent(module.name, module)
}
@@ -41,7 +50,7 @@ class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null
val moduleInfo = JavaModuleInfo.read(file) ?: return null
val moduleInfo = JavaModuleInfo.read(file, javaFileManager, allScope) ?: return null
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file)
}
}

View File

@@ -18,18 +18,24 @@ package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import java.util.concurrent.ConcurrentHashMap
class CliJavaModuleResolver(
private val moduleGraph: JavaModuleGraph,
private val userModules: List<JavaModule>,
private val systemModules: List<JavaModule.Explicit>
private val systemModules: List<JavaModule.Explicit>,
private val project: Project
) : JavaModuleResolver {
init {
assert(userModules.count(JavaModule::isSourceModule) <= 1) {
@@ -37,6 +43,14 @@ class CliJavaModuleResolver(
}
}
private val virtualFileFinder by lazy { VirtualFileFinder.getInstance(project) }
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? {
val virtualFile = virtualFileFinder.findSourceOrBinaryVirtualFile(classId) ?: return null
return (findJavaModule(virtualFile) as? JavaModule.Explicit)?.moduleInfo?.annotations
}
private val sourceModule: JavaModule? = userModules.firstOrNull(JavaModule::isSourceModule)
private fun findJavaModule(file: VirtualFile): JavaModule? {
@@ -77,4 +91,8 @@ class CliJavaModuleResolver(
return null
}
companion object {
private const val MODULE_ANNOTATIONS_CACHE_SIZE = 10000
}
}

View File

@@ -101,7 +101,11 @@ object KotlinCompilerClient {
fun CompileService.leaseImpl(): CompileServiceSession? {
// the newJVMOptions could be checked here for additional parameters, if needed
registerClient(clientAliveFlagFile.absolutePath)
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
val javaExecutablePath = compilerId.javaExecutable?.absolutePath ?: "'user jvm'"
reportingTargets.report(
DaemonReportCategory.DEBUG,
"connected to the daemon. Daemon is using following 'java' executable to run itself: $javaExecutablePath"
)
if (!leaseSession) return CompileServiceSession(this, CompileService.NO_SESSION)

View File

@@ -1,5 +1,5 @@
public open class MethodWithFunctionTypes : R|kotlin/Any| {
public open fun foo(f: R|(kotlin/String?) -> kotlin/String|): R|kotlin/String.() -> kotlin/String?|
public open fun foo(f: R|(kotlin/String?) -> kotlin/String|): R|(kotlin/String.() -> kotlin/String?)?|
public constructor(): R|test/MethodWithFunctionTypes|

View File

@@ -1,8 +1,16 @@
public final fun test1(): R|suspend () -> kotlin/Unit|
public final fun test1N(): R|(suspend () -> kotlin/Unit)?|
public final fun test2(): R|suspend kotlin/Int.() -> kotlin/Int|
public final fun test2N(): R|(suspend kotlin/Int.() -> kotlin/Int)?|
public final fun test3(): R|kotlin/collections/List<kotlin/coroutines/SuspendFunction0<kotlin/Unit>>|
public final fun test3N(): R|kotlin/collections/List<kotlin/coroutines/SuspendFunction0<kotlin/Unit>?>|
public final fun test4(): R|suspend () -> kotlin/coroutines/SuspendFunction0<kotlin/Unit>|
public final fun test4N(): R|(suspend () -> kotlin/coroutines/SuspendFunction0<kotlin/Unit>?)?|

View File

@@ -1,5 +1,5 @@
FILE: safeCallOnTypeAlias.kt
public final typealias MyTypeAlias = R|() -> kotlin/String?|
public final typealias MyTypeAlias = R|(() -> kotlin/String?)?|
public final fun foo(x: R|MyTypeAlias|): R|kotlin/Unit| {
R|<local>/x|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/String?|, R|kotlin/String?|>(<L> = let@fun <anonymous>(y: R|() -> kotlin/String?|): R|kotlin/String?| <inline=Inline, kind=EXACTLY_ONCE> {
^ R|<local>/y|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/String?|>|()?.{ $subj$.R|kotlin/let|<R|kotlin/String|, R|kotlin/String|>(<L> = let@fun <anonymous>(result: R|kotlin/String|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {

View File

@@ -18,7 +18,7 @@ FILE: kt41982.kt
}
}
public final fun <Type : R|Base|, Base : R|DelegateProvider<Base>|> R|Type|.long(initializer: R|() -> kotlin/Long?| = Null(null)): R|Delegate<Type, kotlin/Long>| {
public final fun <Type : R|Base|, Base : R|DelegateProvider<Base>|> R|Type|.long(initializer: R|(() -> kotlin/Long?)?| = Null(null)): R|Delegate<Type, kotlin/Long>| {
^long Null(null)!!
}
public final class Test : R|DelegateProvider<kotlin/Any>| {

View File

@@ -1,11 +1,11 @@
FILE: propertyWithExtensionType.kt
public final class A : R|kotlin/Any| {
public constructor(x: R|kotlin/String.() -> kotlin/Unit|, y: R|kotlin/String.() -> kotlin/Int|): R|A| {
public constructor(x: R|(kotlin/String.() -> kotlin/Unit)?|, y: R|kotlin/String.() -> kotlin/Int|): R|A| {
super<R|kotlin/Any|>()
}
public final val x: R|kotlin/String.() -> kotlin/Unit| = R|<local>/x|
public get(): R|kotlin/String.() -> kotlin/Unit|
public final val x: R|(kotlin/String.() -> kotlin/Unit)?| = R|<local>/x|
public get(): R|(kotlin/String.() -> kotlin/Unit)?|
public final val y: R|kotlin/String.() -> kotlin/Int| = R|<local>/y|
public get(): R|kotlin/String.() -> kotlin/Int|
@@ -14,7 +14,7 @@ FILE: propertyWithExtensionType.kt
public final fun test(a: R|A|): R|kotlin/Unit| {
when () {
!=(R|<local>/a|.R|/A.x|, Null(null)) -> {
lval b: R|kotlin/String.() -> kotlin/Unit| = R|<local>/a|.R|/A.x|
lval b: R|(kotlin/String.() -> kotlin/Unit)?| = R|<local>/a|.R|/A.x|
R|<local>/b|.R|SubstitutionOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(String())
}
}

View File

@@ -5,7 +5,7 @@ interface I {
}
class A {
fun too(): <!NOT_AN_ANNOTATION_CLASS, NOT_AN_ANNOTATION_CLASS!>@Annotation<!> Unit {}
fun too(): <!NOT_AN_ANNOTATION_CLASS!>@Annotation<!> Unit {}
fun foo(): <!REDUNDANT_RETURN_UNIT_TYPE!>Unit<!>
{

View File

@@ -8,8 +8,8 @@ FILE: kt41989.kt
}
public abstract interface C : R|B| {
public open val lineCellStyle: R|A.() -> kotlin/Unit|
public get(): R|A.() -> kotlin/Unit| {
public open val lineCellStyle: R|(A.() -> kotlin/Unit)?|
public get(): R|(A.() -> kotlin/Unit)?| {
^ when () {
R|/cond|() -> {
fun R|A|.<anonymous>(): R|kotlin/Unit| <inline=Unknown> {

View File

@@ -21,14 +21,14 @@ FILE: lambdaArgInScopeFunction.kt
this@R|special/anonymous|.R|/_|<R|KotlinClass?|>()
}
)
lval lambda: R|() -> KotlinClass| = R|<local>/kotlinClass|?.{ $subj$.R|kotlin/let|<R|KotlinClass|, R|() -> KotlinClass|>(<L> = let@fun <anonymous>(it: R|KotlinClass|): R|() -> KotlinClass| <inline=Inline, kind=EXACTLY_ONCE> {
lval lambda: R|(() -> KotlinClass)?| = R|<local>/kotlinClass|?.{ $subj$.R|kotlin/let|<R|KotlinClass|, R|() -> KotlinClass|>(<L> = let@fun <anonymous>(it: R|KotlinClass|): R|() -> KotlinClass| <inline=Inline, kind=EXACTLY_ONCE> {
^ let@fun <anonymous>(): R|KotlinClass| <inline=Unknown> {
^ R|<local>/it|
}
}
) }
R|<local>/lambda|.R|/checkType|<R|() -> KotlinClass|>(<L> = checkType@fun R|CheckTypeInv<kotlin/Function0<KotlinClass>?>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
R|<local>/lambda|.R|/checkType|<R|(() -> KotlinClass)?|>(<L> = checkType@fun R|CheckTypeInv<kotlin/Function0<KotlinClass>?>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
this@R|special/anonymous|.<Inapplicable(INAPPLICABLE_WRONG_RECEIVER): /_>#<R|(kotlin/Unit) -> KotlinClass?|>()
}
)

View File

@@ -1,5 +1,5 @@
FILE: smartcastOnLambda.kt
public final fun test(func: R|() -> kotlin/Unit|): R|kotlin/Unit| {
public final fun test(func: R|(() -> kotlin/Unit)?|): R|kotlin/Unit| {
when () {
!=(R|<local>/func|, Null(null)) -> {
R|<local>/func|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()

View File

@@ -5680,6 +5680,136 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype")
@TestDataPath("$PROJECT_ROOT")
public class SuspendFunctionAsSupertype {
@Test
public void testAllFilesPresentInSuspendFunctionAsSupertype() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN")
@TestDataPath("$PROJECT_ROOT")
public class KSuspendFunctionN {
@Test
public void testAllFilesPresentInKSuspendFunctionN() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/simple.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple")
@TestDataPath("$PROJECT_ROOT")
public class Simple {
@Test
public void testAllFilesPresentInSimple() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/simple.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN")
@TestDataPath("$PROJECT_ROOT")
public class SuspendFunctionN {
@Test
public void testAllFilesPresentInSuspendFunctionN() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/simple.kt");
}
}
}
}
@Nested
@@ -12457,6 +12587,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt");
}
@Test
@TestMetadata("violatingUpperBoundForSelfTypeError.kt")
public void testViolatingUpperBoundForSelfTypeError() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference")
@TestDataPath("$PROJECT_ROOT")
@@ -21000,6 +21136,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
}
@Test
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
}
@Test
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
}
@Test
@TestMetadata("errorType.kt")
public void testErrorType() throws Exception {
@@ -21090,6 +21238,30 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
}
@Test
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
}
@Test
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
}
@Test
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
}
@Test
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
}
@Test
@TestMetadata("typeEnhancement.kt")
public void testTypeEnhancement() throws Exception {
@@ -29017,6 +29189,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt");
}
@Test
@TestMetadata("kt42042Error.kt")
public void testKt42042Error() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt");
}
@Test
@TestMetadata("kt42396.kt")
public void testKt42396() throws Exception {

View File

@@ -5680,6 +5680,136 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype")
@TestDataPath("$PROJECT_ROOT")
public class SuspendFunctionAsSupertype {
@Test
public void testAllFilesPresentInSuspendFunctionAsSupertype() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN")
@TestDataPath("$PROJECT_ROOT")
public class KSuspendFunctionN {
@Test
public void testAllFilesPresentInKSuspendFunctionN() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/kSuspendFunctionN/simple.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple")
@TestDataPath("$PROJECT_ROOT")
public class Simple {
@Test
public void testAllFilesPresentInSimple() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/simple/simple.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN")
@TestDataPath("$PROJECT_ROOT")
public class SuspendFunctionN {
@Test
public void testAllFilesPresentInSuspendFunctionN() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypes.kt")
public void testMixingSuspendAndNonSuspendSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypes.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperClass.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperFunInterface.kt");
}
@Test
@TestMetadata("mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt")
public void testMixingSuspendAndNonSuspendSupertypesThruSuperinterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/mixingSuspendAndNonSuspendSupertypesThruSuperinterface.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/coroutines/suspendFunctionAsSupertype/suspendFunctionN/simple.kt");
}
}
}
}
@Nested
@@ -12457,6 +12587,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt");
}
@Test
@TestMetadata("violatingUpperBoundForSelfTypeError.kt")
public void testViolatingUpperBoundForSelfTypeError() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference")
@TestDataPath("$PROJECT_ROOT")
@@ -21000,6 +21136,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
}
@Test
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
}
@Test
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
}
@Test
@TestMetadata("errorType.kt")
public void testErrorType() throws Exception {
@@ -21090,6 +21238,30 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
}
@Test
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
}
@Test
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
}
@Test
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
}
@Test
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
}
@Test
@TestMetadata("typeEnhancement.kt")
public void testTypeEnhancement() throws Exception {
@@ -29017,6 +29189,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt");
}
@Test
@TestMetadata("kt42042Error.kt")
public void testKt42042Error() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt");
}
@Test
@TestMetadata("kt42396.kt")
public void testKt42396() throws Exception {

View File

@@ -9,11 +9,17 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.generateDiagnostics
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.FirTypeRef
import java.io.File
fun main(args: Array<String>) {
val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/fir/checkers/gen").absoluteFile
val typePackage = "org.jetbrains.kotlin.fir.analysis.checkers.type"
generateCheckersComponents(generationPath, typePackage, "FirTypeChecker") {
alias<FirTypeRef>("TypeRefChecker")
}
val expressionPackage = "org.jetbrains.kotlin.fir.analysis.checkers.expression"
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
alias<FirStatement>("BasicExpressionChecker")

View File

@@ -67,6 +67,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
FUN_MODIFIER,
SUSPEND_MODIFIER,
FUN_INTERFACE,
RESERVED_UNDERSCORE,
;

View File

@@ -82,6 +82,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val NO_THIS by error<PsiElement>()
}
val CALL_RESOLUTION by object : DiagnosticGroup("Call resolution") {
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error<KtExpression>()
}
val SUPER by object : DiagnosticGroup("Super") {
val SUPER_IS_NOT_AN_EXPRESSION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val SUPER_NOT_AVAILABLE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
@@ -696,6 +700,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<String>("expectedFunctionSignature")
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
val UNDERSCORE_IS_RESERVED by error<KtExpression>(PositioningStrategy.RESERVED_UNDERSCORE)
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<KtExpression>(PositioningStrategy.RESERVED_UNDERSCORE)
}
val TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
@@ -725,6 +731,49 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val RETURN_NOT_ALLOWED by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
}
val INLINE by object : DiagnosticGroup("Inline") {
val USAGE_IS_NOT_INLINABLE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("parameter")
}
val NON_LOCAL_RETURN_NOT_ALLOWED by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("parameter")
}
val RECURSION_IN_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("symbol")
}
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("inlineDeclaration")
parameter<Symbol>("referencedDeclaration")
}
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("inlineDeclaration")
parameter<Symbol>("referencedDeclaration")
}
val PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("inlineDeclaration")
parameter<Symbol>("referencedDeclaration")
}
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("inlineDeclaration")
parameter<Symbol>("referencedDeclaration")
}
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("inlineDeclaration")
parameter<Symbol>("referencedDeclaration")
}
val SUPER_CALL_FROM_PUBLIC_INLINE by warning<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("symbol")
}
}
}
private val exposedVisibilityDiagnosticInit: DiagnosticBuilder.() -> Unit = {

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class ComposedTypeCheckers : TypeCheckers() {
override val typeRefCheckers: Set<FirTypeRefChecker>
get() = _typeRefCheckers
private val _typeRefCheckers: MutableSet<FirTypeRefChecker> = mutableSetOf()
@CheckersComponentInternal
internal fun register(checkers: TypeCheckers) {
_typeRefCheckers += checkers.typeRefCheckers
}
}

View File

@@ -0,0 +1,15 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
import org.jetbrains.kotlin.fir.types.FirTypeRef
typealias FirTypeRefChecker = FirTypeChecker<FirTypeRef>

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class TypeCheckers {
companion object {
val EMPTY: TypeCheckers = object : TypeCheckers() {}
}
open val typeRefCheckers: Set<FirTypeRefChecker> = emptySet()
@CheckersComponentInternal internal val allTypeRefCheckers: Set<FirTypeRefChecker> get() = typeRefCheckers
}

View File

@@ -105,6 +105,9 @@ object FirErrors {
val MISSING_STDLIB_CLASS by error0<PsiElement>()
val NO_THIS by error0<PsiElement>()
// Call resolution
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error0<KtExpression>()
// Super
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val SUPER_NOT_AVAILABLE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
@@ -409,6 +412,8 @@ object FirErrors {
val DELEGATE_SPECIAL_FUNCTION_MISSING by error3<KtExpression, String, ConeKotlinType, String>()
val DELEGATE_SPECIAL_FUNCTION_AMBIGUITY by error2<KtExpression, String, Collection<AbstractFirBasedSymbol<*>>>()
val DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE by error2<KtExpression, String, Collection<AbstractFirBasedSymbol<*>>>()
val UNDERSCORE_IS_RESERVED by error0<KtExpression>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<KtExpression>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
// Type alias
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
@@ -435,4 +440,15 @@ object FirErrors {
val RETURN_NOT_ALLOWED by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
// Inline
val USAGE_IS_NOT_INLINABLE by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val NON_LOCAL_RETURN_NOT_ALLOWED by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val RECURSION_IN_INLINE by error1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val SUPER_CALL_FROM_PUBLIC_INLINE by warning1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
}

View File

@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.ComposedDeclaratio
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ComposedExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.type.ComposedTypeCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
@RequiresOptIn
@@ -26,6 +28,9 @@ class CheckersComponent : FirSessionComponent {
val expressionCheckers: ExpressionCheckers get() = _expressionCheckers
private val _expressionCheckers = ComposedExpressionCheckers()
val typeCheckers: TypeCheckers get() = _typeCheckers
private val _typeCheckers = ComposedTypeCheckers()
@SessionConfiguration
@OptIn(CheckersComponentInternal::class)
fun register(checkers: DeclarationCheckers) {
@@ -38,10 +43,17 @@ class CheckersComponent : FirSessionComponent {
_expressionCheckers.register(checkers)
}
@SessionConfiguration
@OptIn(CheckersComponentInternal::class)
fun register(checkers: TypeCheckers) {
_typeCheckers.register(checkers)
}
@SessionConfiguration
fun register(checkers: FirAdditionalCheckersExtension) {
register(checkers.declarationCheckers)
register(checkers.expressionCheckers)
register(checkers.typeCheckers)
}
}

View File

@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
package org.jetbrains.kotlin.fir.analysis.checkers
import com.intellij.lang.ASTNode
import com.intellij.lang.LighterASTNode
@@ -11,8 +11,6 @@ import com.intellij.psi.tree.TokenSet
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierList
@@ -95,6 +93,6 @@ internal fun FirSourceElement?.getModifierList(): FirModifierList? {
internal operator fun FirModifierList?.contains(token: KtModifierKeywordToken): Boolean = this?.contains(token) == true
internal fun FirDeclaration.getModifier(token: KtModifierKeywordToken): FirModifier<*>? = source.getModifierList()?.get(token)
internal fun FirElement.getModifier(token: KtModifierKeywordToken): FirModifier<*>? = source.getModifierList()?.get(token)
internal fun FirDeclaration.hasModifier(token: KtModifierKeywordToken): Boolean = token in source.getModifierList()
internal fun FirElement.hasModifier(token: KtModifierKeywordToken): Boolean = token in source.getModifierList()

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.canBeUsedForConstVal
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -9,7 +9,10 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.contains
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
import org.jetbrains.kotlin.fir.analysis.checkers.modality
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
@@ -183,7 +186,8 @@ internal val FirDeclaration.isEnumEntryInitializer: Boolean
return (containingClassAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.fir?.classKind == ClassKind.ENUM_ENTRY
}
internal val FirMemberDeclaration.isLocalMember: Boolean
// contract: returns(true) implies (this is FirMemberDeclaration)
internal val FirDeclaration.isLocalMember: Boolean
get() = when (this) {
is FirProperty -> this.isLocal
is FirRegularClass -> this.isLocal

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors

View File

@@ -0,0 +1,312 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.util.checkChildrenWithCustomVisitor
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isMarkedNullable
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.util.OperatorNameConventions
object FirInlineDeclarationChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isInline) return
// local inline functions are prohibited
if (declaration.isLocalMember) return
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
val effectiveVisibility = declaration.effectiveVisibility
val function = declaration as FirFunction<*>
checkInlineFunctionBody(function, effectiveVisibility, context, reporter)
}
private fun checkInlineFunctionBody(
function: FirFunction<*>,
effectiveVisibility: EffectiveVisibility,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val body = function.body ?: return
val inlinableParameters = function.valueParameters.filter {
if (it.isNoinline) return@filter false
val type = it.returnTypeRef.coneType
!type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType }
}
val visitor = Visitor(
function,
effectiveVisibility,
inlinableParameters,
context.session,
reporter
)
body.checkChildrenWithCustomVisitor(context, visitor)
}
private class Visitor(
val inlineFunction: FirFunction<*>,
val inlineFunEffectiveVisibility: EffectiveVisibility,
val inlinableParameters: List<FirValueParameter>,
val session: FirSession,
val reporter: DiagnosticReporter
) : FirDefaultVisitor<Unit, CheckerContext>() {
private val isEffectivelyPrivateApiFunction: Boolean = inlineFunEffectiveVisibility.privateApi
private val prohibitProtectedCallFromInline: Boolean =
session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitProtectedCallFromInline)
override fun visitElement(element: FirElement, data: CheckerContext) {}
override fun visitFunctionCall(functionCall: FirFunctionCall, data: CheckerContext) {
val targetSymbol = functionCall.toResolvedCallableSymbol()
checkReceiversOfQualifiedAccessExpression(functionCall, targetSymbol, data)
checkArgumentsOfCall(functionCall, targetSymbol, data)
checkQualifiedAccess(functionCall, targetSymbol, data)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
val targetSymbol = qualifiedAccessExpression.toResolvedCallableSymbol()
checkQualifiedAccess(qualifiedAccessExpression, targetSymbol, data)
checkReceiversOfQualifiedAccessExpression(qualifiedAccessExpression, targetSymbol, data)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
val propertySymbol = variableAssignment.calleeReference.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
val setterSymbol = propertySymbol.fir.setter?.symbol ?: return
checkQualifiedAccess(variableAssignment, setterSymbol, data)
}
private fun checkReceiversOfQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
targetSymbol: AbstractFirBasedSymbol<*>?,
context: CheckerContext
) {
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.dispatchReceiver, targetSymbol, context)
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.extensionReceiver, targetSymbol, context)
}
private fun checkArgumentsOfCall(
functionCall: FirFunctionCall,
targetSymbol: AbstractFirBasedSymbol<*>?,
context: CheckerContext
) {
val calledFunction = (targetSymbol as? FirNamedFunctionSymbol)?.fir ?: return
val argumentMapping = functionCall.resolvedArgumentMapping ?: return
for ((wrappedArgument, valueParameter) in argumentMapping) {
val argument = wrappedArgument.unwrapArgument()
val resolvedArgumentSymbol = argument.toResolvedCallableSymbol() as? FirVariableSymbol<*> ?: continue
val valueParameterOfOriginalInlineFunction = inlinableParameters.firstOrNull { it == resolvedArgumentSymbol.fir }
if (valueParameterOfOriginalInlineFunction != null) {
val factory = when {
calledFunction.isInline -> when {
valueParameter.isNoinline -> FirErrors.USAGE_IS_NOT_INLINABLE
valueParameter.isCrossinline && !valueParameterOfOriginalInlineFunction.isCrossinline
-> FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
else -> continue
}
else -> FirErrors.USAGE_IS_NOT_INLINABLE
}
reporter.reportOn(argument.source, factory, valueParameterOfOriginalInlineFunction.symbol, context)
}
}
}
private fun checkReceiver(
qualifiedAccessExpression: FirQualifiedAccessExpression,
receiverExpression: FirExpression,
targetSymbol: AbstractFirBasedSymbol<*>?,
context: CheckerContext
) {
val receiverSymbol = receiverExpression.toResolvedCallableSymbol() ?: return
if (receiverSymbol.fir in inlinableParameters) {
val valueParameter = receiverSymbol.fir as FirValueParameter
if (!isInvokeOrInlineExtension(targetSymbol)) {
reporter.reportOn(
qualifiedAccessExpression.source,
FirErrors.USAGE_IS_NOT_INLINABLE,
valueParameter.symbol,
context
)
}
}
}
private fun isInvokeOrInlineExtension(targetSymbol: AbstractFirBasedSymbol<*>?): Boolean {
if (targetSymbol !is FirNamedFunctionSymbol) return false
val function = targetSymbol.fir
if (function.isInline) return true
return function.name == OperatorNameConventions.INVOKE &&
function.dispatchReceiverType?.isBuiltinFunctionalType(session) == true
}
private fun checkQualifiedAccess(
qualifiedAccess: FirQualifiedAccess,
targetSymbol: AbstractFirBasedSymbol<*>?,
context: CheckerContext
) {
val source = qualifiedAccess.source ?: return
if (targetSymbol == null) return
val targetFir = targetSymbol.fir as? FirCallableMemberDeclaration<*>
if (targetSymbol.fir in inlinableParameters) {
if (!qualifiedAccess.partOfCall(context)) {
val valueParameter = targetSymbol.fir as FirValueParameter
reporter.reportOn(source, FirErrors.USAGE_IS_NOT_INLINABLE, valueParameter.symbol, context)
}
}
checkVisibilityAndAccess(qualifiedAccess, targetFir, source, context)
checkRecursion(targetSymbol, source, context)
}
private fun FirQualifiedAccess.partOfCall(context: CheckerContext): Boolean {
if (this !is FirExpression) return false
val containingQualifiedAccess = context.qualifiedAccesses.getOrNull(context.qualifiedAccesses.size - 2) ?: return false
if (this == containingQualifiedAccess.explicitReceiver) return true
val call = containingQualifiedAccess as? FirCall ?: return false
return call.arguments.any { it.unwrapArgument() == this }
}
private fun checkVisibilityAndAccess(
accessExpression: FirQualifiedAccess,
calledDeclaration: FirCallableMemberDeclaration<*>?,
source: FirSourceElement,
context: CheckerContext
) {
if (calledDeclaration == null) return
val recordedEffectiveVisibility = calledDeclaration.publishedApiEffectiveVisibility ?: calledDeclaration.effectiveVisibility
val calledFunEffectiveVisibility = recordedEffectiveVisibility.let {
if (it == EffectiveVisibility.Local) {
EffectiveVisibility.Public
} else {
it
}
}
val isCalledFunPublicOrPublishedApi = calledFunEffectiveVisibility.publicApi
val isInlineFunPublicOrPublishedApi = inlineFunEffectiveVisibility.publicApi
if (isInlineFunPublicOrPublishedApi &&
!isCalledFunPublicOrPublishedApi &&
calledDeclaration.visibility !== Visibilities.Local
) {
reporter.reportOn(
source,
FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE,
calledDeclaration.symbol,
inlineFunction.symbol,
context
)
} else {
checkPrivateClassMemberAccess(calledDeclaration, source, context)
if (isInlineFunPublicOrPublishedApi) {
checkSuperCalls(calledDeclaration, accessExpression, context)
}
}
val isConstructorCall = calledDeclaration is FirConstructor
if (
isInlineFunPublicOrPublishedApi &&
inlineFunEffectiveVisibility.toVisibility() !== Visibilities.Protected &&
calledFunEffectiveVisibility.toVisibility() === Visibilities.Protected
) {
val factory = when {
isConstructorCall -> FirErrors.PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE
prohibitProtectedCallFromInline -> FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR
else -> FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE
}
reporter.reportOn(source, factory, calledDeclaration.symbol, inlineFunction.symbol, context)
}
}
private fun checkPrivateClassMemberAccess(
calledDeclaration: FirCallableMemberDeclaration<*>,
source: FirSourceElement,
context: CheckerContext
) {
if (!isEffectivelyPrivateApiFunction) {
if (calledDeclaration.isInsidePrivateClass()) {
reporter.reportOn(
source,
FirErrors.PRIVATE_CLASS_MEMBER_FROM_INLINE,
calledDeclaration.symbol,
inlineFunction.symbol,
context
)
}
}
}
private fun checkSuperCalls(
calledDeclaration: FirCallableMemberDeclaration<*>,
callExpression: FirQualifiedAccess,
context: CheckerContext
) {
val receiver = callExpression.dispatchReceiver as? FirQualifiedAccessExpression ?: return
if (receiver.calleeReference is FirSuperReference) {
val dispatchReceiverType = receiver.dispatchReceiver.typeRef.coneType
val classSymbol = dispatchReceiverType.toSymbol(session) ?: return
if (!classSymbol.isDefinedInInlineFunction()) {
reporter.reportOn(
callExpression.dispatchReceiver.source,
FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE,
calledDeclaration.symbol,
context
)
}
}
}
private fun AbstractFirBasedSymbol<*>.isDefinedInInlineFunction(): Boolean {
return when (val fir = this.fir) {
is FirAnonymousFunction -> true
is FirMemberDeclaration -> fir.isLocalMember
is FirAnonymousObject -> true
is FirRegularClass -> fir.classId.isLocal
else -> error("Unknown callable declaration type: ${fir.render()}")
}
}
private fun checkRecursion(
targetSymbol: AbstractFirBasedSymbol<*>,
source: FirSourceElement,
context: CheckerContext
) {
if (targetSymbol == inlineFunction.symbol) {
reporter.reportOn(source, FirErrors.RECURSION_IN_INLINE, targetSymbol, context)
}
}
private fun FirCallableMemberDeclaration<*>.isInsidePrivateClass(): Boolean {
val containingClass = this.containingClass()?.toSymbol(session)?.fir ?: return false
val containingClassVisibility = when (containingClass) {
is FirAnonymousObject -> return false
is FirRegularClass -> containingClass.visibility
is FirTypeAlias -> containingClass.visibility
}
return containingClassVisibility == Visibilities.Private || containingClassVisibility == Visibilities.PrivateToThis
}
}
}

View File

@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.contains
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -12,7 +12,9 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfo
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfoCollector
import org.jetbrains.kotlin.fir.analysis.checkers.contains
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty

View File

@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration.jvm
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifier
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.isAbstract
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.coneType
object FirConstructorCallChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
val constructorSymbol =
(expression.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol ?: return
val declarationClass = constructorSymbol.fir.returnTypeRef.coneType.toRegularClass(context.session)
if (declarationClass != null && declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
}
}
}

View File

@@ -0,0 +1,226 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import com.intellij.lang.LighterASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
import org.jetbrains.kotlin.psi.stubs.elements.KtDotQualifiedExpressionElementType
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
import org.jetbrains.kotlin.psi.stubs.elements.KtParameterElementType
object FirReservedUnderscoreExpressionChecker : FirBasicExpressionChecker() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val source = expression.source
if (expression is FirFunctionCall) {
val calleeReferenceSource = expression.calleeReference.source
if (calleeReferenceSource is FirLightSourceElement && calleeReferenceSource.lighterASTNode.tokenType == KtNodeTypes.OPERATION_REFERENCE) {
return
}
reportIfUnderscore(
expression.calleeReference.source.text, expression.calleeReference.source, context, reporter,
isExpression = true
)
} else if (expression is FirQualifiedAccess) {
if (source is FirPsiSourceElement<*>) {
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
} else if (source is FirLightSourceElement) {
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
}
} else if (expression is FirGetClassCall) {
for (argument in expression.argumentList.arguments) {
reportIfUnderscore(argument.source.text, expression.source, context, reporter, isExpression = true)
}
} else if (expression is FirReturnExpression) {
var labelName: String? = null
if (source is FirPsiSourceElement<*>) {
labelName = (source.psi.parent as? KtLabeledExpression)?.getLabelName()
} else if (source is FirLightSourceElement) {
val parent = source.treeStructure.getParent(source.lighterASTNode)
if (parent != null && parent.tokenType == KtNodeTypes.LABELED_EXPRESSION) {
labelName = source.treeStructure.findDescendantByType(parent, KtNodeTypes.LABEL).toString()
labelName = labelName.substring(0, labelName.length - 1)
}
}
reportIfUnderscore(labelName, expression.source, context, reporter)
}
}
private fun reportIfUnderscoreInQualifiedAccess(
source: FirPsiSourceElement<*>,
expression: FirStatement,
context: CheckerContext,
reporter: DiagnosticReporter
) {
fun processQualifiedAccess(psi: PsiElement?) {
if (psi is KtNameReferenceExpression) {
reportIfUnderscore(psi.text, expression.source, context, reporter, isExpression = true)
} else if (psi is KtDotQualifiedExpression || psi is KtCallableReferenceExpression) {
processQualifiedAccess(psi.firstChild)
processQualifiedAccess(psi.lastChild)
}
}
val psi = source.psi
if (psi.parent !is KtDotQualifiedExpression && psi.parent !is KtCallableReferenceExpression) {
processQualifiedAccess(psi)
}
}
private fun reportIfUnderscoreInQualifiedAccess(
source: FirLightSourceElement,
expression: FirStatement,
context: CheckerContext,
reporter: DiagnosticReporter
) {
fun processQualifiedAccess(lightSourceElement: LighterASTNode?) {
val tokenType = lightSourceElement?.tokenType
if (tokenType is KtNameReferenceExpressionElementType) {
reportIfUnderscore(lightSourceElement.toString(), expression.source, context, reporter, isExpression = true)
} else if (lightSourceElement != null && (tokenType is KtDotQualifiedExpressionElementType || tokenType == KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION)) {
val children = lightSourceElement.getChildren(source.treeStructure)
processQualifiedAccess(children.first())
processQualifiedAccess(children.last())
}
}
val astNode = source.lighterASTNode
val parent = source.treeStructure.getParent(astNode)
if (parent?.tokenType !is KtDotQualifiedExpressionElementType && parent?.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION) {
processQualifiedAccess(astNode)
}
}
}
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (
declaration is FirClass<*> ||
declaration is FirFunction<*> ||
declaration is FirTypeParameter ||
declaration is FirProperty ||
declaration is FirTypeAlias
) {
reportIfUnderscore(declaration, context, reporter)
if (declaration is FirFunction<*>) {
for (parameter in declaration.valueParameters) {
reportIfUnderscore(
parameter,
context,
reporter,
isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
)
}
}
} else if (declaration is FirFile) {
for (import in declaration.imports) {
reportIfUnderscore(import.aliasName?.asString(), import.source, context, reporter)
}
}
}
}
private fun reportIfUnderscore(
declaration: FirDeclaration,
context: CheckerContext,
reporter: DiagnosticReporter,
isSingleUnderscoreAllowed: Boolean = false
) {
val source = declaration.source
val rawIdentifier = when (source) {
is FirPsiSourceElement<*> ->
(source.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
is FirLightSourceElement ->
source.treeStructure.nameIdentifier(source.lighterASTNode)?.toString()
else ->
null
}
reportIfUnderscore(rawIdentifier, source, context, reporter, isSingleUnderscoreAllowed)
fun reportIfAnyDescendantIsUnderscore(typeRefSource: FirSourceElement?) {
if (typeRefSource == null) return
val isReport = when (typeRefSource) {
is FirPsiSourceElement<*> -> {
val psi = typeRefSource.psi
psi !is KtFunctionLiteral && psi.anyDescendantOfType<LeafPsiElement> { isUnderscore(it.text) }
}
is FirLightSourceElement ->
source?.treeStructure?.findFirstDescendant(typeRefSource.lighterASTNode) { node -> isUnderscore(node.toString()) } != null
else ->
false
}
if (isReport) {
reporter.reportOn(
typeRefSource,
FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
context
)
}
}
if (declaration is FirValueParameter) {
val isReport = when (val returnTypeRefSource = declaration.returnTypeRef.source) {
is FirPsiSourceElement<*> -> {
val psi = returnTypeRefSource.psi
psi !is KtFunctionLiteral && psi !is KtParameter
}
is FirLightSourceElement -> {
val tokenType = returnTypeRefSource.lighterASTNode.tokenType
tokenType !is KtParameterElementType && tokenType != KtNodeTypes.CLASS
}
else -> {
false
}
}
if (isReport) {
reportIfAnyDescendantIsUnderscore(declaration.returnTypeRef.source)
}
} else if (declaration is FirFunction<*>) {
reportIfAnyDescendantIsUnderscore(declaration.receiverTypeRef?.source)
}
}
private fun reportIfUnderscore(
text: CharSequence?,
source: FirSourceElement?,
context: CheckerContext,
reporter: DiagnosticReporter,
isSingleUnderscoreAllowed: Boolean = false,
isExpression: Boolean = false
) {
if (text == null || isSingleUnderscoreAllowed && text == "_") {
return
}
if (isUnderscore(text)) {
reporter.reportOn(
source,
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
context
)
}
}
private fun isUnderscore(text: CharSequence) = text.all { it == '_' }

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRefWithNullability
import org.jetbrains.kotlin.lexer.KtTokens
object FirSuspendModifierChecker : FirTypeRefChecker() {
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
// We are only interested in source type refs (i.e., Fir(Dynamic|User|Function)TypeRef).
if (typeRef !is FirTypeRefWithNullability) return
val suspendModifier = typeRef.getModifier(KtTokens.SUSPEND_KEYWORD) ?: return
// `suspend` is invalid for non-function types (i.e., FirDynamicTypeRef or FirUserTypeRef).
//
// It is also invalid for nullable function types, e.g., `suspend (() -> Int)?`.
// The correct way to denote a nullable suspend function type is `(suspend () -> Int)?`.
// (To clarify: You can "mark nullable" a suspend function type, but you cannot "mark suspend" a nullable function type.)
//
// In both invalid and correct cases, the source for the FirFunctionTypeRef is the TYPE_REFERENCE element.
// In the invalid case, the `suspend` modifier is in the source TYPE_REFERENCE element.
// But in the correct case, the `suspend` modifier is in the child NULLABLE_TYPE element, i.e., the source TYPE_REFERENCE element
// will not have the `suspend` modifier.
//
// In both cases, the FirFunctionTypeRef is marked nullable. But it is invalid to have the `suspend` modifier on the source element.
if (typeRef !is FirFunctionTypeRef || typeRef.isMarkedNullable) {
reporter.reportOn(
suspendModifier.source,
FirErrors.WRONG_MODIFIER_TARGET,
suspendModifier.token,
"non-functional type",
context
)
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.types.FirTypeRef
abstract class FirTypeChecker<in T : FirTypeRef> {
/**
* [FirTypeChecker] should only be used when the check can be performed independent of the context of the type refs. That is,
* you should NOT be examining containing declarations, qualified accesses, etc. when writing a FirTypeChecker.
*
* If the check is dependent on context, or if it is specific to type refs in a certain kind of declaration or expression,
* please write a [org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker] or
* [org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker] instead.
*/
abstract fun check(typeRef: T, context: CheckerContext, reporter: DiagnosticReporter)
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.util
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
import org.jetbrains.kotlin.fir.visitors.FirVisitor
fun FirElement.checkChildrenWithCustomVisitor(
parentContext: CheckerContext,
visitorVoid: FirVisitor<Unit, CheckerContext>
) {
val collectingVisitor = object : AbstractDiagnosticCollectorVisitor(parentContext as PersistentCheckerContext) {
override fun checkElement(element: FirElement) {
element.accept(visitorVoid, context)
}
}
this.accept(collectingVisitor, null)
}

View File

@@ -72,6 +72,7 @@ fun AbstractDiagnosticCollector.registerAllComponents() {
initializeComponents(
DeclarationCheckersDiagnosticComponent(this),
ExpressionCheckersDiagnosticComponent(this),
TypeCheckersDiagnosticComponent(this),
ErrorNodeDiagnosticCollectorComponent(this),
ControlFlowAnalysisDiagnosticComponent(this),
)

View File

@@ -15,11 +15,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.name.Name
@@ -30,7 +27,10 @@ abstract class AbstractDiagnosticCollectorVisitor(
protected open fun shouldVisitDeclaration(declaration: FirDeclaration) = true
protected open fun onDeclarationExit(declaration: FirDeclaration) {}
protected abstract fun visitNestedElements(element: FirElement)
protected open fun visitNestedElements(element: FirElement) {
element.acceptChildren(this, null)
}
protected abstract fun checkElement(element: FirElement)
override fun visitElement(element: FirElement, data: Nothing?) {
@@ -165,7 +165,12 @@ abstract class AbstractDiagnosticCollectorVisitor(
}
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?) {
super.visitResolvedTypeRef(resolvedTypeRef, data)
// Assuming no errors, the children of FirResolvedTypeRef (currently this can be FirAnnotationCalls) will also be present
// as children in delegatedTypeRef. We should make sure those elements are only visited once, otherwise diagnostics will be
// collected twice: once through resolvedTypeRef's children and another through resolvedTypeRef.delegatedTypeRef's children.
if (resolvedTypeRef.type is ConeClassErrorType) {
super.visitResolvedTypeRef(resolvedTypeRef, data)
}
resolvedTypeRef.delegatedTypeRef?.accept(this, data)
}
@@ -208,15 +213,13 @@ abstract class AbstractDiagnosticCollectorVisitor(
private fun visitWithQualifiedAccess(qualifiedAccess: FirQualifiedAccess) {
return withQualifiedAccess(qualifiedAccess) {
checkElement(qualifiedAccess)
visitNestedElements(qualifiedAccess)
visitElement(qualifiedAccess, null)
}
}
private fun visitWithGetClassCall(getClassCall: FirGetClassCall) {
return withGetClassCall(getClassCall) {
checkElement(getClassCall)
visitNestedElements(getClassCall)
visitElement(getClassCall, null)
}
}
@@ -301,4 +304,4 @@ abstract class AbstractDiagnosticCollectorVisitor(
allErrorsSuppressed = AbstractDiagnosticCollector.SUPPRESS_ALL_ERRORS in arguments
)
}
}
}

View File

@@ -14,10 +14,6 @@ open class CheckerRunningDiagnosticCollectorVisitor(
protected val components: List<AbstractDiagnosticCollectorComponent>
) : AbstractDiagnosticCollectorVisitor(context) {
override fun visitNestedElements(element: FirElement) {
element.acceptChildren(this, null)
}
override fun checkElement(element: FirElement) {
components.forEach {
element.accept(it, context)

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeChecker
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.types.*
@OptIn(CheckersComponentInternal::class)
class TypeCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: TypeCheckers = collector.session.checkersComponent.typeCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(dynamicTypeRef, data, reporter)
}
override fun visitFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(functionTypeRef, data, reporter)
}
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(userTypeRef, data, reporter)
}
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(resolvedTypeRef, data, reporter)
}
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(errorTypeRef, data, reporter)
}
override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability, data: CheckerContext) {
checkers.allTypeRefCheckers.check(typeRefWithNullability, data, reporter)
}
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(implicitTypeRef, data, reporter)
}
override fun visitTypeRef(typeRef: FirTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(typeRef, data, reporter)
}
private fun <T : FirTypeRef> Collection<FirTypeChecker<T>>.check(
typeRef: T,
context: CheckerContext,
reporter: DiagnosticReporter
) {
for (checker in this) {
checker.check(typeRef, context, reporter)
}
}
}

View File

@@ -71,6 +71,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITHOUT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
@@ -169,9 +170,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
@@ -192,6 +195,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTI
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_CLASS_MEMBER_FROM_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_FUNCTION_WITH_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_PROPERTY_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY
@@ -202,8 +206,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALI
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD
@@ -234,6 +242,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_NOT_INITIALIZED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_IS_NOT_AN_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_NOT_AVAILABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX
@@ -268,6 +277,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATU
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USAGE_IS_NOT_INLINABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIGHT_IS_NULL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
@@ -345,6 +355,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
"Cannot access ''{0}'' before superclass constructor has been called",
TO_STRING
)
map.put(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, "Cannot create an instance of an abstract class")
// Supertypes
map.put(ENUM_AS_SUPERTYPE, "Enum as supertype")
@@ -903,6 +914,45 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
"Returns are not allowed for functions with expression body. Use block body in '{...}'"
)
// Inline
map.put(
USAGE_IS_NOT_INLINABLE,
"Illegal usage of inline-parameter ''{0}''. Add ''noinline'' modifier to the parameter declaration",
SYMBOL
)
map.put(
NON_LOCAL_RETURN_NOT_ALLOWED,
"Can''t inline ''{0}'' here: it may contain non-local returns. Add ''crossinline'' modifier to parameter declaration ''{0}''",
SYMBOL
)
map.put(RECURSION_IN_INLINE, "Inline function ''{0}'' cannot be recursive", SYMBOL)
map.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{1}''", SYMBOL, SYMBOL)
map.put(
PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE,
"Protected constructor call from public-API inline function is deprecated",
SYMBOL,
SYMBOL
)
map.put(
PROTECTED_CALL_FROM_PUBLIC_INLINE,
"Protected function call from public-API inline function is deprecated",
SYMBOL,
SYMBOL
)
map.put(
PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR,
"Protected function call from public-API inline function is prohibited",
SYMBOL,
SYMBOL
)
map.put(
PRIVATE_CLASS_MEMBER_FROM_INLINE,
"Non-private inline function cannot access members of private classes: ''{1}''",
SYMBOL,
SYMBOL
)
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
// Extended checkers group
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")

View File

@@ -642,6 +642,31 @@ object LightTreePositioningStrategies {
return markElement(tree.typeParametersList(node) ?: node, startOffset, endOffset, tree, node)
}
}
val RESERVED_UNDERSCORE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
if (node.tokenType == KtNodeTypes.RETURN) {
val parent = tree.getParent(node)
if (parent != null) {
val label = tree.findDescendantByType(parent, KtNodeTypes.LABEL)
if (label != null) {
return markElement(label, startOffset, endOffset - 1, tree, node)
}
}
}
val descendants =
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } };
if (descendants.isNotEmpty())
return descendants.map { markSingleElement(it, it, startOffset, endOffset, tree, node) }
return super.mark(node, startOffset, endOffset, tree)
}
}
}
fun FirSourceElement.hasValOrVar(): Boolean =
@@ -855,6 +880,35 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.findFirstDescendant(
?: childrenRef.get()?.firstNotNullResult { child -> child?.let { findFirstDescendant(it, predicate) } }
}
fun FlyweightCapableTreeStructure<LighterASTNode>.collectDescendantsOfType(
node: LighterASTNode, type: IElementType,
predicate: (LighterASTNode) -> Boolean = { true }
): List<LighterASTNode> {
val result = mutableListOf<LighterASTNode>()
fun FlyweightCapableTreeStructure<LighterASTNode>.collectDescendantByType(node: LighterASTNode) {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
val childrenRefGet = childrenRef.get()
if (childrenRefGet != null) {
for (child in childrenRefGet) {
if (child?.tokenType == type && predicate(child)) {
result.add(child)
}
if (child != null) {
collectDescendantByType(child)
}
}
}
}
collectDescendantByType(node)
return result
}
private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: TokenSet): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)

View File

@@ -46,11 +46,22 @@ fun markRange(
tree: FlyweightCapableTreeStructure<LighterASTNode>,
originalNode: LighterASTNode
): List<TextRange> {
return listOf(markSingleElement(from, to, startOffset, endOffset, tree, originalNode))
}
fun markSingleElement(
from: LighterASTNode,
to: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
originalNode: LighterASTNode
): TextRange {
val betterFrom = from.nonFillerFirstChildOrSelf(tree)
val betterTo = to.nonFillerLastChildOrSelf(tree)
val startDelta = tree.getStartOffset(betterFrom) - tree.getStartOffset(originalNode)
val endDelta = tree.getEndOffset(betterTo) - tree.getEndOffset(originalNode)
return listOf(TextRange(startDelta + startOffset, endDelta + endOffset))
return TextRange(startDelta + startOffset, endDelta + endOffset)
}
private val DOC_AND_COMMENT_TOKENS = setOf(

View File

@@ -228,4 +228,9 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.TYPE_PARAMETERS_LIST,
PositioningStrategies.TYPE_PARAMETERS_LIST
)
val RESERVED_UNDERSCORE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.RESERVED_UNDERSCORE,
PositioningStrategies.RESERVED_UNDERSCORE
)
}

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.extensions
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
import org.jetbrains.kotlin.fir.extensions.AbstractFirAdditionalCheckersExtension
import org.jetbrains.kotlin.fir.extensions.FirExtensionPointName
import org.jetbrains.kotlin.fir.extensions.FirExtensionService
@@ -19,6 +20,7 @@ abstract class FirAdditionalCheckersExtension(session: FirSession) : AbstractFir
open val declarationCheckers: DeclarationCheckers = DeclarationCheckers.EMPTY
open val expressionCheckers: ExpressionCheckers = ExpressionCheckers.EMPTY
open val typeCheckers: TypeCheckers = TypeCheckers.EMPTY
final override val name: FirExtensionPointName
get() = NAME

View File

@@ -69,7 +69,7 @@ fun ConeKotlinType.renderFunctionType(
kind: FunctionClassKind?, isExtension: Boolean, renderType: ConeTypeProjection.() -> String = { render() }
): String {
if (!kind.withPrettyRender()) return renderType()
return buildString {
val renderedType = buildString {
if (kind == FunctionClassKind.SuspendFunction) {
append("suspend ")
}
@@ -88,6 +88,7 @@ fun ConeKotlinType.renderFunctionType(
append(" -> ")
append(returnType.renderType())
}
return if (isMarkedNullable) "($renderedType)?" else renderedType
}
@OptIn(ExperimentalContracts::class)

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.session.FirSessionFactory
fun FirSessionFactory.FirSessionConfigurator.registerCommonCheckers() {
useCheckers(CommonDeclarationCheckers)
useCheckers(CommonExpressionCheckers)
useCheckers(CommonTypeCheckers)
}
fun FirSessionFactory.FirSessionConfigurator.registerExtendedCommonCheckers() {

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirReservedUnderscoreDeclarationChecker
object CommonDeclarationCheckers : DeclarationCheckers() {
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
@@ -20,6 +21,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirConflictsChecker,
FirConflictingProjectionChecker,
FirTypeConstraintsChecker,
FirReservedUnderscoreDeclarationChecker
)
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
@@ -29,6 +31,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirSealedSupertypeChecker,
FirTypeAliasChecker,
FirCyclicTypeBoundsChecker,
FirInlineDeclarationChecker,
)
override val functionCheckers: Set<FirFunctionChecker>

View File

@@ -15,6 +15,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf(
FirReservedUnderscoreExpressionChecker
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
@@ -31,13 +32,14 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirTypeParameterInQualifiedAccessChecker,
FirSealedClassConstructorCallChecker,
FirUninitializedEnumChecker,
FirFunInterfaceConstructorReferenceChecker,
FirFunInterfaceConstructorReferenceChecker
)
override val functionCallCheckers: Set<FirFunctionCallChecker>
get() = setOf(
FirConventionFunctionCallChecker,
FirDivisionByZeroChecker
FirDivisionByZeroChecker,
FirConstructorCallChecker
)
override val tryExpressionCheckers: Set<FirTryExpressionChecker>

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.checkers
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.cfa.FirCallsEffectAnalyzer
import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirSuspendModifierChecker
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
object CommonTypeCheckers : TypeCheckers() {
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
FirSuspendModifierChecker
)
}

View File

@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
@@ -53,6 +54,10 @@ object FirSessionFactory {
session.checkersComponent.register(checkers)
}
fun useCheckers(checkers: TypeCheckers) {
session.checkersComponent.register(checkers)
}
@SessionConfiguration
fun configure() {
session.extensionService.registerExtensions(registeredExtensions.reduce(BunchOfRegisteredExtensions::plus))

View File

@@ -234,6 +234,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags))
val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
if (Flags.IS_NOT_DEFAULT.get(getterFlags)) {
buildPropertyAccessor {
declarationSiteSession = c.session
@@ -244,7 +245,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
status = FirResolvedDeclarationStatusImpl(
visibility,
modality,
visibility.toEffectiveVisibility(classSymbol)
effectiveVisibility
).apply {
isInline = Flags.IS_INLINE_ACCESSOR.get(getterFlags)
isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags)
@@ -255,7 +256,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
versionRequirementsTable = c.versionRequirementTable
}
} else {
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility, effectiveVisibility)
}.apply {
(annotations as MutableList<FirAnnotationCall>) +=
c.annotationDeserializer.loadPropertyGetterAnnotations(
@@ -270,6 +271,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags))
val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
if (Flags.IS_NOT_DEFAULT.get(setterFlags)) {
buildPropertyAccessor {
declarationSiteSession = c.session
@@ -280,7 +282,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
status = FirResolvedDeclarationStatusImpl(
visibility,
modality,
visibility.toEffectiveVisibility(classSymbol)
effectiveVisibility
).apply {
isInline = Flags.IS_INLINE_ACCESSOR.get(setterFlags)
isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags)
@@ -297,7 +299,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
versionRequirementsTable = c.versionRequirementTable
}
} else {
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility, effectiveVisibility)
}.apply {
(annotations as MutableList<FirAnnotationCall>) +=
c.annotationDeserializer.loadPropertySetterAnnotations(

View File

@@ -13,19 +13,19 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.AbstractTypeMapper
import org.jetbrains.kotlin.types.TypeMappingContext
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -50,6 +50,9 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext<JvmSignatur
return typeConstructor.classId.asString().replace(".", "$").replace("/", ".")
}
override fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String =
TODO("Not yet implemented")
override fun JvmSignatureWriter.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode) {
if (type !is ConeClassLikeType) return
if (skipGenericSignature() || hasNothingInNonContravariantPosition(type) || type.typeArguments.isEmpty()) {

View File

@@ -55,10 +55,11 @@ class Fir2IrConverter(
processClassMembers(regularClass, irClass)
}
fun registerFileAndClasses(file: FirFile): IrFile {
fun registerFileAndClasses(file: FirFile, moduleFragment: IrModuleFragment) {
val irFile = IrFileImpl(
PsiIrFileEntry(file.psi as KtFile),
moduleDescriptor.getPackage(file.packageFqName).fragments.first()
moduleDescriptor.getPackage(file.packageFqName).fragments.first(),
moduleFragment
)
declarationStorage.registerFile(file, irFile)
file.declarations.forEach {
@@ -66,7 +67,7 @@ class Fir2IrConverter(
registerClassAndNestedClasses(it, irFile)
}
}
return irFile
moduleFragment.files += irFile
}
fun processClassHeaders(file: FirFile) {
@@ -279,12 +280,11 @@ class Fir2IrConverter(
components.visibilityConverter = visibilityConverter
components.builtIns = builtIns
components.annotationGenerator = annotationGenerator
val irFiles = mutableListOf<IrFile>()
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
for (firFile in firFiles) {
irFiles += converter.registerFileAndClasses(firFile)
converter.registerFileAndClasses(firFile, irModuleFragment)
}
val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns, irFiles)
val irProviders =
generateTypicalIrProviderList(irModuleFragment.descriptor, irBuiltIns, symbolTable, extensions = generatorExtensions)
val externalDependenciesGenerator = ExternalDependenciesGenerator(

View File

@@ -529,7 +529,7 @@ class CallAndReferenceGenerator(
}
private fun IrMemberAccessExpression<*>.applyArgumentsWithReorderingIfNeeded(
argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>,
argumentMapping: Map<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>,
substitutor: ConeSubstitutor,
annotationMode: Boolean

View File

@@ -2794,6 +2794,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/isAs.kt");
}
@Test
@TestMetadata("nullableParameter.kt")
public void testNullableParameter() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/nullableParameter.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
@@ -8653,6 +8659,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
}
@Test
@TestMetadata("nonLocalReturnInTryFinally.kt")
public void testNonLocalReturnInTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
}
@Test
@TestMetadata("splitTry.kt")
public void testSplitTry() throws Exception {
@@ -9252,6 +9264,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt");
}
@Test
@TestMetadata("nullableSuspendFunctionType.kt")
public void testNullableSuspendFunctionType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/nullableSuspendFunctionType.kt");
}
@Test
@TestMetadata("overrideDefaultArgument.kt")
public void testOverrideDefaultArgument() throws Exception {
@@ -9354,6 +9372,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/suspendFunImportedFromObject.kt");
}
@Test
@TestMetadata("suspendFunctionAsSupertype.kt")
public void testSuspendFunctionAsSupertype() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/suspendFunctionAsSupertype.kt");
}
@Test
@TestMetadata("suspendFunctionMethodReference.kt")
public void testSuspendFunctionMethodReference() throws Exception {
@@ -9777,6 +9801,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
}
@Test
@TestMetadata("overrideInInnerClass.kt")
public void testOverrideInInnerClass() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt");
}
@Test
@TestMetadata("safeCallOnTwoReceivers.kt")
public void testSafeCallOnTwoReceivers() throws Exception {
@@ -17160,6 +17190,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/kt39824.kt");
}
@Test
@TestMetadata("kt42042.kt")
public void testKt42042() throws Exception {
runTest("compiler/testData/codegen/box/inference/kt42042.kt");
}
@Test
@TestMetadata("kt42130.kt")
public void testKt42130() throws Exception {
@@ -17184,6 +17220,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
}
@Test
@TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt")
public void testManyConstraintsDueToFlexibleRawTypes() throws Exception {
runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt");
}
@Test
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
@@ -17268,6 +17310,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
}
@Test
@TestMetadata("violatingUpperBoundForSelfType.kt")
public void testViolatingUpperBoundForSelfType() throws Exception {
runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/inference/builderInference")
@TestDataPath("$PROJECT_ROOT")
@@ -38591,6 +38639,22 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/script")
@TestDataPath("$PROJECT_ROOT")
public class Script {
@Test
public void testAllFilesPresentInScript() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/script"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("classReference.kt")
public void testClassReference() throws Exception {
runTest("compiler/testData/codegen/box/script/classReference.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/sealed")
@TestDataPath("$PROJECT_ROOT")
@@ -41086,6 +41150,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsForMaxLongValue.kt");
}
@Test
@TestMetadata("unsignedLiteralsInApiVersion14.kt")
public void testUnsignedLiteralsInApiVersion14() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsInApiVersion14.kt");
}
@Test
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {

View File

@@ -3702,6 +3702,18 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt");
}
@Test
@TestMetadata("kt44770.kt")
public void testKt44770() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt44770.kt");
}
@Test
@TestMetadata("kt44770_2.kt")
public void testKt44770_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
}
@Test
@TestMetadata("kt6988.kt")
public void testKt6988() throws Exception {

View File

@@ -238,6 +238,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
runTest("compiler/testData/ir/irText/classes/kt43217.kt");
}
@Test
@TestMetadata("kt44013.kt")
public void testKt44013() throws Exception {
runTest("compiler/testData/ir/irText/classes/kt44013.kt");
}
@Test
@TestMetadata("kt45853.kt")
public void testKt45853() throws Exception {

View File

@@ -916,7 +916,8 @@ class DeclarationsConverter(
}
constructedTypeRef = delegatedType.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
this.isThis = isThis
val calleeKind = if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
val calleeKind =
if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
val calleeSource = constructorDelegationCall.getChildNodeByType(CONSTRUCTOR_DELEGATION_REFERENCE)
?.toFirSourceElement(calleeKind)
?: this@buildDelegatedConstructorCall.source?.fakeElement(calleeKind)
@@ -1281,7 +1282,8 @@ class DeclarationsConverter(
CONTRACT_EFFECT -> {
val effect = it.getFirstChild()
if (effect == null) {
val errorExpression = buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected))
val errorExpression =
buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionExpected))
destination.add(errorExpression)
} else {
val expression = expressionConverter.convertExpression(effect, errorReason)
@@ -1671,33 +1673,62 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
*/
fun convertType(type: LighterASTNode): FirTypeRef {
val typeRefSource = type.toFirSourceElement()
if (type.asText.isEmpty()) {
return buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax) }
}
var typeModifiers = TypeModifier()
var firType: FirTypeRef = buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) }
var afterLPar = false
type.forEachChildren {
when (it.tokenType) {
LPAR -> afterLPar = true
TYPE_REFERENCE -> firType = convertType(it)
MODIFIER_LIST -> if (!afterLPar || typeModifiers.hasNoAnnotations()) typeModifiers = convertTypeModifierList(it)
USER_TYPE -> firType = convertUserType(it)
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it)
NULLABLE_TYPE -> firType = convertNullableType(it)
FUNCTION_TYPE -> firType = convertFunctionType(it, isSuspend = typeModifiers.hasSuspend)
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
source = type.toFirSourceElement()
isMarkedNullable = false
}
TokenType.ERROR_ELEMENT -> firType =
buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax) }
return buildErrorTypeRef {
source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax)
}
}
return firType.also { (it.annotations as MutableList<FirAnnotationCall>) += typeModifiers.annotations }
// There can be MODIFIER_LIST children on the TYPE_REFERENCE node AND the descendant NULLABLE_TYPE nodes.
// We aggregate them to get modifiers and annotations. Not only that, there could be multiple modifier lists on each. Examples:
//
// `@A() (@B Int)` -> Has 2 modifier lists (@A and @B) in TYPE_REFERENCE
// `(@A() (@B Int))? -> No modifier list on TYPE_REFERENCE, but 2 modifier lists (@A and @B) on child NULLABLE_TYPE
// `@A() (@B Int)? -> Has 1 modifier list (@A) on TYPE_REFERENCE, and 1 modifier list (@B) on child NULLABLE_TYPE
// `@A (@B() (@C() (@Bar D)?)?)?` -> Has 1 modifier list (@A) on B and 1 modifier list on each of the
// 3 descendant NULLABLE_TYPE (@B, @C, @D)
//
// We need to examine all modifier lists for some cases:
// 1. `@A Int?` and `(@A Int)?` are effectively the same, but in the latter, the modifier list is on the child NULLABLE_TYPE
// 2. `(suspend @A () -> Int)?` is a nullable suspend function type but the modifier list is on the child NULLABLE_TYPE
//
// TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them?
val allTypeModifiers = mutableListOf<TypeModifier>()
var firType: FirTypeRef = buildErrorTypeRef {
source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax)
}
type.forEachChildren {
when (it.tokenType) {
TYPE_REFERENCE -> firType = convertType(it)
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
USER_TYPE -> firType = convertUserType(typeRefSource, it)
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers)
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isSuspend = allTypeModifiers.hasSuspend())
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
source = typeRefSource
isMarkedNullable = false
}
TokenType.ERROR_ELEMENT -> firType =
buildErrorTypeRef {
source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax)
}
}
}
for (modifierList in allTypeModifiers) {
(firType.annotations as MutableList<FirAnnotationCall>) += modifierList.annotations
}
return firType
}
private fun Collection<TypeModifier>.hasSuspend() = any { it.hasSuspend }
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRefContents
*/
@@ -1715,17 +1746,23 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseNullableTypeSuffix
*/
private fun convertNullableType(nullableType: LighterASTNode): FirTypeRef {
private fun convertNullableType(
typeRefSource: FirSourceElement,
nullableType: LighterASTNode,
allTypeModifiers: MutableList<TypeModifier>,
isNullable: Boolean = true
): FirTypeRef {
lateinit var firType: FirTypeRef
nullableType.forEachChildren {
when (it.tokenType) {
USER_TYPE -> firType =
convertUserType(it, true)
FUNCTION_TYPE -> firType = convertFunctionType(it, true)
NULLABLE_TYPE -> firType = convertNullableType(it)
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it, nullable = true)
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
USER_TYPE -> firType = convertUserType(typeRefSource, it, isNullable)
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isNullable, isSuspend = allTypeModifiers.hasSuspend())
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
DEFINITELY_NOT_NULL_TYPE -> firType =
unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers, isNullable = true)
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
source = nullableType.toFirSourceElement()
source = typeRefSource
isMarkedNullable = true
}
}
@@ -1734,18 +1771,23 @@ class DeclarationsConverter(
return firType
}
private fun unwrapDefinitelyNotNullableType(definitelyNotNullType: LighterASTNode, nullable: Boolean = false): FirTypeRef {
private fun unwrapDefinitelyNotNullableType(
typeRefSource: FirSourceElement,
definitelyNotNullType: LighterASTNode,
allTypeModifiers: MutableList<TypeModifier>,
isNullable: Boolean = false
): FirTypeRef {
lateinit var firType: FirTypeRef
// TODO: Support proper DefinitelyNotNullableType
definitelyNotNullType.forEachChildren {
when (it.tokenType) {
USER_TYPE -> firType =
convertUserType(it, nullable)
FUNCTION_TYPE -> firType = convertFunctionType(it, nullable)
NULLABLE_TYPE -> firType = convertNullableType(it)
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(it, nullable)
MODIFIER_LIST -> allTypeModifiers += convertTypeModifierList(it)
USER_TYPE -> firType = convertUserType(typeRefSource, it, isNullable)
FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, isNullable, isSuspend = allTypeModifiers.hasSuspend())
NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers, isNullable = false)
DEFINITELY_NOT_NULL_TYPE -> firType = unwrapDefinitelyNotNullableType(typeRefSource, it, allTypeModifiers, isNullable)
DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
source = definitelyNotNullType.toFirSourceElement()
source = typeRefSource
isMarkedNullable = false
}
}
@@ -1757,32 +1799,37 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseUserType
*/
private fun convertUserType(userType: LighterASTNode, isNullable: Boolean = false): FirTypeRef {
private fun convertUserType(
typeRefSource: FirSourceElement,
userType: LighterASTNode,
isNullable: Boolean = false
): FirTypeRef {
var simpleFirUserType: FirUserTypeRef? = null
var identifier: String? = null
val firTypeArguments = mutableListOf<FirTypeProjection>()
userType.forEachChildren {
when (it.tokenType) {
USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type
USER_TYPE -> simpleFirUserType = convertUserType(typeRefSource, it) as? FirUserTypeRef //simple user type
REFERENCE_EXPRESSION -> identifier = it.asText
TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it)
}
}
if (identifier == null)
return buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax) }
return buildErrorTypeRef {
source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax)
}
// Note: we take TYPE_REFERENCE, not USER_TYPE, as the source (to be consistent with RawFirBuilder)
val theSource = tree.getParent(userType)!!.toFirSourceElement()
val qualifierPart = FirQualifierPartImpl(
identifier.nameAsSafeName(),
FirTypeArgumentListImpl(theSource).apply {
FirTypeArgumentListImpl(typeRefSource).apply {
typeArguments += firTypeArguments
}
)
return buildUserTypeRef {
source = theSource
source = typeRefSource
isMarkedNullable = isNullable
qualifier.add(qualifierPart)
simpleFirUserType?.qualifier?.let { this.qualifier.addAll(0, it) }
@@ -1827,7 +1874,12 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunctionType
*/
private fun convertFunctionType(functionType: LighterASTNode, isNullable: Boolean = false, isSuspend: Boolean = false): FirTypeRef {
private fun convertFunctionType(
typeRefSource: FirSourceElement,
functionType: LighterASTNode,
isNullable: Boolean = false,
isSuspend: Boolean = false
): FirTypeRef {
var receiverTypeReference: FirTypeRef? = null
lateinit var returnTypeReference: FirTypeRef
val valueParametersList = mutableListOf<ValueParameter>()
@@ -1840,7 +1892,7 @@ class DeclarationsConverter(
}
return buildFunctionTypeRef {
source = functionType.toFirSourceElement()
source = typeRefSource
isMarkedNullable = isNullable
receiverTypeRef = receiverTypeReference
returnTypeRef = returnTypeReference

View File

@@ -46,6 +46,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
}
@TestMetadata("annotationsOnParenthesizedTypes.kt")
public void testAnnotationsOnParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
}
@TestMetadata("complexTypes.kt")
public void testComplexTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
@@ -156,6 +166,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
}
@TestMetadata("splitModifierList.kt")
public void testSplitModifierList() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
}
@TestMetadata("suspendFunctionTypes.kt")
public void testSuspendFunctionTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
}
@TestMetadata("typeAliasWithGeneric.kt")
public void testTypeAliasWithGeneric() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");

View File

@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.name.LocalCallableIdConstructor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -1354,11 +1355,37 @@ open class RawFirBuilder(
val source = typeReference.toFirSourceElement()
val isNullable = typeElement is KtNullableType
// There can be KtDeclarationModifierLists in the KtTypeReference AND the descendant KtNullableTypes.
// We aggregate them to get modifiers and annotations. Not only that, there could be multiple modifier lists on each. Examples:
//
// `@A() (@B Int)` -> Has 2 modifier lists (@A and @B) on KtTypeReference
// `(@A() (@B Int))? -> No modifier list on KtTypeReference, but 2 modifier lists (@A and @B) on child KtNullableType
// `@A() (@B Int)? -> Has 1 modifier list (@A) on KtTypeReference, and 1 modifier list (@B) on child KtNullableType
// `@A (@B() (@C() (@Bar D)?)?)?` -> Has 1 modifier list (@A) on KtTypeReference and 1 modifier list on each of the
// 3 descendant KtNullableTypes (@B, @C, @D)
//
// We need to examine all modifier lists for some cases:
// 1. `@A Int?` and `(@A Int)?` are effectively the same, but in the latter, the modifier list is on the child KtNullableType
// 2. `(suspend @A () -> Int)?` is a nullable suspend function type but the modifier list is on the child KtNullableType
//
// `getModifierList()` only returns the first one so we have to get all modifier list children.
// TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them?
fun KtElementImplStub<*>.getAllModifierLists(): Array<out KtDeclarationModifierList> =
getStubOrPsiChildren(KtStubElementTypes.MODIFIER_LIST, KtStubElementTypes.MODIFIER_LIST.arrayFactory)
val allModifierLists = mutableListOf<KtModifierList>(*typeReference.getAllModifierLists())
fun KtTypeElement?.unwrapNullable(): KtTypeElement? =
when (this) {
is KtNullableType -> this.innerType.unwrapNullable()
is KtNullableType -> {
allModifierLists += getAllModifierLists()
this.innerType.unwrapNullable()
}
// TODO: Support explicit definitely not null type
is KtDefinitelyNotNullType -> this.innerType.unwrapNullable()
is KtDefinitelyNotNullType -> {
allModifierLists += getAllModifierLists()
this.innerType.unwrapNullable()
}
else -> this
}
@@ -1403,7 +1430,7 @@ open class RawFirBuilder(
FirFunctionTypeRefBuilder().apply {
this.source = source
isMarkedNullable = isNullable
isSuspend = typeReference.hasModifier(SUSPEND_KEYWORD)
isSuspend = allModifierLists.any { it.hasSuspendModifier() }
receiverTypeRef = unwrappedElement.receiverTypeReference.convertSafe()
// TODO: probably implicit type should not be here
returnTypeRef = unwrappedElement.returnTypeReference.toFirOrErrorType()
@@ -1422,8 +1449,10 @@ open class RawFirBuilder(
else -> throw AssertionError("Unexpected type element: ${unwrappedElement.text}")
}
for (annotationEntry in typeReference.annotationEntries) {
firTypeBuilder.annotations += annotationEntry.convert<FirAnnotationCall>()
for (modifierList in allModifierLists) {
for (annotationEntry in modifierList.annotationEntries) {
firTypeBuilder.annotations += annotationEntry.convert<FirAnnotationCall>()
}
}
return firTypeBuilder.build()
}

View File

@@ -0,0 +1,27 @@
interface AnnotationsOnNullableParenthesizedTypes {
fun B<(@A C)?>.receiverArgument() {}
fun parameter(a: (@A C)?) {}
fun parameterArgument(a: B<(@A C)?>) {}
fun returnValue(): (@A C)?
fun <T> returnTypeParameterValue(): (@A T)?
fun returnArgument(): B<(@A C)?>
val lambdaType: (@A() (() -> C))?
val lambdaParameter: ((@A C)?) -> C
val lambdaReturnValue: () -> (@A C)?
val lambdaReceiver: (@A C)?.() -> C
}
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
annotation class A
interface B<T>
interface C

View File

@@ -0,0 +1,37 @@
FILE: annotationsOnNullableParenthesizedTypes.kt
public? final? interface AnnotationsOnNullableParenthesizedTypes : R|kotlin/Any| {
public? final? fun B<@A() C?>.receiverArgument(): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun parameter(a: @A() C?): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun parameterArgument(a: B<@A() C?>): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun returnValue(): @A() C?
public? final? fun <T> returnTypeParameterValue(): @A() T?
public? final? fun returnArgument(): B<@A() C?>
public? final? val lambdaType: @A() ( () -> C )?
public? get(): @A() ( () -> C )?
public? final? val lambdaParameter: ( (@A() C?) -> C )
public? get(): ( (@A() C?) -> C )
public? final? val lambdaReturnValue: ( () -> @A() C? )
public? get(): ( () -> @A() C? )
public? final? val lambdaReceiver: ( @A() C?.() -> C )
public? get(): ( @A() C?.() -> C )
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public? final? interface B<T> : R|kotlin/Any| {
}
public? final? interface C : R|kotlin/Any| {
}

View File

@@ -0,0 +1,40 @@
FILE: annotationsOnNullableParenthesizedTypes.kt
public? final? interface AnnotationsOnNullableParenthesizedTypes : R|kotlin/Any| {
public? final? fun B<@A() C?>.receiverArgument(): R|kotlin/Unit| {
}
public? final? fun parameter(a: @A() C?): R|kotlin/Unit| {
}
public? final? fun parameterArgument(a: B<@A() C?>): R|kotlin/Unit| {
}
public? final? fun returnValue(): @A() C?
public? final? fun <T> returnTypeParameterValue(): @A() T?
public? final? fun returnArgument(): B<@A() C?>
public? final? val lambdaType: @A() ( () -> C )?
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): @A() ( () -> C )?
public? final? val lambdaParameter: ( (@A() C?) -> C )
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( (@A() C?) -> C )
public? final? val lambdaReturnValue: ( () -> @A() C? )
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( () -> @A() C? )
public? final? val lambdaReceiver: ( @A() C?.() -> C )
[ContainingClassKey=AnnotationsOnNullableParenthesizedTypes] public? get(): ( @A() C?.() -> C )
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? [ContainingClassKey=A] constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public? final? interface B<T> : R|kotlin/Any| {
}
public? final? interface C : R|kotlin/Any| {
}

View File

@@ -0,0 +1,29 @@
interface AnnotationsOnParenthesizedTypes {
fun B<(@A C)>.receiverArgument() {}
fun parameter(a: (@A C)) {}
fun parameterArgument(a: B<(@A C)>) {}
fun returnValue(): (@A C)
fun <T> returnTypeParameterValue(): (@A T)
fun returnArgument(): B<(@A C)>
val lambdaType: (@A() (() -> C))
val lambdaParameter: ((@A C)) -> C
val lambdaReturnValue: () -> (@A C)
val lambdaReceiver: (@A C).() -> C
val lambdaParameterNP: (@A C) -> C
}
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
annotation class A
interface B<T>
interface C

View File

@@ -0,0 +1,40 @@
FILE: annotationsOnParenthesizedTypes.kt
public? final? interface AnnotationsOnParenthesizedTypes : R|kotlin/Any| {
public? final? fun B<@A() C>.receiverArgument(): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun parameter(a: @A() C): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun parameterArgument(a: B<@A() C>): R|kotlin/Unit| { LAZY_BLOCK }
public? final? fun returnValue(): @A() C
public? final? fun <T> returnTypeParameterValue(): @A() T
public? final? fun returnArgument(): B<@A() C>
public? final? val lambdaType: @A() ( () -> C )
public? get(): @A() ( () -> C )
public? final? val lambdaParameter: ( (@A() C) -> C )
public? get(): ( (@A() C) -> C )
public? final? val lambdaReturnValue: ( () -> @A() C )
public? get(): ( () -> @A() C )
public? final? val lambdaReceiver: ( @A() C.() -> C )
public? get(): ( @A() C.() -> C )
public? final? val lambdaParameterNP: ( (@A() C) -> C )
public? get(): ( (@A() C) -> C )
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public? final? interface B<T> : R|kotlin/Any| {
}
public? final? interface C : R|kotlin/Any| {
}

View File

@@ -0,0 +1,43 @@
FILE: annotationsOnParenthesizedTypes.kt
public? final? interface AnnotationsOnParenthesizedTypes : R|kotlin/Any| {
public? final? fun B<@A() C>.receiverArgument(): R|kotlin/Unit| {
}
public? final? fun parameter(a: @A() C): R|kotlin/Unit| {
}
public? final? fun parameterArgument(a: B<@A() C>): R|kotlin/Unit| {
}
public? final? fun returnValue(): @A() C
public? final? fun <T> returnTypeParameterValue(): @A() T
public? final? fun returnArgument(): B<@A() C>
public? final? val lambdaType: @A() ( () -> C )
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): @A() ( () -> C )
public? final? val lambdaParameter: ( (@A() C) -> C )
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( (@A() C) -> C )
public? final? val lambdaReturnValue: ( () -> @A() C )
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( () -> @A() C )
public? final? val lambdaReceiver: ( @A() C.() -> C )
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( @A() C.() -> C )
public? final? val lambdaParameterNP: ( (@A() C) -> C )
[ContainingClassKey=AnnotationsOnParenthesizedTypes] public? get(): ( (@A() C) -> C )
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? [ContainingClassKey=A] constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public? final? interface B<T> : R|kotlin/Any| {
}
public? final? interface C : R|kotlin/Any| {
}

View File

@@ -0,0 +1,16 @@
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
annotation class A
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
annotation class B
typealias Test0 = @A @B Int
typealias Test1 = @A() (@A Int)
typealias Test2 = @A() (@B Int)
typealias Test3 = @A() (@A Int) -> Int
typealias Test4 = @A() (@B Int)?
typealias Test5 = @A() ( (@B Int)? )
typealias Test6 = (@A @B Int)
typealias Test7 = (@A @B Int)?
typealias Test8 = (@A() (@B Int)? )
typealias Test9 = (@A() (@B Int) )?

View File

@@ -0,0 +1,23 @@
FILE: splitModifierList.kt
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class B : R|kotlin/Annotation| {
public? constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public? final typealias Test0 = @A() @B() Int
public? final typealias Test1 = @A() @A() Int
public? final typealias Test2 = @A() @B() Int
public? final typealias Test3 = @A() ( (@A() Int) -> Int )
public? final typealias Test4 = @A() @B() Int?
public? final typealias Test5 = @A() @B() Int?
public? final typealias Test6 = @A() @B() Int
public? final typealias Test7 = @A() @B() Int?
public? final typealias Test8 = @A() @B() Int?
public? final typealias Test9 = @A() @B() Int?

View File

@@ -0,0 +1,23 @@
FILE: splitModifierList.kt
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class A : R|kotlin/Annotation| {
public? [ContainingClassKey=A] constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
@Target(AnnotationTarget#.TYPE#, AnnotationTarget#.TYPE_PARAMETER#) public? final? annotation class B : R|kotlin/Annotation| {
public? [ContainingClassKey=B] constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public? final typealias Test0 = @A() @B() Int
public? final typealias Test1 = @A() @A() Int
public? final typealias Test2 = @A() @B() Int
public? final typealias Test3 = @A() ( (@A() Int) -> Int )
public? final typealias Test4 = @A() @B() Int?
public? final typealias Test5 = @A() @B() Int?
public? final typealias Test6 = @A() @B() Int
public? final typealias Test7 = @A() @B() Int?
public? final typealias Test8 = @A() @B() Int?
public? final typealias Test9 = @A() @B() Int?

View File

@@ -0,0 +1,8 @@
suspend fun <T> simpleRun(f: suspend () -> T): T = f()
suspend fun <T, R> List<T>.simpleMap(f: suspend (T) -> R): R {
}
suspend fun <T> simpleWith(t: T, f: suspend T.() -> Unit): Unit = t.f()

View File

@@ -0,0 +1,4 @@
FILE: suspendFunctionTypes.kt
public? final? suspend fun <T> simpleRun(f: ( suspend () -> T )): T { LAZY_BLOCK }
public? final? suspend fun <T, R> List<T>.simpleMap(f: ( suspend (T) -> R )): R { LAZY_BLOCK }
public? final? suspend fun <T> simpleWith(t: T, f: ( suspend T.() -> Unit )): Unit { LAZY_BLOCK }

View File

@@ -0,0 +1,9 @@
FILE: suspendFunctionTypes.kt
public? final? suspend fun <T> simpleRun(f: ( suspend () -> T )): T {
^simpleRun f#()
}
public? final? suspend fun <T, R> List<T>.simpleMap(f: ( suspend (T) -> R )): R {
}
public? final? suspend fun <T> simpleWith(t: T, f: ( suspend T.() -> Unit )): Unit {
^simpleWith t#.f#()
}

View File

@@ -46,6 +46,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
}
@TestMetadata("annotationsOnParenthesizedTypes.kt")
public void testAnnotationsOnParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
}
@TestMetadata("complexTypes.kt")
public void testComplexTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
@@ -156,6 +166,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
}
@TestMetadata("splitModifierList.kt")
public void testSplitModifierList() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
}
@TestMetadata("suspendFunctionTypes.kt")
public void testSuspendFunctionTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
}
@TestMetadata("typeAliasWithGeneric.kt")
public void testTypeAliasWithGeneric() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");

View File

@@ -46,6 +46,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
}
@TestMetadata("annotationsOnParenthesizedTypes.kt")
public void testAnnotationsOnParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnParenthesizedTypes.kt");
}
@TestMetadata("complexTypes.kt")
public void testComplexTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt");
@@ -156,6 +166,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt");
}
@TestMetadata("splitModifierList.kt")
public void testSplitModifierList() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/splitModifierList.kt");
}
@TestMetadata("suspendFunctionTypes.kt")
public void testSuspendFunctionTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/suspendFunctionTypes.kt");
}
@TestMetadata("typeAliasWithGeneric.kt")
public void testTypeAliasWithGeneric() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt");

View File

@@ -22,16 +22,16 @@ fun Visibility.toEffectiveVisibility(
fun Visibility.toEffectiveVisibility(
owner: ConeClassLikeLookupTag?,
forClass: Boolean = false,
checkPublishedApi: Boolean = false
ownerIsPublishedApi: Boolean = false
): EffectiveVisibility {
customEffectiveVisibility()?.let { return it }
return when (this.normalize()) {
Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass
Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass
Visibilities.Protected -> EffectiveVisibility.Protected(owner)
Visibilities.Internal -> when (!checkPublishedApi /*|| !owner.isPublishedApi()*/) { // TODO
true -> EffectiveVisibility.Internal
false -> EffectiveVisibility.Public
Visibilities.Internal -> when (ownerIsPublishedApi) {
true -> EffectiveVisibility.Public
false -> EffectiveVisibility.Internal
}
Visibilities.Public -> EffectiveVisibility.Public
Visibilities.Local -> EffectiveVisibility.Local

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassAttr
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
@@ -167,7 +169,12 @@ class FirSamResolverImpl(
source = firRegularClass.source
name = classId.shortClassName
origin = FirDeclarationOrigin.SamConstructor
status = FirDeclarationStatusImpl(firRegularClass.visibility, Modality.FINAL).apply {
val visibility = firRegularClass.visibility
status = FirResolvedDeclarationStatusImpl(
visibility,
Modality.FINAL,
EffectiveVisibility.Local
).apply {
isExpect = firRegularClass.isExpect
isActual = firRegularClass.isActual
isOverride = false

View File

@@ -47,7 +47,7 @@ fun ConeKotlinType.isKMutableProperty(session: FirSession): Boolean {
classId.shortClassName.identifier.startsWith("KMutableProperty")
}
private fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
return classId(session)?.toFunctionClassKind()
}
@@ -55,29 +55,34 @@ private fun ClassId.toFunctionClassKind(): FunctionClassKind? {
return FunctionClassKind.byClassNamePrefix(packageFqName, relativeClassName.asString())
}
// Function, SuspendFunction, KFunction, KSuspendFunction
fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean {
return functionClassKind(session) != null
}
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.Function
}
// Function, SuspendFunction, KFunction, KSuspendFunction
fun ConeClassLikeLookupTag.isBuiltinFunctionalType(): Boolean {
return classId.toFunctionClassKind() != null
}
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
inline fun ConeKotlinType.isFunctionalType(session: FirSession, predicate: (FunctionClassKind) -> Boolean): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.SuspendFunction ||
kind == FunctionClassKind.KSuspendFunction
return predicate(kind)
}
// Function
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
return isFunctionalType(session) { it == FunctionClassKind.Function }
}
// SuspendFunction, KSuspendFunction
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
return isFunctionalType(session) { it.isSuspendType }
}
// KFunction, KSuspendFunction
fun ConeKotlinType.isKFunctionType(session: FirSession): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.KFunction ||
kind == FunctionClassKind.KSuspendFunction
return isFunctionalType(session) { it.isReflectType }
}
fun ConeKotlinType.kFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType {

View File

@@ -16,6 +16,9 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.StandardClassIds
class FirStatusResolver(
val session: FirSession,
@@ -172,6 +175,22 @@ class FirStatusResolver(
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>
)
val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext)
val annotations = ((containingProperty ?: declaration) as? FirAnnotatedDeclaration)?.annotations ?: emptyList()
if (annotations.any { it.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == StandardClassIds.PublishedApi }) {
val publishedApiSelfEffectiveVisibility = visibility.toEffectiveVisibility(
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>, ownerIsPublishedApi = true
)
val parentPublishedEffectiveVisibility = when {
containingProperty != null -> containingProperty.publishedApiEffectiveVisibility
containingClass is FirRegularClass -> containingClass.publishedApiEffectiveVisibility
else -> null
} ?: parentEffectiveVisibility
declaration.publishedApiEffectiveVisibility = parentPublishedEffectiveVisibility.lowerBound(
publishedApiSelfEffectiveVisibility,
session.typeContext
)
}
return status.resolved(visibility, modality, effectiveVisibility)
}
@@ -243,3 +262,6 @@ private fun FirDeclaration.hasOwnBodyOrAccessorBody(): Boolean {
else -> true
}
}
private object PublishedApiEffectiveVisibilityKey : FirDeclarationDataKey()
var FirDeclaration.publishedApiEffectiveVisibility: EffectiveVisibility? by FirDeclarationDataRegistry.data(PublishedApiEffectiveVisibilityKey)

Some files were not shown because too many files have changed in this diff Show More