Compare commits

...

159 Commits

Author SHA1 Message Date
Mikhael Bogdanov
147ab6fe3d Support Unit/V types in string-concat indy calls
unitComponent.kt test fails with JVM target 9+
2021-02-17 17:16:57 +01:00
Mikhael Bogdanov
f7801fdd78 Make indy-with-constants default for -jvm-target 9+
#KT-42522 Fixed
2021-02-17 17:16:57 +01:00
Mikhael Bogdanov
e7f8df810d Fail on compilation errors in AbstractBytecodeTextTest 2021-02-17 17:16:57 +01:00
Mikhael Bogdanov
1101ebb111 Support new targets in KotlinBytecodeToolWindow
#KT-30222 Fixed
2021-02-17 17:16:57 +01:00
Alexander Udalov
67e91b7ebd Minor, add workaround for KT-45008 2021-02-17 16:39:19 +01:00
Alexander Udalov
4d9cffccf2 Support structural equals/hashCode for type constructors of type parameters
Use the same logic as for type constructors of classes, based on the
fully-qualified name of the classifier, with special cases for error
types and local declarations, with an additional check that the type
constructors' declaration descriptors are structurally equal via
`DescriptorEquivalenceForOverrides`. The latter is required because type
parameters of overloaded functions must be different, even though their
full FQ name is the same.

This (hopefully) has no effect for the compiler, but is useful for
kotlin-reflect where `KType.equals` runs the type checker on the
underlying `KotlinType` instances, which eventually ends up comparing
type constructors. Descriptors and types in kotlin-reflect are cached on
soft references, so they may be suddenly garbage-collected and
recomputed, and we want copies of the same type parameter to be equal to
each other.

This fixes flaky codegen tests which started to fail after migration to
the new test infrastructure, where tests are now run in parallel in the
same process, thus with higher memory pressure and more soft references
being GC'd:

* `codegen/box/reflection/types/createType/typeParameter.kt`
* `codegen/box/reflection/supertypes/genericSubstitution.kt`

Also, add a new test to check that we do the instanceof check in
overrides of `AbstractTypeConstructor.isSameClassifier`.

 #KT-44850 Fixed
2021-02-17 14:41:07 +01:00
Alexander Udalov
aaecb87d1b Tests: compute runtime classpath for JVM box tests manually
Taking just the `jvmClasspathRoots` is not correct because it also
contains stuff needed for resolve to work correctly, such as JDK (full
or mock), stdlib (full or mock), reflect. JDK is obviously not needed in
the classpath, and stdlib/reflect are available via the parent class
loader, which is specifically reused across all tests to make them run
faster.

Also, don't try to create class loader for Java-only modules in
`JvmBoxRunner.processModule`. This happens, for example, for all tests
which were moved from `boxAgainstJava`.
2021-02-17 14:41:07 +01:00
Dmitriy Novozhilov
df42868874 [Inference] Fix subtyping on classes with same FQN but with different number of arguments
Such situations may appear if there are multiple classes with same
  names from different modules in dependencies
2021-02-17 16:23:08 +03:00
Dmitriy Novozhilov
0b22c30ab1 [FIR] Fix dispatch receiver type for members of builtin functional types 2021-02-17 16:23:08 +03:00
Dmitriy Novozhilov
e5ab684127 [FIR] Support methods of cone type contexts with annotation markers 2021-02-17 16:23:08 +03:00
Dmitriy Novozhilov
57d29009ee [FIR] Fix TODOs and cleanup ConeTypeContext and ConeInferenceContext 2021-02-17 16:23:08 +03:00
Dmitriy Novozhilov
373bc578fb [FIR] Implement capturing of cone types same as for kotlin types 2021-02-17 16:23:08 +03:00
Dmitriy Novozhilov
5ce36a528e [FE] Prohibit sealed fun interfaces
#KT-44947 Fixed
2021-02-17 13:54:10 +03:00
Dmitriy Novozhilov
cdf7de5524 [FE] Change message for sealed interfaces with language target < 1.5 2021-02-17 13:51:14 +03:00
Dmitriy Novozhilov
8521d844e2 Advance bootstrap to 1.5.20-dev-814 2021-02-17 12:01:06 +03:00
Georgy Bronnikov
83343f3a7a IR: get rid of some type checks in JvmBackendContext 2021-02-17 11:05:22 +03:00
Georgy Bronnikov
68cabba698 IR: preserve signatures when copying IrFiles in performByIrFile 2021-02-17 11:05:22 +03:00
Georgy Bronnikov
db18ffc764 IR: only worry about threads in JvmIrSignatureDescriptor
General IdSignatureDescriptor is used from other backends, which have no
multi-threaded backend for now and do not need to carry the associated
runtime costs.

So IdSignatureDescriptor keeps the thread-unsafe caching of signature
builder.
2021-02-17 11:05:22 +03:00
Georgy Bronnikov
cacfe53065 IR: move performByIrFile to a separate .kt 2021-02-17 11:05:22 +03:00
Georgy Bronnikov
4c701cf44c IR: make extractedLocalClasses a JS-only field 2021-02-17 11:05:22 +03:00
Georgy Bronnikov
445f6eac3d IR: IrBasedDescriptor fix 2021-02-17 11:05:21 +03:00
Georgy Bronnikov
c081bc8d7e Fir concurrent maps 2021-02-17 11:05:21 +03:00
Georgy Bronnikov
9cdad272de Fir threadLocal 2021-02-17 11:05:21 +03:00
Georgy Bronnikov
ec2dc9c0fa IR: synchronize on SymbolTable operations 2021-02-17 11:05:21 +03:00
Georgy Bronnikov
c9d0448fd1 IR: use threadLocal 2021-02-17 11:05:21 +03:00
Georgy Bronnikov
56a26113cd IR: threadLocal
To be used for per-file state in global structures during parallel
lowering.
2021-02-17 11:05:20 +03:00
Georgy Bronnikov
57167922e2 IR: make lazyVar synchronized 2021-02-17 11:05:20 +03:00
Georgy Bronnikov
4e9bedc2fc JVM_IR: use ConcurrentHashMap
Replace mutable maps and sets accessed from by-file lowerings with
ConcurrentHashMap, so that lowerings can operate on them in parallel.
2021-02-17 11:03:27 +03:00
Georgy Bronnikov
23da2bde67 IR: fixes for IR by-file copying 2021-02-17 11:03:27 +03:00
Georgy Bronnikov
54a76977db IR: fix fake override computation
Due to IR copying in performByIrFile, we need to only distinguish
overrides up to their fqName.
2021-02-17 11:03:27 +03:00
Georgy Bronnikov
d154c8d8e6 IR: copy each file before lowering.
Avoid inter-file dependencies while lowering.
2021-02-17 11:03:27 +03:00
Georgy Bronnikov
103f82c95c IR: an option to automatically select the number of lowering threads 2021-02-17 11:03:27 +03:00
Georgy Bronnikov
52b3cb362b IR: thread pool in PerformByIrFilePhase 2021-02-17 11:03:27 +03:00
Georgy Bronnikov
eae416d739 IR: Handle exceptions from by-file lowering thread 2021-02-17 11:03:27 +03:00
Georgy Bronnikov
bea5d955d4 JVM_IR: perform file lowerings in parallel
Selected by -Xir-run-lowerings-in-paralled compiler flag.
2021-02-17 11:03:26 +03:00
Anton Bannykh
c06b345f3c Hide stageController into the IrFactory 2021-02-17 10:42:50 +03:00
Anton Bannykh
97080c49fc Persistent IR generator
Goal:
- avoid hand-writing the boilerplate
- easier PIR evolution

Output is reasonably close the hand-writtern version
2021-02-17 10:42:50 +03:00
Anton Bannykh
8a0ce20d43 PIR: minor restructuring 2021-02-17 10:42:50 +03:00
pyos
1310a65f0c JVM: rename this$0 when regenerating nested objects too
In the old backend, this was unnecessary because nested objects would
reference their lambdas' captures through the original this$0. On
JVM_IR, using loose capture fields means a name/descriptor clash can
occur on any level of nesting, not just the top.
2021-02-17 07:56:03 +01:00
Nikolay Krasko
ec89cb2313 Ignore hanging KotlinAndroid36GradleIT.testAndroidMppSourceSets()
Ignore till the proper investigation.
Probably caused in b262d09a81...5c7aadece9.
2021-02-17 00:26:19 +03:00
Ilmir Usmanov
ec569a4c89 Minor. Suppress errors in tests 2021-02-16 20:59:25 +01:00
Ilmir Usmanov
bad197e075 Raise RESERVED_VAR_PROPERTY_OF_VALUE_CLASS to error 2021-02-16 20:59:21 +01:00
Dmitry Petrov
56a104dda9 JVM_IR KT-44974 fix SAM-converted capturing extension lambda 2021-02-16 19:51:59 +03:00
Dmitriy Novozhilov
83ed67546b [Test] Support WITH_STDLIB directive in js box tests 2021-02-16 17:51:32 +03:00
Dmitriy Novozhilov
dfcff132fd [FIR] Fix false-positive smartcast on receiver in rhs of elvis
#KT-44942 Fixed
2021-02-16 17:51:32 +03:00
Dmitriy Novozhilov
2b39282682 [FIR] Render original type before smartcasted type in DEBUG_INFO_EXPRESSION_TYPE
This is made for keep consistency with same renderer in FE 1.0
2021-02-16 17:51:32 +03:00
Dmitriy Novozhilov
d4c26cca52 [FIR] Use type without smartcast for local variable with smartcasted initializer 2021-02-16 17:51:32 +03:00
Dmitriy Novozhilov
40e286b354 [FIR] Increase level of sequential when branches
Level of CFGNode is used to determine which call is a common one for
  creating node with union of arguments (to merge flow from multiple
  in-place lambdas). Before this change calls in different when branches
  may have same node level, which entail passing smartcasts from moddle of
  one branch to another

```
val x: Any = ...
when {
    ... -> run { x as String } // (1)
    ... -> {
        run {
            x.foo()
        } // (2)
        "hello"
    }
}
```

Call `(1)` was assumed as argument of call `(2)` which is incorrect

#KT-44814 Fixed
2021-02-16 17:51:31 +03:00
Dmitriy Novozhilov
92271527cb [Test] Add CFG and IR dump handlers to FirBlackBoxTests 2021-02-16 17:51:31 +03:00
Dmitriy Novozhilov
b5619dbf37 [FIR] Add ability to render node levels in CFG graph dumper 2021-02-16 17:51:31 +03:00
Ilya Kirillov
3e22011626 Fix compilation of HLRedundantVisibilityModifierInspection 2021-02-16 15:47:08 +01:00
Ilya Kirillov
e8f3ebdd19 FIR IDE: introduce HLRedundantVisibilityModifierInspection by extended checker 2021-02-16 15:23:18 +01:00
Ilya Kirillov
6d97841f38 FIR IDE: introduce HLLocalInspectionTest 2021-02-16 15:23:18 +01:00
Ilya Kirillov
7fb6c22889 FIR IDE: allow creating inspections by extended checkers 2021-02-16 15:23:17 +01:00
Ilya Kirillov
b9a4613e44 FIR IDE: remove getMessage from HLPresentation as it duplicates HLApplicator.getActionName 2021-02-16 15:23:17 +01:00
Ilya Kirillov
c13889c2ea FIR: add ability to specify checkers list for checker components 2021-02-16 15:23:17 +01:00
Ilya Kirillov
ca4a07f73f Unify message bundles used in IDEA FIR into KotlinBundle 2021-02-16 15:23:17 +01:00
Vladimir Dolzhenko
6352814d45 Fix NPE
#KTIJ-898 Fixed

Original commit: 12d8e88b846f29598ca3904b49996bd6a9891ccd
2021-02-16 14:21:40 +00:00
Vladimir Dolzhenko
98ba379e07 Fixed NPE on StandaloneScriptRootsCache instantiation
Relates to ^EA-218043
#KTIJ-1137 Fixed

Original commit: 1d63a1b48d480b958ff44676c42b698a8ca5f64a
2021-02-16 14:21:39 +00:00
Dmitriy Dolovov
45b17120ad [Commonizer] Minor. Rename: 'dependee' -> 'dependency' 2021-02-16 17:19:49 +03:00
Dmitriy Dolovov
ec7e411d80 [Commonizer] Remove classifierId from CIR class/TA nodes 2021-02-16 17:19:43 +03:00
Dmitriy Dolovov
ef931d5561 [Commonizer] Don't keep kotlin/Any as the single supertype in CirClass 2021-02-16 17:19:38 +03:00
Victor Petukhov
baeee8988e [all-open] Don't affect private declarations to change their modality to open 2021-02-16 17:18:08 +03:00
Victor Petukhov
ec41775d7e [all-open] Fix formatting 2021-02-16 17:18:07 +03:00
Mads Ager
05ff2b1292 [JVM_IR] Extend when to switch translation to deal with nested ors.
FIR translates:

```
when (x) {
  1, 2, 3 -> action
  else -> other_action
}
```

to an IR structure with nested ors:

```
if ((x == 1 || x == 2) || (x == 3)) action
else other_action
```

This change allows that to turn into switch instructions in the
JVM backend.
2021-02-16 03:20:07 -08:00
Ilya Kirillov
91581d6c1a Move KotlinBundle to frontend-independent module
to use from IDEA FIR
2021-02-16 12:16:17 +01:00
Mikhail Glukhikh
a8c23e1c3a FirDefaultStarImportingScope: filter INVISIBLE_CLASSES properly 2021-02-16 12:38:46 +03:00
Mikhail Glukhikh
940588a9bb FE: commonize throw-related annotation FQ names 2021-02-16 12:38:46 +03:00
pyos
2dc0404751 FIR: prioritize visible imported classes during type resolution
and produce an error on ambiguity.
2021-02-16 12:38:45 +03:00
pyos
291ed4a38a FIR: handle typealiases during conflict resolution 2021-02-16 12:38:45 +03:00
Hung Nguyen
592c285198 Kapt: Don't create KDocCommentKeeper when not needed
Previously, even if `keepKdocComments=false`, we would still create the
KDocCommentKeeper object unnecessarily.

This commit makes sure we create the object only if
`keepKdocComments=true`.

Bug: Clean-up after commit e252171 for KT-43593
Test: Existing tests
2021-02-16 11:53:49 +03:00
Ilya Kirillov
0a72e16451 FIR: transform DiagnosticBuilder DSL to an object
To make diagnostics visible in symbol search in IJ
2021-02-15 22:28:13 +01:00
SokolovaMaria
15aaf3a078 Copy typeParameters from original declaration to the exportedDefaultStubFun before substitution of type parameters 2021-02-15 23:17:11 +03:00
Mark Punzalan
706d3e5aa8 FIR IDE: Add quickfix for VAR_ANNOTATION_PARAMETER. 2021-02-15 21:07:32 +01:00
Mark Punzalan
2f450549ab FIR IDE: Update FIR diagnostic test data for
INAPPLICABLE_LATEINIT_MODIFIER.
2021-02-15 19:37:14 +01:00
Mark Punzalan
4e44804c77 FIR IDE: Add quickfix for INAPPLICABLE_LATEINIT_MODIFIER.
Also changed FE1.0 checker and all related fix factories to report error
on the declaration instead of the lateinit modifier. This is consistent
with the direction of all checkers in FIR (no reporting on modifiers).
2021-02-15 19:37:14 +01:00
Dmitry Petrov
b1ab64e854 JVM_IR KT-44483 argument adaptation is already done in PSI2IR 2021-02-15 19:41:39 +03:00
Alexander Udalov
f1b0e893ae Remove kotlin-annotations-android
#KT-44815 Fixed
2021-02-15 17:23:44 +01:00
Alexander Udalov
899f75466d Remove tests on kotlin-annotations-android
#KT-44815
2021-02-15 17:23:44 +01:00
Alexander Udalov
3432f581cb Remove compiler support for kotlin-annotations-android
#KT-44815
2021-02-15 17:23:44 +01:00
Jinseong Jeon
a884555171 FIR: bail out early for override check if base candidate is private 2021-02-15 19:16:36 +03:00
Jinseong Jeon
09640d9d63 FIR checker: apply override checker to anonymous objects
^KT-44695 Fixed
2021-02-15 19:16:35 +03:00
Jinseong Jeon
9370f918e9 FIR: use override checker when populating directOverriddenProperties 2021-02-15 19:16:35 +03:00
Victor Petukhov
fa1507fb91 Fix FIR test lambdaParameterTypeInElvis 2021-02-15 18:51:51 +03:00
Simon Ogorodnik
83836037f8 Add documentation on type checker context / type system context 2021-02-15 18:29:00 +03:00
Simon Ogorodnik
3909e3c54c Decouple TypeCheckerContext and TypeSystemContext 2021-02-15 18:28:58 +03:00
Andrei Klunnyi
53a7dc1126 KT-44839 [Sealed interfaces]: restore move-tests for lang-version < 15
This commit restores tests removed in 690fb47c.
2021-02-15 15:28:00 +00:00
Andrei Klunnyi
eb0c73fd5e KT-44839 [Sealed interfaces]: ability to specify compiler options in tests 2021-02-15 15:28:00 +00:00
Andrei Klunnyi
c63a9afa56 KT-44839 [Sealed interfaces]: move refactoring for language level < 1.5
This commit restores sealed-check-logic for language level < 1.5
mistakenly removed in 690fb47c.

^KT-44839 fixed
2021-02-15 15:27:59 +00:00
Yahor Berdnikau
5c7aadece9 Fix test founds more lines then expected.
Now Gradle additionally prints warning message regarding using debug
logs that wrapped in '####*' lines.
2021-02-15 15:35:23 +01:00
Yahor Berdnikau
224aea0953 Ignore test due to the bug in AGP on Gradle 6.8+.
It is not possible to make it work via reflection.
2021-02-15 15:35:23 +01:00
Yahor Berdnikau
9d9df0c4ff Expect new attributes compatibility error.
Since Gradle 6.4 error message was changed, when dependency does not
provide all required attributes.
2021-02-15 15:35:22 +01:00
Yahor Berdnikau
6c0ee2f9ea Update test to use new test xml output format.
This format was slightly changed starting Gradle 6.6. Adapted
tests to use new expected output when current Gradle runner is greater
then 6.5.
2021-02-15 15:35:22 +01:00
Yahor Berdnikau
6d2465d00c Update Gradle version for tests to 6.8.1. 2021-02-15 15:35:18 +01:00
Dmitry Petrov
b262d09a81 JVM_IR KT-44627 fix bridge signature for parameter with primitive bound 2021-02-15 17:19:33 +03:00
Mikhail Glukhikh
fa0f967c83 FIR2IR: support adapted references for constructors 2021-02-15 17:08:13 +03:00
Mikhail Glukhikh
8bab208322 FIR2IR: use information about callable reference adaptation from resolve 2021-02-15 17:08:08 +03:00
Victor Petukhov
dcad9c84fc Don't fix type variables into Nothing in priority way
^KT-44546 Fixed
2021-02-15 15:12:45 +03:00
Yahor Berdnikau
440fc8c4e4 Deprecated 'kotlin.useCompilerFallbackSearch' property.
This property was introduced in 2018 and no longer supported.
See https://discuss.kotlinlang.org/t/how-to-set-usefallbackcompilersearch/9039
for details why it was introduced.
2021-02-15 12:43:22 +01:00
Yahor Berdnikau
069941cdaf Provide compiler classpath as task input.
This ensures that compiler classpath is what is expected
by Kotlin Plugin and removes possibility of leaking wrong jars
from Gradle wrapper classpath.

For 'kotlin.useFallbackCompilerSearch' old behaviour is still present,
but this option should be marked as deprecated and removed in one
of the Kotlin releases.
2021-02-15 12:43:18 +01:00
Dmitriy Dolovov
0eaea655d0 [Commonization] Improvements in approx. keys
- Don't print upper bounds if it contains only kotlin/Any?
- Print variance in lowercase
2021-02-15 13:25:52 +03:00
Dmitriy Dolovov
3c6eb8f8f4 Minor. Formatted 2021-02-15 13:25:47 +03:00
Dmitriy Dolovov
0af31abb04 [Commonizer] Add tests for overloading purely by different upper bounds 2021-02-15 13:25:40 +03:00
Dmitriy Dolovov
90cdb9203f [Commonizer] Fix integration tests: wrong mismatches filter 2021-02-15 13:25:34 +03:00
Dmitriy Dolovov
8a17de38d0 [Commonizer] Fix integration tests: serialize only own module contents 2021-02-15 13:25:28 +03:00
Dmitriy Dolovov
7f8f1dc4f8 [Commonizer] Calculate hash code by pure name in approximation keys 2021-02-15 13:25:22 +03:00
Mikhael Bogdanov
6ff5704ef9 Delete obsolete test 2021-02-15 11:24:10 +01:00
Mikhael Bogdanov
f493766563 Add IR tests to Android codegen test 2021-02-15 11:24:10 +01:00
Victor Petukhov
c0759f96e9 Fix FIR test lambdaParameterTypeInElvis 2021-02-15 12:59:07 +03:00
Yaroslav Chernyshev
8acf3b1d76 [Cocoapods] Fail import if project's version wasn't specified
#Fixed KT-44000
2021-02-15 12:39:40 +03:00
Victor Petukhov
c158c64ee0 Reformat TypeWithEnhancement.kt 2021-02-15 12:13:57 +03:00
Victor Petukhov
0d40022d6d Add reporting of the warnings based on Java annotations for expanded type aliases
Before that, such warnings weren't reported as the corresponding errors were reported during type inference (only original types took part there)
2021-02-15 12:13:55 +03:00
Victor Petukhov
d783d99443 Use upper bound checker for typealias expansion 2021-02-15 12:13:53 +03:00
Victor Petukhov
edb8007d52 Add test for errors reporting of UPPER_BOUND_VIOLATED 2021-02-15 12:13:52 +03:00
Victor Petukhov
befe8599c4 Report warnings or errors for violated type parameter's upper bounds from Java annotated with nullability annotations
^KT-43262 Fixed
2021-02-15 12:13:50 +03:00
Dmitriy Novozhilov
cf4e61bebb [FIR] Add spec diagnostic tests to [JPS] Fast FIR tests run configuration 2021-02-15 11:37:40 +03:00
Dmitriy Novozhilov
5711a8d610 [FIR] Support PreliminaryLoopVisitor in FIR DFA 2021-02-15 11:37:39 +03:00
Dmitriy Novozhilov
0e46a961a3 [FIR] Implement util Multimap classes 2021-02-15 11:37:39 +03:00
Dmitriy Novozhilov
67ad4249c8 [Test] Add FirDumpHandler to AbstractFirBlackBoxCodegenTest
This is needed to add ability to enable `FIR_DUMP` directive which
  may be helpful in investigating bugs
2021-02-15 11:37:39 +03:00
Victor Petukhov
a94086224d Clear request cache properly during disposing component 2021-02-15 11:13:11 +03:00
Victor Petukhov
6f64fd2fec Propagate inference session into declaration analyzers
It prevents missing inference session for local declaration (local functions, local classes or objects)

^KT-44801 Fixed
2021-02-15 11:12:58 +03:00
Victor Petukhov
dae1f4c05d Remove redundant extension receiver substitution during lambda's completion 2021-02-15 11:12:56 +03:00
Alexander Likhachev
b463a0fa58 [Gradle] Use property provider for configuration time only if available 2021-02-15 09:58:51 +03:00
Alexander Likhachev
683bd0ed38 [Gradle, JVM] Don't create deprecated compile/runtime configurations
Gradle also removes these configurations in 7.0. See gradle/gradle@2cb45cdbd0
#KT-44462 Fixed
2021-02-15 09:35:54 +03:00
Alexander Likhachev
ef458b20e1 [Gradle] Replace deprecated dependencies configurations in buildscript 2021-02-15 09:21:44 +03:00
Alexander Likhachev
c7427a751a [Gradle, K/N] Add integration tests for framework artifacts
#KT-43556 Fixed
2021-02-15 09:21:44 +03:00
Alexander Likhachev
383b9834a1 [Gradle, K/N] Make BitcodeEmbeddingMode move backward compatible 2021-02-15 09:21:44 +03:00
Alexander Likhachev
cbeb031099 [Gradle, K/N] Move NativeBinaryTypes from kotlin-gradle-plugin to kotlin-gradle-plugin-api 2021-02-15 09:21:44 +03:00
Alexander Likhachev
a6cdfeafed [Gradle, K/N] Consumable frameworks review fixes 2021-02-15 09:21:43 +03:00
Alexander Likhachev
604dda839a [Gradle, K/N] Generate fat framework tasks and consumable configurations 2021-02-15 09:21:43 +03:00
Alexander Likhachev
d844296629 [Gradle, K/N] Add user-defined variant attributes to framework artifact 2021-02-15 09:21:43 +03:00
Alexander Likhachev
cbdcd8f2bc [Gradle, K/N] Add consumable configuration with K/N frameworks 2021-02-15 09:21:42 +03:00
Alexander Likhachev
ba969410c2 [Gradle, JS] Make MultiplePluginDeclarationDetector compatible w/ conf cache 2021-02-15 09:21:42 +03:00
Alexander Likhachev
1cceec3642 [Gradle, JS] Postpone TeamCity project property read using 'by lazy'
Replace direct Gradle property access to provider usage. See https://docs.gradle.org/6.8.2/userguide/configuration_cache.html#config_cache:requirements:undeclared_gradle_prop_read
2021-02-15 09:21:42 +03:00
Alexander Likhachev
240fdfa7a8 [Gradle] Support multiple failures in KotlinTestReport back again 2021-02-15 09:21:42 +03:00
Alexander Likhachev
2b0ad70242 [Gradle, JS] Add integration test for js plugin configuration cache
#KT-42911 Fixed
2021-02-15 09:21:41 +03:00
Alexander Likhachev
a6bf9bf51b [Gradle, JS] Remove workaround for configuration cache enabled builds
It's removed as those tasks now support Gradle configuration cache
2021-02-15 09:21:41 +03:00
Alexander Likhachev
432c6486d5 [Gradle] Make KotlinTest, KotlinTestReport partially cc-compatible 2021-02-15 09:21:41 +03:00
Alexander Likhachev
c7421e2bea [Gradle, JS] Use FileSystemOperations only when it's available
FileSystemOperations is available since Gradle 6.0. ArchiveOperations usage is also refactored. Integration tests Gradle version requirements are reverted.
2021-02-15 09:21:41 +03:00
Alexander Likhachev
0e29a9df6c [Gradle, JS] Use target disambiguation classifier for compilation name 2021-02-15 09:21:40 +03:00
Alexander Likhachev
6eac5e1907 [Gradle, JS] Tasks that uses ArchiveOperations compatible w/ Gradle < 6.6 2021-02-15 09:21:40 +03:00
Alexander Likhachev
15f6bb9506 [Gradle, JS] Make NodeJsSetup cc-compatible 2021-02-15 09:21:40 +03:00
Alexander Likhachev
daa9c81bcb [Gradle, JS] Make KotlinJsDce, Dukat, KotlinPackageJson cc-compatible 2021-02-15 09:21:39 +03:00
Alexander Likhachev
da80d53796 [Gradle, JS] Make KotlinWebpack cc-compatible 2021-02-15 09:21:39 +03:00
Alexander Likhachev
65faf20472 [Gradle, JS] Make PublicPackageJsonTask cc-compatible 2021-02-15 09:21:39 +03:00
Ilya Goncharov
521b722c09 [Gradle, JS] Compilation to compilationName 2021-02-15 09:21:39 +03:00
Ilya Goncharov
4566b7c6e5 [Gradle, JS] rootPackageJson and kotlinNpmInstall cache-friendly 2021-02-15 09:21:38 +03:00
Ilya Goncharov
8c79baa998 [Gradle, JS] Partially rootPackageJson and kotlinNpmInstall with conf cache 2021-02-15 09:21:38 +03:00
Ilya Goncharov
a41d3e5b04 [Gradle, JS] Webpack task with conf cache (w/o install of dependencies) 2021-02-15 09:21:38 +03:00
Ilya Goncharov
e6bfe9a702 [Gradle, JS] Npm dependencies as transient, and store only declarations 2021-02-15 09:21:38 +03:00
Ilya Goncharov
b9aa577f84 [Gradle, JS] KotlinPackageJson configuration cache works 2021-02-15 09:21:37 +03:00
Ilya Goncharov
cd0dfd6fa9 [Gradle, JS] Use transient for compilation npm resolver 2021-02-15 09:21:37 +03:00
Ilya Goncharov
60da9281a2 [Gradle, JS] Next step of configurstion cache 2021-02-15 09:21:37 +03:00
Ilya Goncharov
19e59fe770 [Gradle, JS] Experimenting with making everything transient in npm 2021-02-15 09:21:36 +03:00
Andrey Zinovyev
cc51869a2a [KAPT] Take function argument names from original descriptor
#KT-43804 Fixed
2021-02-14 10:45:00 +03:00
Andrey Zinovyev
4a0437a507 [KAPT] Fix field type correction for delegates (#4107)
#KT-37586 Fixes
2021-02-14 10:38:38 +03:00
Vladimir Dolzhenko
bf9fa4c9da Lightweight hashCode calc for LibraryInfo
#EA-6040509 Fixed
2021-02-13 21:25:46 +01:00
Tianyu Geng
6882cf820e FIR IDE: move RemoveModifierFix to ...
idea-frontend-independent
2021-02-12 17:56:57 +01:00
Vyacheslav Karpukhin
75f6780b90 AndroidDependencyResolver: Don't load android-related classes on class load 2021-02-12 16:00:13 +01:00
935 changed files with 18006 additions and 13951 deletions

View File

@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.android.tools.build:gradle:4.1.2'
}
}
apply plugin: 'com.android.application'
@@ -37,14 +37,6 @@ android {
packagingOptions { exclude 'META-INF/build.txt' }
//TODO run under java 6, cause there is error on implicit 'stream' import in 'asWithMutable' test
lintOptions {
abortOnError false
}
compileOptions {
incremental = false
}
dexOptions {
dexInProcess false
@@ -80,6 +72,22 @@ android {
reflect0 {
dimension "box"
}
common_ir0 {
dimension "box"
}
common_ir1 {
dimension "box"
}
common_ir2 {
dimension "box"
}
reflect_ir0 {
dimension "box"
}
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.android.tests;
import org.jetbrains.kotlin.jps.build.BaseKotlinJpsBuildTestCase;
import org.junit.Ignore;
import java.io.File;
import java.io.IOException;
@Ignore
public class AndroidJpsBuildTestCase extends BaseKotlinJpsBuildTestCase {
private static final String PROJECT_NAME = "android-module";
private static final String SDK_NAME = "Android_SDK";
private final File workDir = new File(AndroidRunner.getPathManager().getTmpFolder());
public void doTest() {
initProject();
rebuildAllModules();
buildAllModules().assertSuccessful();
}
@Override
protected String getProjectName() {
return "android-module";
}
@Override
protected void runTest() {
doTest();
}
@Override
public String getName() {
return "AndroidJpsTest";
}
@Override
protected File doGetProjectDir() throws IOException {
return workDir;
}
private void initProject() {
addJdk(SDK_NAME, AndroidRunner.getPathManager().getPlatformFolderInAndroidSdk() + "/android.jar");
loadProject(workDir.getAbsolutePath() + File.separator + PROJECT_NAME + ".ipr");
}
}

View File

@@ -46,12 +46,8 @@ public class AndroidRunner {
CodegenTestsOnAndroidGenerator.generate(pathManager);
System.out.println("Run tests on android...");
TestSuite suite = CodegenTestsOnAndroidRunner.runTestsInEmulator(pathManager);
//AndroidJpsBuildTestCase indirectly depends on UsefulTestCase which compiled against java 8
//TODO: Need add separate run configuration for AndroidJpsBuildTestCase
//suite.addTest(new AndroidJpsBuildTestCase());
return suite;
System.out.println("Run tests on Android...");
return CodegenTestsOnAndroidRunner.runTestsInEmulator(pathManager);
}
public void tearDown() throws Exception {

View File

@@ -12,7 +12,6 @@ import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.kotlin.cli.common.output.writeAllTo
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.codegen.CodegenTestFiles
import org.jetbrains.kotlin.codegen.GenerationUtils
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
@@ -22,8 +21,6 @@ import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.*
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
@@ -57,15 +54,18 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
//keep it globally to avoid test grouping on TC
private val generatedTestNames = hashSetOf<String>()
private val COMMON = FlavorConfig("common", 3)
private val REFLECT = FlavorConfig("reflect", 1)
private val COMMON = FlavorConfig(TargetBackend.ANDROID,"common", 3)
private val REFLECT = FlavorConfig(TargetBackend.ANDROID, "reflect", 1)
class FlavorConfig(private val prefix: String, val limit: Int) {
private val COMMON_IR = FlavorConfig(TargetBackend.ANDROID_IR, "common_ir", 3)
private val REFLECT_IR = FlavorConfig(TargetBackend.ANDROID_IR,"reflect_ir", 1)
class FlavorConfig(private val backend: TargetBackend, private val prefix: String, val limit: Int) {
private var writtenFilesCount = 0
fun printStatistics() {
println("FlavorTestCompiler: $prefix, generated file count: $writtenFilesCount")
println("FlavorTestCompiler for $backend: $prefix, generated file count: $writtenFilesCount")
}
fun getFlavorForNewFiles(newFilesCount: Int): String {
@@ -148,25 +148,47 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
private fun generateTestsAndFlavourSuites() {
println("Generating test files...")
generateTestMethodsForDirectories(File("compiler/testData/codegen/box"), File("compiler/testData/codegen/boxInline"))
val folders = arrayOf(
File("compiler/testData/codegen/box"),
File("compiler/testData/codegen/boxInline")
)
generateTestMethodsForDirectories(
TargetBackend.ANDROID,
COMMON,
REFLECT,
*folders
)
generateTestMethodsForDirectories(
TargetBackend.ANDROID_IR,
COMMON_IR,
REFLECT_IR,
*folders
)
pendingUnitTestGenerators.values.forEach { it.generate() }
}
private fun generateTestMethodsForDirectories(vararg dirs: File) {
private fun generateTestMethodsForDirectories(
backend: TargetBackend,
commonFlavor: FlavorConfig,
reflectionFlavor: FlavorConfig,
vararg dirs: File
) {
val holders = mutableMapOf<ConfigurationKey, FilesWriter>()
for (dir in dirs) {
val files = dir.listFiles() ?: error("Folder with testData is empty: ${dir.absolutePath}")
processFiles(files, holders)
processFiles(files, holders, backend, commonFlavor, reflectionFlavor)
}
holders.values.forEach {
it.writeFilesOnDisk()
}
COMMON.printStatistics()
REFLECT.printStatistics()
commonFlavor.printStatistics()
reflectionFlavor.printStatistics()
}
internal inner class FilesWriter(
@@ -254,7 +276,10 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
@Throws(IOException::class)
private fun processFiles(
files: Array<File>,
holders: MutableMap<ConfigurationKey, FilesWriter>
holders: MutableMap<ConfigurationKey, FilesWriter>,
backend: TargetBackend,
commmonFlavor: FlavorConfig,
reflectionFlavor: FlavorConfig
) {
holders.values.forEach {
it.writeFilesOnDiskIfNeeded()
@@ -264,7 +289,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
if (file.isDirectory) {
val listFiles = file.listFiles()
if (listFiles != null) {
processFiles(listFiles, holders)
processFiles(listFiles, holders, backend, commmonFlavor, reflectionFlavor)
}
} else if (FileUtilRt.getExtension(file.name) != KotlinFileType.EXTENSION) {
// skip non kotlin files
@@ -273,7 +298,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
continue
}
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file) ||
if (!InTextDirectivesUtils.isPassingTarget(backend.compatibleWith, file) ||
InTextDirectivesUtils.isIgnoredTarget(TargetBackend.ANDROID, file)
) {
continue
@@ -304,7 +329,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
if (fullFileText.contains("// SKIP_JDK6")) continue
if (hasBoxMethod(fullFileText)) {
val testConfiguration = createTestConfiguration(file)
val testConfiguration = createTestConfiguration(file, backend)
val services = testConfiguration.testServices
val moduleStructure = try {
@@ -335,7 +360,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
keyConfiguration.languageVersionSettings = module.languageVersionSettings
val key = ConfigurationKey(kind, jdkKind, keyConfiguration.toString())
val compiler = if (kind.withReflection) REFLECT else COMMON
val compiler = if (kind.withReflection) reflectionFlavor else commmonFlavor
val compilerConfigurationProvider = services.compilerConfigurationProvider as CompilerConfigurationProviderImpl
val filesHolder = holders.getOrPut(key) {
FilesWriter(compiler, compilerConfigurationProvider.createCompilerConfiguration(module)).also {
@@ -349,9 +374,9 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}
}
private fun createTestConfiguration(testDataFile: File): TestConfiguration {
private fun createTestConfiguration(testDataFile: File, backend: TargetBackend): TestConfiguration {
return TestConfigurationBuilder().apply {
testConfiguration()
configure(backend)
testInfo = KotlinTestInfo(
"org.jetbrains.kotlin.android.tests.AndroidRunner",
"test${testDataFile.nameWithoutExtension.capitalize()}",
@@ -360,10 +385,10 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}.build(testDataFile.path)
}
private val testConfiguration: TestConfigurationBuilder.() -> Unit = {
private fun TestConfigurationBuilder.configure(backend: TargetBackend) {
globalDefaults {
frontend = FrontendKinds.ClassicFrontend
targetBackend = TargetBackend.ANDROID
targetBackend = backend
targetPlatform = JvmPlatforms.defaultJvmPlatform
dependencyKind = DependencyKind.Binary
}
@@ -386,9 +411,6 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
}
private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> =
CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
companion object {
const val GRADLE_VERSION = "6.8.1" // update GRADLE_SHA_256 on change
const val GRADLE_SHA_256 = "fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd"

View File

@@ -71,15 +71,20 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
return rootSuite
}
private fun processReport(suite: TestSuite, resultOutput: String) {
private fun processReport(rootSuite: TestSuite, resultOutput: String) {
val reportFolder = File(flavorFolder())
try {
val folders = reportFolder.listFiles()
assertTrue(folders != null && folders.isNotEmpty(), "No folders in ${reportFolder.path}")
folders.forEach {
assertTrue("${it.path} is not directory") { it.isDirectory }
val isIr = it.name.contains("_ir")
val testCases = parseSingleReportInFolder(it)
testCases.forEach { aCase -> suite.addTest(aCase) }
testCases.forEach { aCase ->
if (isIr) aCase.name += "_ir"
rootSuite.addTest(aCase)
}
Assert.assertNotEquals("There is no test results in report", 0, testCases.size.toLong())
}
} catch (e: Throwable) {
@@ -87,10 +92,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
}
}
private fun renameFlavorFolder() {
val reportFolder = File(flavorFolder())
reportFolder.renameTo(File(reportFolder.parentFile, reportFolder.name + "_d8"))
}
private fun flavorFolder() = pathManager.tmpFolder + "/build/test/results/connected/flavors"
@@ -119,7 +120,7 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
private fun cleanAndBuildProject(gradleRunner: GradleRunner) {
gradleRunner.clean()
gradleRunner.build()
gradleRunner.assembleAndroidTest()
}
@Throws(IOException::class, SAXException::class, ParserConfigurationException::class)
@@ -138,21 +139,14 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
return (0 until testCases.length).map { i ->
val item = testCases.item(i) as Element
val failure = item.getElementsByTagName("failure")
val failure = item.getElementsByTagName("failure").takeIf { it.length != 0 }?.item(0)
val name = item.getAttribute("name")
if (failure.length == 0) {
object : TestCase(name) {
@Throws(Throwable::class)
override fun runTest() {
}
}
} else {
object : TestCase(name) {
@Throws(Throwable::class)
override fun runTest() {
Assert.fail(failure.item(0).textContent)
object : TestCase(name) {
@Throws(Throwable::class)
override fun runTest() {
if (failure != null) {
Assert.fail(failure.textContent)
}
}
}

View File

@@ -45,9 +45,9 @@ public class GradleRunner {
OutputUtils.checkResult(result);
}
public void build() {
public void assembleAndroidTest() {
System.out.println("Building gradle project...");
GeneralCommandLine build = generateCommandLine("build");
GeneralCommandLine build = generateCommandLine("assembleAndroidTest");
build.addParameter("--stacktrace");
build.addParameter("--warn");
RunResult result = RunUtils.execute(build);

View File

@@ -20,11 +20,9 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.mapToIndex
class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int)
@@ -70,12 +68,8 @@ abstract class ArgumentGenerator {
generateExpression(declIndex, argument)
}
is DefaultValueArgument -> {
if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) {
generateDefaultJava(declIndex, argument)
} else {
defaultArgs.mark(declIndex)
generateDefault(declIndex, argument)
}
defaultArgs.mark(declIndex)
generateDefault(declIndex, argument)
}
is VarargValueArgument -> {
generateVararg(declIndex, argument)
@@ -103,10 +97,6 @@ abstract class ArgumentGenerator {
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
}
protected open fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
throw UnsupportedOperationException("Unsupported default java argument #$i: $argument")
}
protected open fun generateOther(i: Int, argument: ResolvedValueArgument) {
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
}
@@ -116,28 +106,6 @@ abstract class ArgumentGenerator {
}
}
private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny(
listOf(this),
{ current -> current.original.overriddenDescriptors.map { it.original } },
{ descriptor ->
descriptor.original.overriddenDescriptors.isEmpty() &&
descriptor is JavaCallableMemberDescriptor &&
descriptor.valueParameters[index].declaresDefaultValue()
}
)
fun shouldInvokeDefaultArgumentsStub(resolvedCall: ResolvedCall<*>): Boolean {
val descriptor = resolvedCall.resultingDescriptor
val valueArgumentsByIndex = resolvedCall.valueArgumentsByIndex ?: return false
for (index in valueArgumentsByIndex.indices) {
val resolvedValueArgument = valueArgumentsByIndex[index]
if (resolvedValueArgument is DefaultValueArgument && !descriptor.defaultValueFromJava(index)) {
return true
}
}
return false
}
fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): FunctionDescriptor {
if (functionDescriptor.containingDeclaration !is ClassDescriptor) return functionDescriptor
if (functionDescriptor.overriddenDescriptors.isEmpty()) return functionDescriptor
@@ -155,4 +123,4 @@ fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): Fun
function.valueParameters.any { valueParameter -> valueParameter.hasDefaultValue() }
}
?: functionDescriptor
}
}

View File

@@ -72,12 +72,6 @@ class CallBasedArgumentGenerator(
callGenerator.putValueIfNeeded(getJvmKotlinType(i), lazyVararg, ValueKind.GENERAL_VARARG, i)
}
override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
val argumentValue = valueParameters[i].findJavaDefaultArgumentValue(valueParameterTypes[i], codegen.typeMapper)
callGenerator.putValueIfNeeded(getJvmKotlinType(i), argumentValue)
}
override fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
callGenerator.reorderArgumentsIfNeeded(args, valueParameterTypes)
}

View File

@@ -74,7 +74,10 @@ import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.*;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices;
import org.jetbrains.kotlin.resolve.jvm.JvmConstantsKt;
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
@@ -2690,7 +2693,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@NotNull
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) {
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall<?> resolvedCall) {
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd);
if (intrinsic != null) {
return intrinsic.toCallable(fd, superCall, resolvedCall, this);
@@ -2698,7 +2701,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
fd = SamCodegenUtil.resolveSamAdapter(fd);
if (ArgumentGeneratorKt.shouldInvokeDefaultArgumentsStub(resolvedCall)) {
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
if (valueArguments != null && valueArguments.stream().anyMatch(it -> it instanceof DefaultValueArgument)) {
// When we invoke a function with some arguments mapped as defaults,
// we later reroute this call to an overridden function in a base class that processes the default arguments.
// If the base class is generic, this overridden function can have a different Kotlin signature

View File

@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.annotations.ThrowUtilKt;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -1105,7 +1105,7 @@ public class FunctionCodegen {
return Collections.emptyList();
}
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(AnnotationUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(ThrowUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
if (annotation == null) return Collections.emptyList();
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();

View File

@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
internal class ObjectSuperCallArgumentGenerator(
@@ -65,12 +64,6 @@ internal class ObjectSuperCallArgumentGenerator(
pushDefaultValueOnStack(type, iv)
}
public override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
val type = parameters[i].asmType
val value = superValueParameters[i].findJavaDefaultArgumentValue(type, typeMapper)
value.put(type, iv)
}
public override fun generateVararg(i: Int, argument: VarargValueArgument) {
generateSuperCallArgument(i)
}

View File

@@ -5,18 +5,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.AsmUtil.unboxPrimitiveTypeOrNull
import org.jetbrains.kotlin.codegen.StackValue.*
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.Constant
import org.jetbrains.kotlin.load.java.EnumEntry
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.getDefaultValueFromAnnotation
import org.jetbrains.kotlin.load.java.lexicalCastFrom
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -86,40 +75,3 @@ class FunctionCallStackValue(
resultKotlinType: KotlinType?,
lambda: (v: InstructionAdapter) -> Unit
) : OperationStackValue(resultType, resultKotlinType, lambda)
fun ValueParameterDescriptor.findJavaDefaultArgumentValue(targetType: Type, typeMapper: KotlinTypeMapper): StackValue {
val descriptorWithDefaultValue = DFS.dfs(
listOf(this.original),
{ it.original.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
object : DFS.AbstractNodeHandler<ValueParameterDescriptor, ValueParameterDescriptor?>() {
var result: ValueParameterDescriptor? = null
override fun beforeChildren(current: ValueParameterDescriptor?): Boolean {
if (current?.declaresDefaultValue() == true && current.getDefaultValueFromAnnotation() != null) {
result = current
return false
}
return true
}
override fun result(): ValueParameterDescriptor? = result
}
) ?: error("Should be at least one descriptor with default value: $this")
val defaultValue = descriptorWithDefaultValue.getDefaultValueFromAnnotation()
if (defaultValue is NullDefaultValue) {
return constant(null, targetType)
}
val value = (defaultValue as StringDefaultValue).value
val castResult = type.lexicalCastFrom(value) ?: error("Should be checked in frontend")
return when (castResult) {
is EnumEntry -> enumEntry(castResult.descriptor, typeMapper)
is Constant -> {
val unboxedType = unboxPrimitiveTypeOrNull(targetType) ?: targetType
return coercion(constant(castResult.value, unboxedType), targetType, null)
}
}
}

View File

@@ -462,6 +462,29 @@ class AnonymousObjectTransformer(
val indexToFunctionalArgument = transformationInfo.functionalArguments
val capturedParams = HashSet<Int>()
// Possible cases where we need to add each lambda's captures separately:
//
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
// the object will be removed and its contents inlined).
//
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
// `capturedLambdas` contains all lambdas used by this object and nested objects.
//
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
// we *could* group them into `this$0` now, but choose not to. Lambdas are replaced by their captures to match.
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
// empty anyway.
//
// The only remaining case is a top-level object inside a (crossinline) lambda that is inlined into another object.
// Then, the reference to the soon-to-be-removed lambda class containing the captures (and it exists, or else the object
// would not have needed regeneration in the first place) is simply replaced with a reference to the outer object, and
// that object will contain loose fields for everything we need to capture.
val topLevelInCrossinlineLambda = parentFieldRemapper is InlinedLambdaRemapper && !parentFieldRemapper.parent!!.isRoot
//load captured parameters and patch instruction list
// NB: there is also could be object fields
val toDelete = arrayListOf<AbstractInsnNode>()
@@ -470,10 +493,12 @@ class AnonymousObjectTransformer(
val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var`
val functionalArgument = indexToFunctionalArgument[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
getNewFieldName(fieldName, true)
else
fieldName
// If an outer `this` is already captured by this object, rename it if any inline lambda will capture
// one of the same type, causing the code below to create a clash. Note that the values can be different.
// TODO: this is only really necessary if there will be a name *and* type clash.
val shouldRename = !topLevelInCrossinlineLambda && isThis0(fieldName) &&
indexToFunctionalArgument.values.any { it is LambdaInfo && it.capturedVars.any { it.fieldName == fieldName } }
val newFieldName = if (shouldRename) addUniqueField(fieldName + INLINE_FUN_THIS_0_SUFFIX) else fieldName
val info = capturedParamBuilder.addCapturedParam(
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
Type.getType(fieldNode.desc), functionalArgument is LambdaInfo, null
@@ -508,35 +533,17 @@ class AnonymousObjectTransformer(
//For all inlined lambdas add their captured parameters
//TODO: some of such parameters could be skipped - we should perform additional analysis
val allRecapturedParameters = ArrayList<CapturedParamDesc>()
if (parentFieldRemapper !is InlinedLambdaRemapper || parentFieldRemapper.parent!!.isRoot) {
// Possible cases:
//
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
// the object will be removed and its contents inlined).
//
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
// `capturedLambdas` contains all lambdas used by this object and nested objects.
//
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
// we could group them into `this$0` now, but choose not to. Lambdas are replaced by their captures.
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
// empty and the choice doesn't matter.
//
val alreadyAdded = HashMap<String, CapturedParamInfo>()
if (!topLevelInCrossinlineLambda) {
val capturedOuterThisTypes = mutableSetOf<String>()
for (info in capturedLambdas) {
for (desc in info.capturedVars) {
val key = desc.fieldName + "$$$" + desc.type.className
val alreadyAddedParam = alreadyAdded[key]
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(
desc,
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
alreadyAddedParam != null
)
// Merge all outer `this` of the same type captured by inlined lambdas, since they have to be the same
// object. Outer `this` captured by the original object itself should have been renamed above,
// and can have a different value even if the same type is captured by a lambda.
val recapturedParamInfo = if (isThis0(desc.fieldName))
capturedParamBuilder.addCapturedParam(desc, desc.fieldName, !capturedOuterThisTypes.add(desc.type.className))
else
capturedParamBuilder.addCapturedParam(desc, addUniqueField(desc.fieldName + INLINE_TRANSFORMATION_SUFFIX), false)
if (info is ExpressionLambda && info.isCapturedSuspend(desc)) {
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend
}
@@ -551,10 +558,6 @@ class AnonymousObjectTransformer(
allRecapturedParameters.add(desc)
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.newFieldName).remapValue = composed
if (isThis0(desc.fieldName)) {
alreadyAdded.put(key, recapturedParamInfo)
}
}
}
} else if (capturedLambdas.isNotEmpty()) {
@@ -579,24 +582,6 @@ class AnonymousObjectTransformer(
return constructorAdditionalFakeParams
}
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
values.any { it is LambdaInfo && it.capturedVars.any { isThis0(it.fieldName) } }
} else false
}
private fun getNewFieldName(oldName: String, originalField: Boolean): String {
if (AsmUtil.CAPTURED_THIS_FIELD == oldName) {
return if (!originalField) {
oldName
} else {
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX)
}
}
return addUniqueField(oldName + INLINE_TRANSFORMATION_SUFFIX)
}
private fun addUniqueField(name: String): String {
val existNames = fieldNames.getOrPut(name) { LinkedList() }
val suffix = if (existNames.isEmpty()) "" else "$" + existNames.size
@@ -604,7 +589,4 @@ class AnonymousObjectTransformer(
existNames.add(newName)
return newName
}
private fun isFirstDeclSiteLambdaFieldRemapper(parentRemapper: FieldRemapper): Boolean =
parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper
}

View File

@@ -204,7 +204,7 @@ class GenerationState private constructor(
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val runtimeStringConcat =
if (target.majorVersion >= JvmTarget.JVM_9.majorVersion)
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INDY_WITH_CONSTANTS
else JvmStringConcat.INLINE
val samConversionsScheme = run {

View File

@@ -114,6 +114,14 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var doNotClearBindingContext: Boolean by FreezableVar(false)
@Argument(
value = "-Xparallel-backend-threads",
description = "When using the IR backend, run lowerings by file in N parallel threads.\n" +
"0 means use a thread per processor core.\n" +
"Default value is 1"
)
var parallelBackendThreads: String by FreezableVar("1")
@Argument(value = "-Xmodule-path", valueDescription = "<path>", description = "Paths where to find Java 9+ modules")
var javaModulePath: String? by NullableStringFreezableVar(null)
@@ -361,7 +369,9 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
description = """Select code generation scheme for string concatenation.
-Xstring-concat=indy-with-constants Concatenate strings using `invokedynamic` `makeConcatWithConstants`. Requires `-jvm-target 9` or greater.
-Xstring-concat=indy Concatenate strings using `invokedynamic` `makeConcat`. Requires `-jvm-target 9` or greater.
-Xstring-concat=inline Concatenate strings using `StringBuilder`"""
-Xstring-concat=inline Concatenate strings using `StringBuilder`
default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise"""
)
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)

View File

@@ -88,7 +88,7 @@ fun buildKLib(
configuration = configuration,
allDependencies = allDependencies,
friendDependencies = emptyList(),
irFactory = PersistentIrFactory,
irFactory = PersistentIrFactory(), // TODO: IrFactoryImpl?
outputKlibPath = outputPath,
nopack = true
)

View File

@@ -199,7 +199,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
configuration = config.configuration,
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
irFactory = PersistentIrFactory,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir
)

View File

@@ -291,6 +291,10 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
val nThreadsRaw = arguments.parallelBackendThreads.toIntOrNull() ?: 1
val nThreads = if (nThreadsRaw == 0) Runtime.getRuntime().availableProcessors() else nThreadsRaw
put(CommonConfigurationKeys.PARALLEL_BACKEND_THREADS, nThreads)
}
fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments) {

View File

@@ -50,6 +50,10 @@ object CommonConfigurationKeys {
@JvmField
val USE_FIR_EXTENDED_CHECKERS = CompilerConfigurationKey.create<Boolean>("fir extended checkers")
@JvmField
val PARALLEL_BACKEND_THREADS =
CompilerConfigurationKey.create<Int>("When using the IR backend, run lowerings by file in N parallel threads")
}
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings

View File

@@ -29,6 +29,10 @@ inline fun <reified T : Any> StorageComponentContainer.useImpl() {
registerSingleton(T::class.java)
}
inline fun <reified T : Any> StorageComponentContainer.useImplIf(cond: Boolean) {
if (cond) useImpl<T>()
}
inline fun <reified T : Any> ComponentProvider.get(): T {
return getService(T::class.java)
}

View File

@@ -1484,24 +1484,6 @@ public class FirTypeEnhancementTestGenerated extends AbstractFirTypeEnhancementT
}
}
@TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SignatureAnnotations extends AbstractFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
}
@TestMetadata("StableName.java")
public void testStableName() throws Exception {
runTest("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java");
}
}
@TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -132,67 +132,4 @@ public class OwnFirTypeEnhancementTestGenerated extends AbstractOwnFirTypeEnhanc
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/enhancement/mapping"), Pattern.compile("^(.+)\\.java$"), null, true);
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SignatureAnnotations extends AbstractOwnFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
}
@TestMetadata("DefaultEnum.java")
public void testDefaultEnum() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultEnum.java");
}
@TestMetadata("DefaultLongLiteral.java")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java");
}
@TestMetadata("DefaultNull.java")
public void testDefaultNull() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultNull.java");
}
@TestMetadata("DefaultNullAndParameter.java")
public void testDefaultNullAndParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java");
}
@TestMetadata("DefaultParameter.java")
public void testDefaultParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultParameter.java");
}
@TestMetadata("EmptyParameterName.java")
public void testEmptyParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/EmptyParameterName.java");
}
@TestMetadata("ReorderedParameterNames.java")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java");
}
@TestMetadata("SameParameterName.java")
public void testSameParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/SameParameterName.java");
}
@TestMetadata("SpecialCharsParameterName.java")
public void testSpecialCharsParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java");
}
@TestMetadata("StaticMethodWithDefaultValue.java")
public void testStaticMethodWithDefaultValue() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java");
}
}
}

View File

@@ -65,9 +65,6 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
private fun createEnvironment(content: String): KotlinCoreEnvironment {
val classpath = mutableListOf(getAnnotationsJar(), ForTestCompileRuntime.runtimeJarForTests())
if (InTextDirectivesUtils.isDirectiveDefined(content, "ANDROID_ANNOTATIONS")) {
classpath.add(ForTestCompileRuntime.androidAnnotationsForTests())
}
if (InTextDirectivesUtils.isDirectiveDefined(content, "JVM_ANNOTATIONS")) {
classpath.add(ForTestCompileRuntime.jvmAnnotationsForTests())
}

View File

@@ -1 +1 @@
Most FIR enhancement tests use compiler/testData/loadJava/compilerJava
Most FIR enhancement tests use compiler/testData/loadJava/compiledJava

View File

@@ -1,33 +0,0 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun a(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(HELLO)) arg: R|ft<@FlexibleNullability Signs, Signs?>!| = R|/Signs.HELLO|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(X)) arg: R|ft<@FlexibleNullability Signs, Signs?>!| = R|/Signs.X|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<@FlexibleNullability Signs, Signs?>!|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<@FlexibleNullability Mixed, Mixed?>!| = R|/Mixed.NOT_ENTRY_EITHER|): R|ft<@FlexibleNullability Mixed, Mixed?>!|
public/*package*/ constructor(): R|A|
}
public final enum class Mixed : R|kotlin/Enum<ft<@FlexibleNullability Mixed, Mixed?>!>| {
public final static enum entry NOT_ENTRY_EITHER: R|@FlexibleNullability Mixed|
public final static fun values(): R|kotlin/Array<Mixed>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|Mixed| {
}
}
public final enum class Signs : R|kotlin/Enum<ft<@FlexibleNullability Signs, Signs?>!>| {
public final static enum entry HELLO: R|@FlexibleNullability Signs|
public final static enum entry WORLD: R|@FlexibleNullability Signs|
public final static field X: R|ft<@FlexibleNullability Signs, Signs?>!|
public final static fun values(): R|kotlin/Array<Signs>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|Signs| {
}
}

View File

@@ -1,39 +0,0 @@
// FILE: Signs.java
// ANDROID_ANNOTATIONS
public enum Signs {
HELLO,
WORLD;
public static final Signs X;
public static final class NOT_ENTRY_EITHER {}
}
// FILE: Mixed.java
public enum Mixed {
NOT_ENTRY_EITHER;
public static final class NOT_ENTRY_EITHER {}
}
// FILE: A.java
import kotlin.annotations.jvm.internal.*;
class A {
public Signs a(@DefaultValue("HELLO") Signs arg) {
return arg;
}
public Signs bar(@DefaultValue("X") Signs arg) {
return arg;
}
public Signs baz(@DefaultValue("NOT_ENTRY_EITHER") Signs arg) {
return arg;
}
public Mixed bam(@DefaultValue("NOT_ENTRY_EITHER") Mixed arg) {
return arg;
}
}

View File

@@ -1,24 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x1F)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(31)): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0X1F)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(31)): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b1010)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(10)): R|kotlin/Unit|
public open fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1010)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(10)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0xZZ)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1234)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public constructor(): R|B|
}

View File

@@ -1,36 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void first(@DefaultValue("0x1F") Long value) {
}
public void second(@DefaultValue("0X1F") Long value) {
}
public void third(@DefaultValue("0b1010") Long value) {
}
public void fourth(@DefaultValue("0B1010") Long value) {
}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B {
public void first(@DefaultValue("0x") Long value) {
}
public void second(@DefaultValue("0xZZ") Long value) {
}
public void third(@DefaultValue("0b") Long value) {
}
public void fourth(@DefaultValue("0B1234") Long value) {
}
}

View File

@@ -1,14 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|kotlin/Int| = Null(null)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B<T : R|ft<kotlin/Any, kotlin/Any?>!|> : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() t: R|ft<@FlexibleNullability T, T?>!| = Null(null)): R|kotlin/Unit|
public constructor<T : R|ft<kotlin/Any, kotlin/Any?>!|>(): R|B<T>|
}

View File

@@ -1,17 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void foo(@DefaultNull Integer x) {}
public void bar(@DefaultNull int x) {}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B<T> {
public void foo(@DefaultNull T t) { }
}

View File

@@ -1,32 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public constructor(): R|A|
}
public abstract interface AInt : R|kotlin/Any| {
public abstract fun foo(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public abstract fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
}
public open class B : R|A| {
public open fun foo(i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!|): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() @R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public constructor(): R|B|
}
public open class C : R|A|, R|AInt| {
public constructor(): R|C|
}

View File

@@ -1,38 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void foo(@DefaultNull Integer i) {}
public void bar(@DefaultNull Integer a) {}
public void bam(@DefaultNull Integer a) {}
public void baz(@DefaultValue("42") Integer a) {}
}
// FILE: AInt.java
import kotlin.annotations.jvm.internal.*;
public interface AInt {
public void foo(@DefaultValue("42") Integer i) {}
public void bar(@DefaultNull Integer a) {}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B extends A {
public void foo(Integer i) {}
public void bar(@DefaultValue("42") Integer a) {}
public void bam(@DefaultNull @DefaultValue("42") Integer a) {}
}
// FILE: C.java
public class C extends A implements AInt {
}

View File

@@ -1,14 +0,0 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) value: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(hello)): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(first), @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) b: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(second)): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(first), b: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun fourth(first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) second: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(second)): R|kotlin/Unit|
public open fun wrong(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!|): R|kotlin/Unit|
public/*package*/ constructor(): R|A|
}

View File

@@ -1,23 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public void first(@DefaultValue("hello") String value) {
}
public void second(@DefaultValue("first") String a, @DefaultValue("second") String b) {
}
public void third(@DefaultValue("first") String a, String b) {
}
public void fourth(String first, @DefaultValue("second") String second) {
}
public void wrong(@DefaultValue("hello") Integer i) {
}
}

View File

@@ -1,10 +0,0 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun emptyName(@R|kotlin/annotations/jvm/internal/ParameterName|(String()) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|kotlin/Int|): R|kotlin/Unit|
public open fun missingName(@R|kotlin/annotations/jvm/internal/ParameterName|() first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(Int(42)) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public/*package*/ constructor(): R|A|
}

View File

@@ -1,16 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public void emptyName(@ParameterName("") String first, @ParameterName("ok") int second) {
}
public void missingName(@ParameterName() String first) {
}
public void numberName(@ParameterName(42) String first) {
}
}

View File

@@ -1,6 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun connect(@R|kotlin/annotations/jvm/internal/ParameterName|(String(host)) host: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(port)) port: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,10 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void connect(@ParameterName("host") String host, @ParameterName("port") int port) {
}
}

View File

@@ -1,6 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun same(@R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,10 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void same(@ParameterName("ok") String first, @ParameterName("ok") String second) {
}
}

View File

@@ -1,8 +0,0 @@
public open class A : R|kotlin/Any| {
public open fun dollarName(@R|kotlin/annotations/jvm/internal/ParameterName|(String($)) host: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(String(42)) field: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,13 +0,0 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
import kotlin.internal.*;
public class A {
public void dollarName(@ParameterName("$") String host) {
}
public void numberName(@ParameterName("42") String field) {
}
}

View File

@@ -1,6 +0,0 @@
public/*package*/ open class A : R|kotlin/Any| {
public open static fun withDefault(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(OK)) arg: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(OK)): R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|
public/*package*/ constructor(): R|A|
}

View File

@@ -1,13 +0,0 @@
// IGNORE_BACKEND: JS, NATIVE
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public static String withDefault(@DefaultValue("OK") String arg) {
return arg;
}
}

View File

@@ -3,36 +3,36 @@ object Delegate {
operator fun setValue(instance: Any?, property: Any, value: String) {}
}
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var test: Int<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var kest by Delegate<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var test: Int
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var kest by Delegate
lateinit var good: String
class A {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val fest = "10"<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val fest = "10"
lateinit var mest: String
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var xest: String?<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var nest: Int<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var west: Char<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var qest: Boolean<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var aest: Short<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var hest: Byte<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var jest: Long<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val dest: String
get() = "KEKER"<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var xest: String?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var nest: Int
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var west: Char
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var qest: Boolean
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var aest: Short
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var hest: Byte
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var jest: Long
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val dest: String
get() = "KEKER"
}
class B<T> {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var best: T<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var best: T
}
class C<K : Any> {
lateinit var pest: K
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var vest: K?<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var vest: K?
}
fun rest() {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var i: Int<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var i: Int
lateinit var a: A
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var b: B<String> = B()<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var b: B<String> = B()
}

View File

@@ -15,7 +15,7 @@ class SomeClass : SomeInterface {
get() = true
set(value) {}
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var fau: Double<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var fau: Double
}
inline class InlineClass

View File

@@ -16428,42 +16428,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("defaultEnum.kt")
public void testDefaultEnum() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt");
}
@Test
@TestMetadata("defaultLongLiteral.kt")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt");
}
@Test
@TestMetadata("defaultNull.kt")
public void testDefaultNull() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt");
}
@Test
@TestMetadata("defaultNullAndParameter.kt")
public void testDefaultNullAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt");
}
@Test
@TestMetadata("defaultParameter.kt")
public void testDefaultParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt");
}
@Test
@TestMetadata("emptyParameterName.kt")
public void testEmptyParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt");
}
@Test
@TestMetadata("notNullVarargOverride.kt")
public void testNotNullVarargOverride() throws Exception {
@@ -16475,48 +16439,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testNullableVarargOverride() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/nullableVarargOverride.kt");
}
@Test
@TestMetadata("overridesDefaultValue.kt")
public void testOverridesDefaultValue() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt");
}
@Test
@TestMetadata("overridesParameterName.kt")
public void testOverridesParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt");
}
@Test
@TestMetadata("reorderedParameterNames.kt")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt");
}
@Test
@TestMetadata("sameParameterName.kt")
public void testSameParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt");
}
@Test
@TestMetadata("specialCharsParameterName.kt")
public void testSpecialCharsParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt");
}
@Test
@TestMetadata("stableParameterName.kt")
public void testStableParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt");
}
@Test
@TestMetadata("staticMethodWithDefaultValue.kt")
public void testStaticMethodWithDefaultValue() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt");
}
}
@Nested
@@ -24574,6 +24496,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/inheritorInDifferentModule.kt");
}
@Test
@TestMetadata("sealedFunInterface.kt")
public void testSealedFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/sealedFunInterface.kt");
}
@Test
@TestMetadata("sealedInterfacesDisabled.kt")
public void testSealedInterfacesDisabled() throws Exception {
@@ -34327,6 +34255,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/java"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("checkEnhancedUpperBounds.kt")
public void testCheckEnhancedUpperBounds() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.kt");
}
@Test
@TestMetadata("checkEnhancedUpperBoundsWithEnabledImprovements.kt")
public void testCheckEnhancedUpperBoundsWithEnabledImprovements() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBoundsWithEnabledImprovements.kt");
}
@Test
@TestMetadata("concurrentHashMapContains.kt")
public void testConcurrentHashMapContains() throws Exception {

View File

@@ -15,7 +15,6 @@ data class DiagnosticData(
val psiType: KType,
val parameters: List<DiagnosticParameter>,
val positioningStrategy: PositioningStrategy,
val group: String?,
)
data class DiagnosticParameter(
@@ -42,6 +41,7 @@ enum class PositioningStrategy(private val strategy: String) {
WHEN_EXPRESSION("WHEN_EXPRESSION"),
IF_EXPRESSION("IF_EXPRESSION"),
VARIANCE_MODIFIER("VARIANCE_MODIFIER"),
LATEINIT_MODIFIER("LATEINIT_MODIFIER"),
;
@@ -54,8 +54,4 @@ enum class PositioningStrategy(private val strategy: String) {
fun DiagnosticData.hasDefaultPositioningStrategy(): Boolean =
positioningStrategy == PositioningStrategy.DEFAULT
data class DiagnosticList(
val diagnostics: List<DiagnosticData>,
)
positioningStrategy == PositioningStrategy.DEFAULT

View File

@@ -0,0 +1,56 @@
/*
* 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.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.typeOf
abstract class DiagnosticGroup @PrivateForInline constructor(val name: String) {
@Suppress("PropertyName")
@PrivateForInline
val _diagnostics = mutableListOf<DiagnosticData>()
@OptIn(PrivateForInline::class)
val diagnostics: List<DiagnosticData>
get() = _diagnostics
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> error(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.ERROR, positioningStrategy, init)
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> warning(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.WARNING, positioningStrategy, init)
@PrivateForInline
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> diagnosticDelegateProvider(
severity: Severity,
positioningStrategy: PositioningStrategy,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<DiagnosticGroup, DiagnosticData>> { _, property ->
val diagnostic = DiagnosticBuilder(
severity,
name = property.name,
sourceElementType = typeOf<E>(),
psiType = typeOf<P>(),
positioningStrategy,
).apply(init).build()
_diagnostics += diagnostic
ReadOnlyProperty { _, _ -> diagnostic }
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.generator.diagnostics
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.typeOf
abstract class DiagnosticList {
@Suppress("PropertyName")
@PrivateForInline
val _groups = mutableListOf<DiagnosticGroup>()
@OptIn(PrivateForInline::class)
val groups: List<DiagnosticGroup>
get() = _groups
val allDiagnostics: List<DiagnosticData>
get() = groups.flatMap { it.diagnostics }
@OptIn(PrivateForInline::class)
operator fun DiagnosticGroup.provideDelegate(
thisRef: DiagnosticList,
prop: KProperty<*>
): ReadOnlyProperty<DiagnosticList, DiagnosticGroup> {
val group = this
_groups += group
return ReadOnlyProperty { _, _ -> group }
}
}
class DiagnosticBuilder(
private val severity: Severity,
private val name: String,
private val sourceElementType: KType,
private val psiType: KType,
private val positioningStrategy: PositioningStrategy,
) {
@PrivateForInline
val parameters = mutableListOf<DiagnosticParameter>()
@OptIn(PrivateForInline::class, ExperimentalStdlibApi::class)
inline fun <reified T> parameter(name: String) {
if (parameters.size == 3) {
error("Diagnostic cannot have more than 3 parameters")
}
parameters += DiagnosticParameter(
name = name,
type = typeOf<T>()
)
}
@OptIn(PrivateForInline::class)
fun build() = DiagnosticData(
severity,
name,
sourceElementType,
psiType,
parameters,
positioningStrategy,
)
}

View File

@@ -1,112 +0,0 @@
/*
* 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.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.typeOf
class DiagnosticListBuilder private constructor() {
@PrivateForInline
val diagnostics = mutableListOf<DiagnosticData>()
@PrivateForInline
var currentGroupName: String? = null
@OptIn(PrivateForInline::class)
inline fun group(groupName: String, inner: () -> Unit) {
if (currentGroupName != null) {
error("Groups can not be nested ")
}
currentGroupName = groupName
inner()
currentGroupName = null
}
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> error(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.ERROR, positioningStrategy, init)
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> warning(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.WARNING, positioningStrategy, init)
@PrivateForInline
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> diagnosticDelegateProvider(
severity: Severity,
positioningStrategy: PositioningStrategy,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = PropertyDelegateProvider<Any?, AlwaysReturningUnitPropertyDelegate> { _, property ->
diagnostics += DiagnosticBuilder(
severity,
name = property.name,
sourceElementType = typeOf<E>(),
psiType = typeOf<P>(),
positioningStrategy,
group = currentGroupName,
).apply(init).build()
AlwaysReturningUnitPropertyDelegate
}
@PrivateForInline
object AlwaysReturningUnitPropertyDelegate : ReadOnlyProperty<Any?, Unit> {
override fun getValue(thisRef: Any?, property: KProperty<*>) = Unit
}
@OptIn(PrivateForInline::class)
private fun build() = DiagnosticList(diagnostics)
companion object {
fun buildDiagnosticList(init: DiagnosticListBuilder.() -> Unit) =
DiagnosticListBuilder().apply(init).build()
}
}
class DiagnosticBuilder(
private val severity: Severity,
private val name: String,
private val sourceElementType: KType,
private val psiType: KType,
private val positioningStrategy: PositioningStrategy,
private val group: String?
) {
@PrivateForInline
val parameters = mutableListOf<DiagnosticParameter>()
@OptIn(PrivateForInline::class, ExperimentalStdlibApi::class)
inline fun <reified T> parameter(name: String) {
if (parameters.size == 3) {
error("Diagnostic cannot have more than 3 parameters")
}
parameters += DiagnosticParameter(
name = name,
type = typeOf<T>()
)
}
@OptIn(PrivateForInline::class)
fun build() = DiagnosticData(
severity,
name,
sourceElementType,
psiType,
parameters,
positioningStrategy,
group
)
}

View File

@@ -33,19 +33,18 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
private fun SmartPrinter.printErrorsObject(diagnosticList: DiagnosticList) {
inBracketsWithIndent("object FirErrors") {
val groups = diagnosticList.diagnostics.groupBy { it.group }
for ((group, diagnostics) in groups) {
printDiagnosticGroup(group, diagnostics)
for (group in diagnosticList.groups) {
printDiagnosticGroup(group.name, group.diagnostics)
println()
}
}
}
private fun SmartPrinter.printDiagnosticGroup(
group: String?,
group: String,
diagnostics: List<DiagnosticData>
) {
println("// ${group ?: "NO GROUP"}")
println("// $group")
for (it in diagnostics) {
printDiagnostic(it)
}
@@ -110,7 +109,7 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
@OptIn(ExperimentalStdlibApi::class)
private fun collectImports(diagnosticList: DiagnosticList): Collection<String> = buildSet {
diagnosticList.diagnostics.forEach { diagnostic ->
diagnosticList.allDiagnostics.forEach { diagnostic ->
for (typeArgument in diagnostic.getAllTypeArguments()) {
typeArgument.collectClassNamesTo(this)
}

View File

@@ -25,15 +25,15 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@OptIn(PrivateForInline::class)
val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
group("Miscellaneous") {
object DIAGNOSTICS_LIST : DiagnosticList() {
val Miscellaneous by object : DiagnosticGroup("Miscellaneous") {
val SYNTAX by error<FirSourceElement, PsiElement>()
val OTHER_ERROR by error<FirSourceElement, PsiElement>()
}
group("General syntax") {
val GENERAL_SYNTAX by object : DiagnosticGroup("General syntax") {
val ILLEGAL_CONST_EXPRESSION by error<FirSourceElement, PsiElement>()
val ILLEGAL_UNDERSCORE by error<FirSourceElement, PsiElement>()
val EXPRESSION_REQUIRED by error<FirSourceElement, PsiElement>()
@@ -44,7 +44,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val DELEGATION_IN_INTERFACE by error<FirSourceElement, PsiElement>()
}
group("Unresolved") {
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
val HIDDEN by error<FirSourceElement, PsiElement> {
parameter<AbstractFirBasedSymbol<*>>("hidden")
}
@@ -59,7 +59,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val NO_THIS by error<FirSourceElement, PsiElement>()
}
group("Super") {
val SUPER by object : DiagnosticGroup("Super") {
val SUPER_IS_NOT_AN_EXPRESSION by error<FirSourceElement, PsiElement>()
val SUPER_NOT_AVAILABLE by error<FirSourceElement, PsiElement>()
val ABSTRACT_SUPER_CALL by error<FirSourceElement, PsiElement>()
@@ -68,7 +68,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
}
}
group("Supertypes") {
val SUPERTYPES by object : DiagnosticGroup("Supertypes") {
val TYPE_PARAMETER_AS_SUPERTYPE by error<FirSourceElement, PsiElement>()
val ENUM_AS_SUPERTYPE by error<FirSourceElement, PsiElement>()
val RECURSION_IN_SUPERTYPES by error<FirSourceElement, PsiElement>()
@@ -84,7 +84,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error<FirSourceElement, PsiElement>()
}
group(" Constructor problems") {
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
val CONSTRUCTOR_IN_OBJECT by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val CONSTRUCTOR_IN_INTERFACE by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by error<FirSourceElement, PsiElement>()
@@ -98,7 +98,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val SEALED_CLASS_CONSTRUCTOR_CALL by error<FirSourceElement, PsiElement>()
}
group("Annotations") {
val ANNOTATIONS by object : DiagnosticGroup("Annotations") {
val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by error<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_CONST by error<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by error<FirSourceElement, KtExpression>()
@@ -116,7 +116,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val VAR_ANNOTATION_PARAMETER by error<FirSourceElement, KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE)
}
group("Exposed visibility group") {
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
@@ -128,7 +128,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val EXPOSED_TYPE_PARAMETER_BOUND by exposedVisibilityError<KtTypeReference>()
}
group("Modifiers") {
val MODIFIERS by object : DiagnosticGroup("Modifiers") {
val INAPPLICABLE_INFIX_MODIFIER by error<FirSourceElement, PsiElement>()
val REPEATED_MODIFIER by error<FirSourceElement, PsiElement> {
parameter<KtModifierKeywordToken>("modifier")
@@ -148,7 +148,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val REDUNDANT_OPEN_IN_INTERFACE by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.OPEN_MODIFIER)
}
group("Applicability") {
val APPLICABILITY by object : DiagnosticGroup("Applicability") {
val NONE_APPLICABLE by error<FirSourceElement, PsiElement> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
@@ -156,12 +156,12 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val INAPPLICABLE_CANDIDATE by error<FirSourceElement, PsiElement> {
parameter<AbstractFirBasedSymbol<*>>("candidate")
}
val INAPPLICABLE_LATEINIT_MODIFIER by error<FirSourceElement, PsiElement> {
val INAPPLICABLE_LATEINIT_MODIFIER by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.LATEINIT_MODIFIER) {
parameter<String>("reason")
}
}
group("Ambiguity") {
val AMBIGUIRY by object : DiagnosticGroup("Ambiguity") {
val AMBIGUITY by error<FirSourceElement, PsiElement> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
@@ -170,7 +170,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
}
}
group("Types & type parameters") {
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
val TYPE_MISMATCH by error<FirSourceElement, PsiElement> {
parameter<ConeKotlinType>("expectedType")
parameter<ConeKotlinType>("actualType")
@@ -203,7 +203,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME)
}
group("overrides") {
val OVERRIDES by object : DiagnosticGroup("overrides") {
val NOTHING_TO_OVERRIDE by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.OVERRIDE_MODIFIER) {
parameter<FirMemberDeclaration>("declaration")
}
@@ -242,7 +242,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
}
}
group("Redeclarations") {
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
val MANY_COMPANION_OBJECTS by error<FirSourceElement, PsiElement>()
val CONFLICTING_OVERLOADS by error<FirSourceElement, PsiElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<Collection<AbstractFirBasedSymbol<*>>>("conflictingOverloads")
@@ -253,7 +253,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val ANY_METHOD_IMPLEMENTED_IN_INTERFACE by error<FirSourceElement, PsiElement>()
}
group("Invalid local declarations") {
val INVALID_LOCAL_DECLARATIONS by object : DiagnosticGroup("Invalid local declarations") {
val LOCAL_OBJECT_NOT_ALLOWED by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
parameter<Name>("objectName")
}
@@ -262,7 +262,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
}
}
group("Functions") {
val FUNCTIONS by object : DiagnosticGroup("Functions") {
val ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS by error<FirSourceElement, KtFunction>(PositioningStrategy.MODALITY_MODIFIER) {
parameter<FirMemberDeclaration>("function")
parameter<FirMemberDeclaration>("containingClass") // TODO use FirClass instead of FirMemberDeclaration
@@ -288,7 +288,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val USELESS_VARARG_ON_PARAMETER by warning<FirSourceElement, KtParameter>()
}
group("Properties & accessors") {
val PROPERTIES_ANS_ACCESSORS by object : DiagnosticGroup("Properties & accessors") {
val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.MODALITY_MODIFIER) {
parameter<FirMemberDeclaration>("property")
parameter<FirMemberDeclaration>("containingClass") // TODO use FirClass instead of FirMemberDeclaration
@@ -314,14 +314,15 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val EXPECTED_PRIVATE_DECLARATION by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
}
group("Multi-platform projects") {
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
val EXPECTED_DECLARATION_WITH_BODY by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val EXPECTED_PROPERTY_INITIALIZER by error<FirSourceElement, KtExpression>()
// TODO: need to cover `by` as well as delegate expression
val EXPECTED_DELEGATED_PROPERTY by error<FirSourceElement, KtPropertyDelegate>()
}
group("Destructuring declaration") {
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error<FirSourceElement, KtDestructuringDeclaration>()
val COMPONENT_FUNCTION_MISSING by error<FirSourceElement, PsiElement> {
parameter<Name>("missingFunctionName")
@@ -339,7 +340,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
// TODO: val COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH by ...
}
group("Control flow diagnostics") {
val CONTROL_FLOW by object : DiagnosticGroup("Control flow diagnostics") {
val UNINITIALIZED_VARIABLE by error<FirSourceElement, PsiElement> {
parameter<FirPropertySymbol>("variable")
}
@@ -354,7 +355,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
val WRONG_IMPLIES_CONDITION by warning<FirSourceElement, PsiElement>()
}
group("Nullability") {
val NULLABILITY by object : DiagnosticGroup("Nullability") {
val UNSAFE_CALL by error<FirSourceElement, PsiElement>(PositioningStrategy.DOT_BY_SELECTOR) {
parameter<ConeKotlinType>("receiverType")
}
@@ -374,20 +375,20 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
// TODO: val UNEXPECTED_SAFE_CALL by ...
}
group("When expressions") {
val WHNE_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
val NO_ELSE_IN_WHEN by error<FirSourceElement, KtWhenExpression>(PositioningStrategy.WHEN_EXPRESSION) {
parameter<List<WhenMissingCase>>("missingWhenCases")
}
val INVALID_IF_AS_EXPRESSION by error<FirSourceElement, KtIfExpression>(PositioningStrategy.IF_EXPRESSION)
}
group("Function contracts") {
val FUNCTION_CONTRACTS by object : DiagnosticGroup("Function contracts") {
val ERROR_IN_CONTRACT_DESCRIPTION by error<FirSourceElement, KtElement> {
parameter<String>("reason")
}
}
group("Extended checkers") {
val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") {
val REDUNDANT_VISIBILITY_MODIFIER by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
val REDUNDANT_MODALITY_MODIFIER by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.MODALITY_MODIFIER)
val REDUNDANT_RETURN_UNIT_TYPE by warning<FirSourceElement, PsiTypeElement>()
@@ -407,7 +408,7 @@ val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
}
}
private inline fun <reified P : PsiElement> DiagnosticListBuilder.exposedVisibilityError(
private inline fun <reified P : PsiElement> DiagnosticGroup.exposedVisibilityError(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT
) = error<FirSourceElement, P>(positioningStrategy) {
parameter<FirEffectiveVisibility>("elementVisibility")

View File

@@ -91,7 +91,7 @@ object FirErrors {
val SEALED_SUPERTYPE by error0<FirSourceElement, PsiElement>()
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<FirSourceElement, PsiElement>()
// Constructor problems
// Constructor problems
val CONSTRUCTOR_IN_OBJECT by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val CONSTRUCTOR_IN_INTERFACE by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by error0<FirSourceElement, PsiElement>()
@@ -119,7 +119,7 @@ object FirErrors {
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0<FirSourceElement, KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error0<FirSourceElement, KtParameter>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
// Exposed visibility group
// Exposed visibility
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, KtNamedDeclaration, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, KtNamedDeclaration, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPOSED_RECEIVER_TYPE by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
@@ -140,7 +140,7 @@ object FirErrors {
// Applicability
val NONE_APPLICABLE by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>()
val INAPPLICABLE_CANDIDATE by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>()
val INAPPLICABLE_LATEINIT_MODIFIER by error1<FirSourceElement, PsiElement, String>()
val INAPPLICABLE_LATEINIT_MODIFIER by error1<FirSourceElement, KtModifierListOwner, String>(SourceElementPositioningStrategies.LATEINIT_MODIFIER)
// Ambiguity
val AMBIGUITY by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>()

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.cfa
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirClass
@@ -15,9 +16,12 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
class FirControlFlowAnalyzer(session: FirSession) {
private val cfaCheckers = session.checkersComponent.declarationCheckers.controlFlowAnalyserCheckers
private val variableAssignmentCheckers = session.checkersComponent.declarationCheckers.variableAssignmentCfaBasedCheckers
class FirControlFlowAnalyzer(
session: FirSession,
declarationCheckers: DeclarationCheckers = session.checkersComponent.declarationCheckers
) {
private val cfaCheckers = declarationCheckers.controlFlowAnalyserCheckers
private val variableAssignmentCheckers = declarationCheckers.variableAssignmentCfaBasedCheckers
// Currently declaration in analyzeXXX is not used, but it may be useful in future
@Suppress("UNUSED_PARAMETER")

View File

@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeCheckerContext
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -317,4 +317,4 @@ val FirFunctionCall.isIterator
internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type
fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) =
throwableClassLikeType(session).isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
throwableClassLikeType(session).isSupertypeOf(session.typeContext, this.fullyExpandedType(session))

View File

@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.utils.addToStdlib.min
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirOverrideChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
object FirOverrideChecker : FirClassChecker() {
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false

View File

@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.utils.addToStdlib.min
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -63,18 +62,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
parameterPairs.mapValues { it.value.coneType }
)
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
)
parameterPairs.forEach { (proto, actual) ->
if (actual.source == null) {
// inferred types don't report INAPPLICABLE_CANDIDATE for type aliases!
return@forEach
}
if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) {
if (!satisfiesBounds(proto, actual.coneType, substitutor, context.session.typeContext)) {
reporter.reportOn(actual.source, proto, actual.coneType, context)
return
}
@@ -82,7 +76,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// we must analyze nested things like
// S<S<K, L>, T<K, L>>()
actual.coneType.safeAs<ConeClassLikeType>()?.let {
val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source)
val errorOccurred = analyzeTypeParameters(it, context, reporter, context.session.typeContext, actual.source)
if (errorOccurred) {
return
@@ -99,14 +93,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// typealias A<G> = B<List<G>>
// val a = A<Int>()
when (calleeFir) {
is FirConstructor -> analyzeConstructorCall(expression, substitutor, typeCheckerContext, reporter, context)
is FirConstructor -> analyzeConstructorCall(expression, substitutor, context.session.typeContext, reporter, context)
}
}
private fun analyzeConstructorCall(
functionCall: FirQualifiedAccessExpression,
callSiteSubstitutor: ConeSubstitutor,
typeCheckerContext: AbstractTypeCheckerContext,
typeSystemContext: ConeTypeContext,
reporter: DiagnosticReporter,
context: CheckerContext
) {
@@ -157,7 +151,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
constructorsParameterPairs.forEach { (proto, actual) ->
// just in case
var intersection = typeCheckerContext.intersectTypes(
var intersection = typeSystemContext.intersectTypes(
proto.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return@forEach
@@ -167,7 +161,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// substitute Int for G from
// the example above
val target = callSiteSubstitutor.substituteOrSelf(actual)
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection)
if (!satisfiesBounds) {
reporter.reportOn(functionCall.source, proto, actual, context)
@@ -187,7 +181,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
type: ConeClassLikeType,
context: CheckerContext,
reporter: DiagnosticReporter,
typeCheckerContext: AbstractTypeCheckerContext,
typeSystemContext: ConeTypeContext,
reportTarget: FirSourceElement?
): Boolean {
val prototypeClass = type.lookupTag.toSymbol(context.session)
@@ -218,13 +212,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
)
parameterPairs.forEach { (proto, actual) ->
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
if (!satisfiesBounds(proto, actual.type, substitutor, typeSystemContext)) {
// should report on the parameter instead!
reporter.reportOn(reportTarget, proto, actual, context)
return true
}
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeCheckerContext, reportTarget)
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeSystemContext, reportTarget)
if (errorOccurred) {
return true
@@ -242,14 +236,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
prototypeSymbol: FirTypeParameterSymbol,
target: ConeKotlinType,
substitutor: ConeSubstitutor,
typeCheckerContext: AbstractTypeCheckerContext
typeSystemContext: ConeTypeContext
): Boolean {
var intersection = typeCheckerContext.intersectTypes(
var intersection = typeSystemContext.intersectTypes(
prototypeSymbol.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return true
intersection = substitutor.substituteOrSelf(intersection)
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
return AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection, stubTypesEqualToAnything = false)
}
private fun DiagnosticReporter.reportOn(

View File

@@ -7,13 +7,18 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.cfa.FirControlFlowAnalyzer
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
class ControlFlowAnalysisDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session)
class ControlFlowAnalysisDiagnosticComponent(
collector: AbstractDiagnosticCollector,
declarationCheckers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session, declarationCheckers)
// ------------------------------- Class initializer -------------------------------

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
@@ -13,9 +14,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.*
class DeclarationCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector
collector: AbstractDiagnosticCollector,
private val checkers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
private val checkers = session.checkersComponent.declarationCheckers
override fun visitFile(file: FirFile, data: CheckerContext) {
checkers.fileCheckers.check(file, data, reporter)

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
@@ -13,8 +14,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.*
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
private val checkers = session.checkersComponent.expressionCheckers
class ExpressionCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: ExpressionCheckers = collector.session.checkersComponent.expressionCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
checkers.basicExpressionCheckers.check(anonymousFunction, data, reporter)

View File

@@ -14,10 +14,12 @@ object StandardClassIds {
val BASE_KOTLIN_PACKAGE = FqName("kotlin")
val BASE_REFLECT_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("reflect"))
val BASE_COLLECTIONS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("collections"))
private fun String.baseId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier(this))
private fun ClassId.unsignedId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier("U" + shortClassName.identifier))
private fun String.reflectId() = ClassId(BASE_REFLECT_PACKAGE, Name.identifier(this))
private fun Name.primitiveArrayId() = ClassId(Array.packageFqName, Name.identifier(identifier + Array.shortClassName.identifier))
private fun String.collectionsId() = ClassId(BASE_COLLECTIONS_PACKAGE, Name.identifier(this))
val Nothing = "Nothing".baseId()
val Unit = "Unit".baseId()
@@ -85,6 +87,25 @@ object StandardClassIds {
return "Function$n".baseId()
}
val Iterator = "Iterator".collectionsId()
val Iterable = "Iterable".collectionsId()
val Collection = "Collection".collectionsId()
val List = "List".collectionsId()
val ListIterator = "ListIterator".collectionsId()
val Set = "Set".collectionsId()
val Map = "Map".collectionsId()
val MutableIterator = "MutableIterator".collectionsId()
val MutableIterable = "MutableIterable".collectionsId()
val MutableCollection = "MutableCollection".collectionsId()
val MutableList = "MutableList".collectionsId()
val MutableListIterator = "MutableListIterator".collectionsId()
val MutableSet = "MutableSet".collectionsId()
val MutableMap = "MutableMap".collectionsId()
val MapEntry = Map.createNestedClassId(Name.identifier("Entry"))
val MutableMapEntry = MutableMap.createNestedClassId(Name.identifier("MutableEntry"))
val Suppress = "Suppress".baseId()
}

View File

@@ -82,6 +82,17 @@ object CompilerConeAttributes {
override fun toString(): String = "@UnsafeVariance"
}
val compilerAttributeByClassId: Map<ClassId, ConeAttribute<*>> = mapOf(
Exact.ANNOTATION_CLASS_ID to Exact,
NoInfer.ANNOTATION_CLASS_ID to NoInfer,
EnhancedNullability.ANNOTATION_CLASS_ID to EnhancedNullability,
ExtensionFunctionType.ANNOTATION_CLASS_ID to ExtensionFunctionType,
FlexibleNullability.ANNOTATION_CLASS_ID to FlexibleNullability,
UnsafeVariance.ANNOTATION_CLASS_ID to UnsafeVariance
)
val compilerAttributeByFqName: Map<FqName, ConeAttribute<*>> = compilerAttributeByClassId.mapKeys { it.key.asSingleFqName() }
}
val ConeAttributes.exact: CompilerConeAttributes.Exact? by ConeAttributes.attributeAccessor<CompilerConeAttributes.Exact>()

View File

@@ -9,11 +9,12 @@ import org.jetbrains.kotlin.fir.utils.AttributeArrayOwner
import org.jetbrains.kotlin.fir.utils.Protected
import org.jetbrains.kotlin.fir.utils.TypeRegistry
import org.jetbrains.kotlin.fir.utils.isEmpty
import org.jetbrains.kotlin.types.model.AnnotationMarker
import org.jetbrains.kotlin.utils.addIfNotNull
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
abstract class ConeAttribute<T : ConeAttribute<T>> {
abstract class ConeAttribute<T : ConeAttribute<T>> : AnnotationMarker {
abstract fun union(other: @UnsafeVariance T?): T?
abstract fun intersect(other: @UnsafeVariance T?): T?
abstract fun isSubtypeOf(other: @UnsafeVariance T?): Boolean
@@ -69,6 +70,13 @@ class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : A
return perform(other) { this.intersect(it) }
}
fun remove(attribute: ConeAttribute<*>): ConeAttributes {
if (arrayMap.isEmpty()) return this
val attributes = arrayMap.filter { it != attribute }
if (attributes.size == arrayMap.size) return this
return create(attributes)
}
override fun iterator(): Iterator<ConeAttribute<*>> {
return arrayMap.iterator()
}

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
@@ -83,7 +84,7 @@ class FirAnalyzerFacade(
fun convertToIr(extensions: GeneratorExtensions): Fir2IrResult {
if (scopeSession == null) runResolution()
val signaturer = IdSignatureDescriptor(JvmManglerDesc())
val signaturer = JvmIdSignatureDescriptor(JvmManglerDesc())
return Fir2IrConverter.createModuleFragment(
session, scopeSession!!, firFiles!!,

View File

@@ -37,6 +37,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
)
override val classCheckers: Set<FirClassChecker> = setOf(
FirOverrideChecker,
FirThrowableSubclassChecker,
)
@@ -51,7 +52,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirLocalEntityNotAllowedChecker,
FirManyCompanionObjectsChecker,
FirMethodOfAnyImplementedInInterfaceChecker,
FirOverrideChecker,
FirPrimaryConstructorRequiredForDataClassChecker,
FirSupertypeInitializedInInterfaceChecker,
FirSupertypeInitializedWithoutPrimaryConstructor,

View File

@@ -30,6 +30,9 @@ import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
@OptIn(SessionConfiguration::class)
fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersionSettings) {
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
register(InferenceComponents::class, InferenceComponents(this))
register(FirDeclaredMemberScopeProvider::class, FirDeclaredMemberScopeProvider())
register(FirCorrespondingSupertypesCache::class, FirCorrespondingSupertypesCache(this))
register(FirDefaultParametersResolver::class, FirDefaultParametersResolver())
@@ -38,8 +41,6 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this))
register(FirPredicateBasedProvider::class, FirPredicateBasedProvider.create(this))
register(GeneratedClassIndex::class, GeneratedClassIndex.create())
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
register(InferenceComponents::class, InferenceComponents(this))
}
@OptIn(SessionConfiguration::class)

View File

@@ -220,7 +220,7 @@ class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: Kot
isVararg = false
}
}
dispatchReceiverType = classId.defaultType(typeParameters.map { it.symbol })
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
}
)
}

View File

@@ -51,6 +51,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.threadLocal
import java.util.concurrent.ConcurrentHashMap
@OptIn(ObsoleteDescriptorBasedAPI::class)
class Fir2IrDeclarationStorage(
@@ -60,28 +62,28 @@ class Fir2IrDeclarationStorage(
private val firProvider = session.firProvider
private val fragmentCache = mutableMapOf<FqName, IrExternalPackageFragment>()
private val fragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val builtInsFragmentCache = mutableMapOf<FqName, IrExternalPackageFragment>()
private val builtInsFragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val fileCache = mutableMapOf<FirFile, IrFile>()
private val fileCache = ConcurrentHashMap<FirFile, IrFile>()
private val functionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
private val functionCache = ConcurrentHashMap<FirFunction<*>, IrSimpleFunction>()
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
private val constructorCache = ConcurrentHashMap<FirConstructor, IrConstructor>()
private val initializerCache = mutableMapOf<FirAnonymousInitializer, IrAnonymousInitializer>()
private val initializerCache = ConcurrentHashMap<FirAnonymousInitializer, IrAnonymousInitializer>()
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
private val propertyCache = ConcurrentHashMap<FirProperty, IrProperty>()
// For pure fields (from Java) only
private val fieldToPropertyCache = mutableMapOf<FirField, IrProperty>()
private val fieldToPropertyCache = ConcurrentHashMap<FirField, IrProperty>()
private val delegatedReverseCache = mutableMapOf<IrDeclaration, FirDeclaration>()
private val delegatedReverseCache = ConcurrentHashMap<IrDeclaration, FirDeclaration>()
private val fieldCache = mutableMapOf<FirField, IrField>()
private val fieldCache = ConcurrentHashMap<FirField, IrField>()
private val localStorage = Fir2IrLocalStorage()
private val localStorage by threadLocal { Fir2IrLocalStorage() }
private val delegatedMemberGenerator = DelegatedMemberGenerator(components)

View File

@@ -12,7 +12,10 @@ import org.jetbrains.kotlin.fir.backend.convertWithOffsets
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.FirFakeArgumentForCallableReference
import org.jetbrains.kotlin.fir.resolve.calls.ResolvedCallArgument
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -29,10 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
@@ -58,7 +58,7 @@ internal class AdapterGenerator(
function: IrFunction
): Boolean =
needSuspendConversion(type, function) || needCoercionToUnit(type, function) ||
needVarargSpread(callableReferenceAccess, type, function)
needVarargSpread(callableReferenceAccess)
/**
* For example,
@@ -96,26 +96,11 @@ internal class AdapterGenerator(
*
* At the use site, instead of referenced, we can put the adapter: { a, b -> referenced(a, b) }
*/
private fun needVarargSpread(
callableReferenceAccess: FirCallableReferenceAccess,
type: IrSimpleType,
function: IrFunction
): Boolean {
private fun needVarargSpread(callableReferenceAccess: FirCallableReferenceAccess): Boolean {
// Unbound callable reference 'A::foo'
val shift = if (callableReferenceAccess.explicitReceiver is FirResolvedQualifier) 1 else 0
val typeArguments = type.arguments
// Drop the return type from type arguments
val expectedParameterSize = typeArguments.size - 1 - shift
if (expectedParameterSize < function.valueParameters.size) {
return false
}
var hasSpreadCase = false
function.valueParameters.forEachIndexed { index, irValueParameter ->
if (irValueParameter.isVararg && typeArguments[shift + index] == irValueParameter.varargElementType) {
hasSpreadCase = true
}
}
return hasSpreadCase
return (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments?.any {
it.value is ResolvedCallArgument.VarargArgument || it.value is ResolvedCallArgument.DefaultArgument
} == true
}
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
@@ -127,7 +112,7 @@ internal class AdapterGenerator(
adapteeSymbol: IrFunctionSymbol,
type: IrSimpleType
): IrExpression {
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirFunction
val adaptee = adapteeSymbol.owner
val expectedReturnType = type.arguments.last().typeOrNull
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
@@ -138,7 +123,7 @@ internal class AdapterGenerator(
callableReferenceAccess, startOffset, endOffset, firAdaptee!!, adaptee, type, boundDispatchReceiver, boundExtensionReceiver
)
val irCall = createAdapteeCallForCallableReference(
callableReferenceAccess, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver
callableReferenceAccess, firAdaptee, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver
)
irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) {
if (expectedReturnType?.isUnit() == true) {
@@ -179,7 +164,7 @@ internal class AdapterGenerator(
callableReferenceAccess: FirCallableReferenceAccess,
startOffset: Int,
endOffset: Int,
firAdaptee: FirSimpleFunction,
firAdaptee: FirFunction<*>,
adaptee: IrFunction,
type: IrSimpleType,
boundDispatchReceiver: IrExpression?,
@@ -187,6 +172,7 @@ internal class AdapterGenerator(
): IrSimpleFunction {
val returnType = type.arguments.last().typeOrNull!!
val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! }
val firMemberAdaptee = firAdaptee as FirMemberDeclaration
return irFactory.createFunction(
startOffset, endOffset,
IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE,
@@ -195,13 +181,13 @@ internal class AdapterGenerator(
DescriptorVisibilities.LOCAL,
Modality.FINAL,
returnType,
isInline = firAdaptee.isInline,
isExternal = firAdaptee.isExternal,
isTailrec = firAdaptee.isTailRec,
isSuspend = firAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firAdaptee.isOperator,
isInfix = firAdaptee.isInfix,
isExpect = firAdaptee.isExpect,
isInline = firMemberAdaptee.isInline,
isExternal = firMemberAdaptee.isExternal,
isTailrec = firMemberAdaptee.isTailRec,
isSuspend = firMemberAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firMemberAdaptee.isOperator,
isInfix = firMemberAdaptee.isInfix,
isExpect = firMemberAdaptee.isExpect,
isFakeOverride = false
).also { irAdapterFunction ->
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
@@ -268,6 +254,7 @@ internal class AdapterGenerator(
private fun createAdapteeCallForCallableReference(
callableReferenceAccess: FirCallableReferenceAccess,
firAdaptee: FirFunction<*>,
adapteeSymbol: IrFunctionSymbol,
adapterFunction: IrFunction,
boundDispatchReceiver: IrExpression?,
@@ -296,6 +283,7 @@ internal class AdapterGenerator(
}
var adapterParameterIndex = 0
var parameterShift = 0
if (boundDispatchReceiver != null || boundExtensionReceiver != null) {
val receiverValue = IrGetValueImpl(
startOffset, endOffset, adapterFunction.extensionReceiverParameter!!.symbol, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
@@ -312,50 +300,56 @@ internal class AdapterGenerator(
)
if (adapteeFunction.extensionReceiverParameter != null) {
irCall.extensionReceiver = adaptedReceiverValue
adapterParameterIndex++
} else {
irCall.dispatchReceiver = adaptedReceiverValue
}
parameterShift++
}
adapteeFunction.valueParameters.mapIndexed { index, valueParameter ->
when {
valueParameter.isVararg -> {
if (adapterFunction.valueParameters.size <= index) {
irCall.putValueArgument(index, null)
val mappedArguments = (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments
fun buildIrGetValueArgument(argument: FirExpression): IrGetValue {
val parameterIndex = (argument as? FirFakeArgumentForCallableReference)?.index ?: adapterParameterIndex
adapterParameterIndex++
return adapterFunction.valueParameters[parameterIndex + parameterShift].toIrGetValue(startOffset, endOffset)
}
adapteeFunction.valueParameters.zip(firAdaptee.valueParameters).mapIndexed { index, (valueParameter, firParameter) ->
when (val mappedArgument = mappedArguments?.get(firParameter)) {
is ResolvedCallArgument.VarargArgument -> {
val valueArgument = if (mappedArgument.arguments.isEmpty()) {
null
} else {
val adaptedValueArgument =
IrVarargImpl(startOffset, endOffset, valueParameter.type, valueParameter.varargElementType!!)
var neitherArrayNorSpread = false
while (adapterParameterIndex < adapterFunction.valueParameters.size) {
val irValueArgument =
adapterFunction.valueParameters[adapterParameterIndex].toIrGetValue(startOffset, endOffset)
if (irValueArgument.type == valueParameter.type) {
adaptedValueArgument.addElement(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
adapterParameterIndex++
break
} else if (irValueArgument.type == valueParameter.varargElementType) {
adaptedValueArgument.addElement(irValueArgument)
adapterParameterIndex++
} else {
neitherArrayNorSpread = true
break
}
}
if (neitherArrayNorSpread) {
irCall.putValueArgument(index, null)
} else {
irCall.putValueArgument(index, adaptedValueArgument)
val adaptedValueArgument = IrVarargImpl(
startOffset, endOffset,
valueParameter.type, valueParameter.varargElementType!!,
)
for (argument in mappedArgument.arguments) {
val irValueArgument = buildIrGetValueArgument(argument)
adaptedValueArgument.addElement(irValueArgument)
}
adaptedValueArgument
}
irCall.putValueArgument(index, valueArgument)
}
valueParameter.hasDefaultValue() -> {
ResolvedCallArgument.DefaultArgument -> {
irCall.putValueArgument(index, null)
}
else -> {
irCall.putValueArgument(
index, adapterFunction.valueParameters[adapterParameterIndex++].toIrGetValue(startOffset, endOffset)
)
is ResolvedCallArgument.SimpleArgument -> {
val irValueArgument = buildIrGetValueArgument(mappedArgument.callArgument)
if (valueParameter.isVararg) {
irCall.putValueArgument(
index, IrVarargImpl(
startOffset, endOffset,
valueParameter.type, valueParameter.varargElementType!!,
listOf(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
)
)
} else {
irCall.putValueArgument(index, irValueArgument)
}
}
null -> {
}
}
}

View File

@@ -122,16 +122,6 @@ class CallAndReferenceGenerator(
origin
)
}
is IrConstructorSymbol -> {
val constructor = symbol.owner
val klass = constructor.parent as? IrClass
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = constructor.typeParameters.size + (klass?.typeParameters?.size ?: 0),
valueArgumentsCount = constructor.valueParameters.size,
reflectionTarget = symbol
)
}
is IrFunctionSymbol -> {
assert(type.isFunctionTypeOrSubtype()) {
"Callable reference whose symbol refers to a function should be of functional type."
@@ -144,9 +134,12 @@ class CallAndReferenceGenerator(
generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType)
}
} else {
val klass = function.parent as? IrClass
val typeArgumentCount = function.typeParameters.size +
if (function is IrConstructor) klass?.typeParameters?.size ?: 0 else 0
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = function.typeParameters.size,
typeArgumentsCount = typeArgumentCount,
valueArgumentsCount = function.valueParameters.size,
reflectionTarget = symbol
)
@@ -643,7 +636,7 @@ class CallAndReferenceGenerator(
// If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion.
if (argument.typeRef !is FirResolvedTypeRef ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx,
session.inferenceComponents.ctx.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true),
argument.typeRef.coneType,
parameter.returnTypeRef.coneType,
isFromNullabilityConstraint = true

View File

@@ -2440,6 +2440,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/callableReference/kt37604.kt");
}
@Test
@TestMetadata("kt44483.kt")
public void testKt44483() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
}
@Test
@TestMetadata("nested.kt")
public void testNested() throws Exception {
@@ -16723,6 +16729,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@Test
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/propagateInferenceSessionIntoDeclarationAnalyzers.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferences.kt")
public void testSpecialCallsWithCallableReferences() throws Exception {
@@ -19975,6 +19987,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
}
@Test
@TestMetadata("samExtFunWithCapturingLambda.kt")
public void testSamExtFunWithCapturingLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/samExtFunWithCapturingLambda.kt");
}
@Test
@TestMetadata("simpleFunInterfaceConstructor.kt")
public void testSimpleFunInterfaceConstructor() throws Exception {
@@ -35369,6 +35387,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/types/classifiersOfBuiltInTypes.kt");
}
@Test
@TestMetadata("equalsForClassAndTypeParameterWithSameFqName.kt")
public void testEqualsForClassAndTypeParameterWithSameFqName() throws Exception {
runTest("compiler/testData/codegen/box/reflection/types/equalsForClassAndTypeParameterWithSameFqName.kt");
}
@Test
@TestMetadata("innerGenericArguments.kt")
public void testInnerGenericArguments() throws Exception {
@@ -37301,94 +37325,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class SignatureAnnotations {
@Test
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("defaultAndNamedCombination.kt")
public void testDefaultAndNamedCombination() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt");
}
@Test
@TestMetadata("defaultBoxTypes.kt")
public void testDefaultBoxTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt");
}
@Test
@TestMetadata("defaultEnumType.kt")
public void testDefaultEnumType() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt");
}
@Test
@TestMetadata("defaultLongLiteral.kt")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt");
}
@Test
@TestMetadata("defaultMultipleParams.kt")
public void testDefaultMultipleParams() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt");
}
@Test
@TestMetadata("defaultNull.kt")
public void testDefaultNull() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt");
}
@Test
@TestMetadata("defaultNullableBoxTypes.kt")
public void testDefaultNullableBoxTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt");
}
@Test
@TestMetadata("defaultOverrides.kt")
public void testDefaultOverrides() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt");
}
@Test
@TestMetadata("defaultPrimitiveTypes.kt")
public void testDefaultPrimitiveTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt");
}
@Test
@TestMetadata("defaultValueInConstructor.kt")
public void testDefaultValueInConstructor() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt");
}
@Test
@TestMetadata("defaultWithJavaBase.kt")
public void testDefaultWithJavaBase() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt");
}
@Test
@TestMetadata("defaultWithKotlinBase.kt")
public void testDefaultWithKotlinBase() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt");
}
@Test
@TestMetadata("reorderedParameterNames.kt")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/smap")
@TestDataPath("$PROJECT_ROOT")
@@ -37510,6 +37446,30 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
}
@Test
@TestMetadata("kt44804.kt")
public void testKt44804() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
}
@Test
@TestMetadata("kt44814.kt")
public void testKt44814() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44814.kt");
}
@Test
@TestMetadata("kt44932.kt")
public void testKt44932() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44932.kt");
}
@Test
@TestMetadata("kt44942.kt")
public void testKt44942() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {

View File

@@ -647,6 +647,18 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_3.kt");
}
@Test
@TestMetadata("kt8668_nested.kt")
public void testKt8668_nested() throws Exception {
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_nested.kt");
}
@Test
@TestMetadata("kt8668_nested_2.kt")
public void testKt8668_nested_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_nested_2.kt");
}
@Test
@TestMetadata("twoDifferentDispatchReceivers.kt")
public void testTwoDifferentDispatchReceivers() throws Exception {

View File

@@ -5080,6 +5080,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concatDynamicIndyDataClass.kt");
}
@Test
@TestMetadata("concatDynamicUnit.kt")
public void testConcatDynamicUnit() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concatDynamicUnit.kt");
}
@Test
@TestMetadata("concatNotDynamic.kt")
public void testConcatNotDynamic() throws Exception {
@@ -5574,6 +5580,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
}
@Test
@TestMetadata("whenOr.kt")
public void testWhenOr() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/whenOr.kt");
}
@Test
@TestMetadata("withoutElse.kt")
public void testWithoutElse() throws Exception {

View File

@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.resolveSupertypesInTheAir
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -241,9 +242,7 @@ private fun ConeClassLikeType.mapToCanonicalNoExpansionString(session: FirSessio
} + "[]"
}
val context = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session = session)
with(context) {
with(session.typeContext) {
val typeConstructor = typeConstructor()
typeConstructor.getPrimitiveType()?.let { return JvmPrimitiveType.get(it).wrapperFqName.asString() }
typeConstructor.getPrimitiveArrayType()?.let { return JvmPrimitiveType.get(it).javaKeywordName + "[]" }

View File

@@ -18,8 +18,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.render
@@ -30,12 +28,9 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.typeEnhancement.*
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -185,27 +180,26 @@ class FirSignatureEnhancement(
enhanceReturnType(firMethod, overriddenMembers, memberContext, predefinedEnhancementInfo)
}
val newValueParameterInfo = mutableListOf<EnhanceValueParameterResult>()
val enhancedValueParameterTypes = mutableListOf<FirResolvedTypeRef>()
for ((index, valueParameter) in firMethod.valueParameters.withIndex()) {
if (hasReceiver && index == 0) continue
newValueParameterInfo += enhanceValueParameter(
enhancedValueParameterTypes += enhanceValueParameterType(
firMethod, overriddenMembers, hasReceiver,
memberContext, predefinedEnhancementInfo, valueParameter as FirJavaValueParameter,
if (hasReceiver) index - 1 else index
)
}
val newValueParameters = firMethod.valueParameters.zip(newValueParameterInfo) { valueParameter, newInfo ->
val (newTypeRef, newDefaultValue) = newInfo
val newValueParameters = firMethod.valueParameters.zip(enhancedValueParameterTypes) { valueParameter, enhancedReturnType ->
buildValueParameter {
source = valueParameter.source
session = this@FirSignatureEnhancement.session
origin = FirDeclarationOrigin.Enhancement
returnTypeRef = newTypeRef
returnTypeRef = enhancedReturnType
this.name = valueParameter.name
symbol = FirVariableSymbol(this.name)
defaultValue = valueParameter.defaultValue ?: newDefaultValue
defaultValue = valueParameter.defaultValue
isCrossinline = valueParameter.isCrossinline
isNoinline = valueParameter.isNoinline
isVararg = valueParameter.isVararg
@@ -298,9 +292,7 @@ class FirSignatureEnhancement(
return signatureParts.type
}
private data class EnhanceValueParameterResult(val typeRef: FirResolvedTypeRef, val defaultValue: FirExpression?)
private fun enhanceValueParameter(
private fun enhanceValueParameterType(
ownerFunction: FirFunction<*>,
overriddenMembers: List<FirCallableMemberDeclaration<*>>,
hasReceiver: Boolean,
@@ -308,7 +300,7 @@ class FirSignatureEnhancement(
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?,
ownerParameter: FirJavaValueParameter,
index: Int
): EnhanceValueParameterResult {
): FirResolvedTypeRef {
val signatureParts = ownerFunction.partsForValueParameter(
typeQualifierResolver,
overriddenMembers,
@@ -321,13 +313,7 @@ class FirSignatureEnhancement(
predefinedEnhancementInfo?.parametersInfo?.getOrNull(index),
forAnnotationMember = owner.classKind == ClassKind.ANNOTATION_CLASS
)
val firResolvedTypeRef = signatureParts.type
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
NullDefaultValue -> buildConstExpression(null, ConstantValueKind.Null, null)
is StringDefaultValue -> firResolvedTypeRef.type.lexicalCastFrom(session, defaultValue.value)
null -> null
}
return EnhanceValueParameterResult(firResolvedTypeRef, defaultValueExpression)
return signatureParts.type
}
private fun enhanceReturnType(

View File

@@ -13,11 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildQualifiedAccessExpression
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
@@ -31,11 +26,6 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.JavaDefaultQualifiers
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_NULL_FQ_NAME
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME
import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
import org.jetbrains.kotlin.load.java.structure.JavaType
import org.jetbrains.kotlin.load.java.typeEnhancement.*
@@ -45,7 +35,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.RawType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.extractRadix
internal class IndexedJavaTypeQualifiers(private val data: Array<JavaTypeQualifiers>) {
@@ -317,22 +306,6 @@ internal fun ConeKotlinType.lexicalCastFrom(session: FirSession, value: String):
}
}
internal fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
annotations.find { it.classId == DEFAULT_VALUE_ID }
?.arguments?.firstOrNull()
?.safeAs<FirConstExpression<*>>()?.value?.safeAs<String>()
?.let { return StringDefaultValue(it) }
if (annotations.any { it.classId == DEFAULT_NULL_ID }) {
return NullDefaultValue
}
return null
}
private val DEFAULT_VALUE_ID = ClassId.topLevel(DEFAULT_VALUE_FQ_NAME)
private val DEFAULT_NULL_ID = ClassId.topLevel(DEFAULT_NULL_FQ_NAME)
internal fun List<FirAnnotationCall>.computeTypeAttributesForJavaType(): ConeAttributes =
computeTypeAttributes { classId ->
when (classId) {

View File

@@ -6,21 +6,19 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
val FirSession.typeContext: ConeInferenceContext
get() = inferenceComponents.ctx
val FirSession.typeCheckerContext: ConeTypeCheckerContext
get() = inferenceComponents.ctx
/**
* Returns the list of functions that overridden by given
*/

View File

@@ -0,0 +1,31 @@
/*
* 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.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.model.typeConstructor
fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType)
?.lookupTag
?.toSymbol(session) as? FirRegularClassSymbol
?: return null
symbol.ensureResolved(FirResolvePhase.STATUS, session)
val firClass = symbol.fir
if (!firClass.status.isInline) return null
val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null
val valueParameter = constructor.valueParameters.singleOrNull() ?: return null
val unsubstitutedType = valueParameter.returnTypeRef.coneType
val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context)
return substitutor.substituteOrNull(unsubstitutedType)
}

View File

@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.util.PersistentSetMultimap
import org.jetbrains.kotlin.name.Name
class PersistentImplicitReceiverStack private constructor(

View File

@@ -104,6 +104,7 @@ abstract class AbstractConeCallConflictResolver(
is FirConstructor -> createFlatSignature(call, declaration)
is FirVariable<*> -> createFlatSignature(call, declaration)
is FirClass<*> -> createFlatSignature(call, declaration)
is FirTypeAlias -> createFlatSignature(call, declaration)
else -> error("Not supported: $declaration")
}
}
@@ -163,10 +164,10 @@ abstract class AbstractConeCallConflictResolver(
?: call.argumentMapping?.map { it.value.argumentType() }.orEmpty())
}
private fun createFlatSignature(call: Candidate, klass: FirClass<*>): FlatSignature<Candidate> {
private fun createFlatSignature(call: Candidate, klass: FirClassLikeDeclaration<*>): FlatSignature<Candidate> {
return FlatSignature(
call,
(klass as? FirRegularClass)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
valueParameterTypes = emptyList(),
hasExtensionReceiver = false,
hasVarargs = false,

View File

@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclarati
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.typeCheckerContext
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
@@ -26,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompat
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.model.TypeSystemCommonSuperTypesContext
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun Candidate.resolveArgumentExpression(
@@ -416,7 +416,10 @@ fun FirExpression.isFunctional(
val returnTypeCompatible =
expectedReturnType is ConeTypeParameterType ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx,
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = true
),
invokeSymbol.fir.returnTypeRef.coneType,
expectedReturnType,
isFromNullabilityConstraint = false
@@ -433,7 +436,10 @@ fun FirExpression.isFunctional(
val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible()
expectedParameterType is ConeTypeParameterType ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx,
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = true
),
invokeParameter.returnTypeRef.coneType,
expectedParameterType,
isFromNullabilityConstraint = false
@@ -488,7 +494,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
val simplifiedArgumentType = argumentType.lowerBoundIfFlexible() as? ConeTypeParameterType ?: return argumentType
val typeParameter = simplifiedArgumentType.lookupTag.typeParameterSymbol.fir
val context = session.typeCheckerContext
val context = session.typeContext
val chosenSupertype = typeParameter.bounds.map { it.coneType }
.singleOrNull { it.hasSupertypeWithGivenClassId(expectedTypeClassId, context) } ?: return argumentType
@@ -501,7 +507,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
}
}
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: ConeTypeCheckerContext): Boolean {
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: TypeSystemCommonSuperTypesContext): Boolean {
return with(context) {
anySuperTypeConstructor {
it is ConeClassLikeLookupTag && it.classId == classId

View File

@@ -51,8 +51,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
}
candidate.resultingTypeForCallableReference = resultingType
candidate.usesSuspendConversion =
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
candidate.callableReferenceAdaptation = callableReferenceAdaptation
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
addOtherSystem(candidate.system.asReadOnlyStorage())
@@ -133,7 +132,7 @@ internal class CallableReferenceAdaptation(
val argumentTypes: Array<ConeKotlinType>,
val coercionStrategy: CoercionStrategy,
val defaults: Int,
val mappedArguments: Map<FirValueParameter, ResolvedCallArgument>,
val mappedArguments: CallableReferenceMappedArguments,
val suspendConversionStrategy: SuspendConversionStrategy
)
@@ -351,7 +350,7 @@ private fun createFakeArgumentsForReference(
}
}
private class FirFakeArgumentForCallableReference(
class FirFakeArgumentForCallableReference(
val index: Int
) : FirExpression() {
override val source: FirSourceElement?

View File

@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
@@ -97,6 +98,13 @@ class Candidate(
var resultingTypeForCallableReference: ConeKotlinType? = null
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
var usesSAM: Boolean = false
internal var callableReferenceAdaptation: CallableReferenceAdaptation? = null
set(value) {
field = value
usesSuspendConversion = value?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
}
var usesSuspendConversion: Boolean = false
var argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>? = null

View File

@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.Name
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
import kotlin.collections.component1

View File

@@ -29,19 +29,20 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class DataFlowAnalyzerContext<FLOW : Flow>(
val graphBuilder: ControlFlowGraphBuilder,
variableStorage: VariableStorage,
flowOnNodes: MutableMap<CFGNode<*>, FLOW>,
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>,
val preliminaryLoopVisitor: PreliminaryLoopVisitor
) {
var flowOnNodes = flowOnNodes
private set
@@ -54,13 +55,15 @@ class DataFlowAnalyzerContext<FLOW : Flow>(
variableStorage = variableStorage.clear()
flowOnNodes = mutableMapOf()
preliminaryLoopVisitor.resetState()
}
companion object {
fun <FLOW : Flow> empty(session: FirSession) =
fun <FLOW : Flow> empty(session: FirSession): DataFlowAnalyzerContext<FLOW> =
DataFlowAnalyzerContext<FLOW>(
ControlFlowGraphBuilder(), VariableStorage(session),
mutableMapOf(), mutableMapOf()
mutableMapOf(), mutableMapOf(), PreliminaryLoopVisitor()
)
}
}
@@ -210,12 +213,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
// TODO: questionable
postponedLambdaExitNode?.mergeIncomingFlow()
functionExitNode.mergeIncomingFlow()
exitCapturingStatement(anonymousFunction)
return FirControlFlowGraphReferenceImpl(graph)
}
fun visitPostponedAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
val (enterNode, exitNode) = graphBuilder.visitPostponedAnonymousFunction(anonymousFunction)
enterNode.mergeIncomingFlow()
enterCapturingStatement(enterNode, anonymousFunction)
exitNode.mergeIncomingFlow()
enterNode.flow = enterNode.flow.fork()
}
@@ -236,12 +241,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
}
private fun exitLocalClass(klass: FirRegularClass): ControlFlowGraph {
// TODO: support capturing of mutable properties, KT-44877
val (node, controlFlowGraph) = graphBuilder.exitLocalClass(klass)
node.mergeIncomingFlow()
return controlFlowGraph
}
fun exitAnonymousObject(anonymousObject: FirAnonymousObject): ControlFlowGraph {
// TODO: support capturing of mutable properties, KT-44877
val (node, controlFlowGraph) = graphBuilder.exitAnonymousObject(anonymousObject)
node.mergeIncomingFlow()
return controlFlowGraph
@@ -601,11 +608,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
shouldRemoveSynthetics = true
)
}
exitCapturingStatement(exitNode.fir)
}
fun enterWhileLoop(loop: FirLoop) {
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
loopEnterNode.mergeIncomingFlow()
enterCapturingStatement(loopEnterNode, loop)
loopConditionEnterNode.mergeIncomingFlow()
}
@@ -630,11 +639,30 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
exitCommonLoop(exitNode)
}
private fun enterCapturingStatement(node: CFGNode<*>, statement: FirStatement) {
val reassignedNames = context.preliminaryLoopVisitor.enterCapturingStatement(statement)
if (reassignedNames.isEmpty()) return
val possiblyChangedVariables = variableStorage.realVariables.filterKeys {
val fir = (it.symbol as? FirVariableSymbol<*>)?.fir ?: return@filterKeys false
fir.isVar && fir.name in reassignedNames
}.values
if (possiblyChangedVariables.isEmpty()) return
val flow = node.flow
for (variable in possiblyChangedVariables) {
logicSystem.removeAllAboutVariableIncludingAliasInformation(flow, variable)
}
}
private fun exitCapturingStatement(statement: FirStatement) {
context.preliminaryLoopVisitor.exitCapturingStatement(statement)
}
// ----------------------------------- Do while Loop -----------------------------------
fun enterDoWhileLoop(loop: FirLoop) {
val (loopEnterNode, loopBlockEnterNode) = graphBuilder.enterDoWhileLoop(loop)
loopEnterNode.mergeIncomingFlow()
enterCapturingStatement(loopEnterNode, loop)
loopBlockEnterNode.mergeIncomingFlow()
}
@@ -1108,12 +1136,6 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
lhsExitNode.mergeIncomingFlow()
val flow = lhsExitNode.flow
val lhsVariable = variableStorage.getOrCreateVariable(flow, elvisExpression.lhs)
rhsEnterNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable eq null,
shouldForkFlow = true,
shouldRemoveSynthetics = false
)
lhsIsNotNullNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable notEq null,
@@ -1124,6 +1146,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
it.addTypeStatement(lhsVariable typeEq any)
}
}
rhsEnterNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable eq null,
shouldForkFlow = true,
shouldRemoveSynthetics = false
).also {
logicSystem.updateAllReceivers(it)
}
}
fun exitElvis(elvisExpression: FirElvisExpression) {

View File

@@ -36,6 +36,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
abstract fun addImplication(flow: FLOW, implication: Implication)
abstract fun removeAllAboutVariable(flow: FLOW, variable: RealVariable)
abstract fun removeAllAboutVariableIncludingAliasInformation(flow: FLOW, variable: RealVariable)
abstract fun translateVariableFromConditionInStatements(
flow: FLOW,
@@ -142,7 +143,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
if (types.any { it.isEmpty() }) return mutableSetOf()
val intersectedTypes = types.map {
if (it.size > 1) {
context.intersectTypes(it.toList()) as ConeKotlinType
context.intersectTypes(it.toList())
} else {
assert(it.size == 1) { "We've already checked each set of types is not empty." }
it.single()

View File

@@ -254,6 +254,21 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
// TODO: should we search variable in all logic statements?
}
override fun removeAllAboutVariableIncludingAliasInformation(flow: PersistentFlow, variable: RealVariable) {
removeAllAboutVariable(flow, variable)
val existedAlias = flow.directAliasMap[variable]?.variable
if (existedAlias != null) {
flow.directAliasMap = flow.directAliasMap.remove(variable)
val updatedBackwardsAliasList = flow.backwardsAliasMap.getValue(existedAlias).remove(variable)
flow.backwardsAliasMap = if (updatedBackwardsAliasList.isEmpty()) {
flow.backwardsAliasMap.remove(existedAlias)
} else {
flow.backwardsAliasMap.put(existedAlias, updatedBackwardsAliasList)
}
flow.updatedAliasDiff = flow.updatedAliasDiff.add(variable)
}
}
override fun translateVariableFromConditionInStatements(
flow: PersistentFlow,
originalVariable: DataFlowVariable,

View File

@@ -0,0 +1,87 @@
/*
* 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.resolve.dfa
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.util.SetMultimap
import org.jetbrains.kotlin.fir.util.setMultimapOf
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name
class PreliminaryLoopVisitor {
private val reassignedVariablesPerElement: SetMultimap<FirStatement, Name> = setMultimapOf()
fun enterCapturingStatement(statement: FirStatement): Set<Name> {
assert(statement is FirLoop || statement is FirClass<*> || statement is FirFunction<*>)
if (statement !in reassignedVariablesPerElement) {
statement.accept(visitor, null)
}
return reassignedVariablesPerElement[statement]
}
fun exitCapturingStatement(statement: FirStatement) {
assert(statement is FirLoop || statement is FirClass<*> || statement is FirFunction<*>)
reassignedVariablesPerElement.removeKey(statement)
}
fun resetState() {
reassignedVariablesPerElement.clear()
}
// FirStatement -- closest statement (loop/lambda/local declaration) which may contain reassignments
private val visitor = object : FirVisitor<Unit, FirStatement?>() {
override fun visitElement(element: FirElement, data: FirStatement?) {
element.acceptChildren(this, data)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: FirStatement?) {
val reference = variableAssignment.lValue as? FirNamedReference
if (reference != null) {
requireNotNull(data)
reassignedVariablesPerElement.put(data, reference.name)
}
visitElement(variableAssignment, data)
}
override fun visitWhileLoop(whileLoop: FirWhileLoop, data: FirStatement?) {
visitCapturingStatement(whileLoop, data)
}
override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: FirStatement?) {
visitCapturingStatement(doWhileLoop, data)
}
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: FirStatement?) {
visitCapturingStatement(anonymousFunction, data)
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: FirStatement?) {
visitCapturingStatement(simpleFunction, data)
}
override fun <F : FirFunction<F>> visitFunction(function: FirFunction<F>, data: FirStatement?) {
visitCapturingStatement(function, data)
}
override fun visitRegularClass(regularClass: FirRegularClass, data: FirStatement?) {
visitCapturingStatement(regularClass, data)
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: FirStatement?) {
visitCapturingStatement(anonymousObject, data)
}
private fun visitCapturingStatement(statement: FirStatement, parent: FirStatement?) {
visitElement(statement, statement)
if (parent != null) {
reassignedVariablesPerElement.putAll(parent, reassignedVariablesPerElement[statement])
}
}
}
}

View File

@@ -26,7 +26,10 @@ import kotlin.contracts.contract
@OptIn(DfaInternals::class)
class VariableStorage(private val session: FirSession) {
private var counter = 1
private val realVariables: MutableMap<Identifier, RealVariable> = HashMap()
private val _realVariables: MutableMap<Identifier, RealVariable> = HashMap()
val realVariables: Map<Identifier, RealVariable>
get() = _realVariables
private val syntheticVariables: MutableMap<FirElement, SyntheticVariable> = HashMap()
fun clear(): VariableStorage = VariableStorage(session)
@@ -34,7 +37,7 @@ class VariableStorage(private val session: FirSession) {
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
val realFir = fir.unwrapElement()
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
return realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
}
private fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
@@ -108,7 +111,7 @@ class VariableStorage(private val session: FirSession) {
fun getRealVariableWithoutUnwrappingAlias(symbol: AbstractFirBasedSymbol<*>?, fir: FirElement, flow: Flow): RealVariable? {
val realFir = fir.unwrapElement()
return symbol.takeIf { it.isStable(realFir) }?.let {
realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
_realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
}
}
@@ -131,7 +134,7 @@ class VariableStorage(private val session: FirSession) {
}
fun removeRealVariable(symbol: AbstractFirBasedSymbol<*>) {
realVariables.remove(Identifier(symbol, null, null))
_realVariables.remove(Identifier(symbol, null, null))
}
fun removeSyntheticVariable(variable: DataFlowVariable) {

View File

@@ -79,6 +79,7 @@ class ControlFlowGraphBuilder {
private val exitsFromCompletedPostponedAnonymousFunctions: MutableList<PostponedLambdaExitNode> = mutableListOf()
private val whenExitNodes: NodeStorage<FirWhenExpression, WhenExitNode> = NodeStorage()
private val whenBranchIndices: Stack<Map<FirWhenBranch, Int>> = stackOf()
private val binaryAndExitNodes: Stack<BinaryAndExitNode> = stackOf()
private val binaryOrExitNodes: Stack<BinaryOrExitNode> = stackOf()
@@ -596,6 +597,7 @@ class ControlFlowGraphBuilder {
val node = createWhenEnterNode(whenExpression)
addNewSimpleNode(node)
whenExitNodes.push(createWhenExitNode(whenExpression))
whenBranchIndices.push(whenExpression.branches.mapIndexed { index, branch -> branch to index }.toMap())
levelCounter++
return node
}
@@ -613,6 +615,7 @@ class ControlFlowGraphBuilder {
lastNodes.push(it)
addEdge(conditionExitNode, it)
}
levelCounter += whenBranchIndices.top().getValue(whenBranch)
return conditionExitNode to branchEnterNode
}
@@ -622,6 +625,7 @@ class ControlFlowGraphBuilder {
popAndAddEdge(node)
val whenExitNode = whenExitNodes.top()
addEdge(node, whenExitNode, propagateDeadness = false)
levelCounter -= whenBranchIndices.top().getValue(whenBranch)
return node
}
@@ -640,6 +644,7 @@ class ControlFlowGraphBuilder {
lastNodes.push(whenExitNode)
dropPostponedLambdasForNonDeterministicCalls()
levelCounter--
whenBranchIndices.pop()
return whenExitNode to syntheticElseBranchNode
}

View File

@@ -18,6 +18,7 @@ import java.util.*
class FirControlFlowGraphRenderVisitor(
builder: StringBuilder,
private val renderLevels: Boolean = false
) : FirVisitorVoid() {
companion object {
private const val EDGE = " -> "
@@ -81,7 +82,13 @@ class FirControlFlowGraphRenderVisitor(
color = BLUE
}
val attributes = mutableListOf<String>()
attributes += "label=\"${node.render().replace("\"", "")}\""
val label = buildString {
append(node.render().replace("\"", ""))
if (renderLevels) {
append(" [${node.level}]")
}
}
attributes += "label=\"$label\""
fun fillColor(color: String) {
attributes += "style=\"filled\""
@@ -218,4 +225,4 @@ private fun ControlFlowGraph.forEachSubGraph(block: (ControlFlowGraph) -> Unit)
block(subGraph)
subGraph.forEachSubGraph(block)
}
}
}

View File

@@ -7,14 +7,16 @@ package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.types.AbstractTypeApproximator
@NoMutableState
class InferenceComponents(val session: FirSession) : FirSessionComponent {
val ctx: ConeTypeCheckerContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session)
val ctx: ConeInferenceContext = object : ConeInferenceContext {
override val session: FirSession
get() = this@InferenceComponents.session
}
val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {}
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)

View File

@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
@@ -45,16 +46,15 @@ fun ConeKotlinType.isKMutableProperty(session: FirSession): Boolean {
}
private fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
val classId = classId(session) ?: return null
return FunctionClassKind.byClassNamePrefix(classId.packageFqName, classId.relativeClassName.asString())
return classId(session)?.toFunctionClassKind()
}
private fun ClassId.toFunctionClassKind(): FunctionClassKind? {
return FunctionClassKind.byClassNamePrefix(packageFqName, relativeClassName.asString())
}
fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.Function ||
kind == FunctionClassKind.KFunction ||
kind == FunctionClassKind.SuspendFunction ||
kind == FunctionClassKind.KSuspendFunction
return functionClassKind(session) != null
}
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
@@ -62,6 +62,10 @@ fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
return kind == FunctionClassKind.Function
}
fun ConeClassLikeLookupTag.isBuiltinFunctionalType(): Boolean {
return classId.toFunctionClassKind() != null
}
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.SuspendFunction ||

View File

@@ -10,6 +10,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.types.model.typeConstructor
abstract class AbstractConeSubstitutor : ConeSubstitutor() {
private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
@@ -162,3 +166,15 @@ data class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, Co
return result
}
}
fun createTypeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, ConeKotlinType>, context: ConeTypeContext): ConeSubstitutor {
if (map.isEmpty()) return ConeSubstitutor.Empty
return object : AbstractConeSubstitutor(),
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null
val new = map[type.typeConstructor(context)] ?: return null
return new.approximateIntegerLiteralType().updateNullabilityIfNeeded(type)
}
}
}

View File

@@ -14,10 +14,8 @@ import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.varargElementType
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceAdaptation
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -295,6 +293,7 @@ class FirCallCompletionResultsWriterTransformer(
name = calleeReference.name
resolvedSymbol = calleeReference.candidateSymbol
inferredTypeArguments.addAll(computeTypeArgumentTypes(calleeReference.candidate))
mappedArguments = subCandidate.callableReferenceAdaptation?.mappedArguments ?: emptyMap()
},
).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
.transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression())

View File

@@ -989,7 +989,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
if (variable.returnTypeRef is FirImplicitTypeRef) {
when {
initializer != null -> {
val expectedType = when (val resultType = initializer.resultType) {
val unwrappedInitializer = (initializer as? FirExpressionWithSmartcast)?.originalExpression ?: initializer
val expectedType = when (val resultType = unwrappedInitializer.resultType) {
is FirImplicitTypeRef -> buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("No result type for initializer", DiagnosticKind.InferenceError)
}

View File

@@ -496,7 +496,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
if (baseType !is ConeClassLikeType) return this
val baseFirClass = baseType.lookupTag.toSymbol(session)?.fir ?: return this
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(session.typeCheckerContext, baseType.lookupTag, type.lookupTag)) {
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(
session.typeContext.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), baseType.lookupTag, type.lookupTag)) {
// If actual type of declaration is more specific than bare type then we should just find
// corresponding supertype with proper arguments
with(session.typeContext) {

View File

@@ -13,9 +13,11 @@ import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.name.FqName
private object FirDefaultStarImportingScopeKey : ScopeSessionKey<DefaultImportPriority, FirScope>()
private object FirDefaultSimpleImportingScopeKey : ScopeSessionKey<DefaultImportPriority, FirScope>()
private object FileImportingScopeKey : ScopeSessionKey<FirFile, ListStorageFirScope>()
private val INVISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val VISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultSimpleImportingScope>()
private val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
private val ALL_IMPORTS = scopeSessionKey<FirFile, ListStorageFirScope>()
private class ListStorageFirScope(val result: List<FirScope>) : FirScope()
@@ -25,7 +27,7 @@ fun createImportingScopes(
scopeSession: ScopeSession,
useCaching: Boolean = true
): List<FirScope> = if (useCaching) {
scopeSession.getOrBuild(file, FileImportingScopeKey) {
scopeSession.getOrBuild(file, ALL_IMPORTS) {
ListStorageFirScope(doCreateImportingScopes(file, session, scopeSession))
}.result
} else {
@@ -39,17 +41,26 @@ private fun doCreateImportingScopes(
): List<FirScope> {
return listOf(
// from low priority to high priority
scopeSession.getOrBuild(DefaultImportPriority.LOW, FirDefaultStarImportingScopeKey) {
FirDefaultStarImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
scopeSession.getOrBuild(DefaultImportPriority.LOW, INVISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, FirDefaultStarImportingScopeKey) {
FirDefaultStarImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
scopeSession.getOrBuild(DefaultImportPriority.HIGH, INVISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.HIGH)
},
FirExplicitStarImportingScope(file.imports, session, scopeSession),
scopeSession.getOrBuild(DefaultImportPriority.LOW, FirDefaultSimpleImportingScopeKey) {
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES),
// TODO: invisible classes from current package should go before this point
scopeSession.getOrBuild(DefaultImportPriority.LOW, VISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, VISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.HIGH)
},
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES),
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, FirDefaultSimpleImportingScopeKey) {
scopeSession.getOrBuild(DefaultImportPriority.HIGH, DEFAULT_SIMPLE_IMPORT) {
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
},
scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
@@ -60,8 +71,6 @@ private fun doCreateImportingScopes(
)
}
private val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSession: ScopeSession): FirScope? {
val klass = toSymbol(session)?.fir as? FirRegularClass ?: return null
return klass.scopeProvider.getNestedClassifierScope(klass, session, scopeSession)

View File

@@ -6,9 +6,12 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.moduleVisibilityChecker
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls
@@ -17,52 +20,90 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.annotations.JVM_THROWS_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_NATIVE_THROWS_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
enum class FirImportingScopeFilter {
ALL, INVISIBLE_CLASSES, MEMBERS_AND_VISIBLE_CLASSES;
fun check(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
if (this == ALL) return true
// TODO: also check DeprecationLevel.HIDDEN and required Kotlin version
val fir = symbol.fir as? FirMemberDeclaration ?: return false
val isVisible = when (fir.status.visibility) {
// When importing from the same module, status may be unknown because the status resolver depends on super types
// to determine visibility for functions, so it may not have finished yet. Since we only care about classes,
// though, "unknown" will always become public anyway.
Visibilities.Unknown -> true
Visibilities.Internal ->
symbol.fir.session == session || session.moduleVisibilityChecker?.isInFriendModule(fir) == true
// All non-`internal` visibilities are either even more restrictive (e.g. `private`) or must not
// be checked in imports (e.g. `protected` may be valid in some use sites).
else -> !fir.status.visibility.mustCheckInImports()
}
return isVisible == (this == MEMBERS_AND_VISIBLE_CLASSES)
}
}
abstract class FirAbstractImportingScope(
session: FirSession,
protected val scopeSession: ScopeSession,
protected val filter: FirImportingScopeFilter,
lookupInFir: Boolean
) : FirAbstractProviderBasedScope(session, lookupInFir) {
private fun getStaticsScope(symbol: FirClassLikeSymbol<*>): FirScope? {
if (symbol is FirTypeAliasSymbol) {
val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(session)
if (expansionSymbol != null) {
return getStaticsScope(expansionSymbol)
}
} else {
val firClass = (symbol as FirClassSymbol<*>).fir
return if (firClass.classKind == ClassKind.OBJECT) {
FirObjectImportedCallableScope(
symbol.classId,
firClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
)
} else {
firClass.scopeProvider.getStaticScope(firClass, session, scopeSession)
}
private val FirClassLikeSymbol<*>.fullyExpandedSymbol: FirClassSymbol<*>?
get() = when (this) {
is FirTypeAliasSymbol -> fir.expandedConeType?.lookupTag?.toSymbol(session)?.fullyExpandedSymbol
is FirClassSymbol<*> -> this
}
return null
private fun FirClassSymbol<*>.getStaticsScope(): FirScope? =
if (fir.classKind == ClassKind.OBJECT) {
FirObjectImportedCallableScope(
classId, fir.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
)
} else {
fir.scopeProvider.getStaticScope(fir, session, scopeSession)
}
fun getStaticsScope(classId: ClassId): FirScope? =
provider.getClassLikeSymbolByFqName(classId)?.fullyExpandedSymbol?.getStaticsScope()
protected fun findSingleClassifierSymbolByName(name: Name?, imports: List<FirResolvedImport>): FirClassLikeSymbol<*>? {
var result: FirClassLikeSymbol<*>? = null
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val classId = import.resolvedClassId?.createNestedClassId(importedName)
?: ClassId.topLevel(import.packageFqName.child(importedName))
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: continue
if (!filter.check(symbol, session)) continue
result = when {
result == null || result == symbol -> symbol
// Importing multiple versions of the same type is normally an ambiguity, but in the case of `kotlin.Throws`,
// it should take precedence over platform-specific variants. This is lifted directly from `LazyImportScope`
// from the old backend; most likely `Throws` predates expect-actual, and this is a backwards compatibility hack.
// TODO: remove redundant versions of `Throws` from the standard library
result.classId.isJvmOrNativeThrows && symbol.classId.isCommonThrows -> symbol
result.classId.isCommonThrows && symbol.classId.isJvmOrNativeThrows -> result
// TODO: if there is an ambiguity at this scope, further scopes should not be checked.
// Doing otherwise causes KT-39073. Also, returning null here instead of an error symbol
// or something produces poor quality diagnostics ("unresolved name" rather than "ambiguity").
else -> return null
}
}
return result
}
fun getStaticsScope(classId: ClassId): FirScope? {
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: return null
return getStaticsScope(symbol)
}
protected inline fun processFunctionsByNameWithImport(
name: Name,
import: FirResolvedImport,
crossinline processor: (FirNamedFunctionSymbol) -> Unit
) {
import.resolvedClassId?.let { classId ->
getStaticsScope(classId)?.processFunctionsByName(name) { processor(it) }
} ?: run {
if (name.isSpecial || name.identifier.isNotEmpty()) {
val symbols = provider.getTopLevelFunctionSymbols(import.packageFqName, name)
for (symbol in symbols) {
protected fun processFunctionsByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirNamedFunctionSymbol) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val staticsScope = import.resolvedClassId?.let(::getStaticsScope)
if (staticsScope != null) {
staticsScope.processFunctionsByName(importedName, processor)
} else if (importedName.isSpecial || importedName.identifier.isNotEmpty()) {
for (symbol in provider.getTopLevelFunctionSymbols(import.packageFqName, importedName)) {
symbol.ensureResolvedForCalls(session)
processor(symbol)
}
@@ -70,17 +111,15 @@ abstract class FirAbstractImportingScope(
}
}
protected inline fun processPropertiesByNameWithImport(
name: Name,
import: FirResolvedImport,
crossinline processor: (FirVariableSymbol<*>) -> Unit
) {
import.resolvedClassId?.let { classId ->
getStaticsScope(classId)?.processPropertiesByName(name) { processor(it) }
} ?: run {
if (name.isSpecial || name.identifier.isNotEmpty()) {
val symbols = provider.getTopLevelPropertySymbols(import.packageFqName, name)
for (symbol in symbols) {
protected fun processPropertiesByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirVariableSymbol<*>) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val staticsScope = import.resolvedClassId?.let(::getStaticsScope)
if (staticsScope != null) {
staticsScope.processPropertiesByName(importedName, processor)
} else if (importedName.isSpecial || importedName.identifier.isNotEmpty()) {
for (symbol in provider.getTopLevelPropertySymbols(import.packageFqName, importedName)) {
symbol.ensureResolvedForCalls(session)
processor(symbol)
}
@@ -88,3 +127,9 @@ abstract class FirAbstractImportingScope(
}
}
}
private val ClassId.isJvmOrNativeThrows: Boolean
get() = asSingleFqName().let { it == JVM_THROWS_ANNOTATION_FQ_NAME || it == KOTLIN_NATIVE_THROWS_ANNOTATION_FQ_NAME }
private val ClassId.isCommonThrows: Boolean
get() = asSingleFqName() == KOTLIN_THROWS_ANNOTATION_FQ_NAME

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