Compare commits

..

759 Commits

Author SHA1 Message Date
Dmitry Petrov
de25359a90 Fix stdlib compilation after updated @JvmName check
Previously, extension receiver type was not taken into account when
checking for @JvmName annotation applicability to possibly mangled
functions (such functions, however, were mangled).
This bug was fixed, but, unfortunately, not before such functions were
added to stdlib ('sumOf' family).
2020-06-04 12:16:28 +03:00
Dmitry Petrov
202bbdf8dd Forward compatibility hacks for Result.{success, failure}
Don't mangled functions annotated with @JvmName.
Annotate 'Result.success' and 'Result.failure' with @JvmName and
@Suppress("INAPPLICABLE_JVM_NAME").
NB this would require bootstrap.
2020-06-04 12:16:27 +03:00
Ilya Kirillov
8a4521864e Wizard: use cache redirector on project importing tests 2020-06-04 12:00:42 +03:00
Ilya Kirillov
cce5a9a1ca Wizard: download latest dev version for tests from bintray 2020-06-04 12:00:42 +03:00
Mikhail Glukhikh
1ea72ec378 Fix test data in FIR diagnostic test (merge with local eff. visibility) 2020-06-04 10:35:01 +03:00
Ilya Goncharov
74e4a817cb [Gradle, JS] Fix test after changing type of IR link task on mode 2020-06-04 10:24:06 +03:00
Jinseong Jeon
0d6e309372 FIR: construct type with actual type arguments during GetClassCall transformation 2020-06-04 10:13:37 +03:00
Mikhail Bogdanov
4f8ad6bdcb Remove compatibility hack 2020-06-04 08:01:30 +02:00
Valeriy.Vyrva
c023a02884 Create SortedMap with Comparator and items
KT-34142
2020-06-04 02:04:22 +03:00
Abduqodiri Qurbonzoda
e3fb74b656 Promote KClass.cast/safeCast, KAnnotatedElement.hasAnnotation() to stable 2020-06-03 23:50:48 +03:00
Dmitry Petrov
a4b9e8fdc6 Minor: mute test in JS_IR 2020-06-03 23:24:16 +03:00
Georgy Bronnikov
0db02926f5 JVM_IR: remove descriptors from MethodSignatureMapper 2020-06-03 22:42:02 +03:00
Georgy Bronnikov
77c20066a8 JVM_IR: implement getJvmModuleNameForDeserialized in MethodSignatureMapper 2020-06-03 22:42:02 +03:00
Georgy Bronnikov
80afe42d17 JVM_IR: implement getJvmNameIfSpecial in MethodSignatureMapper 2020-06-03 22:42:02 +03:00
Pavel Kirpichenkov
986b13c3a1 Optimize synchronization for resolution anchors
Use volatile state instead of synchronized access to it.
This should be enough as the component's state is only read
by the component users and never changed.
2020-06-03 20:58:07 +03:00
Pavel Kirpichenkov
175fe163af Add cancelation check when building anchor mappings 2020-06-03 20:58:07 +03:00
Pavel Kirpichenkov
7fff8f82e2 Changes after review
- Replace leaking ModuleResolverTracker with use of ModuleDescriptor.Capabilies
- Provide API for retrieving ResolverForProject from ResolutionFacade
- Update names
2020-06-03 20:58:07 +03:00
Pavel Kirpichenkov
db1210fc67 Introduce components for library-to-source resolution in IDE
#KT-24309 In progress
2020-06-03 20:58:07 +03:00
Yan Zhulanow
0b2c9ff77a IDE plugin dependencies: publish kotlin-main-kts artifact 2020-06-04 02:49:42 +09:00
Ilmir Usmanov
822c14814b Revert "Completely rewrite reifiedIntTypeAnalysis, making it more streamline"
This reverts commit 1ed4324613.

Otherwise, bootstrap is broken.
2020-06-03 19:43:59 +02:00
Toshiaki Kameyama
148f49d54a UselessCallOnCollectionInspection: fix false positive when lambda last statement is function call that returns generic type
#KT-38267 Fixed
2020-06-03 20:42:42 +03:00
Vyacheslav Gerasimov
3c8ef5749f Build: Remove identifying info from build scans 2020-06-03 19:04:07 +03:00
Sergey Igushkin
35b1bb05c8 Merge KT-MR-1260 from rr/gradle/igushkin/fix-kt-39304-unused-source-sets-failure 2020-06-03 14:32:53 +00:00
Anton Bannykh
a18bfad53a Add stdlib API test + remove some extra IR stdlib API's 2020-06-03 17:14:29 +03:00
Ilmir Usmanov
1ed4324613 Completely rewrite reifiedIntTypeAnalysis, making it more streamline
and easy to understand and optimize if it would be a bottleneck.
Use LVT to get information of refined int type in one specific case

 #KT-38925 Fixed
2020-06-03 16:03:50 +02:00
Ilmir Usmanov
0e908b720d Replace SourceInterpreter with specific one in tail-call optimization 2020-06-03 16:03:49 +02:00
Ilmir Usmanov
3fa9ea9bc0 Remove unreachable instructions 2020-06-03 16:03:48 +02:00
Ilmir Usmanov
ea60b83f16 Fix merging two sources with same type 2020-06-03 16:03:48 +02:00
Ilmir Usmanov
cd0e218a07 Rewrite RedundantLocalsEliminationMethodTransformer
Use specific interpreter instead of SourceInterpreter.
2020-06-03 16:03:48 +02:00
Ilmir Usmanov
f247ea7c27 Replace SourceInterpreter with a specific one in coroutines inlining 2020-06-03 16:03:48 +02:00
Dmitry Petrov
99a1ef0460 Minor: mute test in JS_IR 2020-06-03 16:09:52 +03:00
Ilya Goncharov
426f164e02 [Gradle, JS] Webpack on file providers for task configuration avoidance 2020-06-03 15:59:33 +03:00
Ilya Goncharov
01f3e4b083 [Gradle, JS] Make destinationDir as var 2020-06-03 15:59:33 +03:00
Ilya Goncharov
402dfd5da7 [Gradle, JS] Use RegularFile to not explicit dependsOn
^KT-32273 fixed
^KT-36451 fixed
^KT-37258 fixed
2020-06-03 15:59:33 +03:00
Ilya Goncharov
e27bd04ba2 [Gradle, JS] Add dependency on dce task
^KT-32273 fixed
^KT-36451 fixed
^KT-37258 fixed
2020-06-03 15:59:32 +03:00
Ilya Goncharov
d3260bca27 [Gradle, JS] JsBinaryType to KotlinJsBinaryType 2020-06-03 15:59:32 +03:00
Ilya Goncharov
d27ad99daa [Gradle, JS] KotlinJsType to KotlinJsMode 2020-06-03 15:59:32 +03:00
Ilya Goncharov
a5e46568ee [Gradle, JS] Move common part of webpack configuration to separate fun
^KT-32273 fixed
^KT-36451 fixed
^KT-37258 fixed
2020-06-03 15:59:32 +03:00
Ilya Goncharov
ef63d6f84c [Gradle, JS] Add resolveFromModulesFirst to build tasks 2020-06-03 15:59:32 +03:00
Ilya Goncharov
d4d8495840 [Gradle, JS] Use property for webpack entry 2020-06-03 15:59:32 +03:00
Ilya Goncharov
65db6bb2a5 [Gradle, JS] Add dce to development
^KT-32273 fixed
^KT-36451 fixed
^KT-37258 fixed
2020-06-03 15:59:31 +03:00
Ilya Goncharov
9d8eb65a5e [Gradle, JS] Use API form Gradle 5.0 2020-06-03 15:59:31 +03:00
Dmitry Petrov
ba43ee8410 Handle error type in SamType 2020-06-03 15:57:24 +03:00
Svyatoslav Kuzmich
b0445496bb [JS] Autogenerate and mute missing test 2020-06-03 15:19:36 +03:00
Svyatoslav Kuzmich
af13ae1ef2 [JS] Add klib to kostlin-stdlib-js.jar distribution
Fixes KTI-177 and KT-35857
2020-06-03 14:16:46 +03:00
Igor Yakovlev
ebae6332aa Fix invalid resources placement
For ExpandBooleanExpressionIntention and RedundantAsSequence intention
2020-06-03 14:02:58 +03:00
Dmitriy Novozhilov
f2d0d8b422 [FIR-PLUGIN] Add test for supertype modification extension 2020-06-03 13:10:17 +03:00
Dmitriy Novozhilov
dae2acca88 [FIR] Remove useless hack for builtins from supertype resolution 2020-06-03 13:10:17 +03:00
Dmitriy Novozhilov
9fa4ff750b [FIR] Fix ArrayMapImpl.iterator() 2020-06-03 13:10:17 +03:00
Dmitriy Novozhilov
15d85bdc05 [FIR] Add extension for adding new supertypes 2020-06-03 13:10:17 +03:00
Dmitriy Novozhilov
0c18cb054d [FIR-PLUGIN] Add tests for generating declarations from plugin 2020-06-03 13:10:17 +03:00
Dmitriy Novozhilov
eceeacdf61 [FIR] Change nested class generation extension to generate top-level classes also 2020-06-03 13:10:16 +03:00
Dmitriy Novozhilov
9cc13c8324 [FIR-PLUGIN] Add dummy implementation for nested class generator extension 2020-06-03 13:10:16 +03:00
Dmitriy Novozhilov
8acdb39bdd [FIR-PLUGIN] Add dummy implementation for member generator extension 2020-06-03 13:10:16 +03:00
Dmitriy Novozhilov
1b120c189e [FIR] Record generated classes in FirProvider 2020-06-03 13:10:16 +03:00
Dmitriy Novozhilov
ed55e84afa [FIR] Distinct declarations found by FirPredicateBasedProvider 2020-06-03 13:10:15 +03:00
Dmitriy Novozhilov
87f0f123a8 [FIR] Add extension for generating new members for existing classes 2020-06-03 13:10:15 +03:00
Ilya Goncharov
bd194686df [Gradle, JS] Add index.html to Kotlin DSL wizard
^KT-39275 fixed
2020-06-03 12:58:59 +03:00
Toshiaki Kameyama
6cb0190fad FoldInitializerAndIfToElvis: should not add new line for multiline initializer
#KT-35805 Fixed
2020-06-03 12:35:50 +03:00
Roman Artemev
5eae262264 [PLUGIN API] Implement custom linkage for plugin extensions 2020-06-03 12:17:14 +03:00
Roman Artemev
a401374ed4 [PLUGIN API] Add extension point to customize linkage process 2020-06-03 12:17:14 +03:00
Roman Artemev
f9c2c846f7 [IR] Move IrProvider and 'IrDeserializer' into separate package 2020-06-03 12:17:14 +03:00
Henrik Tunedal
71da941c8b Use system-specific user cache directory in main-kts
#KT-38222 fixed
2020-06-03 11:11:33 +02:00
Henrik Tunedal
8f80cf5664 Improve hashing of script files 2020-06-03 11:11:30 +02:00
Ilya Goncharov
890da492fb [Gradle, JS] Fix grammar in methods for JS import 2020-06-03 12:04:20 +03:00
Ilya Goncharov
bc4d7e0020 [Gradle, JS] Fix grammar on comment 2020-06-03 12:04:20 +03:00
Svyatoslav Kuzmich
e9e850ad8f [JS IR] Fix findInterfaceImplementation
isOrOverridesSynthesized uses descriptors which does not work with
wrapped descriptors
2020-06-03 10:47:15 +03:00
Denis Zharkov
19219c37b6 FIR: Fix test data for KT-13650 related test
Now, the behavior seems to be more correct then in FE 1.0
2020-06-03 10:43:37 +03:00
Denis Zharkov
7a22827af4 FIR: Unify all references to FIR nodes from non-parents 2020-06-03 10:43:37 +03:00
Denis Zharkov
4a4dce1766 FIR: Use more refined names instead of "safe"
^KT-38444 Fixed
2020-06-03 10:43:37 +03:00
Denis Zharkov
6507656496 FIR: Remove FirQualifiedAccessWithoutCallee.safe from generated code
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
291afd8448 FIR: Remove FirQualifiedAcces.safe in non-generated code
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
55a4c40970 FIR: Fix diagnostics test data after safe-call refactoring
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
723b275d99 FIR: Fix rendered fir and DFA graph test data after safe-calls refactoring
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
409e90e7de FIR: Fix codegen test data after safe-call refactoring
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
080565e482 FIR: Support safe-calls new format in DFA
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
ec746e17c9 FIR: Get rid of RealVariable.originalType
Store original type only for local variable aliases
The problem with the former is that RealVariable may be referenced
via safe-calls and via usual calls, but its type is fixed

^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
b0b7cf4042 FIR: Support safe-calls new format in FIR2IR
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
7ba1371466 FIR: Support safe-calls new format in body resolution
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
755b846877 FIR: Support safe-calls in renderers
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
9f793f1486 FIR: Support safe-calls new format in FIR builders
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
cb1c3f87f0 FIR: Prepare tree structure for safe-call refactoring
^KT-38444 In Progress
2020-06-03 10:43:37 +03:00
Denis Zharkov
14a41d91f6 FIR: Extract foldFlow from joinFlow/unionFlow in PersistentLogicSystem 2020-06-03 10:43:37 +03:00
Denis Zharkov
a3d6c42810 FIR: Reuse some common parts in PersistentLogicSystem 2020-06-03 10:43:37 +03:00
Denis Zharkov
233cf13bdc FIR: Minor. Remove when branch that is just the same as "else" 2020-06-03 10:43:37 +03:00
Denis Zharkov
93f39d5df9 FIR: Minor. Refactor processLevelForPropertyWithInvoke
- Rename
- Inline unused default parameter
2020-06-03 10:43:37 +03:00
Denis Zharkov
be4d3783a4 FIR: Fix type resolution for anonymous objects
^KT-39050 Fixed
2020-06-03 10:43:37 +03:00
Denis Zharkov
4d484dd971 FIR: Support java array in type argument
^KT-37321 Fixed
2020-06-03 10:43:37 +03:00
Dmitriy Novozhilov
164b4dd439 [FIR-TEST] Update testdata according to #KT-39340 2020-06-03 10:36:00 +03:00
Svyatoslav Kuzmich
f8fdb0dc7e [JS] Add ; after functions in .d.ts
Fixes nit from KT-37752
2020-06-03 10:33:46 +03:00
Svyatoslav Kuzmich
2ca751a9fc [JS] Prevent default class constructors in d.ts files.
Generate private TypeScript constructor for classes without public
primary Kotlin constructor.
2020-06-03 10:33:45 +03:00
Svyatoslav Kuzmich
695d383ed1 [JS] Support secondary constructors in JsExport 2020-06-03 10:33:45 +03:00
Mads Ager
f128e5222a [JVM_IR] Fix line number information for try-catch.
In particular, the current line numbers could lead to stepping
into the catch handler even when the code in the try did not
throw an exception.

This was caused by the code materializing the final value having
the catch line number. This patch delays the materialization
until the line number of the usage has been emitted.
2020-06-03 07:33:21 +02:00
Dmitry Petrov
5efbe6ae15 PSI2IR: SAM conversion in varargs 2020-06-02 23:53:47 +03:00
Dmitry Petrov
16f175612e KT-31908 Handle SAM conversion on vararg elements 2020-06-02 23:53:47 +03:00
Toshiaki Kameyama
343af60cb4 Add intention to expand boolean expression
#KT-38597 Fixed
2020-06-02 23:52:06 +03:00
Vladimir Dolzhenko
f005091dfb Fix performance test stats reporting 2020-06-02 21:44:55 +02:00
Toshiaki Kameyama
afd544cbab Introduce "Redundant 'asSequence' call" inspections
#KT-35893 Fixed
2020-06-02 22:17:54 +03:00
Ilya Gorbunov
e2c3455445 Document NaN propagation in top-level minOf/maxOf functions 2020-06-02 19:01:44 +03:00
Ilya Gorbunov
d19f9ee0c5 Simplify min/max implementation 2020-06-02 19:01:44 +03:00
Ilya Gorbunov
b4ba00ca36 Document and test NaN propagation of maxOf/minOf
Also simplify minOf/maxOf implementations

#KT-38708
2020-06-02 19:01:44 +03:00
Ilya Gorbunov
7b68de38e1 Introduce minOf/maxOf, minOfWith/maxOfWith and their OrNull variants
#KT-38708 Fixed
2020-06-02 19:01:44 +03:00
Ilya Gorbunov
6a24becd1d Introduce sumOf with various selector types
#KT-11253
2020-06-02 19:01:43 +03:00
Ilya Gorbunov
bdd53ee9cd Introduce new overloads of flatMap and flatMapTo
- Sequence<T>.flatMap((T) -> Iterable<R>)
- Iterable<T>.flatMap((T) -> Sequence<R>)
- Array<T>.flatMap((T) -> Sequence<R>)
- Map.flatMap((Entry) -> Sequence<R>)

KT-34506
2020-06-02 19:01:43 +03:00
Ilya Gorbunov
562788ceb9 stdlib-gen: allow template function sequences 2020-06-02 19:01:43 +03:00
Ilya Gorbunov
79afc4f72b stdlib-gen: avoid placing exact duplicates of annotations 2020-06-02 19:01:43 +03:00
Ilya Gorbunov
4ae6665b94 Advance bootstrap to 1.4.0-dev-9619 2020-06-02 19:01:43 +03:00
Mikhail Glukhikh
0ffa0b2bd7 [FIR] Fix effective visibility handling for local members
In future 'Local' effective visibility could be used
as a flag of local declaration
2020-06-02 18:47:58 +03:00
Mikhail Glukhikh
cb345a4c19 [FIR mangler] Search for type parameters also in overridden declarations 2020-06-02 18:47:58 +03:00
Mikhail Glukhikh
8c422fbfc7 [FIR2IR] Use signature composer to read external callables 2020-06-02 18:47:58 +03:00
Mikhail Glukhikh
9ea69b4b3c Introduce first version of FirJvmKotlinMangler & its parts 2020-06-02 18:47:50 +03:00
Mikhail Glukhikh
a239604c24 Rename & make public: Collection.collect -> collectForMangler 2020-06-02 18:43:16 +03:00
Mikhail Glukhikh
ecb48b7ed9 [FIR2IR] Support callables in signature composer 2020-06-02 18:43:16 +03:00
Vyacheslav Gerasimov
563981808d Build: Move dependencies cleanup to corresponding task action
Do cleanup only before dependencies unpacking to avoid tasks which are
always not up-to-date
2020-06-02 16:42:38 +03:00
Vyacheslav Gerasimov
f8b423046e Build: Don't build idea sources for teamcity builds 2020-06-02 16:42:38 +03:00
Mikhail Glukhikh
05d160b130 Revert "IR linked: introduce IrElement.isExpectMember instead of descriptor use"
This reverts commit 4b47eb35
2020-06-02 16:14:27 +03:00
Mikhail Glukhikh
72dd2ef448 [FIR] Fix CFG building for secondary constructor with delegation 2020-06-02 16:12:32 +03:00
Mikhail Glukhikh
b40709649d [FIR TEST] Add more detailed CFG inconsistency message 2020-06-02 16:12:27 +03:00
Mikhail Glukhikh
718f0240a1 [FIR TEST] Add problematic CFG test 2020-06-02 16:12:21 +03:00
Ilya Goncharov
a476d1dbc4 String prototypes polyfills on Object.defineProperty 2020-06-02 14:56:29 +03:00
Ilya Goncharov
9431fc4693 Polyfill for Arrays should be declared with Object.defineProperty
To not be enumerable
2020-06-02 14:56:29 +03:00
Ilya Goncharov
83e17cbf09 [Gradle, JS] Use name of target, not name of preset 2020-06-02 14:42:54 +03:00
Ilya Goncharov
b68715441f [Gradle, JS] Remove redundant fixing names
- in case when target name is `jsLegacy` with enabled both mode, we should get `jsLegacyMain` and `jsLegacyTest`, and Gradle plugin creates targets `jsLegacyLegacy` and `jsLegacyIr`, schema is name+suffix where name can be any, KotlinJsTargetPreset's name is name+`Both` so in KotlinJsTargetPreset in `both` case we need remove only `Both` suffix

#KT-39213 Fixed
2020-06-02 12:52:13 +03:00
Andrey Uskov
44f16eac2e Fixed resolution of dependencies on js libraries compiled in both mode
#KT-39213 Fixed
2020-06-02 12:52:13 +03:00
Igor Chevdar
e41b5fc1c6 [IR] Turned on a test for K/N + minor refactoring
NothingValueException has already been supported in K/N
2020-06-02 14:50:17 +05:00
Abduqodiri Qurbonzoda
c29e434d33 Remove SuccessOrFailure.kt 2020-06-02 12:04:47 +03:00
Jinseong Jeon
6eb21031b2 FIR JVM serializer: serialize property signature 2020-06-02 12:00:52 +03:00
nataliya.valtman
d6cb469e66 use Gradle 5.6 for tests with android build tool 28.0.3 2020-06-02 11:26:56 +03:00
Konstantin Tskhovrebov
08438dade2 Add project resolver for adding commonizer gradle task to IDEA import 2020-06-02 11:03:51 +03:00
Konstantin Tskhovrebov
94a4aacd9e Move commonizer to gradle task and attach to lazy file collection. 2020-06-02 11:03:51 +03:00
Vyacheslav Gerasimov
048559c053 as41: Register OCBundle for AS tests
fixes mass test fail with 'navigation.class.hierarchy' is not found in java.util.PropertyResourceBundle
2020-06-02 09:23:44 +03:00
Sergey Igushkin
f7ed3139ab Fix unused source sets missing in compilationsBySourceSets (KT-39304)
Issue #KT-39304 Fixed
2020-06-02 00:48:55 +03:00
Dmitriy Novozhilov
069adebf01 [NI] Fix checking for inline lambdas without candidate
#KT-34506
2020-06-01 23:40:32 +03:00
Abduqodiri Qurbonzoda
30037682f8 Revert "Promote String <-> utf8 and CharArray conversions to stable"
This reverts commit aba97033
2020-06-01 23:30:55 +03:00
Abduqodiri Qurbonzoda
aba97033f0 Promote String <-> utf8 and CharArray conversions to stable 2020-06-01 22:47:01 +03:00
Abduqodiri Qurbonzoda
f6a739bbc5 Promote bit query api to stable 2020-06-01 22:18:55 +03:00
Abduqodiri Qurbonzoda
55eb75d237 Remove IGNORE_BACKEND directives from forInCharSeqWithIndexStops.kt 2020-06-01 22:00:37 +03:00
Abduqodiri Qurbonzoda
1bd63bb07f Make consistent parameter nullability with appendLine 2020-06-01 22:00:36 +03:00
Abduqodiri Qurbonzoda
e05eeea6cd Promote common StringBuilder to stable 2020-06-01 22:00:34 +03:00
Abduqodiri Qurbonzoda
4568e438a9 Promote ExperimentalStdlibApi to stable 2020-06-01 21:59:32 +03:00
Ilya Gorbunov
7cc4cc0cec Make testDeepTreeOddEvenNodesMutual two times easier
Otherwise it often times out in JS tests in a parallel build.
2020-06-01 20:15:55 +03:00
Yunir Salimzyanov
77608c8785 Add temporary fixMeExtensions to pass test on extensions check (KTI-240) 2020-06-01 18:43:11 +03:00
Yunir Salimzyanov
3b9000cc0c Cleanup 191 extension files (KTI-240) 2020-06-01 18:43:10 +03:00
Yunir Salimzyanov
7ab7ca5ff0 Cleanup as35 extension files (KTI-240) 2020-06-01 18:43:10 +03:00
Yan Zhulanow
4d859a7212 Revert "TrailingCommaInspection: don't report Missing line break for when entry that has no trailing comma"
This reverts commit 25787eb8
2020-06-02 00:17:24 +09:00
Yan Zhulanow
a421f74ef0 Revert "Minor: extract new line allowance check"
This reverts commit e2f0b76e
2020-06-02 00:17:23 +09:00
Leonid Startsev
1d589e3f56 Rework access to properties in IR plugin
use accessors instead of fields whenever possible
2020-06-01 17:48:17 +03:00
Leonid Startsev
02bd8cbd6b Use SYNTHETIC_OFFSET instead of UNDEFINED
because Native's debug information does not accept undefined offsets
2020-06-01 17:48:17 +03:00
Leonid Startsev
7c8c5b057f Extensible mechanism for plugin metadata during descriptor serialization
A mechanism that allows kotlinx.serialization plugin to preserve the
correct (program) order of properties after serializing/deserializing
descriptors to kotlin metadata, which is needed for correct and stable
json serialization of class hierarchies in incremental/multi-module scenario.
It uses protobuf extensions.
2020-06-01 17:48:16 +03:00
Victor Petukhov
8d05253369 NI: take into account effective variance during adding constraints from LHS instead of only use site variance
^KT-39220 Fixed
2020-06-01 17:24:49 +03:00
Alexander Gorshenev
561c6747a6 Remove tests from muted 2020-06-01 17:16:31 +03:00
Nikita Bobko
2ef46b586d Fix broken NavBar for 201
^KT-38466 Fixed
^KT-38260 Fixed
2020-06-01 17:05:10 +03:00
Dmitry Petrov
246c68b0a9 PSI2IR: Don't generate IMPLICIT_INTEGER_COERCION
Generate integer coercion function calls and properly typed constant
expressions instead.
2020-06-01 16:51:47 +03:00
Juan Chen
bfac0355bf WIP: [FIR] unmute testKt14227 with FULL_JDK
The test used to fail because it has an augmented assignment for
elements in a HashMap of Strings, and "plus" fails to resolve due to
ambiguity: besides String.plus, BigDecimal.plus in the standard
library is also considered. BigDecimal is not resolved and thus
isError returns true. During type checking, the context has
isErrorTypeEqualsAnything set to true, and BigDecimal is now regarded
as a super type of String and BigDecimal.plus is a valid
candidate. Adding the directive "FULL_JDK" enables resolving of
BigDecimal so that BigDecimal.plus is excluded.
2020-06-01 16:47:15 +03:00
Toshiaki Kameyama
45d60baeb0 Add import for member: don't suggest if a class with the same name has been imported
#KT-38492 Fixed
2020-06-01 21:42:04 +09:00
Toshiaki Kameyama
329f0227ec Remove explicit type specification: do not suggest for suspend function type
#KT-38310 Fixed
2020-06-01 21:42:04 +09:00
Toshiaki Kameyama
098469eb85 Implement members: implement functions in the same order as within Java interface
#KT-31760 Fixed
2020-06-01 21:42:04 +09:00
Yan Zhulanow
741ebeb7b8 Mark semicolons after nullable types redundant, despite of '!' after (KT-38240) 2020-06-01 21:42:04 +09:00
Toshiaki Kameyama
4cf83d9526 Redundant semicolon: don't report when semicolon is between type and '!'
#KT-38240 Fixed
2020-06-01 21:42:04 +09:00
Yan Zhulanow
8e8171547b Add super type in "Convert to anonymous object" test 2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
111b2945e1 "Convert to anonymous object" quickfix: false negative when interface has concrete members
#KT-37908 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
5b927d798c Replace explicit parameter with it: don't suggest if overload resolution ambiguity error occurs
#KT-20795 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
69a2697598 Convert lambda to reference: add type parameter to outer call expression if needed
#KT-37744 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
a4239afcb3 Convert to anonymous function: do not suggest for suspend functions
#KT-37842 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
ded996bdf7 PlatformExtensionReceiverOfInline: fix false positive with extension function with nullable type receiver
#KT-37256 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
6868f53f46 "Change JVM name" (@JvmName) quickfix: improve name suggester for generic functions
#KT-38559 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
5efbbdea57 Lift assignment out: do not report when assignment variables are different
#KT-38649 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
498c40548b Structure view: add visibility sorter
#KT-36444 Fixed
2020-06-01 21:42:03 +09:00
Toshiaki Kameyama
9aaba8c759 Structure view: add visibility filter for class properties
#KT-38276 Fixed
2020-06-01 21:42:03 +09:00
Yan Zhulanow
e2f0b76e2f Minor: extract new line allowance check 2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
25787eb869 TrailingCommaInspection: don't report Missing line break for when entry that has no trailing comma
#KT-38568 Fixed
2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
3272b8fc2c CanSealedSubClassBeObjectInspection: don't report if sub-class has classModifier
#KT-38790 Fixed
2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
cea879cbd5 "Make containing function suspend" quickfix: don't suggest for anonymous function
#KT-38948 Fixed
2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
8f3392d635 Convert lambda to reference: fix it works correctly in anonymous object
#KT-31682 Fixed
2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
b9fab1123d Convert lambda to reference: fix it works correctly for labeled expression
#KT-37214 Fixed
2020-06-01 21:42:02 +09:00
Toshiaki Kameyama
2a36a8acac JavaMapForEachInspection: don't report if argument is not single
#KT-39151 Fixed
2020-06-01 21:42:02 +09:00
Yan Zhulanow
7d3b28d75b Add missing runReadAction call (EA-223789) 2020-06-01 21:42:02 +09:00
Mikhail Zarechenskiy
f073e34926 Update forgotten test-data 2020-06-01 15:35:24 +03:00
Natalia Selezneva
fd07d5f301 Scripting setting: auto reloading of script dependencies is now per definition 2020-06-01 15:12:53 +03:00
Roman Golyshev
8726d3dc4e KT-37950 Add io.ktor packages to 'Packages to use * import' list
- Ktor code style [here](https://ktor.io/quickstart/code-style.html)
suggests to use star imports for Ktor packages
- Absence of it in the default code style for Kotlin results in some
inconveniences during auto-import and autocompletion (see the issue)
- Automatic * import should mitigate the issue, since the first
autocompleted item from the proper package should import the whole
package, and then no further auto-import would be required for the
next completions
- KT-37950 Fixed
2020-06-01 14:41:51 +03:00
Yunir Salimzyanov
17a9d93a4f Unmute two successfully finished muted tests for 193 platform 2020-06-01 14:38:55 +03:00
Yan Zhulanow
7014c17a57 IDE plugin dependencies: Publish unshaded kotlin-scripting-compiler 2020-06-01 18:44:44 +09:00
Vyacheslav Gerasimov
8704946498 as41: Fix testResourceBundle hack for AS 4.1 2020-06-01 12:29:10 +03:00
Vyacheslav Gerasimov
7d7835f0f4 as41: Remove ApplicationUtils.kt.as41 which should be same as for 201 2020-06-01 12:29:10 +03:00
Vyacheslav Gerasimov
af1e815f47 as41: Remove AbstractModelBuilderTest.java.as41
Should be same as for 201
2020-06-01 12:29:09 +03:00
Roman Golyshev
7fb5acc718 KT-18538 Fix inspection to detect unnecessary grand-base class qualifier
- Add separate option to enable/disable this inspection, as it is not
obvious if it should be always enabled or not
  - This option can be used to detect all unnecessary qualifiers in
  tests
- Add possibility to configure inspections via `settings.xml` in the
`AbstractMultiFileLocalInspectionTest.kt`
- ^KT-18538 Fixed
2020-06-01 08:59:37 +00:00
Roman Golyshev
2c12d26d28 KT-18538 Unwrap fake override in ShortenReferences
- Fake override prevents reference shortener from shortening of static
methods declared in the class bases when they are located not in
direct parent of the class (for example, in grand-
or grand-grand-parent)
- The completion uses descriptor with unwrapped fake override when it
performs the insertion. It leads to inserting the name of the base which
actually contains the static method instead of the direct parent class.
Now, when reference shortener compares unwrapped descriptors, this
problem should be fixed during insertion handling
2020-06-01 08:59:37 +00:00
Roman Golyshev
43bbfa78d1 KT-18538 Cleanup in ShortenReferences 2020-06-01 08:59:36 +00:00
Roman Golyshev
16bdfa4fee KT-18538 Cleanup in RemoveRedundantQualifierNameInspection 2020-06-01 08:59:36 +00:00
Jinseong Jeon
4a511c7721 FIR: extend arrayOf call transformation to other variants 2020-06-01 10:45:42 +03:00
Mikhail Zarechenskiy
7ec8716d65 Introduce HTML redenred version for compatibility warning 2020-06-01 10:19:36 +03:00
Mikhail Zarechenskiy
569b6eaff2 Don't issue compatibility warning for the candidates in the same group 2020-06-01 10:19:35 +03:00
Mikhail Zarechenskiy
f922e454f9 Don't propagate compatibility resolve from callable reference arguments 2020-06-01 10:19:35 +03:00
Mikhail Zarechenskiy
599f520fd8 Add compatibility warning for chained sam->suspend-conversion 2020-06-01 10:19:35 +03:00
Mikhail Zarechenskiy
a5203428a4 Replace resolution error for suspend-conversion with call checker error 2020-06-01 10:19:34 +03:00
Mikhail Zarechenskiy
eaeaf3c8a3 Add compatibility warning for suspend conversions 2020-06-01 10:19:33 +03:00
Mikhail Zarechenskiy
47e6805186 Add compatibility warning for reference adaptation 2020-06-01 10:19:33 +03:00
Mikhail Zarechenskiy
684dfb959c Don't write any COERCION_STRATEGY for Unit to Unit return types 2020-06-01 10:19:33 +03:00
Mikhail Zarechenskiy
03358c61d4 Add compatibility warning for SAM conversions 2020-06-01 10:19:33 +03:00
Mikhail Zarechenskiy
01de789c76 Add compatibility warning for SAM conversions on Kotlin functions 2020-06-01 10:19:32 +03:00
Yan Zhulanow
080d8fa127 Add missing stdlib-common IDE plugin dependency 2020-06-01 15:16:16 +09:00
Vladimir Ilmov
73f4b61022 (CoroutineDebugger) Windows test fix for kotlinx-coroutines-core 2020-05-31 20:24:41 +02:00
Mikhail Zarechenskiy
ea6a8ce5cd Rename language feature to make it more clear 2020-05-31 18:13:17 +03:00
Ilya Muradyan
bbe00b2fdc Add scripting REPL completion options
nameFilter - way of filtering descriptors by their names;
filterOutShadowedDescriptors - if true, filters out descriptors
shadowed by descriptors in latter-compiled snippets. May slow down
completion performance.
2020-05-31 17:05:24 +02:00
Mikhail Zarechenskiy
0ab9b3639b Approximate types for lambda literals before serialization 2020-05-31 17:38:18 +03:00
Mikhail Zarechenskiy
366ed7d4ca Minor: reformat fakeDescriptorsForReferences.kt 2020-05-31 17:38:17 +03:00
Nicolay Mitropolsky
6ed453dfbc Uast: removing deprecated JvmDeclarationUElement (KT-23887) 2020-05-31 06:54:12 +03:00
Alexander Gorshenev
a112f8acb6 Moved symbol table emptiness assertion to later places,
so that the assert doesn't trigger in the plugin context
2020-05-31 06:00:33 +03:00
Alexander Gorshenev
5e56a52f94 Properly update modality and visibility of property accessors on fake override creation 2020-05-31 06:00:33 +03:00
Alexander Gorshenev
4dd159d4ec Added another fake override validation pass after IR plugins 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
46e3649bd0 Moved all things related to fake overrides to a single directory 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
06abbe468b Signature based fake override validation 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
024385cbbd Construct fake overrides after IR deserialization 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
ee1ea15684 Adapted descriptor fake override construction from OverridingUtil.java to IR as IrOverridingUtil.kt 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
2828aa9ce8 Typechecker and visibility utils for fake overrides 2020-05-31 06:00:32 +03:00
Alexander Gorshenev
789efc7c3a Created a deep copier good for fake overrides.
Adapted it from inliner copier.
It is capable of producing type substituted members.
2020-05-31 06:00:31 +03:00
Alexander Gorshenev
63429c088f Introduced IrFakeOverrideFunctionImpl and IrFakeOverridePropertyImpl 2020-05-31 06:00:31 +03:00
Alexander Gorshenev
20dedd53ff Got rid of LazyIrProvider. It is not used anymore 2020-05-31 06:00:31 +03:00
Alexander Gorshenev
756f7076f6 Got rid of duplicates in resolveFakeOverrides implementations 2020-05-31 06:00:31 +03:00
Yunir Salimzyanov
ea71a57fac Unmute non-flaky tests and mark some flaky tests with FLAKY label
KTI-216
2020-05-30 22:50:34 +03:00
Yunir Salimzyanov
4e732b7ba2 Wrap parametrized tests with muteWithDatabase
Cause: should correctly run muted tests in database (KTI-216)
2020-05-30 22:50:34 +03:00
Yunir Salimzyanov
8d51b027ed Add annotation to prevent test invocation twice
Cause: it helps to fix double inversion of muted non-flaky tests result
(KTI-216).
2020-05-30 22:50:34 +03:00
Yunir Salimzyanov
a256e75909 Run muted non-flaky tests and invert their result (KTI-216)
Cause: if mutedInDatabase test is failing then test result = success
else test result = failure (because now it should be unmuted)
2020-05-30 22:50:33 +03:00
Yunir Salimzyanov
cfb8763b33 Remove redundant Runner logic 2020-05-30 22:50:33 +03:00
Ilya Gorbunov
2e67ccbd6a Advance bootstrap to 1.4.0-dev-9436 2020-05-30 21:34:49 +03:00
Vladimir Ilmov
0b3ae50f31 Revert "(CoroutineDebugger) Windows test fix for kotlinx-coroutines-core"
This reverts commit faaf40dbe5.
2020-05-30 17:09:52 +02:00
Vladimir Ilmov
faaf40dbe5 (CoroutineDebugger) Windows test fix for kotlinx-coroutines-core 2020-05-30 10:55:49 +02:00
simon.ogorodnik
99b2a4745a [FIR2IR] Fix superQualifier in case of composed super type ref 2020-05-29 21:10:56 +03:00
simon.ogorodnik
8afbb4542b [FIR2IR] Fix check if interface is SAM 2020-05-29 21:10:56 +03:00
Nikita Bobko
aa5a5c954f Refactoring: change "// BUNCH: xxx" format
It wasn't obvious how to use this comment properly.
Now it should be clear
2020-05-29 20:31:12 +03:00
Nikita Bobko
b34fe77760 Split bunches with comma 2020-05-29 20:31:12 +03:00
Nikolay Krasko
5e7c82ea01 Fix building dist with JDK 13 (KTI-262)
Return to bootstrap version, that was abandoned because of KT-37235.
It looks like build is fine now.
2020-05-29 20:17:55 +03:00
Steven Schäfer
7ea71a17f0 JVM IR: Use language feature for inline class mangling rules 2020-05-29 19:54:09 +03:00
Ilya Goncharov
a41b746774 Revert "[Gradle, JS] Output file path as input fo js compile task"
This reverts commit df173c8c
2020-05-29 19:39:17 +03:00
Ilya Goncharov
df173c8c93 [Gradle, JS] Output file path as input fo js compile task
^KT-38676 fixed
2020-05-29 17:37:00 +03:00
Dmitriy Novozhilov
1d32cab11d Revert "[FIR] Don't save original user type in FirResolvedTypeRef"
Also fix `FirGeneratedElementsValidator` so it doesn't check
   `FirResolvedTypeRef.delegatedTypeRef`
2020-05-29 17:35:53 +03:00
Dmitriy Novozhilov
72813cefbe [FIR] Store list of sealed inheritors even if there are none of them 2020-05-29 17:35:53 +03:00
Vyacheslav Gerasimov
d612c130e8 Build: Fix jpsStandalone dependency in core.descriptors.runtime 2020-05-29 17:29:27 +03:00
Ilya Goncharov
bb9e8a8a50 [Gradle, JS] Fix warning message with new line
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:20:10 +03:00
Ilya Goncharov
1b841adfff [Gradle, JS] Fix param name
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:20:00 +03:00
Ilya Goncharov
9fd211cfcd [Gradle, JS] Manually singleton because Gradle Daemon
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:19:44 +03:00
Ilya Goncharov
59c2bc25d5 [Gradle, JS] Detect multiple plugins for NodeJsRootPlugin and YarnPlugin
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:19:27 +03:00
Ilya Goncharov
39869f009e [Gradle, JS] Throw error in JS part when plugins goes from different classloaders
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:19:13 +03:00
Ilya Goncharov
2e39c1164d Move detecting of multiple kotlin plugins into extract class
^KT-39210 fixed
^KT-31669 fixed
2020-05-29 17:18:57 +03:00
Alexander Udalov
7d9fe55072 Regenerate tests 2020-05-29 15:15:43 +02:00
Dmitriy Novozhilov
f21d1e1c1b [FIR] Record non-user type refs to resolved type refs
That `delegatedTypeRef` is needed for reporting errors on value
  parameters of function types and errors about cyclic dependencies
  between types
See 6f241c6d
2020-05-29 16:10:38 +03:00
Mads Ager
7d7b9262e7 [JVM] Port remaining line number tests to stepping infrastructure.
These line number tests only tested that a set of line numbers where
present in the java bytecode. Not that they would be hit in the
right order by the debugger. Moving them to stepping tests fixes that.

This exposes a couple of issues (in particular around try-catch-finally)
that should be fixed.

A number of tests are marked as failing now. Will investigate and
work on fixes next.
2020-05-29 15:07:49 +02:00
Dmitry Petrov
5db6a0b563 New mangling rules require language version 1.4 (not compiler version)
Follow-up to a270ee094c
2020-05-29 15:15:54 +03:00
Victor Petukhov
40a4cea530 NI: remove type depth check during adding initial constraints 2020-05-29 12:37:27 +03:00
pyos
35460fed19 JVM_IR: fix a bug when isInlineParameter is applied to default stubs
If an inline parameter has a default value, its type is nullable.
There's already code to handle this in `IrInlineCodegen`, but it
really should be in `isInlineParameter` instead, otherwise e.g.
SyntheticAccessorLowering fails.
2020-05-29 10:04:36 +02:00
Nicolay Mitropolsky
86e434195e Uast: UastKotlinPsiVariable made isEquivalentTo it's physical PSI (KT-39174) 2020-05-29 11:00:47 +03:00
Ilmir Usmanov
5f3e296f19 Fix bugs with capturing rhs into EXACTLY_ONCE lambda
There are multiple ways to declare a named variable-like entity in
Kotlin:
1. val/var variable declaration
2. destructuring declaration
3. parameter of a function
4. parameter of a lambda
5. destructured lambda parameter
6. for-loop's variable declaration
7. catch block exception declaration
8. val in when
9. field declaration

Out of them, only variable and field can be assignable, in other words,
they can be on the left hand side of an assignment.
Val/var variable declarations were already supported.
So, we needed to just support field initialization and tell the backend
that other ways are prohibited. Function and lambda parameters were
already been supported. So, the only thing to explain to the backend are
remaining ways.
 #KT-39113 Fixed
 #KT-34048 Fixed
2020-05-29 09:55:04 +02:00
Ilya Kirillov
0fc43b1f57 Wizard: add possibility to change Kotlin version for generated projects via property
#KT-39247 fixed
2020-05-29 10:48:53 +03:00
Dmitriy Novozhilov
6f241c6dcd [FIR] Don't save original user type in FirResolvedTypeRef 2020-05-29 10:24:39 +03:00
Dmitriy Novozhilov
422a327fca [FIR] Add visitor for validation of generated FIR 2020-05-29 10:24:39 +03:00
Dmitriy Novozhilov
f6dabafe34 [FIR] Make creating of resolve processors type safe
Also get rid of `CompilerMode` enum
2020-05-29 10:24:36 +03:00
Dmitriy Novozhilov
c919f6172e Reformat AbstractSimpleFileBenchmark.kt 2020-05-29 10:24:29 +03:00
Dmitriy Novozhilov
b4ce736814 [FIR] Move registration components out of initializers of FirSession 2020-05-29 10:24:26 +03:00
Dmitriy Novozhilov
fec3e4faf1 [FIR] Move initialization of common services to FirSessionBase 2020-05-29 10:22:04 +03:00
Dmitriy Novozhilov
1973060e8c [FIR-PLUGIN] Fix AllOpenClassGenerator after previous commit 2020-05-29 10:22:03 +03:00
Dmitriy Novozhilov
6d37776267 [FIR] Rename FirClassImpl to FirRegularClassImpl
Also rename `buildClassImpl` to `buildRegularClass` and get rid
  of intermediate `AbstractFirRegularClassBuilder`
2020-05-29 10:22:03 +03:00
Dmitriy Novozhilov
60fd505a9c [FIR] Get rid of FirSealedClass node
Now list of inheritors is hold in attributes of `FirRegularClass`
2020-05-29 10:22:00 +03:00
Dmitriy Novozhilov
41cdb61ef3 [FIR] Move all symbol providers to separate package 2020-05-29 10:20:57 +03:00
Dmitriy Novozhilov
a1c3d2b709 [FIR] Add separate session component for FirIdeProvider 2020-05-29 10:17:22 +03:00
Dmitriy Novozhilov
34d3fe26e6 [FIR] Get rid of FirProvider.getInstance 2020-05-29 10:17:21 +03:00
nataliya.valtman
ff06e60a06 Revert "run for 28.0.2"
This reverts commit 86d52d41
2020-05-29 10:09:50 +03:00
nataliya.valtman
86d52d4123 run for 28.0.2 2020-05-29 10:07:34 +03:00
Dmitriy Novozhilov
1982f80bfb [NI] Leave candidates with annotation if there are no candidates without it 2020-05-29 09:36:33 +03:00
Dmitriy Novozhilov
2812ed0a02 [NI] Use types and systems from return arguments instead of return type of lambda 2020-05-29 09:36:33 +03:00
Dmitriy Novozhilov
f76b57d260 [OI] Prefer candidate without @OverloadResolutionByLambdaReturnType 2020-05-29 09:36:33 +03:00
Dmitriy Novozhilov
a604404bff [NI] Report warning if candidate was chosen using only @OverloadResolutionByLambdaReturnType 2020-05-29 09:36:33 +03:00
Dmitriy Novozhilov
82ce2e7b7c [NI] Update annotation used in testdata 2020-05-29 09:36:32 +03:00
Ilya Gorbunov
e9ef6dbc28 Discriminate OverloadResolutionByLambdaReturnType annotated overloads...
instead of preferring them in case of unsolvable ambiguity.
2020-05-29 09:36:32 +03:00
Dmitriy Novozhilov
e1418a5540 [NI] Check for maximally specific candidate chosen with factory resolution 2020-05-29 09:36:32 +03:00
Dmitriy Novozhilov
e7869bd9d4 [NI] Analyse lambda in factory pattern resolution in independent context 2020-05-29 09:36:32 +03:00
Ilya Gorbunov
a0c7bece93 Overload resolution by lambda return type
Make compiler recognize new annotation enabling this feature.

Change overload selection algorithm to consider all overloads
with that annotation, not just the first one.

#KT-38480
#KT-11265
2020-05-29 09:36:32 +03:00
Ilya Gorbunov
23414496c4 Annotation to enable overload resolution by lambda return type
#KT-38480
2020-05-29 09:36:32 +03:00
Dmitriy Novozhilov
1c32c62a87 [NI] Choose annotated candidate if call still ambiguous
#KT-11265
2020-05-29 09:36:31 +03:00
Dmitriy Novozhilov
8c524769b1 [NI] Add required FactoryPattern annotation for factory pattern resolve
#KT-11265
2020-05-29 09:36:31 +03:00
Dmitriy Novozhilov
865ddac07a [NI] Add feature for choosing candidate by lambda return type 2020-05-29 09:36:31 +03:00
Ilya Gorbunov
f243b8946f Restore testOmittedStdlibVersion originally added in commit 15feeddc 2020-05-29 04:10:17 +03:00
Ilya Gorbunov
d47981f07b Drop gradle ITs depending on AGP versions below 3.2
AGP of these versions cannot handle module-info class included in
kotlin-stdlib artifact from now on.
2020-05-29 04:10:17 +03:00
Dmitry Petrov
a270ee094c Language feature for new inline class mangling rules (since 1.4) 2020-05-29 00:53:01 +03:00
Dmitry Petrov
94509bdb4e KT-39228 Fix inliner when latest 1.4 compiler used with 1.3 stdlib
Since 1.4.0-dev-8774, we mangle functions returning inline class values,
including functions with return type 'kotlin.Result'. This causes
incompatibility when 1.4 compiler is used with 1.3 (or just some
pre-1.4.0-dev-8774) standard library.

Also, write "message from the future" on functions returning inline
class values indicating that they can be used since compiler version 1.4
(otherwise 1.3 compiler using 1.4 stdlib would fail to find some
@InlineOnly functions such as 'Result.success' and 'Result.failure').
2020-05-29 00:53:00 +03:00
Mikhail Glukhikh
ffdab473e2 IR symbols: enhance exception messages / toString() a bit 2020-05-28 22:59:13 +03:00
Mikhail Glukhikh
b6cdcc8d50 [FIR2IR] Mute 2 failing BB tests 2020-05-28 22:51:20 +03:00
Mikhail Glukhikh
19f1a3de1a [FIR2IR] Populate overridden symbols also with public symbol inheritors 2020-05-28 22:19:21 +03:00
Mikhail Glukhikh
85760770a8 [FIR2IR] Initialize built-in symbols at start of conversion 2020-05-28 22:18:20 +03:00
Mikhail Glukhikh
cd24745f1f [FIR2IR] Add primitive signature composer & use it for external classes 2020-05-28 22:18:13 +03:00
Mikhail Glukhikh
048e7a7075 [FIR] Add forgotten FirJvmBackendClassResolver to CLI 2020-05-28 22:18:05 +03:00
Andrey Uskov
0ed9356cd2 Fixed reporting duration between builds in gradle statistics 2020-05-28 22:08:18 +03:00
Andrey Uskov
8dcbc391fe Implemented collecting JS compilation mode
#KT-36410 Fixed
2020-05-28 22:08:13 +03:00
Andrey Uskov
97039926f0 Fixed import of transitive HMPP dependencies
#KT-36792 Fixed
2020-05-28 22:08:04 +03:00
Andrey Uskov
a431e20b45 Fix import of js MPP source sets in both mode
#KT-38706 Fixed
2020-05-28 22:07:55 +03:00
Andrey Uskov
36c9d04cd3 Fix HMPP import tests 2020-05-28 22:07:51 +03:00
Andrey Uskov
9c2918bdd6 Drop import tests with module per source set disabled 2020-05-28 22:07:48 +03:00
Andrey Uskov
104eeb9ffd Fixed KNPE when serialized Kotlin Facet is broken
#KT-37428 Fixed
2020-05-28 22:07:44 +03:00
Andrey Uskov
e6165ed785 Improved performance of MPP projects import
#KT-39059 Fixed
2020-05-28 22:07:39 +03:00
Andrey Uskov
8eca3c8aa8 Fixed building MPP model if project root directory does not exist 2020-05-28 22:07:36 +03:00
Andrey Uskov
c7a53e4435 Fix android import tests 2020-05-28 22:07:31 +03:00
Andrey Uskov
351d706e0d Fixed reporting NPM download time
#KT-39109 Fixed
2020-05-28 22:07:27 +03:00
Andrey Uskov
15ead4cbe6 Fixed representation of project structure when MPP module is involved
KT-37125
2020-05-28 22:07:22 +03:00
Andrey Uskov
2eb354f211 Fixed import of MPP modules with single artifacts
#KT-38037 Fixed
2020-05-28 22:07:16 +03:00
Zalim Bashorov
a8623b9b28 Make sure that library file still exists before calling loadMetadata from JsResolverForModuleFactory since IDE model could be outdated
#EA-218905 fixed
2020-05-28 21:38:01 +03:00
Zalim Bashorov
7f41dc4828 Add more detailed message for EA-227305 and EA-226744 2020-05-28 21:38:00 +03:00
Vyacheslav Karpukhin
7b55a49ddd Dependency on IDEA replaced with AS incompatibility 2020-05-28 19:29:22 +02:00
Steven Schäfer
dc0ef996b7 JVM IR: Implement the new inline class ABI 2020-05-28 18:00:35 +03:00
Nicolay Mitropolsky
e60a32e8d3 Uast: UastFakeLightMethod dependent generic type SOE fix KT-39155 2020-05-28 17:53:30 +03:00
Vladimir Ilmov
de790a3e3b (UnusedSymbolInspection) Added support for typing per inspection tests
relates to #KT-38653
2020-05-28 15:27:58 +02:00
Alexander Udalov
1f1790d60e Do not rely on descriptors in KParameterImpl.equals/hashCode
For the same reason as in the previous commit: descriptors are cached
via weak references in moduleByClassLoader.kt and can be
garbage-collected at any point. So different instances of KParameterImpl
representing the same parameter may store different instances of
descriptors.
2020-05-28 14:17:37 +02:00
Alexander Udalov
55f384cb04 Do not rely on descriptors in KTypeParameterImpl.equals/hashCode
Descriptors are cached via weak references in moduleByClassLoader.kt and
can be garbage-collected at any point. So relying on identity of
descriptors in KTypeParameterImpl is dangerous because the same type
parameter can be represented by different descriptors. For example, the
test equalsOnFunctionParameters.kt was flaky before this change because
of this issue, and that could be reproduced by running it a few hundred
times in the same process.

Instead, use the type parameter's container (which is either KClass or
KCallable) and name, in equals/hashCode. KClass and KCallable already
have equals/hashCode independent of descriptors, so this works in case
the descriptor is invalidated.
2020-05-28 14:17:37 +02:00
Alexander Udalov
d25f9dee62 Minor, remove temporary workarounds for JPS build 2020-05-28 14:17:36 +02:00
Victor Petukhov
e72f7d9a1d NI: return optimization for adding constraints in ConstraintInjector.kt 2020-05-28 14:58:15 +03:00
anastasiia.spaseeva
6c1efbe812 [Spec tests] Update spec testData 2020-05-28 14:23:11 +03:00
Mikhail Glukhikh
25b1059f74 Cleanup: ExpectDependencyGenerator 2020-05-28 14:03:01 +03:00
Mikhail Glukhikh
c9f2876368 [PSI2IR] Drop unnecessary forcing of type alias RHS referencing 2020-05-28 14:03:01 +03:00
Mikhail Glukhikh
cef23a284f [PSI2IR] Use returnTarget.symbol directly in generateReturnExpression 2020-05-28 14:03:00 +03:00
Mikhail Glukhikh
8e8bb9bf08 [IR] Simplify class parent fetching in PrimitiveCompanionLowering 2020-05-28 14:03:00 +03:00
Mikhail Glukhikh
487a698e49 [IR] Add IrSymbolBase.toString() implementation 2020-05-28 14:02:59 +03:00
Mikhail Glukhikh
07b1bd9d99 IrTypeUtils: take name directly from IrDeclaration 2020-05-28 14:02:59 +03:00
Mikhail Glukhikh
4b47eb359a IR linked: introduce IrElement.isExpectMember instead of descriptor use 2020-05-28 14:02:58 +03:00
Mikhail Glukhikh
7c7f87e729 [IR] Replace some usages of KotlinType to IrType 2020-05-28 14:02:58 +03:00
Mikhail Glukhikh
2d842d061e IrSourceCompilerForInline: get ownerKind without descriptor 2020-05-28 14:02:57 +03:00
Mikhail Glukhikh
a631c24e8c [IR] Drop unused 'withDescriptors' dumper 2020-05-28 14:02:57 +03:00
Mikhail Glukhikh
4944fc78b2 [IR] Require bound symbols in classFqNameEquals 2020-05-28 14:02:56 +03:00
Mikhail Glukhikh
cacf5f5a4a [IR] Read isExpect directly from IrDeclaration without using descriptor 2020-05-28 14:02:56 +03:00
Mikhail Glukhikh
934b040152 [IR] Read isSuspend directly from IrFunction without using descriptor 2020-05-28 14:02:55 +03:00
Mikhail Glukhikh
8a15edf5e6 [IR] Extract IrDeclaration(Access).psiElement extension 2020-05-28 14:02:55 +03:00
Mikhail Glukhikh
6b3c390fa7 [FIR2IR] Use IrSymbols directly instead of referencing via SymbolTable 2020-05-28 14:02:54 +03:00
Mikhail Glukhikh
90e6d5bea7 [FIR2IR] Read modality directly from IrFunction without using descriptor 2020-05-28 14:02:54 +03:00
Mikhail Glukhikh
724101cdd2 [IR] Get rid of minor symbol.descriptor usages 2020-05-28 14:02:53 +03:00
Mikhail Glukhikh
bf66929b5b Extract IrClass.syntheticAccessorToSuperSuffix() 2020-05-28 14:02:53 +03:00
Mikhail Glukhikh
66da676b9e [IR] Extract IrCallableReference.referencedName 2020-05-28 14:02:52 +03:00
Mikhail Glukhikh
79fd24f734 IrBuilder: get typeParametersCount from IR owner, not from descriptor 2020-05-28 14:02:52 +03:00
Ilya Goncharov
bf5810a349 [Gradle, JS] Fix text after proof read
#KT-35641 fixed
#KT-35611 fixed
2020-05-28 12:14:34 +03:00
Ilya Goncharov
85e5f8a736 [Gradle, JS] Deprecation of kotlin2js and kotlin-dce-js plugins
#KT-35641 fixed
#KT-35611 fixed
2020-05-28 12:13:28 +03:00
Dmitriy Dolovov
118c4b96cc [Commonizer] Leaf source sets should depend on commonized "common" libs
^KMM-241
2020-05-28 12:12:40 +07:00
Dmitriy Dolovov
45260cee1e [Commonizer] Update stats collector to report lifted up declarations 2020-05-28 12:12:40 +07:00
Dmitriy Dolovov
9f31931bb8 [Commonizer] Tests on lifting up identical const properties
^KMM-241
2020-05-28 12:12:39 +07:00
Dmitriy Dolovov
2ce1625989 [Commonizer] Lift up identical const properties
^KMM-241
2020-05-28 12:12:39 +07:00
Dmitriy Dolovov
a2edb9b547 Minor. Add "commonized" to project dictionary 2020-05-28 12:12:39 +07:00
Dmitriy Dolovov
36a29ce2dd [Commonizer] Split different aspects of CIR
- Entity declaration
- Entity implementation
- Creation of new entities from descriptors
2020-05-28 12:12:29 +07:00
Dmitriy Dolovov
f26a3150ba [Commonizer] Explicitly check if annotation constants are allowed 2020-05-28 12:11:11 +07:00
Dmitriy Dolovov
0827d2e8a3 [Commonizer] Fix Gradle module dependencies 2020-05-28 12:11:04 +07:00
Dmitriy Dolovov
b5245e2df6 [Commonizer] Avoid N^2 during merge of KLIB manifest dependencies 2020-05-28 12:10:58 +07:00
Dmitry Gridin
dbd10380ee Code style settings: fix top border in UI
#KT-39180
2020-05-28 09:28:52 +07:00
Alexander Udalov
d115a1ff9c Minor, fix some warnings such as "unused main argument" in generators 2020-05-27 23:29:21 +02:00
Alexander Udalov
4520e02bae Support fun interfaces in kotlinx-metadata
#KT-37421 Fixed
2020-05-27 23:29:12 +02:00
Vladimir Dolzhenko
c805274d2e Fix projectRoutines.kt compilation under 192/as36 2020-05-27 21:11:23 +02:00
Steven Schäfer
86cd039526 JVM IR: Use original descriptors for lambdas in JvmDeclarationOrigin 2020-05-27 20:21:42 +03:00
Nataliya Valtman
bd66e87440 KT-38250 The minimal supported Gradle version is 5.3 now
Gradle integration tests: use at least OLDEST_SUPPORTED version.

extract minSupportedGradleVersion for using both in check and tests

avoid using Usage.JAVA_API_JARS and JAVA_RUNTIME_JARS
2020-05-27 19:05:45 +03:00
Vyacheslav Gerasimov
af2dce0549 as41: Build against AS 4.1 C10 2020-05-27 18:46:57 +03:00
Vyacheslav Gerasimov
097b93cb2a as41: Setup bunch config and compatibility dsl for AS 4.1 2020-05-27 18:46:57 +03:00
Vyacheslav Gerasimov
d6011103e2 Build: Remove bunch files with intellijUltimateEnabled=false for AS 2020-05-27 18:46:57 +03:00
Victor Petukhov
cadc5ad587 NI: remove deprecated TODO about doing investigation around producing unwanted Any? during incorporation (KT-39154) 2020-05-27 16:52:55 +03:00
Victor Petukhov
0bed055fca NI: small refactoring around TypeCheckerContext and adding new possible constraints 2020-05-27 16:39:31 +03:00
Victor Petukhov
d7f52e8b67 NI: do explicit incorporation of type of fixing type variable into other constraints
^KT-37380 Fixed
2020-05-27 15:44:03 +03:00
Dmitry Gridin
3643b7b0ca trailingComma: cleanup code 2020-05-27 11:24:12 +00:00
Dmitry Gridin
052d06be3f TrailingCommaIntention: fix description
#KT-39180
2020-05-27 11:24:11 +00:00
Dmitry Gridin
bf6dffdf38 Introduce KotlinOtherSettingsPanel
#KT-39180 Fixed
#KT-38036 Fixed
2020-05-27 11:24:10 +00:00
Dmitry Gridin
880658135f TrailingCommaIntention: should call notifyCodeStyleSettingsChanged() 2020-05-27 11:24:10 +00:00
Dmitry Gridin
dcebcc27b4 trailing comma: remove similar test data 2020-05-27 11:24:09 +00:00
Dmitry Gridin
c78fd4aaca TrailingCommaInspection: should suggest fixes for call-site without warnings
#KT-39131 Fixed
2020-05-27 11:24:09 +00:00
Dmitry Gridin
10462c31d2 Join lines should remove useless trailing commas
#KT-39065 Fixed
2020-05-27 11:24:08 +00:00
Dmitry Gridin
e4a9679ec2 TrailingCommaVisitor: improve tree traversal 2020-05-27 11:24:07 +00:00
Dmitry Gridin
eab12a32ac util: add missing constraints 2020-05-27 11:24:07 +00:00
Dmitry Gridin
262c9e6858 TrailingCommaPostFormatProcessor: should work with call-site in limited mode
* remove useless comma
* format call if comma exists

#KT-39079 Fixed
2020-05-27 11:24:06 +00:00
Dmitry Gridin
86827dfc92 TrailingCommaVisitor: adapt to TrailingCommaContext
#KT-39123 Fixed
2020-05-27 11:24:05 +00:00
Dmitry Gridin
6d7c03b6fd Get rid of TrailingCommaHelper.needComma 2020-05-27 11:24:05 +00:00
Dmitry Gridin
0076f1ddd5 Introduce TrailingCommaContext 2020-05-27 11:24:04 +00:00
Dmitry Gridin
bb329c0415 Move TrailingComma* to separate module 2020-05-27 11:24:03 +00:00
Dmitry Gridin
64bcd32661 Introduce TrailingCommaState 2020-05-27 11:24:03 +00:00
Dmitry Gridin
fbddc6921f KotlinCodeStyleSettings: add hidden settings for trailing comma on call site
#KT-39079
2020-05-27 11:24:02 +00:00
Ilya Chernikov
dec8eb7899 Revert renaming scripting plugin jar:
it conflicts with the compilation on daemon, so transistion should
be planned accordingly, and now it is not a good time for it.
The most important part of the renaming remains intact.

Partially reverts commit "Rename scripting libs and plugin - invert embeddable suffix"
2020-05-27 13:15:50 +02:00
Jinseong Jeon
18953c4717 FIR: transform resolved arrayOf call inside annotation to FirArrayOfCall 2020-05-27 11:38:34 +03:00
Jinseong Jeon
265d066878 FIR2IR: minor refactor to share IrVarargElement creation. 2020-05-27 11:38:32 +03:00
Jinseong Jeon
ff509bdcd3 FIR2IR: fix inverted types for array/element in arrayOf call. 2020-05-27 11:38:32 +03:00
Jinseong Jeon
b93868c30b IR: migrate IrType utils about array element type. 2020-05-27 11:38:32 +03:00
Roman Artemev
49690fc620 [JS IR] Properly detect whether nested class is external
- Fix KT-38765
2020-05-27 10:49:57 +03:00
Denis Zharkov
5bb0085f7e FIR: Fix test data after adba0a03a6 2020-05-27 10:29:46 +03:00
Roman Elizarov
46b426ef77 KT-31741: stdlib: DeepRecursiveFunction (#3398)
Introduces experimental coroutines-based framework to execute deeply recursive functions that utilities the heap and thus avoid StackOverflowError.
2020-05-27 10:06:00 +03:00
Mads Ager
9fa1614903 [JVM] Port line number tests to stepping framework.
Allow specifying JVM and JVM_IR as well as shared expectations.

Add the method name to the step.

Discard steps in synthetic methods.
2020-05-27 07:28:47 +02:00
Mikhail Zarechenskiy
4dbd4a56d5 Compose: adapt new API for intercepting candidates in call resolvers
Most part is made by @lelandrichardson
2020-05-27 01:42:48 +03:00
Roman Artemev
500acf412f [JS TESTS] Regenerate ES6 tests 2020-05-27 00:32:56 +03:00
Roman Artemev
2fd6921806 [JS TESTS] Emulate failing of non-run tests 2020-05-27 00:32:56 +03:00
Roman Artemev
086241659e [JS TESTS] Don't run ES6 test on win & mac till j2v8 issue is fixed. 2020-05-27 00:32:56 +03:00
Roman Artemev
50162265da [JS TESTS] Add EP to disable run test on specific platform 2020-05-27 00:32:56 +03:00
Vitaly
fe047f9b47 [JS BE] mutes tests for JS_IR_ES6, which muted for JS_IR 2020-05-27 00:32:56 +03:00
Vitaly
fe65045615 [JS BE] add es6 BE and relevant generated tests 2020-05-27 00:32:56 +03:00
Vitaly
a231b21c69 [JS BE] add tests for es6-classes 2020-05-27 00:32:55 +03:00
Vitaly
adf6831d7f [JS BE] implement es6-classes's codegen 2020-05-27 00:32:55 +03:00
Vitaly
90bcf8bf88 [JS BE] add es6LoweringPhase 2020-05-27 00:32:55 +03:00
Vitaly
fd25a5b3c8 [JS BE] es6: save instance after superCall 2020-05-27 00:32:55 +03:00
Vitaly
8c412adfaa [JS BE] implement es6-classes lowering 2020-05-27 00:32:55 +03:00
Vitaly
be85b36025 [JS BE] add flag es6mode 2020-05-27 00:32:55 +03:00
Vitaly
9ede8445e7 [JS BE] add runtime-function and intrinsics for es6-classes 2020-05-27 00:32:54 +03:00
Vitaly
18bd80eb29 [JS BE] add JsClass node to ast 2020-05-27 00:32:54 +03:00
Dmitry Petrov
69fa067df9 Fix compiler bootstrap (1.4.0-dev-9205) 2020-05-27 00:28:58 +03:00
Vladimir Dolzhenko
5c58a9dfd1 PerfTests gradle interceptor clean up 2020-05-26 21:50:31 +02:00
Ilya Chernikov
a1c173733c Fix gradle tests after renaming scripting libs and plugin 2020-05-26 20:24:15 +02:00
Steven Schäfer
9b7a95b05c Parcelize: Fix test code
On Android, we would need to call `setDataPosition(0)` after
unmarshalling a parcel. The reason why the test code is currently
working is purely because the Robolectric test framework is more
permissive.
2020-05-27 02:39:29 +09:00
Steven Schäfer
d93e5d3dc0 Parcelize: Enable ParcelableDeclarationChecker with the parcelize plugin
Previously, the ParcelableDeclarationChecker was only enabled as part of
the view extensions. In particular, the checker was not enabled for the
parcelize test suite.
2020-05-27 02:39:29 +09:00
Steven Schäfer
f93749ae6a Parcelize: Fall back to readValue/writeValue if no other serializers are available 2020-05-27 02:39:28 +09:00
Steven Schäfer
8d364a8a1a Parcelize: Resolve parcel serializers on demand 2020-05-27 02:39:28 +09:00
Steven Schäfer
cfe168021a Parcelize: Remap functions in overridden symbols and callable references 2020-05-27 02:39:28 +09:00
rbares
b39a65305d Fix Parcelize codegen tests following rebase 2020-05-27 02:38:45 +09:00
rbares
8a9610d3af Update Parcelize codegen tests 2020-05-27 02:38:45 +09:00
rbares
00ec50ff73 Fix Parcelize annotation implementing Parcelable.Creator<T> 2020-05-27 02:38:45 +09:00
Vitaliy.Bibaev
20793a65f4 KT-37486 Don't store instances from stream debugger plugin in companions 2020-05-27 02:38:45 +09:00
Yan Zhulanow
0c71c681e5 Do not reformat expressions in ReplaceCallWithBinaryOperatorInspection and SpecifySuperTypeFix 2020-05-27 02:38:45 +09:00
Yan Zhulanow
5a53c6ebf1 Remove ide-plugin-dependencies/tests-common-for-ide project
tests-common are now copied to the kotlin-ide project, so the artifact
  dependency is not needed any more
2020-05-27 02:38:44 +09:00
Yan Zhulanow
ed82465c3c Fix eager inter-project dependency 2020-05-27 02:38:44 +09:00
Yan Zhulanow
fb8640b3b6 Move compilerComponents project list to the root project 2020-05-27 02:38:44 +09:00
Yan Zhulanow
9d1c405b3c Rename ide-artifacts project to ide-plugin-dependencies 2020-05-27 02:38:44 +09:00
Yan Zhulanow
066b6d830f Put IDE plugin dependency artifact building/publishing under a flag 2020-05-27 02:38:44 +09:00
Yan Zhulanow
b00b6b0614 Remove explicit project paths for ide-artifacts projects
Gradle requires the explicit path mappings only if the physical location
  of Gradle build scripts doesn't match project paths.
2020-05-27 02:38:44 +09:00
Yan Zhulanow
91c24605f2 Minimize changes in 202 bunch 2020-05-27 02:38:44 +09:00
Yan Zhulanow
dea902551d Publish artifacts needed for the kotlin-ide repository 2020-05-27 02:38:44 +09:00
Yan Zhulanow
46ac241e2f 202: Fix compatibility with 202 IDEA branch (code) 2020-05-27 02:38:44 +09:00
Yan Zhulanow
f489ac1d03 Fix compatibility with 202 IDEA branch (dependencies) 2020-05-27 02:38:44 +09:00
Yan Zhulanow
a9d0c16fef Add 2020.2 bunch configuration 2020-05-27 02:38:44 +09:00
Yan Zhulanow
8a3e63aaf6 Minor: Clean up jvm-debugger-core module 2020-05-27 02:38:43 +09:00
Yan Zhulanow
3e05f7c2ab Minor: Move EvaluationStatus to the parent dir match its package name 2020-05-27 02:38:43 +09:00
Yan Zhulanow
0bf63c3000 Minor: Move filters to the companion object 2020-05-27 02:38:43 +09:00
Yan Zhulanow
3a0b0770d7 Debugger, minor: Remove obsolete KotlinRuntimeTypeEvaluator 2020-05-27 02:38:43 +09:00
Yan Zhulanow
9e85e9a036 Debugger, minor: Move method filters to the 'smartStepInto' package 2020-05-27 02:38:43 +09:00
Yan Zhulanow
45c97a2c5e Debugger: Add test for KT-14057 2020-05-27 02:38:43 +09:00
Yan Zhulanow
bf890a1540 Debugger, tests: Change ADDITIONAL_BREAKPOINT directive format
- Make it extendable and easier to parse
- Allow to create additional function breakpoints
2020-05-27 02:38:43 +09:00
Yan Zhulanow
4244f05307 Debugger: Fix step over in functions with default parameters (KT-14828)
Adds a synthetic line number just before the original function call.
The new line number is recognized by the debugger which replaces the
  'step over' action with 'step into' and stops.
2020-05-27 02:38:43 +09:00
Yan Zhulanow
d0f34624bd Debugger: Replace unsafe location() calls with safeLocation() 2020-05-27 02:38:43 +09:00
Yan Zhulanow
e6791ea4c3 Minor: merge KotlinSyntheticTypeComponentProvider with the base class
Base class was needed because of the separate bunch.
The bunch was deleted in 254dc8f71c,
  and now it doesn't make sense to have a base class any more.
2020-05-27 02:38:43 +09:00
Yan Zhulanow
69965eaa5c Implement new stepping for suspend functions 2020-05-27 02:38:43 +09:00
Yan Zhulanow
2044ece335 Kapt: Add DUMP_DEFAULT_PARAMETER_VALUES flag (KT-29355)
Put initializers on fields when corresponding primary constructor
  parameters have a default value specified. The new behavior
  is available under the new 'DUMP_DEFAULT_PARAMETER_VALUES' flag.

Note that this doesn't affect regular functions with default parameter
  values, as well as primary constructor parameters without a
  'val' or 'var' keyword.
2020-05-27 02:38:42 +09:00
Yan Zhulanow
60aa47553d Kapt, minor: Move test logic for KaptFlags to the new base class 2020-05-27 02:38:42 +09:00
Yan Zhulanow
c699a5b54c Pill: Disable Pill support for coroutines-experimental module 2020-05-27 02:38:42 +09:00
Yan Zhulanow
8fc403db94 Check if we are inside Kotlin in KotlinClassWithDelegatedPropertyRenderer
As 'isApplicable()' is called for Java classes as well, we spend too
  much time on calling 'allFields()' for deliberately unrelated classes.
2020-05-27 02:38:42 +09:00
Yan Zhulanow
0afd73b95c Debugger: Pass files with inline functions to backend (KT-36404) 2020-05-27 02:38:42 +09:00
Yan Zhulanow
85a5e5241f Debugger: Fix function breakpoints for libraries (KT-36403) 2020-05-27 02:38:42 +09:00
Yan Zhulanow
18070303d5 Update test data (KT-32511) 2020-05-27 02:38:42 +09:00
Yan Zhulanow
797058f781 Update test data (KT-27651) 2020-05-27 02:38:42 +09:00
Toshiaki Kameyama
f6a13df388 Add quick fix for AMBIGUOUS_SUPER
#KT-5271 Fixed
2020-05-27 02:38:42 +09:00
Toshiaki Kameyama
7c0af78b08 UnnecessaryVariableInspection: fix false positive in lambda
#KT-32565 Fixed
2020-05-27 02:38:42 +09:00
Toshiaki Kameyama
64f6ed586b "Convert to primary constructor" inspection: do not report when property has setter
#KT-22142 Fixed
2020-05-27 02:38:42 +09:00
Yan Zhulanow
08f31758b8 Minor: Extract name comparison 2020-05-27 02:38:41 +09:00
Toshiaki Kameyama
19d1532dc7 AddFunctionParametersFix: use argument name as parameter name if argument is referenced variable
#KT-14021 Fixed
2020-05-27 02:38:41 +09:00
Toshiaki Kameyama
8b8059acdd Add quick fix for MANY_IMPL_MEMBER_NOT_IMPLEMENTED
#KT-17121 Fixed
2020-05-27 02:38:41 +09:00
Toshiaki Kameyama
21d6d50241 Create class quick fix: suggest on supertype entry
#KT-32511 Fixed
2020-05-27 02:38:41 +09:00
Toshiaki Kameyama
4973d3c359 "Create enum constant" quick fix: handle trailing comman correctly
#KT-36461 Fixed
#KT-36462 Fixed
2020-05-27 02:38:41 +09:00
Yan Zhulanow
0bd2643788 Fix EA-209582: Add a missing runReadAction() 2020-05-27 02:38:41 +09:00
Yan Zhulanow
075870fee9 Fix EA-207101: Abort changing property declaration from Java accessor
This is not a proper fix. "Change signature" in Kotlin should support
  changing property name/type through accessors. However, it's not
  easy to achieve without a huge refactoring.
2020-05-27 02:38:41 +09:00
Yan Zhulanow
fc433dece8 Fix EA-221456, check for error types before method signature calculation 2020-05-27 02:38:41 +09:00
Yan Zhulanow
c8bad15ba9 Fix EA-210182, check for context validity 2020-05-27 02:38:41 +09:00
Yan Zhulanow
b756e18962 Never treat @JsExport-annotated declarations as not-used instead of @JsName 2020-05-27 02:38:41 +09:00
Yan Zhulanow
ef698a5747 Fix "PSI/index mismatch" in case of @ParameterName on non-functional types (KT-34524) 2020-05-27 02:38:41 +09:00
Yan Zhulanow
d86b54a2f1 Minor: Fix formatting 2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
4638a97bbc "Call on collection type may be reduced": fix false positive with mapNotNull, generic lambda block and new inference
#KT-32801 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
6ee4b5e393 Condition of 'if' expression is constant: don't report when condition has named reference
#KT-27651 Fixed
2020-05-27 02:38:40 +09:00
Yan Zhulanow
bfb5efd490 Minor: Get rid of the hard-coded modifier value 2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
581f83421a Unnecessary parentheses in function call with lambda: don't report for function named 'suspend'
#KT-22878 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
777995a3a0 Add braces: don't insert extra line break and move the following comment
#KT-36194 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
905d0c1016 Unused symbol: do not report for @JsName annotated declarations
#KT-17368 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
7abd0831a1 Unused unary operator: highlight whole expression in yellow
#KT-37156 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
43b106fc72 Can be replaced with binary operator: do not report if it leads to an error/warning after conversion
#KT-25050 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
81d01a8f8e "To ordinary string literal": don't add unnecessary escapes to characters in template expression
#KT-36406 Fixed
2020-05-27 02:38:40 +09:00
Toshiaki Kameyama
bf3e739edf Replace with string templates: add curly braces if needed
#KT-37173 Fixed
2020-05-27 02:38:39 +09:00
Toshiaki Kameyama
8d3e41ae60 ReplaceToWithInfixFormInspection: don't report when call expression has type typeArguments
#KT-36508 Fixed
2020-05-27 02:38:39 +09:00
Toshiaki Kameyama
f7a69d4aa7 Convert lambda to reference: suggest on lambda argument for suspend function parameter
#KT-34378 Fixed
2020-05-27 02:38:39 +09:00
Toshiaki Kameyama
9b6b25f069 Convert lambda to reference: suggest on lambda argument for extension function parameter
#KT-22014 Fixed
#KT-22015 Fixed
2020-05-27 02:38:39 +09:00
Toshiaki Kameyama
b8ae13b3d9 RedundantLetInspection: remove 'let' safe call correctly
#KT-37148 Fixed
2020-05-27 02:38:39 +09:00
Toshiaki Kameyama
a2f55e8b7c Remove redundant calls of the conversion method: report for unsigned types
#KT-30263 Fixed
2020-05-27 02:38:39 +09:00
Yan Zhulanow
38b6b73745 Add additional diagnostic for EA-225967 2020-05-27 02:38:39 +09:00
Yan Zhulanow
36f3ff7d20 Add stack trace logging for EA-225969 2020-05-27 02:38:39 +09:00
Yan Zhulanow
c1b57e8681 Pill: Remove "Refresh Pill model" run configuration
Just invoke ./gradlew pill task, there is no need in the extra
  run configuration.
2020-05-27 02:38:39 +09:00
Dmitry Petrov
f81be526bc Support deserialized IR in IfNullExpressionsFusionLowering
Deserializer generates simple branches instead of IrElseBranches.
2020-05-26 20:29:12 +03:00
Svyatoslav Scherbina
c9f721848a Fix Throws declaration in Native diagnostics tests
Align annotation target with real declaration in Native stdlib
2020-05-26 20:24:35 +03:00
Svyatoslav Scherbina
fa152593ef Fix false-positive @Throws error diagnostics in Native
Don't report
THROWS_LIST_EMPTY and MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND
caused by unresolved arguments.
2020-05-26 20:24:34 +03:00
Svyatoslav Scherbina
242d0aa26e Add Native diagnostics for @Throws suspend fun
`@Throws suspend fun` must have CancellationException accepted.

Also add more tests.
2020-05-26 20:24:32 +03:00
Svyatoslav Scherbina
3e8b0055ab Decouple Call.hasUnresolvedArguments from ResolutionContext 2020-05-26 20:24:30 +03:00
Sergey Rostov
eb338e2e91 Scripting IDE cache: unblocking concurrent update
#KT-38875 Fixed

(cherry picked from commit 63e355d979)
2020-05-26 19:22:15 +03:00
Sergey Rostov
e3ed8870dd scripting, sdk cache: same key for locating sdk 2020-05-26 19:22:09 +03:00
Sergey Rostov
8d00ec1933 scripting: fixes after rebase 2020-05-26 19:22:08 +03:00
Sergey Rostov
74b189fa54 idea.core.script.ucache: remove cyrilic "c" in package name 2020-05-26 19:22:08 +03:00
Natalia Selezneva
5212054af6 Fix sdk duplication in ProjectSdkTable in tests 2020-05-26 19:22:08 +03:00
Sergey Rostov
72aba2fce2 IDE scripting: add default sdk only when used 2020-05-26 19:22:07 +03:00
Sergey Rostov
53983a99e5 Fix order of ExternalSystemListeners 2020-05-26 19:22:07 +03:00
Sergey Rostov
06dbbe2452 KotlinDslModels: project can be null in ExternalSystemTaskNotificationListener.onStart 2020-05-26 19:22:07 +03:00
Sergey Rostov
44f6d490b6 scripting ucache: update synchronously in unit test mode 2020-05-26 19:22:06 +03:00
Sergey Rostov
e613bc406e 201: proper implementation for AsyncFileChangeListenerHelper.kt
updateFile is called before changes in vfs, so the timestamp is old there.
The proper implementation is to collect changed files in list and get timestamp in apply.
2020-05-26 19:22:06 +03:00
Sergey Rostov
8f8ee1ea83 Scripting unified cache: update sdks synchronously on changes 2020-05-26 19:22:06 +03:00
Sergey Rostov
037ea224a4 GradleBuildRoot: don't store references to virtual files 2020-05-26 19:22:06 +03:00
Sergey Rostov
a97e9f641a remove stale GradleScriptInputsWatcher references 2020-05-26 19:22:06 +03:00
Sergey Rostov
494a4460c1 minor: ScriptingSupport.Provider -> ScriptingSupport, KDoc 2020-05-26 19:22:05 +03:00
Sergey Rostov
40c852e818 GradleScriptOutOfProjectTest: roots are already registered as legacy 2020-05-26 19:22:05 +03:00
Sergey Rostov
cf4ad1908b Fix lastIndexOfOrNull 2020-05-26 19:22:05 +03:00
Sergey Rostov
c604ef1255 Scripting, minor: updateScriptDefinitions -> updateScriptDefinitionReferences 2020-05-26 19:22:05 +03:00
Sergey Rostov
cfe6fee1ca ScriptClassRootsCache, sdk: use toSystemIndependentName 2020-05-26 19:22:05 +03:00
Sergey Rostov
eda95af999 gradle.kts, minor: remove unused code 2020-05-26 19:22:04 +03:00
Sergey Rostov
cb3e08b345 GradleScriptListenerTest: add gradle-wrapper.properties to specify gradle version explicitly 2020-05-26 19:22:04 +03:00
Sergey Rostov
ec9608b00d ScriptClassRootsUpdater, updateSynchronously: cancel before waiting for lock 2020-05-26 19:22:04 +03:00
Sergey Rostov
59c35fe35c ScriptClassRootsUpdater: fix clearing scheduledUpdate and check cancelled in sync 2020-05-26 19:22:04 +03:00
Sergey Rostov
2932c67db7 gradle.kts: remove LastModifiedFiles fs data when removing gradle root 2020-05-26 19:22:04 +03:00
Sergey Rostov
6b53a98399 gradle.kts, minor: move isInAffectedGradleProjectFiles inside GradleBuildRootsManager 2020-05-26 19:22:03 +03:00
Sergey Rostov
b233a2a83a GradleScriptListenerTest: link gradle project 2020-05-26 19:22:03 +03:00
Sergey Rostov
13abfda00b GradleBuildRootsManager: fix onProjectsLinked 2020-05-26 19:22:03 +03:00
Sergey Rostov
5cd9e99caa GradleLegacyScriptListener: call from GradleScriptListener
GradleScriptListener is called from VFS listener
2020-05-26 19:22:03 +03:00
Sergey Rostov
bac68816d2 gradle.kts: use toSystemIndependentName for paths coming from Gradle 2020-05-26 19:22:02 +03:00
Sergey Rostov
381d505430 ScriptClassRootsUpdater: run synchronously in unit test mode 2020-05-26 19:22:02 +03:00
Sergey Rostov
4e8b1634e6 UnusedSymbolInspection: load script configurations from cache 2020-05-26 19:22:02 +03:00
Sergey Rostov
d937b66f30 gradle.kts, scheduleLastModifiedFilesSave: fix race condition 2020-05-26 19:22:02 +03:00
Sergey Rostov
e168cb739c gradle.kts, minor: areRelatedFilesUpToDate -> areRelatedFilesChangedBefore 2020-05-26 19:22:02 +03:00
Sergey Rostov
d84acb8ca2 GradleScriptListener: update lastModifiedFiles on document change 2020-05-26 19:22:01 +03:00
Sergey Rostov
62bd16ddf9 GradleBuildRoot: fix loading lastModifiedFiles 2020-05-26 19:22:01 +03:00
Sergey Rostov
70a3877546 LastModifiedFiles: fix in case of sequential changes in same file 2020-05-26 19:22:01 +03:00
Sergey Rostov
f161276949 .gradle.kts, listener: support multiple gradle projects linked to one IntelliJ project
GradleScriptInputsWatcher moved to GradleScriptListener.kt and GradleBuildRootsManager.kt
2020-05-26 19:22:01 +03:00
Sergey Rostov
e376a04b5a gradle.kts: docs 2020-05-26 19:22:00 +03:00
Sergey Rostov
d6adab785a ScriptConfigurationManager: take OutsidersPsiFileSupport into account 2020-05-26 19:22:00 +03:00
Sergey Rostov
bfa88267ec Scripts, minor: get rid of ScriptingSupportHelper 2020-05-26 19:22:00 +03:00
Sergey Rostov
bae550665e gradle.kts: merge data on failed gradle sync, fix updates scheduling in corner cases 2020-05-26 19:22:00 +03:00
Sergey Rostov
381374d339 gradle.kts: solve the linked gradle builds hell 2020-05-26 19:22:00 +03:00
Sergey Rostov
d8abf60b3d gradle.kts, imported gradle build root: fix equality 2020-05-26 19:21:59 +03:00
Sergey Rostov
560c2b62ef ScriptConfigurationManager, outsider files: search in roots cache too 2020-05-26 19:21:59 +03:00
Sergey Rostov
347f69b1fd ScriptConfigurationManager: rebuild cache synchronously from default loader 2020-05-26 19:21:59 +03:00
Sergey Rostov
feac19f46e gradle.kts: cache definitions 2020-05-26 19:21:59 +03:00
Sergey Rostov
1fdd1bcbf6 gradle.kts: remove useless gradle build root kinds 2020-05-26 19:21:58 +03:00
Sergey Rostov
4e61758188 CompositeScriptConfigurationManager: unified caching 2020-05-26 19:21:58 +03:00
Sergey Rostov
d21a7f54e4 GradleScriptConfigurationLoader: KDocs 2020-05-26 19:21:58 +03:00
Sergey Rostov
8f75f72835 Revert "Fix order of ExternalSystemListeners"
This reverts commit 879fe9b4
2020-05-26 19:21:58 +03:00
Sergey Rostov
7ec82ba279 Revert "KotlinDslModels: project can be null in ExternalSystemTaskNotificationListener.onStart"
This reverts commit 98d3855f
2020-05-26 19:21:57 +03:00
Natalia Selezneva
ba5fe6cda9 Testing: Avoid creating duplicated SDKs 2020-05-26 19:21:57 +03:00
nataliya.valtman
22243c756b Revert "KT-38250 The minimal supported Gradle version is 5.3 now"
This reverts commit 61f213c8
2020-05-26 19:06:47 +03:00
Ilya Goncharov
f7ee9b42d7 [Gradle, JS] Update package json only if version of dependency changed 2020-05-26 18:21:42 +03:00
Ilya Goncharov
f064634eb0 [Gradle, JS] Backport possibility to disable granular workspaces 2020-05-26 18:21:42 +03:00
Ilya Goncharov
60515aad77 [Gradle, JS] Move umbrella task to nodejs extension 2020-05-26 18:21:42 +03:00
Ilya Goncharov
549797c719 [Gradle, JS] Add nodeArgs 2020-05-26 18:21:42 +03:00
Ilya Goncharov
b201ff0168 [Gradle, JS] Args for webpack 2020-05-26 18:21:42 +03:00
Ilya Goncharov
0a704cf52c [Gradle, JS] Add generate config only to webpack 2020-05-26 18:21:42 +03:00
Sergey Rostov
61f213c80c KT-38250 The minimal supported Gradle version is 5.3 now
Gradle integration tests: use at least OLDEST_SUPPORTED version.

extract minSupportedGradleVersion for using both in check and tests

avoid using Usage.JAVA_API_JARS and JAVA_RUNTIME_JARS
2020-05-26 18:08:26 +03:00
Nicolay Mitropolsky
0bb3a4ccb7 201: Uast: KotlinUastCodeGenerationPlugin on the level needed for ReactorSupport (KT-38062) 2020-05-26 17:39:43 +03:00
Nicolay Mitropolsky
8434806f56 Ide-common: resolveToKotlinType moved to TypeUtils.kt in the *ide-common* 2020-05-26 17:39:43 +03:00
Nicolay Mitropolsky
70237ecf31 Uast: explicitly expose implicit Lambda parameters 2020-05-26 17:39:43 +03:00
Nicolay Mitropolsky
5f64c6b9f1 Uast: a proper sourcePsi for lambda parameters 2020-05-26 17:39:43 +03:00
anastasiia.spaseeva
9d862aaa1d [Spec tests] Remove spec info from fir tests 2020-05-26 17:27:06 +03:00
anastasiia.spaseeva
5ba9d09278 [Spec tests] Fix fir test runner for spec tests 2020-05-26 17:27:06 +03:00
Ilya Chernikov
2509dfb287 Rename scripting libs and plugin - invert embeddable suffix
now regular, unshaded libs, are named with suffix `-unshaded`, while
former `-embeddable` ones named without any suffix. This will encoursge
use of the shaded libs by default, avoiding conflicts with 3-party
libs packed into the `kotlin-compiler`.
Note, that only the "frontline" libs are renamed to avoid switching
problems, the ones that not normally used directly are left as is,
including the `kotlin-compiler` itself.
2020-05-26 15:58:25 +02:00
Zalim Bashorov
f39165bb58 Revert accidentally pushed changes
Revert "~~~"

This reverts commit 03fcbfad

Revert "Add an ability to provide own handler for errors inside KotlinJavascriptMetadataUtils.loadMetadata"

This reverts commit 69827fc5

Revert "Add more detailed message for EA-227305 and EA-226744"

This reverts commit b79b3507
2020-05-26 16:15:59 +03:00
Roman Golyshev
eb838b0fa0 KT-39179 Replace ApplicationBundle with KotlinBundle
- Used bundle messages are moved to JavaBundle in platform >= 201
- ^KT-39179 Fixed
2020-05-26 13:00:12 +00:00
Zalim Bashorov
03fcbfad1a ~~~ 2020-05-26 15:43:05 +03:00
Zalim Bashorov
69827fc5af Add an ability to provide own handler for errors inside KotlinJavascriptMetadataUtils.loadMetadata
Use a logger to handle errors inside loadMetadata when it's used from IDE (JsResolverForModuleFactory).

#EA-218905
2020-05-26 15:41:47 +03:00
Zalim Bashorov
b79b3507f2 Add more detailed message for EA-227305 and EA-226744 2020-05-26 15:41:47 +03:00
Krasnoriadtseva Anastasiia
a55dec28b9 [FIR] Fix infinite CFG traverse 2020-05-26 15:30:45 +03:00
Roman Artemev
7644b4baec [KLIB] Improve performance a bit 2020-05-26 14:41:49 +03:00
Roman Artemev
44dfae53f0 [IR BE] Add runtime compilation benchmarks for IR JS compiler 2020-05-26 14:41:49 +03:00
Roman Artemev
e6c855111e [KLIB] Add flag to select between per-file and monolithic layout 2020-05-26 14:41:49 +03:00
Roman Artemev
444ecc0981 [PLUGIN API] Fix misprint 2020-05-26 14:38:18 +03:00
Roman Artemev
bc32688497 [PLUGIN API] Drop PureIrGenerationExtension 2020-05-26 14:38:18 +03:00
Roman Artemev
6f2972ee8b [ANDROID] Move Parcelize plugin to general IrGenerationExtension API 2020-05-26 14:38:18 +03:00
Juan Chen
adba0a03a6 [FIR] Create builtin primitive array types for properties
If the primary constructor has a vararg parameter, the corresponding
property has an array type. This commit creates the builtin array
types for such properties if the vararg element type is primitive,
e.g., CharArray instead of Array.
2020-05-26 14:08:47 +03:00
Vladimir Ilmov
ed6aceca87 (UnusedSymbolInspection) lazy parameter evaluation fix 2020-05-26 12:36:42 +02:00
Nikolay Krasko
4a7854a948 Sign and generate hash for compiler and plugin zip 2020-05-26 12:47:10 +03:00
Vladimir Dolzhenko
bf5c7aea4d Added heapDumper for perfTests 2020-05-26 11:09:25 +02:00
Dmitry Petrov
2f79b4c412 Add test for KT-34902 2020-05-26 11:59:05 +03:00
Mikhail Glukhikh
4455532210 JsIntrinsics: use createEmptyExternalPackageFragment 2020-05-26 11:50:55 +03:00
Mikhail Glukhikh
7818baff1e [FIR2IR] Fix problem with double-generation of local class members 2020-05-26 11:50:33 +03:00
Vyacheslav Gerasimov
64fcbbc89f Build: buildSrc should inherit build cache setup of parent project
https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_composite
2020-05-26 10:39:27 +03:00
Vyacheslav Gerasimov
5bca9c488e Build: Don't unpack ivy repo artifacts if target directory exists 2020-05-26 07:18:09 +03:00
Vladimir Dolzhenko
bca8e96362 Clean up after nicer performance tests suite dsl 2020-05-25 21:54:56 +02:00
simon.ogorodnik
ac1769a474 [FIR2IR] Support SAM constructors 2020-05-25 21:24:39 +03:00
simon.ogorodnik
dbc564e74e [FIR2IR] Approximate types for lambdas before passing to serialization 2020-05-25 21:24:39 +03:00
simon.ogorodnik
b92194229c [FIR] Add fir copy function generation 2020-05-25 21:24:38 +03:00
pyos
f625444be2 Update debugger test data
Note: neither the new nor the old data is actually correct, as the
debugger needs to stop on line 7 twice (once for the call, once for the
lambda) but ignore the synthetic line number in between.
2020-05-25 20:03:56 +02:00
pyos
76c34a07b2 JVM: use 1 as a synthetic line number for @InlineOnly lambdas
The source path already marks it as synthetic.
2020-05-25 20:03:56 +02:00
pyos
25e1fb8502 JVM: map synthetic line numbers through the SMAP
This is necessary so that IDEA does not ignore the line number.
2020-05-25 20:03:56 +02:00
pyos
d17a18f96d JVM: do not write trivial SMAPs to classes outside inline funs
where trivial == those that map the file to itself.
2020-05-25 20:03:56 +02:00
Pavel Punegov
a04aeeb4e1 Ignore broken test in Native 2020-05-25 20:58:43 +03:00
Victor Petukhov
e70242f6f1 NI: some review fixes for improved postponed arguments analysis 2020-05-25 19:37:30 +03:00
Victor Petukhov
756326cefe NI: report error diagnostic about impossible to infer anonymous function's parameter
Partially fixed KT-39098
2020-05-25 19:37:27 +03:00
Dmitry Savvinov
00df562a2b Allow specific native targets to depend on unspecified native target
^KT-38769 Fixed
2020-05-25 16:13:10 +03:00
Vladimir Dolzhenko
55dc308688 Projects HL perf test 2020-05-25 13:11:10 +00:00
Vladimir Dolzhenko
1ae7f693c5 Nicer performance tests suite dsl 2020-05-25 13:11:09 +00:00
Mikhail Zarechenskiy
2cee82a348 [NI] Resolve receiver of provideDelegate independently
#KT-38259 Fixed
2020-05-25 16:06:55 +03:00
Mikhail Zarechenskiy
59f027e3e9 [NI] Don't try performing any conversions on receivers 2020-05-25 16:06:55 +03:00
Vladimir Ilmov
de69962e9d (UnusedSymbolInspection) alternative accessor names for searching references
relates to #KT-38653
2020-05-25 14:49:16 +02:00
Vladimir Ilmov
17df7ade59 (UnusedSymbolInspection) Optimize second call to isCheapEnoughToSearchUsages
relates to #KT-38653
2020-05-25 14:49:16 +02:00
Mikhail Glukhikh
6c124ccd0c [IR] Drop deprecated symbol.descriptor based declaration constructors 2020-05-25 15:40:38 +03:00
Mikhail Glukhikh
bb2e58b6a4 Deprecate IrDeclaration.descriptor and IrSymbol.descriptor 2020-05-25 15:40:38 +03:00
Mikhail Glukhikh
b05a1bb1a2 [IR] Extract IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
12f596c620 [IR] Unbind construction methods of IR file/enum entry/type alias from symbol.descriptor 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
c68de4639f [IR] Unbind construction methods of IrLocalDelegatedPropertyImpl from symbol.descriptor 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
58ef59074d [IR] Unbind construction methods of IrTypeParameterImpl from symbol.descriptor 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
3f09bb40c0 [IR] Unbind construction methods of IrVariableImpl from symbol.descriptor 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
784d3a9005 [IR] Unbind construction methods of IrValueParameterImpl from symbol.descriptor 2020-05-25 15:40:37 +03:00
Mikhail Glukhikh
03f2c6d38a [IR] Unbind construction methods of IrFieldImpl from symbol.descriptor 2020-05-25 15:40:36 +03:00
Mikhail Glukhikh
ab15a88ce4 [IR] Unbind construction methods of IrPropertyImpl from symbol.descriptor 2020-05-25 15:40:36 +03:00
Mikhail Glukhikh
7840adde12 [IR] Unbind construction methods of IrConstructorImpl from symbol.descriptor 2020-05-25 15:40:36 +03:00
Mikhail Glukhikh
262548fd5b [IR] Unbind construction methods of IrFunctionImpl from symbol.descriptor 2020-05-25 15:40:36 +03:00
Mikhail Glukhikh
a7d514a0a9 [IR] Unbind construction methods of IrClassImpl from symbol.descriptor 2020-05-25 15:40:35 +03:00
Vladimir Ilmov
9e807ebb89 (CoroutineDebugger) Prevent navigation to internalCompiledFiles
#KT-39143 fixed
2020-05-25 14:36:22 +02:00
Vladimir Ilmov
545fdb96d5 (CoroutineDebugger) 201 compatibility fix
#KT-39143 fixed
2020-05-25 14:36:22 +02:00
Vladimir Ilmov
7a70f8d29e (CoroutineDebugger) executionContext added to ContinuationVariableValueDescriptor 2020-05-25 14:36:21 +02:00
Roman Artemev
257c4c5604 [PLUGIN API] Extract IrPluginContext into separate interface
- Isolate ir infrastructure implementation details behind special interface
2020-05-25 13:26:35 +03:00
Victor Petukhov
a84780fefb NI: Add regression test for KT-38799
The issue has been fixed by introducing the modified postponed arguments analysis (KT-37952)
2020-05-25 11:56:08 +03:00
Roman Golyshev
4436142f00 KT-38450 Add functional interface converter to the NJ2K
- Enable custom compiler options for
`AbstractNewJavaToKotlinConverterSingleFileTest`
- ^KT-38450 Fixed
2020-05-25 11:11:24 +03:00
gcx11
50fc9d3692 KT-10974 - code review changes 2020-05-25 10:40:24 +03:00
gcx11
2382629209 KT-10974 - code review changes 2020-05-25 10:40:24 +03:00
gcx11
a2dc2fe5bb KT-10974 - small fixes 2020-05-25 10:40:24 +03:00
gcx11
8849a66c00 KT-10974 - add import layout configuration table 2020-05-25 10:40:24 +03:00
Sergey Rostov
9574ac83e4 jps: testPureJavaProject fix 2020-05-25 10:06:11 +03:00
Ilya Chernikov
574b917061 Remove new kotlin daemon from dist
hopefully temporarily, also see #KTI-173
2020-05-24 19:03:43 +02:00
Ilya Chernikov
3dd79ffea6 Update coroutines-core version to 1.3.7 2020-05-24 19:03:43 +02:00
Ilya Chernikov
9d98c90881 Drop coroutines from compiler jar, add appropriate plugin dependency
#KT-30778 fixed
2020-05-24 19:03:42 +02:00
Dmitriy Novozhilov
343e519f7f [FIR-PLUGIN] Update testdata according removed class generation stage 2020-05-24 18:04:48 +03:00
Dmitriy Novozhilov
e340dacb9a [FIR-PLUGIN] Add check to test that jar with annotations exists 2020-05-24 18:04:48 +03:00
Dmitriy Novozhilov
d49c198a7f [FIR] Correctly initialize extensions in all sessions 2020-05-24 18:04:47 +03:00
Dmitriy Novozhilov
96da6d35c5 [FIR] Add processor for transforming statuses with plugins 2020-05-24 18:04:47 +03:00
Dmitriy Novozhilov
8d686226c7 [FIR] Introduce FirResolveProcessors 2020-05-24 18:04:47 +03:00
Dmitriy Novozhilov
96802dde04 [FIR-PLUGIN] Fix compilation 2020-05-24 18:04:47 +03:00
Dmitriy Novozhilov
3de12f9b09 [FIR] Completely remove old extensions service 2020-05-24 18:04:47 +03:00
Dmitriy Novozhilov
9a8d520b85 [FIR] Remove first version of class generation transformer 2020-05-24 18:04:46 +03:00
Dmitriy Novozhilov
3e3387fb69 [FIR] Remove extension status transformation from status resolve 2020-05-24 18:04:46 +03:00
Dmitriy Novozhilov
006232dfb2 [FIR] Fix FirPluginAnnotationsResolveTransformer 2020-05-24 18:04:46 +03:00
Dmitriy Novozhilov
206a646195 [FIR] Use caches for predicate matching 2020-05-24 18:04:45 +03:00
Dmitriy Novozhilov
594a854b4e [FIR] Reimplement FirExtensionService
- Get rid of old FirExtensionsService
- Implement new FirExtensionService
- Remove duplicating code in FirExtensionRegistrar
2020-05-24 18:04:45 +03:00
Dmitriy Novozhilov
846db641be [FIR] Make ArrayMap iterable 2020-05-24 18:04:45 +03:00
Dmitriy Novozhilov
5c12b3df95 [FIR] Introduce FirPredicateBasedProvider 2020-05-24 18:04:45 +03:00
Dmitriy Novozhilov
0b00015424 [FIR] Deprecate FirExtensionsService 2020-05-24 18:04:44 +03:00
Dmitriy Novozhilov
f3d4fa715e [FIR] Introduce DeclarationPredicates for matching declarations for extensions 2020-05-24 18:04:44 +03:00
Dmitriy Novozhilov
74353d8bc9 [FIR] Introduce FirAnnotatedDeclaration 2020-05-24 18:04:44 +03:00
Dmitriy Novozhilov
799253256c [FIR-PLUGIN] Add additional checker to prototype plugin 2020-05-24 18:04:44 +03:00
Dmitriy Novozhilov
f764baad82 [FIR] Add extension with additional checkers 2020-05-24 18:04:43 +03:00
Dmitriy Novozhilov
04a1027b39 [FIR] Add empty instances of DeclarationCheckers and ExpressionCheckers 2020-05-24 18:04:43 +03:00
Dmitriy Novozhilov
c0a57ae55c [FIR] Move expression checkers from package call to expression 2020-05-24 18:04:43 +03:00
Dmitriy Novozhilov
6d6ed1e755 [FIR] Create session component with registered checkers 2020-05-24 18:04:43 +03:00
Mikhail Bogdanov
b61b4e4a97 Use proper distributionSha256Sum for android tests 2020-05-24 15:37:59 +02:00
Andrey Uskov
bfad00e8c9 Mute android-related gradle import tests 2020-05-23 23:16:42 +03:00
Ilya Gorbunov
22c4d30a89 Correct docs of ThreadLocal and SharedImmutable annotations
- clarify that they have effect only in K/N
- correct possible application targets of SharedImmutable

KT-36245
2020-05-23 22:28:46 +03:00
Ilya Gorbunov
dae7a23998 Clarify docs of CharSequence.split(Pattern, limit)
Emphasize differences from Pattern.split(CharSequence, limit).

#KT-39023 Fixed
2020-05-23 22:25:54 +03:00
Abduqodiri Qurbonzoda
f3145454f2 Decommonize collection builder implementations 2020-05-23 03:40:44 +03:00
Victor Petukhov
379c6944a2 NI: extract diagnostics from partially resolved call instead of separately handling it including running all checks
^KT-37630 Fixed
^KT-35494 Fixed
2020-05-22 22:13:53 +03:00
Ilya Matveev
eaa16714f6 [Gradle, native] Allow disabling warning about incorrect dependencies
Issue #KT-32476
2020-05-22 22:16:18 +07:00
Svyatoslav Kuzmich
c9adf22697 [JS] Remove binding context from NameSuggestion instance
Pass bindingContext to suggest method instead.
Revert creating multiple instances of NameSuggestion in checkers.
2020-05-22 17:05:30 +03:00
Ilya Goncharov
104352b313 [Gradle, JS] Remove browser tests from gradle integration tests 2020-05-22 13:25:23 +03:00
Svyatoslav Kuzmich
6e3d3831c2 [JS] JsExport diagnostics and legacy support
Account for JsExport in legacy backend namer. It means we
catch overloaded exported function conflicts for free!

Add error diagnostics:
* NESTED_JS_EXPORT (Fixes KT-36798)
* WRONG_EXPORTED_DECLARATION (Part of the fix for KT-37752)
* NON_EXPORTABLE_TYPE (Fixes KT-37771)
2020-05-22 10:50:22 +03:00
Dmitriy Dolovov
4076bf40a9 [Commonizer] Add Gradle property to pass JVM args
^KT-39094
2020-05-22 12:07:37 +07:00
Dmitriy Dolovov
2a1e014d51 Minor. Add jetbrains to project dictionary 2020-05-22 12:07:26 +07:00
anastasiia.spaseeva
c736a1e5b0 [Spec tests] Update testsMap for when-expression section 2020-05-22 02:52:02 +03:00
anastasiia.spaseeva
d9160a26e9 [Spec tests] Add property helpers to testMaps 2020-05-22 02:52:02 +03:00
anastasiia.spaseeva
cbba52e43c [Spec tests] Make collectInfoFromTests for both spec and implementation tests 2020-05-22 02:52:01 +03:00
anastasiia.spaseeva
270972ca1c [Spec tests] Make main link nullable for case if implementation tests don't have this one 2020-05-22 02:52:00 +03:00
anastasiia.spaseeva
3a46b5a45a [Spec tests] Add path element at testMaps for main links also 2020-05-22 02:52:00 +03:00
anastasiia.spaseeva
d94c212a60 [Spec tests] Add linkType element to testMaps 2020-05-22 02:51:59 +03:00
anastasiia.spaseeva
3a31150df4 [Spec tests] Metadata refactoring: remove duplicated links in testMaps 2020-05-22 02:51:58 +03:00
anastasiia.spaseeva
d32aca87d1 [Spec tests] Change metadata structure of implementation and spec tests 2020-05-22 02:51:57 +03:00
Mikhail Likholetov
80cd26c9df [FIR] Support several annotation class diagnostics 2020-05-21 18:01:36 +03:00
Ilya Chernikov
c112d37ac1 Consolidate resolving in the new lib, deprecate it in script-util
also deprecate Import and CompileOptions annotations, because they
do not seem generic enough. Create specific copie in the main-kts
instead.
2020-05-21 16:49:57 +02:00
Ilya Chernikov
7d426226f9 Switch example to the new maven resolving API 2020-05-21 16:49:56 +02:00
Ilya Chernikov
f363134fbc Do not continue compilation if collected dependencies contain error
avoids additional errors reported by compilation, if configuration
refinement returned error
2020-05-21 16:49:56 +02:00
Ilya Chernikov
d92e4d28f5 Provide a method to update script definitions after loading into IDE
also documenting ScriptDefinitionsProvider
2020-05-21 16:49:56 +02:00
Ilya Chernikov
4b032a14af Refactor host configuration handling and script definition creation
so it is possible now to create custom host configuration with template
and all configurations are handled consistenly.
Also introduce and use new ScriptDefinition class wrapping compilation
and evaluation configurations, that could be consistenly created from a
template.
2020-05-21 16:49:55 +02:00
Ilya Chernikov
255ad47406 Use copied key to extract default jdkHome from host configuration 2020-05-21 16:49:55 +02:00
Ilya Chernikov
20bbcd5d5a Implement copied key with ability to take default from source config 2020-05-21 16:49:55 +02:00
Ilya Goncharov
3c9207a2cd [Gradle, JS] Add test on local project dependency
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
985623eac5 [Gradle, JS] Fix hmpp on only js
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
bed7b23d6c [Gradle, JS] Fix naming of test and test data
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
d089bbe14a [Gradle, JS] Fix for JsIrTarget in mixed mode
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
79984b6e04 [Gradle, JS] Add test on hmpp with both js
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
a6812e5d6a [Gradle, JS] Add fake common usage context for single js plugin publish
#KT-38592 fixed
2020-05-21 17:36:33 +03:00
Ilya Goncharov
4f747072f4 [Gradle, JS] Define fake configuration for single js plugin to publish as common
#KT-38592 fixed
2020-05-21 17:36:32 +03:00
Ilya Goncharov
22f5d3b134 [Gradle, JS] Add isMpp property
#KT-38592 fixed
2020-05-21 17:36:32 +03:00
Pavel Kirpichenkov
0b33e9430b [NI] Report unstable smart cast directly instead of using SmartCastManager
Fix compilation errors, revealed by this fix.

SmartCastManager is unnecessary for error reporting, intermediate diagnostics from the NI contain all required infromation.
When SmartCastManager is used it leads to missing unstable smart casts in case of expressions with captured types.
This happens, because data flow info is recorded for original expression without captured types, which is used as a key.
DataFlowValues created from receivers with captured types can't be used to retrieve that info.

^KT-39010 Fixed
2020-05-21 17:09:10 +03:00
Dmitry Gridin
b808d5f381 TrailingCommaInspection: cleanup code 2020-05-21 13:42:30 +00:00
Dmitry Gridin
ee141ae57b TrailingCommaInspection: add dependency to settings
* Change severity to `INFO`
* Mark useless comma as unused symbol
* Add dependency on `Use trailing comma`

#KT-39069 Fixed
#KT-38568 Fixed
2020-05-21 13:42:29 +00:00
Ilya Matveev
8d77ec83c6 [Gradle, native] Don't set system properties when the compiler runs in daemon
Changing system properties during parallel in-process compiler
execution may cause data races (e.g. see KT-37362, KT-37442).

This commit abandons using system properties when the compiler
is executed in process.

Issue #KT-37550 fixed
2020-05-21 12:05:24 +00:00
Ilya Matveev
f88722ae76 Update K/N: 1.4-M3-dev-15627 2020-05-21 12:05:23 +00:00
Roman Golyshev
a83b0bef96 KT-38841 Do not call preparePsiElementForWrite if not needed
- This call breaks Intention Preview for all intentions that extend
`SelfTargetingIntention`
- This check is actually already performed by the platform before the
intention invocation (but only if `startInWriteAction` returns `true`)
- There are many other intentions which redundantly use this call, but
most of them implement `LocalQuickFix`, which means that they are
inspection based. Currently Intention Preview does not seem to support
this kind of intentions
2020-05-21 11:45:48 +00:00
Dmitry Petrov
b89878a509 Update testData for KAPT tests for new inline class ABI
Since class member functions returning inline class values are now
mangled, they are not visible from Java.
2020-05-21 13:56:57 +03:00
Jinseong Jeon
7a947e8008 FIR: fix default constructor visibility for enum entry. 2020-05-21 08:40:03 +03:00
Jinseong Jeon
0d3301b695 FIR: resolve local class in anonymous initializer. 2020-05-21 08:36:49 +03:00
Mikhail Zarechenskiy
2ff5b253ae [NI] Fix suspend conversions for subtypes of functional types
Fix for recently added tests:
  - testIntersectionTypeToSubtypeConversion
  - testSubtypeOfFunctionalTypeToSuspendConversion
2020-05-21 00:47:12 +03:00
Roman Golyshev
3903814c9c Revert "KT-38841 Remove redundant preparePsiElementForWrite call"
This reverts commit 165b62da

Something went wrong with the AS40 build
2020-05-20 22:58:49 +03:00
Victor Petukhov
12db3d6e83 NI: remove separation of variable fixation order by constraint kind
The commit partially reverts ec4d9d2f1f

^KT-37914 Fixed
2020-05-20 22:37:30 +03:00
Dmitry Petrov
874fa5b998 Bootstrap: 1.4.0-dev-8798 2020-05-20 18:02:11 +03:00
Roman Golyshev
165b62da63 KT-38841 Remove redundant preparePsiElementForWrite call
- This call breaks Intention Preview for all intentions that extend
`SelfTargetingIntention`
- This check is actually already performed by the platform before the
intention invocation
- There are many other intentions which redundantly use this call, but
most of them implement `LocalQuickFix`, which means that they are
inspection based. Currently Intention Preview does not seem to support
this kind of intentions
2020-05-20 14:33:21 +00:00
Steven Schäfer
933440dc63 JVM IR: Fix mangling of @JvmStatic internal function in companion objects 2020-05-20 15:57:03 +02:00
Vladimir Dolzhenko
2d0445ebaa Add klib extension to ARCHIVE fileType
Fixed to #KT-38767
Relates to #KT-38571
2020-05-20 13:24:11 +00:00
Mikhail Zarechenskiy
fceaf65729 [NI] Don't compute conversions for definitely not SAM parameter 2020-05-20 15:30:14 +03:00
Mikhail Zarechenskiy
8bdc4d34f7 [NI] Commonize type-conversions (SAM/Suspend)
- Allow participating subtypes of functional types in conversions
 - Fix several subtle inconsistencies
 - Place logic about conversions at one place

 Now conversions operations have two stages: before usual subtyping
 check and after one. This is needed to support conversions of
 subtypes (of functional types, for example). First, the compiler
 checks if it possible to resolve an argument without conversion and
 only then it tries to perform conversion.
 Note that it'd be incorrect to perform conversion eagerly as it can
 change resolve (Runnable & () -> Unit <: KRunnable), plus we can't
 guess whether conversion is needed at all as it's important not to
 look into supertypes if resolution doesn't actually needed it

 #KT-36448 Fixed
 #KT-37574 Fixed
 #KT-38604 Fixed
2020-05-20 15:30:14 +03:00
Mikhail Zarechenskiy
f702da5c51 [NI] Small refactoring around type conversions 2020-05-20 15:30:13 +03:00
Mikhail Zarechenskiy
d3d162f9c8 Refactoring: start commonization of type-conversions 2020-05-20 15:30:13 +03:00
Mikhail Zarechenskiy
cce9646c7d Refactoring: extract method about SAM conversions out 2020-05-20 15:30:13 +03:00
Mikhail Zarechenskiy
372f378edc [NI] Support nested transactions inside constraint system 2020-05-20 15:30:13 +03:00
Kevin Most
4f26ac9a04 Fix "Koltin" typos throughout codebase (#3383)
* Fix "Koltin" typos throughout codebase

* Update K2MetadataKlibSerializer.kt
2020-05-20 15:12:32 +03:00
Sergey Igushkin
38fd9c3d1a Fix KT-39063 by not adding extendsFrom with metadata configurations
Issue #KT-39063 Fixed
2020-05-20 14:31:36 +03:00
Dmitry Petrov
6fcdab23cc Bootstrap: 1.4.0-dev-8774 2020-05-20 13:47:39 +03:00
Vladimir Dolzhenko
88efac00b3 Disable klib fileType in lue of KLibFileTypeFactory
Relates to #KT-38767
Relates to #KT-38571
2020-05-20 10:07:03 +00:00
Toshiaki Kameyama
081d6c1dff Useless call on collection: propose 'Replace with toList()' instead of 'Remove useless call' if receiver is array type
#KT-38961 Fixed
2020-05-20 12:46:23 +03:00
Ilya Chernikov
994897cee9 Fix textdata after reverting a commit about CompilerMessageLocation 2020-05-20 10:37:56 +02:00
Ilya Kirillov
d825428718 New J2K : move resolve resolve out of EDT in shorten references processing
relates to #KT-31812
2020-05-20 11:11:46 +03:00
Dmitriy Novozhilov
dc57d307f3 [FIR] Clean data flow context before body resolve of file 2020-05-20 10:41:03 +03:00
Dmitriy Novozhilov
8df635a4e0 [FIR] Add cleanup of tower data for imports 2020-05-20 10:41:02 +03:00
Dmitriy Novozhilov
b05546dd64 [FIR] Add check for session consistency in body resolve transformer 2020-05-20 10:41:02 +03:00
Dmitriy Novozhilov
371757309e [FIR] Don't recreate transformer in FirBodyResolveTransformerAdapter 2020-05-20 10:41:01 +03:00
Dmitriy Novozhilov
4e07f8180b [FIR] Don't recreate transformer in FirImplicitTypeBodyResolveTransformerAdapter 2020-05-20 10:41:01 +03:00
Dmitriy Novozhilov
c4407d6d63 [FIR] Don't recreate transformer in FirContractResolveTransformerAdapter 2020-05-20 10:41:00 +03:00
Dmitriy Novozhilov
c1080989b6 [FIR] Suppress pointless unchecked casts in FirStatusResolveTransformer 2020-05-20 10:41:00 +03:00
Dmitriy Novozhilov
329af65996 [FIR] Get rid of FirStatusResolveTransformerAdapter 2020-05-20 10:40:59 +03:00
Dmitriy Novozhilov
93992d1d75 [FIR] Get rid of FirTypeResolveTransformerAdapter 2020-05-20 10:40:58 +03:00
Dmitriy Novozhilov
ca4deec10e [FIR] Don't recreate transformers in FirSupertypeResolverTransformer 2020-05-20 10:40:58 +03:00
Dmitriy Novozhilov
dc30bf5d09 [FIR] Don't recreate transformers in FirPluginAnnotationsResolveTransformer 2020-05-20 10:40:57 +03:00
Dmitriy Novozhilov
0544369503 [FIR] Add transformImports to FirFile 2020-05-20 10:40:57 +03:00
Dmitriy Novozhilov
f60c8eac71 [FIR] Don't rewrite session in FirImportResolveTransformer 2020-05-20 10:40:56 +03:00
Dmitriy Novozhilov
67a259a903 [FIR] Get rid of FirSymbolProvider.getInstance(session)`
Replace with `session.firSymbolProvider`
2020-05-20 10:40:56 +03:00
Dmitriy Novozhilov
24c8a659ee [FIR] Add FirSession as parameter for FirTotalResolveTransformer 2020-05-20 10:40:55 +03:00
Dmitry Petrov
c165b8d55c JVM: Update IR bytecode text and signature tests 2020-05-20 07:19:30 +03:00
Dmitry Petrov
16e7a42aea JVM: Fix line numbers in test 2020-05-20 07:19:30 +03:00
Dmitry Petrov
e625bb375f Temporarily mute unsigned tests in JVM_IR and FIR 2020-05-20 07:19:30 +03:00
Dmitry Petrov
de4ebe4395 Prohibit @JvnName on functions mangled because of return type 2020-05-20 07:19:29 +03:00
Dmitry Petrov
fcf8a91a38 Update kotlin-stdlib-runtime-merged.txt 2020-05-20 07:19:29 +03:00
Dmitry Petrov
cf70c83ab7 JVM: Update tests 2020-05-20 07:19:29 +03:00
Dmitry Petrov
2f82c5b6af JVM: Fix default parameter values handling
When we generate call for 'foo', we make decision about invoking
a 'foo$default' too late, after the call arguments are generated.
If 'foo' was an override, and base class (interface) was generic,
'foo' in base class could have a different Kotlin and JVM
signature, so the arguments we generated could be generated wrong
(primitive or inline class values instead of boxes, see KT-38680).
Also, we always selected first base class in supertypes list,
which caused KT-15971.

Look into resolved call and see if we should actually call
'foo$default' instead of 'foo' when determining actual callable.

Overrides can't introduce default parameter values, and
override-equivalent inherited methods with default parameters
is an error in a child class. Thus, if we are calling a class
member function with a default parameters, there should be one
and only one overridden function that has default parameter values
and overrides nothing.
2020-05-20 07:19:29 +03:00
Dmitry Petrov
dc9f64fc9d JVM: Fix reflection tests for new IC ABI 2020-05-20 07:19:28 +03:00
Dmitry Petrov
b5bd3604b1 JVM: Mangle functions returning inline class values
Mangling suffix is base64-encoded MD5 of ":<returnTypeFQN>"
2020-05-20 07:19:28 +03:00
Dmitry Gridin
9beb36ca2b Code style: add option for blank lines before declarations
#KT-39024 Fixed
#KT-37420 Fixed
#KT-37891 Fixed
2020-05-20 02:22:53 +00:00
Dmitry Gridin
499a02ebe3 AddThrowsAnnotationIntention: improve for mpp
#KT-38391 Fixed
2020-05-20 02:19:10 +00:00
Dmitry Gridin
8b4660031f multiPlatformSetup: cleanup code 2020-05-20 02:19:09 +00:00
Dmitry Gridin
7b079a5f1c Deprecated symbol usages: fix test 2020-05-20 09:04:46 +07:00
Vyacheslav Karpukhin
2c5e42a765 Merge branch 'rr/slava/rename-foreign-usages' 2020-05-19 18:45:59 +02:00
Mikhail Bogdanov
16b4342d92 Add minor test for SMAP
Relates to PR 3248
2020-05-19 18:34:56 +02:00
pyos
73e91af792 IDEA: test the plugin's ability to parse correct JSR-045 data 2020-05-19 18:33:27 +02:00
pyos
c51c537504 JVM: use precise line bounds when regenerating objects with no SMAPs 2020-05-19 18:33:27 +02:00
pyos
7222a732c1 JVM: treat empty SMAP instances as "skip all line numbers" 2020-05-19 18:33:27 +02:00
pyos
86b28b95ca JVM: keep call site markers when inlining lambdas into objects
A follow-up for KT-35006:

    fun f() = foo {
        bar()
    }
    inline fun foo(crossinline x: () -> Unit) = { x() }()
    inline fun bar() = TODO()

does not provide the option to navigate to bar's call site at all.
2020-05-19 18:33:27 +02:00
pyos
5feadd56ef JVM: parse KotlinDebug when regenerating anonymous objects 2020-05-19 18:33:27 +02:00
pyos
1fe7ef6521 JVM: separate the two kinds of source mappers
* a writing source mapper has `mapLineNumber(line, file, class)` that
   inserts a new SMAP entry and returns a fake line number from it;
 * a copying source mapper has `mapLineNumber(line)` that uses an
   existing SMAP to resolve the line number and call the former method
   on a different source mapper;
 * those two types are disjoint.
2020-05-19 18:33:27 +02:00
Ilya Gorbunov
143d8d1520 Minor: fix issue reference 2020-05-19 19:24:00 +03:00
Ilya Gorbunov
d37c412f76 Suppress a couple more warnings 2020-05-19 19:24:00 +03:00
Ilya Gorbunov
bf21e1282a Suppress most of unused parameter warnings 2020-05-19 19:24:00 +03:00
Dmitry Borodin
dd46d5ca5a Add sample for Map.flatMap 2020-05-19 19:24:00 +03:00
Dmitry Borodin
1a0b59da49 KT-20357 Add sortedBy() sample (#3283) 2020-05-19 19:21:21 +03:00
Vyacheslav Gerasimov
0d71758112 Build: Add miscCompilerTest task
for everything except jvmCompilerTest & jsCompilerTest
2020-05-19 18:34:38 +03:00
Victor Petukhov
eff5f3a242 NI: do type checking for anonymous functions not inside a call
^KT-38890 Fixed
^KT-38439 Fixed
2020-05-19 16:29:14 +03:00
Mark Punzalan
425ce8c3ab [FIR] Use flexible type lower bound when approximating type for
IntegerLiteral.
2020-05-19 15:42:49 +03:00
Mark Punzalan
d5141674a3 [FIR] Update GenerateRangesCodegenTestData for newly-enabled FIR tests. 2020-05-19 15:41:29 +03:00
Mark Punzalan
89d706972c [FIR] Use vararg element type when generating argument mapping. 2020-05-19 15:41:29 +03:00
Natalia Selezneva
98d3855fd8 KotlinDslModels: project can be null in ExternalSystemTaskNotificationListener.onStart
For example when project is created from sources
2020-05-19 15:04:15 +03:00
Natalia Selezneva
879fe9b493 Fix order of ExternalSystemListeners
in 201 the order of ExternalSystemListener.EP isn't guaranteed.
But we need to update script definitions and only then we can store script models,
because they need to know script definitions additional classpath
2020-05-19 15:04:14 +03:00
Natalia Selezneva
1a1bcefb2a Add debug logger to ScriptTemplatesFromDependenciesProvider
This will help with investigation of problems with script definition discovery
2020-05-19 15:04:14 +03:00
Natalia Selezneva
16b7232b4f Minor: do not associate with the same extensions multiple times in ScriptDefinitionsManager 2020-05-19 15:04:14 +03:00
Natalia Selezneva
8d22429abc Do not show notification before all definitions are loaded 2020-05-19 15:04:14 +03:00
Natalia Selezneva
1513429613 Load script definitions in IDE on project opening
This will speed up first script opening,
will avoid unexpected indexing because of new definitions
Script definitions are also needed for Kotlin scripting settings
2020-05-19 15:04:14 +03:00
Natalia Selezneva
942c8aaafc Introduce index for folders with script definitions templates
Replace it with nonBlockingReadAction meaning that if update was canceled then loading will be restarted after all write events happen
Also scanning is now started after indexing

^KT-36378 Fixed
^KT-34138 Fixed
^KT-37863 Fixed
2020-05-19 15:04:14 +03:00
Ilya Matveev
839e4ecff2 Allow passing a MessageRenderer to CLITool.mainNoExit
Earlier a system property was used to configure a message renderer
for the K/N compiler. The fix for KT-37550 requires getting rid of
using properties when the compiler is started in a Gradle process.
This patch allows us to specify a correct message renderer at
the K/N side depending on entry point used to run the compiler.

 Issue #KT-37550
2020-05-19 18:57:41 +07:00
Ilya Matveev
5287ffb4a5 [Native] Don't use konan.home to determine a path to the K/N dist
A fix for KT-37550 requires us to stop using system properties when
the compiler is started from Gradle. This patch stops reading the
konan.home property to determine a path to the compiler and requires
this path to be explicitly specified in a constructor of the
Distribution class.

Issue #KT-37550
2020-05-19 18:57:39 +07:00
Ilya Matveev
8e3a62e5fd [Gradle] Get rid of java.library.path when running the K/N compiler
Issue #KT-37550
2020-05-19 18:57:37 +07:00
Dmitry Gridin
0df5d5158d Add resources-en for idea
#KT-38297 Fixed
2020-05-19 16:22:06 +07:00
Dmitry Gridin
12217ef2ab Add regression test for ReplaceWith
#KT-35015 Fixed
2020-05-19 16:15:13 +07:00
Toshiaki Kameyama
02c17378b1 Replace deprecated symbol usage: replace imported object function correctly
#KT-33951 Fixed
2020-05-19 15:40:59 +07:00
Dmitry Gridin
b2be1a53cf SpecifyTypeExplicitlyIntention: remove annotations from result type
#KT-36930 Fixed
2020-05-19 01:17:39 +00:00
Vyacheslav Karpukhin
1ba4d7d99b Update foreign references when renaming a Kotlin file
(cherry picked from commit 1571a87d8f)
2020-05-15 19:45:14 +02:00
Vyacheslav Karpukhin
ba993ba0fe Provide an extension point that allows plugins to handle renaming of references in other languages 2020-04-29 20:56:46 +02:00
5815 changed files with 145735 additions and 50105 deletions

6
.bunch
View File

@@ -1,7 +1,7 @@
193
201
202_201
192
191_192
as35_191_192
as36_192
as40
as40
as41_201

View File

@@ -1,11 +1,14 @@
<component name="ProjectDictionaryState">
<dictionary name="dmitriy.dolovov">
<words>
<w>commonizable</w>
<w>commonization</w>
<w>commonize</w>
<w>commonized</w>
<w>commonizer</w>
<w>commonizers</w>
<w>commonizes</w>
<w>jetbrains</w>
<w>konan</w>
</words>
</dictionary>

2
.idea/misc.xml generated
View File

@@ -66,7 +66,7 @@
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="PsiViewerSettings">

View File

@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
@@ -66,10 +66,10 @@ private val JDK_PATH = File("${System.getProperty("java.home")!!}/lib/rt.jar")
private val RUNTIME_JAR = File(System.getProperty("kotlin.runtime.path") ?: "dist/kotlinc/lib/kotlin-runtime.jar")
private val LANGUAGE_FEATURE_SETTINGS =
LanguageVersionSettingsImpl(
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(LanguageFeature.NewInference to LanguageFeature.State.ENABLED)
)
LanguageVersionSettingsImpl(
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(LanguageFeature.NewInference to LanguageFeature.State.ENABLED)
)
private fun newConfiguration(useNewInference: Boolean): CompilerConfiguration {
val configuration = CompilerConfiguration()
@@ -81,10 +81,10 @@ private fun newConfiguration(useNewInference: Boolean): CompilerConfiguration {
val newInferenceState = if (useNewInference) LanguageFeature.State.ENABLED else LanguageFeature.State.DISABLED
configuration.languageVersionSettings = LanguageVersionSettingsImpl(
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(
LanguageFeature.NewInference to newInferenceState
)
LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3,
specificFeatures = mapOf(
LanguageFeature.NewInference to newInferenceState
)
)
return configuration
}
@@ -105,21 +105,21 @@ abstract class AbstractSimpleFileBenchmark {
fun setUp() {
if (isIR && !useNewInference) error("Invalid configuration")
env = KotlinCoreEnvironment.createForTests(
myDisposable,
newConfiguration(useNewInference),
EnvironmentConfigFiles.JVM_CONFIG_FILES
myDisposable,
newConfiguration(useNewInference),
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
if (isIR) {
Extensions.getArea(env.project)
.getExtensionPoint(PsiElementFinder.EP_NAME)
.unregisterExtension(JavaElementFinder::class.java)
.getExtensionPoint(PsiElementFinder.EP_NAME)
.unregisterExtension(JavaElementFinder::class.java)
}
file = createFile(
"test.kt",
buildText(),
env.project
"test.kt",
buildText(),
env.project
)
}
@@ -134,22 +134,22 @@ abstract class AbstractSimpleFileBenchmark {
private fun analyzeGreenFileFrontend(bh: Blackhole) {
val tracker = ExceptionTracker()
val storageManager: StorageManager =
LockBasedStorageManager.createWithExceptionHandling("benchmarks", tracker)
LockBasedStorageManager.createWithExceptionHandling("benchmarks", tracker)
val context = SimpleGlobalContext(storageManager, tracker)
val module =
ModuleDescriptorImpl(
Name.special("<benchmark>"), storageManager,
JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_DEPENDENCIES)
)
ModuleDescriptorImpl(
Name.special("<benchmark>"), storageManager,
JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_DEPENDENCIES)
)
val moduleContext = context.withProject(env.project).withModule(module)
val result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
moduleContext.project,
listOf(file),
NoScopeRecordCliBindingTrace(),
env.configuration,
{ scope -> JvmPackagePartProvider(LANGUAGE_FEATURE_SETTINGS, scope) }
moduleContext.project,
listOf(file),
NoScopeRecordCliBindingTrace(),
env.configuration,
{ scope -> JvmPackagePartProvider(LANGUAGE_FEATURE_SETTINGS, scope) }
)
assert(result.bindingContext.diagnostics.none { it.severity == Severity.ERROR })
@@ -159,17 +159,15 @@ abstract class AbstractSimpleFileBenchmark {
private fun analyzeGreenFileIr(bh: Blackhole) {
val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile))
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project))
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project))
val session = createSession(env, scope)
val firProvider = session.firProvider as FirProviderImpl
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, stubMode = false)
val totalTransformer = FirTotalResolveTransformer()
val totalTransformer = FirTotalResolveProcessor(session)
val firFile = builder.buildFirFile(file).also(firProvider::recordFile)
for (transformer in totalTransformer.transformers) {
transformer.transformFile(firFile, null)
}
totalTransformer.process(listOf(firFile))
bh.consume(firFile.hashCode())
}
@@ -178,37 +176,37 @@ abstract class AbstractSimpleFileBenchmark {
}
fun createSession(
environment: KotlinCoreEnvironment,
sourceScope: GlobalSearchScope,
librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope)
environment: KotlinCoreEnvironment,
sourceScope: GlobalSearchScope,
librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope)
): FirSession {
val moduleInfo = FirTestModuleInfo()
val project = environment.project
val provider = FirProjectSessionProvider(project)
return FirJavaModuleBasedSession(moduleInfo, provider, sourceScope).also {
return FirJavaModuleBasedSession.create(moduleInfo, provider, sourceScope).also {
createSessionForDependencies(provider, moduleInfo, librariesScope, environment)
}
}
private fun createSessionForDependencies(
provider: FirProjectSessionProvider,
moduleInfo: FirTestModuleInfo,
librariesScope: GlobalSearchScope,
environment: KotlinCoreEnvironment
provider: FirProjectSessionProvider,
moduleInfo: FirTestModuleInfo,
librariesScope: GlobalSearchScope,
environment: KotlinCoreEnvironment
) {
val dependenciesInfo = FirTestModuleInfo()
moduleInfo.dependencies.add(dependenciesInfo)
FirLibrarySession.create(
dependenciesInfo, provider, librariesScope, environment.project,
environment.createPackagePartProvider(librariesScope)
dependenciesInfo, provider, librariesScope, environment.project,
environment.createPackagePartProvider(librariesScope)
)
}
class FirTestModuleInfo(
override val name: Name = Name.identifier("TestModule"),
val dependencies: MutableList<ModuleInfo> = mutableListOf(),
override val platform: TargetPlatform = JvmPlatforms.unspecifiedJvmPlatform,
override val analyzerServices: PlatformDependentAnalyzerServices = JvmPlatformAnalyzerServices
override val name: Name = Name.identifier("TestModule"),
val dependencies: MutableList<ModuleInfo> = mutableListOf(),
override val platform: TargetPlatform = JvmPlatforms.unspecifiedJvmPlatform,
override val analyzerServices: PlatformDependentAnalyzerServices = JvmPlatformAnalyzerServices
) : ModuleInfo {
override fun dependencies(): List<ModuleInfo> = dependencies
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 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.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental

View File

@@ -1,81 +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.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.KeyDescriptor
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class BasicMap<K : Comparable<K>, V>(
internal val storageFile: File,
keyDescriptor: KeyDescriptor<K>,
valueExternalizer: DataExternalizer<V>
) {
protected val storage = LazyStorage(storageFile, keyDescriptor, valueExternalizer)
fun clean() {
storage.clean()
}
fun flush(memoryCachesOnly: Boolean) {
storage.flush(memoryCachesOnly)
}
fun close() {
storage.close()
}
@TestOnly
fun dump(): String {
return with(StringBuilder()) {
with(Printer(this)) {
println(this@BasicMap::class.java.simpleName)
pushIndent()
for (key in storage.keys.sorted()) {
println("${dumpKey(key)} -> ${dumpValue(storage[key]!!)}")
}
popIndent()
}
this
}.toString()
}
@TestOnly
protected abstract fun dumpKey(key: K): String
@TestOnly
protected abstract fun dumpValue(value: V): String
}
abstract class BasicStringMap<V>(
storageFile: File,
keyDescriptor: KeyDescriptor<String>,
valueExternalizer: DataExternalizer<V>
) : BasicMap<String, V>(storageFile, keyDescriptor, valueExternalizer) {
constructor(
storageFile: File,
valueExternalizer: DataExternalizer<V>
) : this(storageFile, EnumeratorStringDescriptor.INSTANCE, valueExternalizer)
override fun dumpKey(key: String): String = key
}

View File

@@ -1,55 +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.incremental.storage
import org.jetbrains.kotlin.incremental.dumpCollection
import org.jetbrains.kotlin.name.FqName
import java.io.File
internal open class ClassOneToManyMap(
storageFile: File
) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
fun add(key: FqName, value: FqName) {
storage.append(key.asString(), value.asString())
}
operator fun get(key: FqName): Collection<FqName> =
storage[key.asString()]?.map(::FqName) ?: setOf()
operator fun set(key: FqName, values: Collection<FqName>) {
if (values.isEmpty()) {
remove(key)
return
}
storage[key.asString()] = values.map(FqName::asString)
}
fun remove(key: FqName) {
storage.remove(key.asString())
}
fun removeValues(key: FqName, removed: Set<FqName>) {
val notRemoved = this[key].filter { it !in removed }
this[key] = notRemoved
}
}
internal class SubtypesMap(storageFile: File) : ClassOneToManyMap(storageFile)
internal class SupertypesMap(storageFile: File) : ClassOneToManyMap(storageFile)

View File

@@ -1,122 +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.incremental.storage
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.IOUtil
import com.intellij.util.io.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.DataOutput
import java.io.File
import java.io.IOException
/**
* It's lazy in a sense that PersistentHashMap is created only on write
*/
class LazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) {
@Volatile
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
if (storageFile.exists()) {
storage = createMap()
return storage
}
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
fun append(key: K, value: String) {
append(key) { out -> IOUtil.writeUTF(out, value) }
}
fun append(key: K, value: Int) {
append(key) { out -> out.writeInt(value) }
}
@Synchronized
fun clean() {
try {
storage?.close()
}
catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
}
else {
existingStorage.force()
}
}
@Synchronized
fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
private fun append(key: K, append: (DataOutput)->Unit) {
getStorageOrCreateNew().appendData(key, append)
}
}

View File

@@ -1,42 +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.incremental.storage
import java.io.File
internal class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<Int>>(storage, LookupSymbolKeyDescriptor, IntCollectionExternalizer) {
override fun dumpKey(key: LookupSymbolKey): String = key.toString()
override fun dumpValue(value: Collection<Int>): String = value.toString()
fun add(name: String, scope: String, fileId: Int) {
storage.append(LookupSymbolKey(name, scope), fileId)
}
operator fun get(key: LookupSymbolKey): Collection<Int>? = storage[key]
operator fun set(key: LookupSymbolKey, fileIds: Set<Int>) {
storage[key] = fileIds
}
fun remove(key: LookupSymbolKey) {
storage.remove(key)
}
val keys: Collection<LookupSymbolKey>
get() = storage.keys
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2010-2017 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.incremental.storage
import org.jetbrains.kotlin.incremental.dumpCollection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
internal class SourceToJvmNameMap(
storageFile: File,
pathConverter: FileToPathConverter
) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile, pathConverter)
internal class SourceToFqNameMap(
storageFile: File,
pathConverter: FileToPathConverter
) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile, pathConverter)
internal abstract class AbstractSourceToOutputMap<Name>(
private val nameTransformer: NameTransformer<Name>,
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
fun clearOutputsForSource(sourceFile: File) {
remove(pathConverter.toPath(sourceFile))
}
fun add(sourceFile: File, className: Name) {
storage.append(pathConverter.toPath(sourceFile), nameTransformer.asString(className))
}
fun contains(sourceFile: File): Boolean =
pathConverter.toPath(sourceFile) in storage
operator fun get(sourceFile: File): Collection<Name> =
storage[pathConverter.toPath(sourceFile)].orEmpty().map(nameTransformer::asName)
fun getFqNames(sourceFile: File): Collection<FqName> =
storage[pathConverter.toPath(sourceFile)].orEmpty().map(nameTransformer::asFqName)
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()
private fun remove(path: String) {
storage.remove(path)
}
}

View File

@@ -1,4 +1,5 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.crypto.checksum.Checksum
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import proguard.gradle.ProGuardTask
@@ -42,6 +43,8 @@ plugins {
idea
id("jps-compatible")
id("org.jetbrains.gradle.plugin.idea-ext")
id("org.gradle.crypto.checksum") version "1.2.0"
signing
}
pill {
@@ -163,7 +166,7 @@ extra["versions.junit"] = "4.12"
extra["versions.javaslang"] = "2.0.6"
extra["versions.ant"] = "1.8.2"
extra["versions.android"] = "2.3.1"
val coroutinesVersion = if (Platform[192].orHigher()) "1.2.1" else "1.1.1"
val coroutinesVersion = if (Platform[192].orHigher()) "1.3.7" else "1.1.1"
extra["versions.kotlinx-coroutines-core"] = coroutinesVersion
extra["versions.kotlinx-coroutines-jdk8"] = coroutinesVersion
extra["versions.json"] = "20160807"
@@ -184,7 +187,7 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.4-M3-dev-15453"
extra["versions.kotlin-native"] = "1.4-M3-dev-15627"
}
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
@@ -276,6 +279,28 @@ extra["compilerModules"] = arrayOf(
":compiler:fir:analysis-tests"
)
extra["compilerModulesForJps"] = listOf(
":core:type-system",
":kotlin-build-common",
":kotlin-util-io",
":kotlin-util-klib",
":kotlin-util-klib-metadata",
":compiler:cli-common",
":kotlin-compiler-runner",
":daemon-common",
":daemon-common-new",
":core:descriptors",
":core:descriptors.jvm",
":idea:idea-jps-common",
":kotlin-preloader",
":compiler:util",
":compiler:config",
":compiler:config.jvm",
":js:js.config",
":core:util.runtime",
":compiler:compiler.version"
)
val coreLibProjects = listOfNotNull(
":kotlin-stdlib",
":kotlin-stdlib-common",
@@ -595,7 +620,7 @@ tasks {
register("scriptingTest") {
dependsOn("dist")
dependsOn(":kotlin-script-util:test")
dependsOn(":kotlin-scripting-compiler:test")
dependsOn(":kotlin-scripting-compiler-embeddable:test")
dependsOn(":kotlin-scripting-common:test")
dependsOn(":kotlin-scripting-jvm:test")
dependsOn(":kotlin-scripting-jvm-host-test:test")
@@ -613,6 +638,10 @@ tasks {
register("compilerTest") {
dependsOn("jvmCompilerTest")
dependsOn("jsCompilerTest")
dependsOn("miscCompilerTest")
}
register("miscCompilerTest") {
dependsOn("wasmCompilerTest")
dependsOn("nativeCompilerTest")
dependsOn("firCompilerTest")
@@ -745,6 +774,37 @@ tasks {
)
}
register("publishIdeArtifacts") {
idePluginDependency {
dependsOn(
":prepare:ide-plugin-dependencies:android-extensions-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:allopen-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:allopen-compiler-plugin-tests-for-ide:publish",
":prepare:ide-plugin-dependencies:incremental-compilation-impl-tests-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlin-build-common-tests-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlin-compiler-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlin-dist-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlin-gradle-statistics-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlinx-serialization-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:compiler-components-for-jps:publish",
":kotlin-script-runtime:publish",
":kotlin-script-util:publish",
":kotlin-scripting-common:publish",
":kotlin-scripting-jvm:publish",
":kotlin-scripting-compiler:publish",
":kotlin-scripting-compiler-impl:publish",
":kotlin-android-extensions-runtime:publish",
":kotlin-stdlib-common:publish",
":kotlin-stdlib:publish",
":kotlin-stdlib-jdk7:publish",
":kotlin-stdlib-jdk8:publish",
":kotlin-reflect:publish",
":kotlin-main-kts:publish"
)
}
}
register("test") {
doLast {
@@ -772,15 +832,15 @@ fun CopySpec.setExecutablePermissions() {
val zipCompiler by task<Zip> {
dependsOn(dist)
destinationDir = file(distDir)
archiveName = "kotlin-compiler-$kotlinVersion.zip"
destinationDirectory.set(file(distDir))
archiveFileName.set("kotlin-compiler-$kotlinVersion.zip")
from(distKotlinHomeDir)
into("kotlinc")
setExecutablePermissions()
doLast {
logger.lifecycle("Compiler artifacts packed to $archivePath")
logger.lifecycle("Compiler artifacts packed to ${archiveFile.get().asFile.absolutePath}")
}
}
@@ -830,6 +890,33 @@ val zipPlugin by task<Zip> {
}
}
fun Project.secureZipTask(zipTask: TaskProvider<Zip>): RegisteringDomainObjectDelegateProviderWithAction<out TaskContainer, Task> {
val checkSumTask = tasks.register("${zipTask.name}Checksum", Checksum::class) {
dependsOn(zipTask)
val compilerFile = zipTask.get().outputs.files.singleFile
files = files(compilerFile)
outputDir = compilerFile.parentFile
algorithm = Checksum.Algorithm.SHA256
}
val signTask = tasks.register("${zipTask.name}Sign", Sign::class) {
description = "Signs the archive produced by the '" + zipTask.name + "' task."
sign(zipTask.get())
}
return tasks.registering {
dependsOn(checkSumTask)
dependsOn(signTask)
}
}
signing {
useGpgCmd()
}
val zipCompilerWithSignature by secureZipTask(zipCompiler)
val zipPluginWithSignature by secureZipTask(zipPlugin)
configure<IdeaModel> {
module {
excludeDirs = files(

View File

@@ -5,8 +5,7 @@ buildscript {
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
extra["defaultSnapshotVersion"] = kotlinBuildProperties.defaultSnapshotVersion
BootstrapOption.BintrayBootstrap("1.4.0-dev-1818", cacheRedirectorEnabled).applyToProject(project)
// kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap(kotlinBuildProperties.kotlinBootstrapVersion!!, cacheRedirectorEnabled))
kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap(kotlinBuildProperties.kotlinBootstrapVersion!!, cacheRedirectorEnabled))
repositories {
if (cacheRedirectorEnabled) {
@@ -73,7 +72,6 @@ rootProject.apply {
val isTeamcityBuild = kotlinBuildProperties.isTeamcityBuild
val intellijUltimateEnabled by extra(kotlinBuildProperties.intellijUltimateEnabled)
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
val verifyDependencyOutput by extra( getBooleanProperty("kotlin.build.dependency.output.verification") ?: isTeamcityBuild)
extra["intellijReleaseType"] = when {
extra["versions.intellijSdk"]?.toString()?.contains("-EAP-") == true -> "snapshots"

View File

@@ -1,8 +0,0 @@
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m -Dfile.encoding=UTF-8
cacheRedirectorEnabled=true
#buildSrc.kotlin.repo=https://jcenter.bintray.com
#buildSrc.kotlin.version=1.1.50
intellijUltimateEnabled=false

View File

@@ -1,8 +0,0 @@
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m -Dfile.encoding=UTF-8
cacheRedirectorEnabled=true
#buildSrc.kotlin.repo=https://jcenter.bintray.com
#buildSrc.kotlin.version=1.1.50
intellijUltimateEnabled=false

View File

@@ -1,8 +0,0 @@
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m -Dfile.encoding=UTF-8
cacheRedirectorEnabled=true
#buildSrc.kotlin.repo=https://jcenter.bintray.com
#buildSrc.kotlin.version=1.1.50
intellijUltimateEnabled=false

View File

@@ -2,7 +2,6 @@
import org.gradle.internal.os.OperatingSystem
import java.io.Closeable
import java.io.FileWriter
import java.io.OutputStreamWriter
import java.net.URI
import java.text.SimpleDateFormat
@@ -10,13 +9,13 @@ import java.util.*
import javax.xml.stream.XMLOutputFactory
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
import java.time.Duration
import java.time.Instant
plugins {
base
}
val verifyDependencyOutput: Boolean by rootProject.extra
val intellijUltimateEnabled: Boolean by rootProject.extra
val intellijReleaseType: String by rootProject.extra
val intellijVersion = rootProject.extra["versions.intellijSdk"] as String
@@ -25,7 +24,7 @@ val androidStudioRelease = rootProject.findProperty("versions.androidStudioRelea
val androidStudioBuild = rootProject.findProperty("versions.androidStudioBuild") as String?
val intellijSeparateSdks: Boolean by rootProject.extra
val installIntellijCommunity = !intellijUltimateEnabled || intellijSeparateSdks
val installIntellijUltimate = intellijUltimateEnabled
val installIntellijUltimate = intellijUltimateEnabled && androidStudioRelease == null
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
if (intellijVersionDelimiterIndex == -1) {
@@ -34,7 +33,6 @@ if (intellijVersionDelimiterIndex == -1) {
val platformBaseVersion = intellijVersion.substring(0, intellijVersionDelimiterIndex)
logger.info("verifyDependencyOutput: $verifyDependencyOutput")
logger.info("intellijUltimateEnabled: $intellijUltimateEnabled")
logger.info("intellijVersion: $intellijVersion")
logger.info("androidStudioRelease: $androidStudioRelease")
@@ -145,21 +143,7 @@ dependencies {
}
}
val cleanupIntellijCore = tasks.register<CleanDataTask>("cleanupIntellijCore") {
cleanableStoreProvider = provider { CleanableStore[repoDir.resolve("intellij-core").absolutePath] }
}
val cleanupIntellijAnnotation = tasks.register<CleanDataTask>("cleanupIntellijAnnotation") {
cleanableStoreProvider = provider { CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath] }
}
val cleanupDependencies = tasks.register("cleanupDependencies") {
dependsOn(cleanupIntellijCore)
dependsOn(cleanupIntellijAnnotation)
}
val makeIntellijCore = buildIvyRepositoryTaskAndRegisterCleanupTask(intellijCore, customDepsOrg, customDepsRepoDir)
val makeIntellijCore = buildIvyRepositoryTask(intellijCore, customDepsOrg, customDepsRepoDir)
val makeIntellijAnnotations by tasks.registering(Copy::class) {
dependsOn(makeIntellijCore)
@@ -167,12 +151,17 @@ val makeIntellijAnnotations by tasks.registering(Copy::class) {
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
val targetDir = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath][intellijVersion].use()
val annotationsStore = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath]
val targetDir = annotationsStore[intellijVersion].use()
into(targetDir)
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
outputs.files(ivyFile)
doFirst {
annotationsStore.cleanStore()
}
doLast {
writeIvyXml(
customDepsOrg,
@@ -191,7 +180,9 @@ val mergeSources by tasks.creating(Jar::class.java) {
dependsOn(sources)
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
from(provider { sources.map(::zipTree) })
if (!kotlinBuildProperties.isTeamcityBuild) {
from(provider { sources.map(::zipTree) })
}
destinationDirectory.set(File(repoDir, sources.name))
archiveBaseName.set("intellij")
archiveClassifier.set("sources")
@@ -201,7 +192,7 @@ val mergeSources by tasks.creating(Jar::class.java) {
val sourcesFile = mergeSources.outputs.files.singleFile
val makeIde = if (androidStudioBuild != null) {
buildIvyRepositoryTaskAndRegisterCleanupTask(
buildIvyRepositoryTask(
androidStudio,
customDepsOrg,
customDepsRepoDir,
@@ -212,9 +203,9 @@ val makeIde = if (androidStudioBuild != null) {
)
} else {
val task = if (installIntellijUltimate) {
buildIvyRepositoryTaskAndRegisterCleanupTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
buildIvyRepositoryTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
} else {
buildIvyRepositoryTaskAndRegisterCleanupTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
buildIvyRepositoryTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
}
task.configure {
@@ -224,7 +215,7 @@ val makeIde = if (androidStudioBuild != null) {
task
}
val buildJpsStandalone = buildIvyRepositoryTaskAndRegisterCleanupTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
tasks.named("build") {
dependsOn(
@@ -238,24 +229,15 @@ tasks.named("build") {
if (installIntellijUltimate) {
val buildNodeJsPlugin =
buildIvyRepositoryTaskAndRegisterCleanupTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
buildIvyRepositoryTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") { dependsOn(buildNodeJsPlugin) }
}
tasks.named("build") { dependsOn(cleanupDependencies) }
// Task to delete legacy repo locations
tasks.register<Delete>("cleanLegacy") {
delete("$projectDir/android-dx")
delete("$projectDir/intellij-sdk")
}
tasks.named<Delete>("clean") {
//TODO specify repos to clean? Use CleanDataTask
delete(customDepsRepoDir)
}
fun buildIvyRepositoryTaskAndRegisterCleanupTask(
fun buildIvyRepositoryTask(
configuration: Configuration,
organization: String,
repoDirectory: File,
@@ -268,29 +250,29 @@ fun buildIvyRepositoryTaskAndRegisterCleanupTask(
fun ResolvedArtifact.moduleDirectory(): File =
storeDirectory()[moduleVersion.id.version].use()
val buildIvyRepositoryTask = tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
return tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
dependsOn(configuration)
inputs.files(configuration)
if (verifyDependencyOutput) {
outputs.dir(
provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory()
}
)
} else {
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
doFirst {
configuration.resolvedConfiguration.resolvedArtifacts.single().run {
val moduleDirectory = moduleDirectory()
val artifactsDirectory = File(moduleDirectory(), "artifacts")
val artifact = configuration.resolvedConfiguration.resolvedArtifacts.single()
val moduleDirectory = artifact.moduleDirectory()
artifact.storeDirectory().cleanStore()
if (moduleDirectory.exists()) {
logger.info("Path ${moduleDirectory.absolutePath} already exists, skipping unpacking.")
return@doFirst
}
with(artifact) {
val artifactsDirectory = File(moduleDirectory, "artifacts")
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
copy {
val fileTree = when (extension) {
@@ -347,20 +329,10 @@ fun buildIvyRepositoryTaskAndRegisterCleanupTask(
}
}
}
val cleanupIvyRepositoryTask = tasks.register<CleanDataTask>("cleanupIvyRepositoryFor${configuration.name.capitalize()}") {
cleanableStoreProvider = provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().storeDirectory()
}
}
cleanupDependencies {
dependsOn(cleanupIvyRepositoryTask)
}
return buildIvyRepositoryTask
}
fun CleanableStore.cleanStore() = cleanDir(Instant.now().minus(Duration.ofDays(30)))
fun writeIvyXml(
organization: String,
moduleName: String,

View File

@@ -27,8 +27,6 @@ buildscript {
def buildProperties = BuildPropertiesKt.getKotlinBuildPropertiesForSettings(settings)
def projectVersions = file("../gradle/versions.properties").text
BuildCacheKt.setupBuildCache(settings)
include "prepare-deps"
def target_AppCode_Clion = buildProperties.includeCidrPlugins && !projectVersions.contains("versions.androidStudioRelease")

View File

@@ -26,7 +26,7 @@ fun CompatibilityPredicate.or(other: CompatibilityPredicate): CompatibilityPredi
}
enum class Platform : CompatibilityPredicate {
P183, P191, P192, P193, P201;
P183, P191, P192, P193, P201, P202;
val version: Int = name.drop(1).toInt()
@@ -47,10 +47,12 @@ enum class Ide(val platform: Platform) : CompatibilityPredicate {
IJ192(Platform.P192),
IJ193(Platform.P193),
IJ201(Platform.P201),
IJ202(Platform.P202),
AS35(Platform.P183),
AS36(Platform.P192),
AS40(Platform.P193);
AS40(Platform.P193),
AS41(Platform.P201);
val kind = Kind.values().first { it.shortName == name.take(2) }
val version = name.dropWhile { !it.isDigit() }.toInt()

View File

@@ -9,10 +9,12 @@ import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.jvm.tasks.Jar
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.kotlin.dsl.*
@@ -155,6 +157,81 @@ fun Project.publish(body: Upload.() -> Unit = {}): Upload {
}
}
fun Project.idePluginDependency(block: () -> Unit) {
val shouldActivate = rootProject.findProperty("publish.ide.plugin.dependencies")?.toString()?.toBoolean() == true
if (shouldActivate) {
block()
}
}
fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List<String> = emptyList()) {
apply<JavaPlugin>()
val fatJarContents by configurations.creating
dependencies {
for (projectName in projects) {
fatJarContents(project(projectName)) { isTransitive = false }
}
for (libraryDependency in libraryDependencies) {
fatJarContents(libraryDependency)
}
}
publish()
val jar: Jar by tasks
jar.apply {
dependsOn(fatJarContents)
from {
fatJarContents.map(::zipTree)
}
}
sourcesJar {
from {
projects.map {
project(it).mainSourceSet.allSource
}
}
}
javadocJar()
}
fun Project.publishTestJar(projectName: String) {
apply<JavaPlugin>()
val fatJarContents by configurations.creating
dependencies {
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
}
publish()
val jar: Jar by tasks
jar.apply {
dependsOn(fatJarContents)
from {
fatJarContents.map(::zipTree)
}
}
sourcesJar {
from {
project(projectName).testSourceSet.allSource
}
}
javadocJar()
}
fun ConfigurationContainer.getOrCreate(name: String): Configuration = findByName(name) ?: create(name)
fun Jar.setupPublicJar(baseName: String, classifier: String = "") {

View File

@@ -20,7 +20,6 @@ val packagesToRelocate =
"org.picocontainer",
"org.jline",
"org.fusesource",
"kotlinx.coroutines",
"net.jpountz",
"one.util.streamex",
"kotlinx.collections.immutable"

View File

@@ -106,6 +106,7 @@ fun Project.projectTest(
environment("PROJECT_BUILD_DIR", buildDir)
systemProperty("jps.kotlin.home", rootProject.extra["distKotlinHomeDir"]!!)
systemProperty("kotlin.ni", if (rootProject.hasProperty("newInferenceTests")) "true" else "false")
systemProperty("org.jetbrains.kotlin.skip.muted.tests", if (rootProject.hasProperty("skipMutedTests")) "true" else "false")
var subProjectTempRoot: Path? = null
doFirst {

View File

@@ -100,9 +100,11 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
File("./gradlew.bat").copyTo(File(projectRoot, "gradlew.bat"));
val file = File(target, "gradle-wrapper.properties")
file.readLines().map {
if (it.startsWith("distributionUrl"))
"distributionUrl=https\\://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip"
else it
when {
it.startsWith("distributionUrl") -> "distributionUrl=https\\://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip"
it.startsWith("distributionSha256Sum") -> "distributionSha256Sum=$GRADLE_SHA_256"
else -> it
}
}.let { lines ->
FileWriter(file).use { fw ->
lines.forEach { line ->
@@ -315,7 +317,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM)
companion object {
const val GRADLE_VERSION = "5.6.4"
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change
const val GRADLE_SHA_256 = "1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d"
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
const val testClassName = "CodegenTestCaseOnAndroid"
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"

View File

@@ -17,11 +17,13 @@
package org.jetbrains.kotlin.codegen
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.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
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
@@ -35,10 +37,10 @@ abstract class ArgumentGenerator {
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
*/
open fun generate(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// may be null for a constructor of an object literal
calleeDescriptor: CallableDescriptor?
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// may be null for a constructor of an object literal
calleeDescriptor: CallableDescriptor?
): DefaultCallArgs {
assert(valueArgumentsByIndex.size == actualArgs.size) {
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
@@ -50,9 +52,9 @@ abstract class ArgumentGenerator {
ArgumentAndDeclIndex(it, arg2Index[it]!!)
}.toMutableList()
valueArgumentsByIndex.withIndex().forEach {
if (it.value is DefaultValueArgument) {
actualArgsWithDeclIndex.add(it.index, ArgumentAndDeclIndex(it.value, it.index))
for ((index, value) in valueArgumentsByIndex.withIndex()) {
if (value is DefaultValueArgument) {
actualArgsWithDeclIndex.add(index, ArgumentAndDeclIndex(value, index))
}
}
@@ -70,8 +72,7 @@ abstract class ArgumentGenerator {
is DefaultValueArgument -> {
if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) {
generateDefaultJava(declIndex, argument)
}
else {
} else {
defaultArgs.mark(declIndex)
generateDefault(declIndex, argument)
}
@@ -116,11 +117,42 @@ 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()
}
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
// We are calling a function with some arguments mapped as defaults.
// Multiple override-equivalent functions from different supertypes with (potentially different) default values
// can't be overridden by any function in a subtype.
// Also, a function overriding some other function can't introduce default parameter values.
// Thus, among all overridden functions should be one (and only one) function
// that doesn't override anything and has parameters with default values.
return functionDescriptor.overriddenTreeUniqueAsSequence(true)
.firstOrNull { function ->
function.kind == CallableMemberDescriptor.Kind.DECLARATION &&
function.overriddenDescriptors.isEmpty() &&
function.valueParameters.any { valueParameter -> valueParameter.hasDefaultValue() }
}
?: functionDescriptor
}

View File

@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -20,7 +19,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer
class CallableMethod(
override val owner: Type,
private val defaultImplOwner: Type?,
computeDefaultMethodDesc: () -> String,
computeDefaultMethod: () -> Method,
private val signature: JvmMethodSignature,
val invokeOpcode: Int,
override val dispatchReceiverType: Type?,
@@ -32,7 +31,10 @@ class CallableMethod(
val isInterfaceMethod: Boolean,
private val isDefaultMethodInInterface: Boolean
) : Callable {
private val defaultMethodDesc: String by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethodDesc)
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
private val defaultImplMethodName: String get() = defaultImplMethod.name
private val defaultMethodDesc: String get() = defaultImplMethod.descriptor
fun getValueParameters(): List<JvmMethodParameterSignature> =
signature.valueParameters
@@ -68,10 +70,14 @@ class CallableMethod(
} else {
v.visitMethodInsn(
INVOKESTATIC, defaultImplOwner.internalName,
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, isDefaultMethodInInterface
defaultImplMethodName, defaultMethodDesc, isDefaultMethodInInterface
)
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
StackValue.coerce(
Type.getReturnType(defaultMethodDesc),
Type.getReturnType(signature.asmMethod.descriptor),
v
)
}
}

View File

@@ -54,7 +54,6 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.CallableReferenceUtilKt.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.initDefaultSourceMappingIfNeeded;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -170,7 +169,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
superInterfaceAsmTypes
);
initDefaultSourceMappingIfNeeded(context, this, state);
initDefaultSourceMappingIfNeeded();
v.visitSource(element.getContainingFile().getName(), null);
}
@@ -260,7 +259,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
assert method != null : "No method for " + frontendFunDescriptor;
FunctionDescriptor freeLambdaDescriptor = FakeDescriptorsForReferencesKt.createFreeFakeLambdaDescriptor(frontendFunDescriptor);
FunctionDescriptor freeLambdaDescriptor = FakeDescriptorsForReferencesKt.createFreeFakeLambdaDescriptor(
frontendFunDescriptor, state.getTypeApproximator()
);
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
DescriptorSerializer serializer =
@@ -407,7 +408,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
if (generateBody) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
CallableReferenceUtilKt.generateCallableReferenceSignature(iv, descriptor, state);
CallableReferenceUtilKt.generateFunctionReferenceSignature(iv, descriptor, state);
iv.areturn(JAVA_STRING_TYPE);
FunctionCodegen.endVisit(iv, "function reference getSignature", element);
}
@@ -465,7 +466,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
assert functionReferenceTarget != null : "No function reference target: " + funDescriptor;
generateCallableReferenceDeclarationContainerClass(iv, functionReferenceTarget, state);
iv.aconst(functionReferenceTarget.getName().asString());
CallableReferenceUtilKt.generateCallableReferenceSignature(iv, functionReferenceTarget, state);
CallableReferenceUtilKt.generateFunctionReferenceSignature(iv, functionReferenceTarget, state);
int flags =
getCallableReferenceTopLevelFlag(functionReferenceTarget) +
(calculateFunctionReferenceFlags(functionReferenceCall, funDescriptor) << 1);

View File

@@ -219,6 +219,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return parentCodegen;
}
@NotNull
public KotlinTypeMapper getTypeMapper() {
return typeMapper;
}
@NotNull
public ObjectLiteralResult generateObjectLiteral(@NotNull KtObjectLiteralExpression literal) {
KtObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
@@ -2561,7 +2566,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return intrinsic.toCallable(fd, superCall, resolvedCall, this);
}
return typeMapper.mapToCallableMethod(SamCodegenUtil.resolveSamAdapter(fd), superCall, null, resolvedCall);
fd = SamCodegenUtil.resolveSamAdapter(fd);
if (ArgumentGeneratorKt.shouldInvokeDefaultArgumentsStub(resolvedCall)) {
// 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
// (see KT-38681 and related issues).
// Here we replace a function with a corresponding overridden function,
// and the rest is figured out by argument generation and type mapper.
fd = ArgumentGeneratorKt.getFunctionWithDefaultArguments(fd);
}
return typeMapper.mapToCallableMethod(fd, superCall, null, resolvedCall);
}
public void invokeMethodWithArguments(

View File

@@ -1038,10 +1038,7 @@ public class FunctionCodegen {
// or all return types are supertypes of inline class (and can't be inline classes).
for (DescriptorBasedFunctionHandleForJvm handle : bridge.getOriginalFunctions()) {
KotlinType returnType = handle.getDescriptor().getReturnType();
if (returnType != null) {
return returnType;
}
return state.getTypeMapper().getReturnValueType(handle.getDescriptor());
}
if (state.getClassBuilderMode().mightBeIncorrectCode) {
@@ -1450,8 +1447,8 @@ public class FunctionCodegen {
}
}
KotlinType returnType = descriptor.getReturnType();
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), bridgeReturnType, iv);
KotlinType returnValueType = state.getTypeMapper().getReturnValueType(descriptor);
StackValue.coerce(delegateTo.getReturnType(), returnValueType, bridge.getReturnType(), bridgeReturnType, iv);
iv.areturn(bridge.getReturnType());
endVisit(mv, "bridge method", origin);
@@ -1619,7 +1616,7 @@ public class FunctionCodegen {
)
);
stackValue.put(delegateMethod.getReturnType(), delegatedTo.getReturnType(), iv);
stackValue.put(delegateMethod.getReturnType(), delegateFunction.getReturnType(), iv);
iv.areturn(delegateMethod.getReturnType());
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -68,7 +68,6 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.getDelegatedLocalVariableMetadata;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.initDefaultSourceMappingIfNeeded;
import static org.jetbrains.kotlin.load.java.JvmAbi.*;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET;
@@ -228,7 +227,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.visitSource(myClass.getContainingKtFile().getName(), null);
initDefaultSourceMappingIfNeeded(context, this, state);
initDefaultSourceMappingIfNeeded();
writeEnclosingMethod();

View File

@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.bridges.findImplementationFromInterfa
import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin
import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.JvmMethodExceptionTypes
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.psi.KtPureClassOrObject
@@ -167,7 +168,7 @@ class InterfaceImplBodyCodegen(
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
exceptions: JvmMethodExceptionTypes
): MethodVisitor {
if (shouldCount) {
isAnythingGenerated = true

View File

@@ -13,9 +13,9 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper;
import org.jetbrains.kotlin.codegen.inline.NameGenerator;
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
@@ -88,7 +88,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
private NameGenerator inlineNameGenerator;
private boolean jvmAssertFieldGenerated;
private DefaultSourceMapper sourceMapper;
private boolean alwaysWriteSourceMap;
private SourceMapper sourceMapper;
public MemberCodegen(
@NotNull GenerationState state,
@@ -182,8 +183,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
writeInnerClasses();
if (sourceMapper != null) {
v.visitSMAP(sourceMapper, !state.getLanguageVersionSettings().supportsFeature(LanguageFeature.CorrectSourceMappingSyntax));
if (alwaysWriteSourceMap || (sourceMapper != null && !sourceMapper.isTrivial())) {
v.visitSMAP(getOrCreateSourceMapper(), !state.getLanguageVersionSettings().supportsFeature(LanguageFeature.CorrectSourceMappingSyntax));
}
v.done();
@@ -467,7 +468,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
Name.special("<clinit>"), SYNTHESIZED, KotlinSourceElementKt.toSourceElement(element));
clInit.initialize(null, null, Collections.emptyList(), Collections.emptyList(),
DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(),
null, Visibilities.PRIVATE);
Modality.FINAL, Visibilities.PRIVATE);
return clInit;
}
@@ -679,7 +680,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
iv.aconst(property.getName().asString());
CallableReferenceUtilKt.generateCallableReferenceSignature(iv, property, state);
CallableReferenceUtilKt.generatePropertyReferenceSignature(iv, property, state);
superCtorArgTypes.add(JAVA_STRING_TYPE);
superCtorArgTypes.add(JAVA_STRING_TYPE);
@@ -722,14 +723,27 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
@NotNull
public DefaultSourceMapper getOrCreateSourceMapper() {
public SourceMapper getOrCreateSourceMapper() {
if (sourceMapper == null) {
// note: this is used in InlineCodegen and the element is always physical (KtElement) there
sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
sourceMapper = new SourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
}
return sourceMapper;
}
protected void initDefaultSourceMappingIfNeeded() {
if (state.isInlineDisabled()) return;
CodegenContext parentContext = context.getParentContext();
while (parentContext != null) {
if (parentContext.isInlineMethodContext()) {
alwaysWriteSourceMap = true;
return;
}
parentContext = parentContext.getParentContext();
}
}
protected void generateConstInstance(@NotNull Type thisAsmType, @NotNull Type fieldAsmType) {
v.newField(
JvmDeclarationOriginKt.OtherOriginFromPure(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD,

View File

@@ -53,7 +53,8 @@ internal class ObjectSuperCallArgumentGenerator(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
calleeDescriptor: CallableDescriptor?
): DefaultCallArgs = super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
): DefaultCallArgs =
super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
public override fun generateExpression(i: Int, argument: ExpressionValueArgument) {
generateSuperCallArgument(i)

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.JvmMethodExceptionTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.tree.*
@@ -42,7 +43,7 @@ class OriginCollectingClassBuilderFactory(private val builderMode: ClassBuilderM
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
exceptions: JvmMethodExceptionTypes
): MethodVisitor {
val methodNode = super.newMethod(origin, access, name, desc, signature, exceptions) as MethodNode
origins[methodNode] = origin

View File

@@ -13,12 +13,13 @@ enum class OwnerKind {
PACKAGE,
IMPLEMENTATION,
DEFAULT_IMPLS,
ERASED_INLINE_CLASS;
ERASED_INLINE_CLASS,
PROPERTY_REFERENCE_SIGNATURE;
companion object {
fun getMemberOwnerKind(descriptor: DeclarationDescriptor): OwnerKind = when (descriptor) {
is PackageFragmentDescriptor -> OwnerKind.PACKAGE
is ClassDescriptor -> OwnerKind.IMPLEMENTATION
is PackageFragmentDescriptor -> PACKAGE
is ClassDescriptor -> IMPLEMENTATION
else -> throw AssertionError("Unexpected declaration container: $this")
}
}

View File

@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtilKt;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -52,6 +51,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND;
import static org.jetbrains.kotlin.fileClasses.JvmFileClassUtilKt.isTopLevelInJvmMultifileClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE;
@@ -135,10 +135,10 @@ public class PropertyCodegen {
boolean isDefaultGetterAndSetter = isDefaultAccessor(getter) && isDefaultAccessor(setter);
if (isAccessorNeeded(declaration, descriptor, getter, isDefaultGetterAndSetter)) {
if (isAccessorNeeded(descriptor, getter, isDefaultGetterAndSetter)) {
generateGetter(descriptor, getter);
}
if (isAccessorNeeded(declaration, descriptor, setter, isDefaultGetterAndSetter)) {
if (isAccessorNeeded(descriptor, setter, isDefaultGetterAndSetter)) {
generateSetter(descriptor, setter);
}
}
@@ -167,17 +167,40 @@ public class PropertyCodegen {
generateSyntheticMethodIfNeeded(descriptor, isBackingFieldOwner);
}
private boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter
) {
return isAccessorNeeded(descriptor, accessor, isDefaultGetterAndSetter, kind);
}
public static boolean isReferenceablePropertyWithGetter(@NotNull PropertyDescriptor descriptor) {
PsiElement psiElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
KtDeclaration ktDeclaration = psiElement instanceof KtDeclaration ? (KtDeclaration) psiElement : null;
if (ktDeclaration instanceof KtProperty) {
KtProperty ktProperty = (KtProperty) ktDeclaration;
boolean isDefaultGetterAndSetter =
isDefaultAccessor(ktProperty.getGetter()) && isDefaultAccessor(ktProperty.getSetter());
return isAccessorNeeded(descriptor, ktProperty.getGetter(), isDefaultGetterAndSetter, OwnerKind.IMPLEMENTATION);
} else if (ktDeclaration instanceof KtParameter) {
return isAccessorNeeded(descriptor, null, true, OwnerKind.IMPLEMENTATION);
} else {
return isAccessorNeeded(descriptor, null, false, OwnerKind.IMPLEMENTATION);
}
}
/**
* Determines if it's necessary to generate an accessor to the property, i.e. if this property can be referenced via getter/setter
* for any reason
*
* @see JvmCodegenUtil#couldUseDirectAccessToProperty
*/
private boolean isAccessorNeeded(
@NotNull KtProperty declaration,
private static boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter
boolean isDefaultGetterAndSetter,
OwnerKind kind
) {
if (isConstOrHasJvmFieldAnnotation(descriptor)) return false;
@@ -187,7 +210,8 @@ public class PropertyCodegen {
if (kind == OwnerKind.DEFAULT_IMPLS && isDefaultAccessor) return false;
// Delegated or extension properties can only be referenced via accessors
if (declaration.hasDelegate() || declaration.getReceiverTypeReference() != null) return true;
//noinspection deprecation
if (descriptor.isDelegated() || descriptor.getExtensionReceiverParameter() != null) return true;
// Companion object properties should have accessors for non-private properties because these properties can be referenced
// via getter/setter. But these accessors getter/setter are not required for private properties that have a default getter
@@ -201,7 +225,7 @@ public class PropertyCodegen {
}
// Non-const properties from multifile classes have accessors regardless of visibility
if (isTopLevelPropertyInMultifileClass(declaration, descriptor)) return true;
if (isTopLevelInJvmMultifileClass(descriptor)) return true;
// Private class properties have accessors only in cases when those accessors are non-trivial
if (Visibilities.isPrivate(descriptor.getVisibility())) {
@@ -215,15 +239,12 @@ public class PropertyCodegen {
return !isDefaultAccessor;
}
return true;
}
// Non-public API (private and internal) primary vals of inline classes don't have getter
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(descriptor) && !descriptor.getVisibility().isPublicAPI()) {
return false;
}
private static boolean isTopLevelPropertyInMultifileClass(
@NotNull KtProperty declaration,
@NotNull PropertyDescriptor descriptor
) {
return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor &&
JvmFileClassUtilKt.isInsideJvmMultifileClassFile(declaration);
return true;
}
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
@@ -401,6 +422,14 @@ public class PropertyCodegen {
}
modifiers |= getVisibilityForBackingField(propertyDescriptor, isDelegate);
// If val is initialized in EXACTLY_ONCE closure, other class from the same package initializes it
// so, its visibility should be package private and not final
if (!propertyDescriptor.isVar() &&
bindingContext.get(BindingContext.FIELD_CAPTURED_IN_EXACLY_ONCE_CLOSURE, propertyDescriptor) != null
) {
modifiers &= ~(ACC_PRIVATE | ACC_FINAL);
}
if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
parentBodyCodegen.addCompanionObjectPropertyToCopy(propertyDescriptor, defaultValue);

View File

@@ -118,7 +118,7 @@ class PropertyReferenceCodegen(
aconst(target.name.asString())
}
generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) {
generateCallableReferenceSignature(this, target, state)
generatePropertyReferenceSignature(this, target, state)
}
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
generateCallableReferenceDeclarationContainer(this, target, state)
@@ -148,7 +148,7 @@ class PropertyReferenceCodegen(
if (isOptimizedPropertyReferenceSupertype(superAsmType)) {
generateCallableReferenceDeclarationContainerClass(this, target, state)
aconst(target.name.asString())
generateCallableReferenceSignature(this, target, state)
generatePropertyReferenceSignature(this, target, state)
aconst(getCallableReferenceTopLevelFlag(target))
superCtorArgTypes.add(JAVA_CLASS_TYPE)
superCtorArgTypes.add(JAVA_STRING_TYPE)

View File

@@ -27,22 +27,41 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils;
import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.KotlinTypeKt;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
public class SamType {
@Nullable
public static SamType createByValueParameter(@NotNull ValueParameterDescriptor valueParameter) {
KotlinType singleArgumentType;
KotlinType originalSingleArgumentType;
KotlinType varargElementType = valueParameter.getVarargElementType();
if (varargElementType != null) {
singleArgumentType = varargElementType;
originalSingleArgumentType = valueParameter.getOriginal().getVarargElementType();
assert originalSingleArgumentType != null :
"Value parameter and original value parameter have inconsistent varargs: " +
valueParameter + "; " + valueParameter.getOriginal();
} else {
singleArgumentType = valueParameter.getType();
originalSingleArgumentType = valueParameter.getOriginal().getType();
}
if (KotlinTypeKt.isError(singleArgumentType) || KotlinTypeKt.isError(originalSingleArgumentType)) {
return null;
}
KotlinType originalTypeToUse =
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
// (see testData genericSamProjectedOut.kt for details)
KotlinBuiltIns.isNothing(valueParameter.getType())
KotlinBuiltIns.isNothing(singleArgumentType)
// In such a case we can't have a proper supertype since wildcards are not allowed there,
// so we use Nothing arguments instead that leads to a raw type used for a SAM wrapper.
// See org.jetbrains.kotlin.codegen.state.KotlinTypeMapper#writeGenericType to understand how
// raw types and Nothing arguments relate.
? TypeUtilsKt.replaceArgumentsWithNothing(valueParameter.getOriginal().getType())
: valueParameter.getType();
? TypeUtilsKt.replaceArgumentsWithNothing(originalSingleArgumentType)
: singleArgumentType;
return create(TypeMapperUtilsKt.removeExternalProjections(originalTypeToUse));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen
import com.intellij.psi.PsiElement
import com.intellij.util.containers.LinkedMultiMap
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.codegen.state.JvmMethodExceptionTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
@@ -63,7 +64,7 @@ abstract class SignatureCollectingClassBuilderFactory(
return super.newField(origin, access, name, desc, signature, value)
}
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor {
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: JvmMethodExceptionTypes): MethodVisitor {
signatures.putValue(RawSignature(name, desc, MemberKind.METHOD), origin)
if (!shouldGenerate(origin)) {
return AbstractClassBuilder.EMPTY_METHOD_VISITOR

View File

@@ -42,10 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -799,12 +796,16 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
CallableDescriptor descriptor = call.getResultingDescriptor();
if (!(descriptor instanceof FunctionDescriptor)) return;
recordSamValueForNewInference(call);
recordSamValuesForNewInference(call);
recordSamConstructorIfNeeded(expression, call);
recordSamValuesForOldInference(call, descriptor);
}
private void recordSamValuesForOldInference(ResolvedCall<?> call, CallableDescriptor descriptor) {
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) descriptor);
if (original == null) return;
// TODO we can just record SAM_VALUE on relevant value arguments as we do in recordSamValuesForNewInference
List<ValueParameterDescriptor> valueParametersWithSAMConversion = new SmartList<>();
for (ValueParameterDescriptor valueParameter : original.getValueParameters()) {
ValueParameterDescriptor adaptedParameter = descriptor.getValueParameters().get(valueParameter.getIndex());
@@ -814,30 +815,43 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
writeSamValueForValueParameters(valueParametersWithSAMConversion, call.getValueArgumentsByIndex());
}
private void recordSamValueForNewInference(@NotNull ResolvedCall<?> call) {
NewResolvedCallImpl<?> newResolvedCall = null;
if (call instanceof NewVariableAsFunctionResolvedCallImpl) {
newResolvedCall = ((NewVariableAsFunctionResolvedCallImpl) call).getFunctionCall();
}
else if(call instanceof NewResolvedCallImpl) {
newResolvedCall = (NewResolvedCallImpl<?>) call;
}
private void recordSamValuesForNewInference(@NotNull ResolvedCall<?> call) {
NewResolvedCallImpl<?> newResolvedCall = getNewResolvedCallForCallWithPossibleSamConversions(call);
if (newResolvedCall == null) return;
List<ValueParameterDescriptor> valueParametersWithSAMConversion = new SmartList<>();
Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = newResolvedCall.getValueArguments();
for (ValueParameterDescriptor valueParameter : arguments.keySet()) {
SamType samType = SamType.createByValueParameter(valueParameter);
if (samType == null) continue;
ResolvedValueArgument argument = arguments.get(valueParameter);
if (!(argument instanceof ExpressionValueArgument)) continue;
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
if (valueArgument == null || newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) == null) continue;
valueParametersWithSAMConversion.add(valueParameter);
if (argument instanceof ExpressionValueArgument) {
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(samType, valueArgument);
}
} else if (argument instanceof VarargValueArgument) {
VarargValueArgument varargValueArgument = (VarargValueArgument) argument;
for (ValueArgument valueArgument : varargValueArgument.getArguments()) {
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(samType, valueArgument);
}
}
}
}
writeSamValueForValueParameters(valueParametersWithSAMConversion, newResolvedCall.getValueArgumentsByIndex());
}
@Nullable
private static NewResolvedCallImpl<?> getNewResolvedCallForCallWithPossibleSamConversions(@NotNull ResolvedCall<?> call) {
if (call instanceof NewVariableAsFunctionResolvedCallImpl) {
return ((NewVariableAsFunctionResolvedCallImpl) call).getFunctionCall();
}
else if (call instanceof NewResolvedCallImpl) {
return (NewResolvedCallImpl<?>) call;
}
else {
return null;
}
}
private void writeSamValueForValueParameters(
@@ -854,13 +868,17 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
assert resolvedValueArgument instanceof ExpressionValueArgument : resolvedValueArgument;
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
assert valueArgument != null;
KtExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
bindingTrace.record(CodegenBinding.SAM_VALUE, argumentExpression, samType);
recordSamTypeOnArgumentExpression(samType, valueArgument);
}
}
private void recordSamTypeOnArgumentExpression(SamType samType, ValueArgument valueArgument) {
KtExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
bindingTrace.record(CodegenBinding.SAM_VALUE, argumentExpression, samType);
}
@Override
public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) {
// Closures in super type constructor calls for anonymous objects are created in outer context
@@ -942,7 +960,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (!(operationDescriptor instanceof FunctionDescriptor)) return;
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
if (resolvedCall != null) recordSamValueForNewInference(resolvedCall);
if (resolvedCall != null) recordSamValuesForNewInference(resolvedCall);
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor);
if (original == null) return;
@@ -967,7 +985,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (!(operationDescriptor instanceof FunctionDescriptor)) return;
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
if (resolvedCall != null) recordSamValueForNewInference(resolvedCall);
if (resolvedCall != null) recordSamValuesForNewInference(resolvedCall);
boolean isSetter = operationDescriptor.getName().asString().equals("set");
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor);

View File

@@ -168,11 +168,15 @@ private fun isTopLevelCallableReference(descriptor: CallableDescriptor): Boolean
internal fun getCallableReferenceTopLevelFlag(descriptor: CallableDescriptor): Int =
if (isTopLevelCallableReference(descriptor)) 1 else 0
internal fun generateCallableReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
internal fun generateFunctionReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
iv.aconst(getSignatureString(callable, state))
}
private fun getSignatureString(callable: CallableDescriptor, state: GenerationState): String {
internal fun generatePropertyReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
iv.aconst(getSignatureString(callable, state, isPropertySignature = true))
}
private fun getSignatureString(callable: CallableDescriptor, state: GenerationState, isPropertySignature: Boolean = false): String {
if (callable is LocalVariableDescriptor) {
val asmType = state.bindingContext.get(CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, callable)
?: throw AssertionError("No delegated property metadata owner for $callable")
@@ -198,10 +202,13 @@ private fun getSignatureString(callable: CallableDescriptor, state: GenerationSt
else -> error("Unsupported callable reference: $callable")
}
val declaration = DescriptorUtils.unwrapFakeOverride(accessor).original
val method =
if (callable.containingDeclaration.isInlineClass() && !declaration.isGetterOfUnderlyingPropertyOfInlineClass())
val method = when {
callable.containingDeclaration.isInlineClass() && !declaration.isGetterOfUnderlyingPropertyOfInlineClass() ->
state.typeMapper.mapSignatureForInlineErasedClassSkipGeneric(declaration).asmMethod
else
isPropertySignature ->
state.typeMapper.mapPropertyReferenceSignature(declaration)
else ->
state.typeMapper.mapAsmMethod(declaration)
}
return method.name + method.descriptor
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen

View File

@@ -60,6 +60,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import java.util.*
fun generateIsCheck(
v: InstructionAdapter,

View File

@@ -727,7 +727,9 @@ class CoroutineCodegenForNamedFunction private constructor(
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av ->
val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state))
val functionProto =
serializer.functionProto(createFreeFakeLambdaDescriptor(suspendFunctionJvmView))?.build() ?: return@writeKotlinMetadata
serializer.functionProto(
createFreeFakeLambdaDescriptor(suspendFunctionJvmView, state.typeApproximator)
)?.build() ?: return@writeKotlinMetadata
AsmUtil.writeAnnotationData(av, serializer, functionProto)
}
}

View File

@@ -5,23 +5,16 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
import org.jetbrains.kotlin.codegen.optimization.common.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
@@ -30,7 +23,6 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.*
import kotlin.math.max
private const val COROUTINES_DEBUG_METADATA_VERSION = 1
@@ -92,14 +84,14 @@ class CoroutineTransformerMethodVisitor(
)
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
RedundantLocalsEliminationMethodTransformer(languageVersionSettings).transform(containingClassInternalName, methodNode)
val suspensionPoints = collectSuspensionPoints(methodNode)
RedundantLocalsEliminationMethodTransformer(suspensionPoints)
.transform(containingClassInternalName, methodNode)
if (languageVersionSettings.isReleaseCoroutines()) {
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
}
updateMaxStack(methodNode)
val suspensionPoints = collectSuspensionPoints(methodNode)
checkForSuspensionPointInsideMonitor(methodNode, suspensionPoints)
// First instruction in the method node may change in case of named function
@@ -114,6 +106,7 @@ class CoroutineTransformerMethodVisitor(
languageVersionSettings,
containingClassInternalName,
methodNode,
suspensionPoints,
disableTailCallOptimizationForFunctionReturningUnit
)
if (examiner.allSuspensionPointsAreTailCalls(suspensionPoints)) {
@@ -577,11 +570,9 @@ class CoroutineTransformerMethodVisitor(
return false
}
val starts = methodNode.instructions.asSequence().filter {
isBeforeSuspendMarker(it) &&
cfg.getPredecessorsIndices(it).isNotEmpty() // Ignore unreachable start markers
}.toList()
return starts.mapNotNull { start ->
return methodNode.instructions.asSequence().filter {
isBeforeSuspendMarker(it)
}.mapNotNull { start ->
val ends = mutableSetOf<AbstractInsnNode>()
if (collectSuspensionPointEnds(start, mutableSetOf(), ends)) return@mapNotNull null
// Ignore suspension points, if the suspension call begin is alive and suspension call end is dead
@@ -590,7 +581,7 @@ class CoroutineTransformerMethodVisitor(
// this is an exit point for the corresponding coroutine.
val end = ends.find { isAfterSuspendMarker(it) } ?: return@mapNotNull null
SuspensionPoint(start.previous, end)
}
}.toList()
}
private fun dropSuspensionMarkers(methodNode: MethodNode) {
@@ -898,197 +889,6 @@ class CoroutineTransformerMethodVisitor(
private data class SpilledVariableDescriptor(val fieldName: String, val variableName: String)
}
// TODO Use this in variable liveness analysis
private class MethodNodeExaminer(
val languageVersionSettings: LanguageVersionSettings,
val containingClassInternalName: String,
val methodNode: MethodNode,
disableTailCallOptimizationForFunctionReturningUnit: Boolean
) {
private val sourceFrames: Array<Frame<SourceValue>?> =
MethodTransformer.analyze(containingClassInternalName, methodNode, IgnoringCopyOperationSourceInterpreter())
private val controlFlowGraph = ControlFlowGraph.build(methodNode)
private val safeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val popsBeforeSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val areturnsAfterSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val meaningfulSuccessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
private val meaningfulPredecessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
init {
if (!disableTailCallOptimizationForFunctionReturningUnit) {
// retrieve all POP insns
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }
// for each of them check that all successors are PUSH Unit
val popsBeforeUnitInstances = pops.map { it to it.meaningfulSuccessors() }
.filter { (_, succs) -> succs.all { it.isUnitInstance() } }
.map { it.first }.toList()
for (pop in popsBeforeUnitInstances) {
val units = pop.meaningfulSuccessors()
val allUnitsAreSafe = units.all { unit ->
// check no other predecessor exists
unit.meaningfulPredecessors().all { it in popsBeforeUnitInstances } &&
// check they have only returns among successors
unit.meaningfulSuccessors().all { it.opcode == Opcodes.ARETURN }
}
if (!allUnitsAreSafe) continue
// save them all to the properties
popsBeforeSafeUnitInstances += pop
safeUnitInstances += units
units.flatMapTo(areturnsAfterSafeUnitInstances) { it.meaningfulSuccessors() }
}
}
}
private fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
// GETSTATIC kotlin/Unit.INSTANCE is considered safe iff
// it is part of POP, PUSH Unit, ARETURN sequence.
private fun AbstractInsnNode.isSafeUnitInstance(): Boolean = this in safeUnitInstances
private fun AbstractInsnNode.isPopBeforeSafeUnitInstance(): Boolean = this in popsBeforeSafeUnitInstances
private fun AbstractInsnNode.isAreturnAfterSafeUnitInstance(): Boolean = this in areturnsAfterSafeUnitInstances
private fun AbstractInsnNode.meaningfulSuccessors(): List<AbstractInsnNode> = meaningfulSuccessorsCache.getOrPut(this) {
meaningfulSuccessorsOrPredecessors(true)
}
private fun AbstractInsnNode.meaningfulPredecessors(): List<AbstractInsnNode> = meaningfulPredecessorsCache.getOrPut(this) {
meaningfulSuccessorsOrPredecessors(false)
}
private fun AbstractInsnNode.meaningfulSuccessorsOrPredecessors(isSuccessors: Boolean): List<AbstractInsnNode> {
fun AbstractInsnNode.isMeaningful() = isMeaningful && opcode != Opcodes.NOP && opcode != Opcodes.GOTO && this !is LineNumberNode
fun AbstractInsnNode.getIndices() =
if (isSuccessors) controlFlowGraph.getSuccessorsIndices(this)
else controlFlowGraph.getPredecessorsIndices(this)
val visited = arrayListOf<AbstractInsnNode>()
fun dfs(insn: AbstractInsnNode) {
if (insn in visited) return
visited += insn
if (!insn.isMeaningful()) {
for (succIndex in insn.getIndices()) {
dfs(methodNode.instructions[succIndex])
}
}
}
for (succIndex in getIndices()) {
dfs(methodNode.instructions[succIndex])
}
return visited.filter { it.isMeaningful() }
}
fun replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks() {
val basicAnalyser = Analyzer(BasicInterpreter())
basicAnalyser.analyze(containingClassInternalName, methodNode)
val typedFrames = basicAnalyser.frames
val isReferenceMap = popsBeforeSafeUnitInstances
.map { it to (!isUnreachable(it.index(), sourceFrames) && typedFrames[it.index()]?.top()?.isReference == true) }
.toMap()
for (pop in popsBeforeSafeUnitInstances) {
if (isReferenceMap[pop] == true) {
val label = Label()
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
ifacmpne(label)
areturn(AsmTypes.OBJECT_TYPE)
mark(label)
})
}
}
}
fun allSuspensionPointsAreTailCalls(suspensionPoints: List<SuspensionPoint>): Boolean {
val safelyReachableReturns = findSafelyReachableReturns()
val instructions = methodNode.instructions
return suspensionPoints.all { suspensionPoint ->
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
if (isUnreachable(endIndex, sourceFrames)) return@all true
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
val tryBlockStartIndex = instructions.indexOf(block.start)
val tryBlockEndIndex = instructions.indexOf(block.end)
beginIndex in tryBlockStartIndex..tryBlockEndIndex
}
if (insideTryBlock) return@all false
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
sourceFrames[returnIndex]?.top().sure {
"There must be some value on stack to return"
}.insns.any { sourceInsn ->
sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex
}
} ?: false
}
}
/**
* Let's call an instruction safe if its execution is always invisible: stack modifications, branching, variable insns (invisible in debug)
*
* For some instruction `insn` define the result as following:
* - if there is a path leading to the non-safe instruction then result is `null`
* - Otherwise result contains all the reachable ARETURN indices
*
* @return indices of safely reachable returns for each instruction in the method node
*/
private fun findSafelyReachableReturns(): Array<Set<Int>?> {
val insns = methodNode.instructions
val reachableReturnsIndices = Array<Set<Int>?>(insns.size()) init@{ index ->
val insn = insns[index]
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
if (isUnreachable(index, sourceFrames)) return@init null
return@init setOf(index)
}
// Since POP, PUSH Unit, ARETURN behaves like normal return in terms of tail-call optimization, set return index to POP
if (insn.isPopBeforeSafeUnitInstance()) {
return@init setOf(index)
}
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) || isInlineMarker(insn)
|| insn.isSafeUnitInstance() || insn.isAreturnAfterSafeUnitInstance()
) {
setOf<Int>()
} else null
}
var changed: Boolean
do {
changed = false
for (index in 0 until insns.size()) {
if (insns[index].opcode == Opcodes.ARETURN) continue
@Suppress("RemoveExplicitTypeArguments")
val newResult =
controlFlowGraph
.getSuccessorsIndices(index).plus(index)
.map(reachableReturnsIndices::get)
.fold<Set<Int>?, Set<Int>?>(mutableSetOf<Int>()) { acc, successorsResult ->
if (acc != null && successorsResult != null) acc + successorsResult else null
}
if (newResult != reachableReturnsIndices[index]) {
reachableReturnsIndices[index] = newResult
changed = true
}
}
} while (changed)
return reachableReturnsIndices
}
}
internal fun InstructionAdapter.generateContinuationConstructorCall(
objectTypeForState: Type?,
methodNode: MethodNode,
@@ -1169,15 +969,25 @@ private fun Type.normalize() =
* ICONST_1
* INVOKESTATIC InlineMarker.mark()
*/
private class SuspensionPoint(
internal class SuspensionPoint(
// ICONST_0
val suspensionCallBegin: AbstractInsnNode,
// INVOKESTATIC InlineMarker.mark()
val suspensionCallEnd: AbstractInsnNode
) {
lateinit var tryCatchBlocksContinuationLabel: LabelNode
operator fun contains(insn: AbstractInsnNode): Boolean {
for (i in InsnSequence(suspensionCallBegin, suspensionCallEnd.next)) {
if (i == insn) return true
}
return false
}
}
internal operator fun List<SuspensionPoint>.contains(insn: AbstractInsnNode): Boolean =
any { insn in it }
internal fun getLastParameterIndex(desc: String, access: Int) =
Type.getArgumentTypes(desc).dropLast(1).map { it.size }.sum() + (if (!isStatic(access)) 1 else 0)
@@ -1208,25 +1018,6 @@ private fun getAllParameterTypes(desc: String, hasDispatchReceiver: Boolean, thi
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
Type.getArgumentTypes(desc)
internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter(Opcodes.API_VERSION) {
override fun copyOperation(insn: AbstractInsnNode?, value: SourceValue?) = value
}
// Check whether this instruction is unreachable, i.e. there is no path leading to this instruction
internal fun <T : Value> isUnreachable(index: Int, sourceFrames: Array<out Frame<out T>?>): Boolean =
sourceFrames.size <= index || sourceFrames[index] == null
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
val insns = methodNode.instructions
val index = insns.indexOf(this)
return (this is VarInsnNode && methodNode.localVariables.none {
it.index == `var` && index in it.start.let(insns::indexOf)..it.end.let(insns::indexOf)
})
}
private val SAFE_OPCODES =
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
val fakeContinuations = methodNode.instructions.asSequence().filter(::isFakeContinuationMarker).toList()
for (fakeContinuation in fakeContinuations) {

View File

@@ -5,93 +5,133 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.inline.nodeText
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.utils.keysToMap
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
private class PossibleSpilledValue(val source: AbstractInsnNode, type: Type?) : BasicValue(type) {
val usages = mutableSetOf<AbstractInsnNode>()
override fun toString(): String = when {
source.opcode == Opcodes.ALOAD -> "" + (source as VarInsnNode).`var`
source.isUnitInstance() -> "U"
else -> error("unreachable")
}
override fun equals(other: Any?): Boolean =
other is PossibleSpilledValue && source == other.source
override fun hashCode(): Int = super.hashCode() xor source.hashCode()
}
private object NonSpillableValue : BasicValue(AsmTypes.OBJECT_TYPE) {
override fun equals(other: Any?): Boolean = other is NonSpillableValue
override fun toString(): String = "N"
}
private object ConstructedValue : BasicValue(AsmTypes.OBJECT_TYPE) {
override fun equals(other: Any?): Boolean = other is ConstructedValue
override fun toString(): String = "C"
}
fun BasicValue?.nonspillable(): BasicValue? = if (this?.type?.sort == Type.OBJECT) NonSpillableValue else this
private class RedundantSpillingInterpreter : BasicInterpreter(Opcodes.API_VERSION) {
val possibleSpilledValues = mutableSetOf<PossibleSpilledValue>()
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
if (insn.opcode == Opcodes.NEW) return ConstructedValue
val basicValue = super.newOperation(insn)
return if (insn.isUnitInstance())
// Unit instances come from inlining suspend functions returning Unit.
// They can be spilled before they are eventually popped.
// Track them.
PossibleSpilledValue(insn, basicValue.type).also { possibleSpilledValues += it }
else basicValue.nonspillable()
}
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
when (value) {
is ConstructedValue -> value
is PossibleSpilledValue -> {
value.usages += insn
if (insn.opcode == Opcodes.ALOAD || insn.opcode == Opcodes.ASTORE) value
else value.nonspillable()
}
else -> value?.nonspillable()
}
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out BasicValue?>): BasicValue? {
for (value in values.filterIsInstance<PossibleSpilledValue>()) {
value.usages += insn
}
return super.naryOperation(insn, values)?.nonspillable()
}
override fun merge(v: BasicValue?, w: BasicValue?): BasicValue? =
if (v is PossibleSpilledValue && w is PossibleSpilledValue && v.source == w.source) v
else v?.nonspillable()
}
// Inliner emits a lot of locals during inlining.
// Remove all of them since these locals are
// 1) going to be spilled into continuation object
// 2) breaking tail-call elimination
class RedundantLocalsEliminationMethodTransformer(private val languageVersionSettings: LanguageVersionSettings) : MethodTransformer() {
lateinit var internalClassName: String
internal class RedundantLocalsEliminationMethodTransformer(private val suspensionPoints: List<SuspensionPoint>) : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
this.internalClassName = internalClassName
do {
var changed = false
changed = simpleRemove(methodNode) || changed
changed = removeWithReplacement(methodNode) || changed
changed = removeAloadCheckcastContinuationAstore(methodNode, languageVersionSettings) || changed
} while (changed)
}
val interpreter = RedundantSpillingInterpreter()
val frames = MethodAnalyzer<BasicValue>(internalClassName, methodNode, interpreter).analyze()
// Replace
// GETSTATIC kotlin/Unit.INSTANCE
// ASTORE N
// ...
// ALOAD N
// with
// ...
// GETSTATIC kotlin/Unit.INSTANCE
// or
// ACONST_NULL
// ASTORE N
// ...
// ALOAD N
// with
// ...
// ACONST_NULL
// or
// ALOAD K
// ASTORE N
// ...
// ALOAD N
// with
// ...
// ALOAD K
//
// But do not remove several at a time, since the same local (for example, ALOAD 0) might be loaded and stored multiple times in
// sequence, like
// ALOAD 0
// ASTORE 1
// ALOAD 1
// ASTORE 2
// ALOAD 3
// Here, it is unsafe to replace ALOAD 3 with ALOAD 1, and then already removed ALOAD 1 with ALOAD 0.
private fun removeWithReplacement(
methodNode: MethodNode
): Boolean {
val cfg = ControlFlowGraph.build(methodNode)
val insns = findSafeAstorePredecessors(methodNode, cfg, ignoreLocalVariableTable = false) {
it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD
val toDelete = mutableSetOf<AbstractInsnNode>()
for (spilledValue in interpreter.possibleSpilledValues.filter { it.usages.isNotEmpty() }) {
@Suppress("UNCHECKED_CAST")
val aloads = spilledValue.usages.filter { it.opcode == Opcodes.ALOAD } as List<VarInsnNode>
if (aloads.isEmpty()) continue
val slot = aloads.first().`var`
if (aloads.any { it.`var` != slot }) continue
for (aload in aloads) {
methodNode.instructions.set(aload, spilledValue.source.clone())
}
toDelete.addAll(spilledValue.usages.filter { it.opcode == Opcodes.ASTORE })
toDelete.add(spilledValue.source)
}
for ((pred, astore) in insns) {
val aload = findSingleLoadFromAstore(astore, cfg, methodNode) ?: continue
methodNode.instructions.removeAll(listOf(pred, astore))
methodNode.instructions.set(aload, pred.clone())
return true
for (pop in methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }) {
val value = (frames[methodNode.instructions.indexOf(pop)]?.top() as? PossibleSpilledValue) ?: continue
if (value.usages.isEmpty() && value.source !in suspensionPoints) {
toDelete.add(pop)
toDelete.add(value.source)
}
}
return false
}
private fun findSingleLoadFromAstore(
astore: AbstractInsnNode,
cfg: ControlFlowGraph,
methodNode: MethodNode
): AbstractInsnNode? {
val aload = methodNode.instructions.asSequence()
.singleOrNull { it.opcode == Opcodes.ALOAD && it.localIndex() == astore.localIndex() } ?: return null
val succ = findImmediateSuccessors(astore, cfg, methodNode).singleOrNull() ?: return null
return if (aload == succ) aload else null
// Remove unreachable instructions to simplify further analyses
for (index in frames.indices) {
if (frames[index] == null) {
val insn = methodNode.instructions[index]
if (insn !is LabelNode) {
toDelete.add(insn)
}
}
}
methodNode.instructions.removeAll(toDelete)
}
private fun AbstractInsnNode.clone() = when (this) {
@@ -101,145 +141,41 @@ class RedundantLocalsEliminationMethodTransformer(private val languageVersionSet
is TypeInsnNode -> TypeInsnNode(opcode, desc)
else -> error("clone of $this is not implemented yet")
}
}
// Remove
// ALOAD N
// POP
// or
// ACONST_NULL
// POP
// or
// GETSTATIC kotlin/Unit.INSTANCE
// POP
private fun simpleRemove(methodNode: MethodNode): Boolean {
val insns =
findPopPredecessors(methodNode) { it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD }
for ((pred, pop) in insns) {
methodNode.instructions.insertBefore(pred, InsnNode(Opcodes.NOP))
methodNode.instructions.removeAll(listOf(pred, pop))
}
return insns.isNotEmpty()
}
private fun findPopPredecessors(
methodNode: MethodNode,
predicate: (AbstractInsnNode) -> Boolean
): Map<AbstractInsnNode, AbstractInsnNode> {
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
val cfg = ControlFlowGraph.build(methodNode)
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
// Handy debugging routing
@Suppress("unused")
fun MethodNode.nodeTextWithFrames(frames: Array<*>): String {
var insns = nodeText.split("\n")
val first = insns.indexOfLast { it.trim().startsWith("@") } + 1
var last = insns.indexOfFirst { it.trim().startsWith("LOCALVARIABLE") }
if (last < 0) last = insns.size
val prefix = insns.subList(0, first).joinToString(separator = "\n")
val postfix = insns.subList(last, insns.size).joinToString(separator = "\n")
insns = insns.subList(first, last)
if (insns.any { it.contains("TABLESWITCH") }) {
var insideTableSwitch = false
var buffer = ""
val res = arrayListOf<String>()
for (insn in insns) {
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
if (succ.opcode != Opcodes.POP) continue
if (insn.opcode == Opcodes.ALOAD && methodNode.localVariables.firstOrNull { it.index == insn.localIndex() } != null) continue
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
if (sources.size != 1) continue
res[insn] = succ
}
return res
}
// Replace
// ALOAD K
// CHECKCAST Continuation
// ASTORE N
// ...
// ALOAD N
// with
// ...
// ALOAD K
// CHECKCAST Continuation
private fun removeAloadCheckcastContinuationAstore(methodNode: MethodNode, languageVersionSettings: LanguageVersionSettings): Boolean {
// Here we ignore the duplicates of continuation in local variable table,
// Since it increases performance greatly.
val cfg = ControlFlowGraph.build(methodNode)
val insns = findSafeAstorePredecessors(methodNode, cfg, ignoreLocalVariableTable = true) {
it.opcode == Opcodes.CHECKCAST &&
(it as TypeInsnNode).desc == languageVersionSettings.continuationAsmType().internalName &&
it.previous?.opcode == Opcodes.ALOAD
}
var changed = false
for ((checkcast, astore) in insns) {
val aloadk = checkcast.previous
val aloadn = findSingleLoadFromAstore(astore, cfg, methodNode) ?: continue
methodNode.instructions.removeAll(listOf(aloadk, checkcast, astore))
methodNode.instructions.insertBefore(aloadn, aloadk.clone())
methodNode.instructions.set(aloadn, checkcast.clone())
changed = true
}
return changed
}
private fun findSafeAstorePredecessors(
methodNode: MethodNode,
cfg: ControlFlowGraph,
ignoreLocalVariableTable: Boolean,
predicate: (AbstractInsnNode) -> Boolean
): Map<AbstractInsnNode, AbstractInsnNode> {
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
for (insn in insns) {
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
if (succ.opcode != Opcodes.ASTORE) continue
if (methodNode.instructions.asSequence().count {
it.opcode == Opcodes.ASTORE && it.localIndex() == succ.localIndex()
} != 1) continue
if (!ignoreLocalVariableTable && methodNode.localVariables.firstOrNull { it.index == succ.localIndex() } != null) continue
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
if (sources.size > 1) continue
res[insn] = succ
}
return res
}
// Find all meaningful successors of insn
private fun findImmediateSuccessors(
insn: AbstractInsnNode,
cfg: ControlFlowGraph,
methodNode: MethodNode
): Collection<AbstractInsnNode> {
val visited = hashSetOf<AbstractInsnNode>()
fun dfs(current: AbstractInsnNode): Collection<AbstractInsnNode> {
if (!visited.add(current)) return emptySet()
return cfg.getSuccessorsIndices(current).flatMap {
val succ = methodNode.instructions[it]
if (!succ.isMeaningful || succ is JumpInsnNode || succ.opcode == Opcodes.NOP) dfs(succ)
else setOf(succ)
if (insn.contains("TABLESWITCH")) {
insideTableSwitch = true
}
if (insideTableSwitch) {
buffer += insn
if (insn.contains("default")) {
insideTableSwitch = false
res += buffer
buffer = ""
continue
}
} else {
res += insn
}
}
return dfs(insn)
}
private fun AbstractInsnNode.localIndex(): Int {
assert(this is VarInsnNode)
return (this as VarInsnNode).`var`
}
}
private fun findSourceInstructions(
internalClassName: String,
methodNode: MethodNode,
insns: Collection<AbstractInsnNode>,
ignoreCopy: Boolean
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
val frames = MethodTransformer.analyze(
internalClassName,
methodNode,
if (ignoreCopy) IgnoringCopyOperationSourceInterpreter() else SourceInterpreter()
)
return insns.keysToMap {
val index = methodNode.instructions.indexOf(it)
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
frames[index].getStack(0).insns
insns = res
}
return prefix + "\n" + insns.withIndex().joinToString(separator = "\n") { (index, insn) ->
if (index >= frames.size) "N/A\t$insn" else "${frames[index]}\t$insn"
} + "\n" + postfix
}

View File

@@ -0,0 +1,11 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
typealias SourceFrames = Array<Frame<SourceValue>?>

View File

@@ -0,0 +1,11 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
typealias SourceFrames = Array<Frame<SourceValue>>

View File

@@ -0,0 +1,257 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.inline.isInlineMarker
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
// TODO Use this in variable liveness analysis
internal class MethodNodeExaminer(
val languageVersionSettings: LanguageVersionSettings,
containingClassInternalName: String,
val methodNode: MethodNode,
suspensionPoints: List<SuspensionPoint>,
disableTailCallOptimizationForFunctionReturningUnit: Boolean
) {
private val frames: Array<Frame<BasicValue>?> =
MethodTransformer.analyze(containingClassInternalName, methodNode, TcoInterpreter(suspensionPoints))
private val controlFlowGraph = ControlFlowGraph.build(methodNode)
private val safeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val popsBeforeSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val areturnsAfterSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
private val meaningfulSuccessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
private val meaningfulPredecessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
init {
if (!disableTailCallOptimizationForFunctionReturningUnit) {
// retrieve all POP insns
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }
// for each of them check that all successors are PUSH Unit
val popsBeforeUnitInstances = pops.map { it to it.meaningfulSuccessors() }
.filter { (_, succs) -> succs.all { it.isUnitInstance() } }
.map { it.first }.toList()
for (pop in popsBeforeUnitInstances) {
val units = pop.meaningfulSuccessors()
val allUnitsAreSafe = units.all { unit ->
// check no other predecessor exists
unit.meaningfulPredecessors().all { it in popsBeforeUnitInstances } &&
// check they have only returns among successors
unit.meaningfulSuccessors().all { it.opcode == Opcodes.ARETURN }
}
if (!allUnitsAreSafe) continue
// save them all to the properties
popsBeforeSafeUnitInstances += pop
safeUnitInstances += units
units.flatMapTo(areturnsAfterSafeUnitInstances) { it.meaningfulSuccessors() }
}
}
}
// GETSTATIC kotlin/Unit.INSTANCE is considered safe iff
// it is part of POP, PUSH Unit, ARETURN sequence.
private fun AbstractInsnNode.isSafeUnitInstance(): Boolean = this in safeUnitInstances
private fun AbstractInsnNode.isPopBeforeSafeUnitInstance(): Boolean = this in popsBeforeSafeUnitInstances
private fun AbstractInsnNode.isAreturnAfterSafeUnitInstance(): Boolean = this in areturnsAfterSafeUnitInstances
private fun AbstractInsnNode.meaningfulSuccessors(): List<AbstractInsnNode> = meaningfulSuccessorsCache.getOrPut(this) {
meaningfulSuccessorsOrPredecessors(true)
}
private fun AbstractInsnNode.meaningfulPredecessors(): List<AbstractInsnNode> = meaningfulPredecessorsCache.getOrPut(this) {
meaningfulSuccessorsOrPredecessors(false)
}
private fun AbstractInsnNode.meaningfulSuccessorsOrPredecessors(isSuccessors: Boolean): List<AbstractInsnNode> {
fun AbstractInsnNode.isMeaningful() = isMeaningful && opcode != Opcodes.NOP && opcode != Opcodes.GOTO && this !is LineNumberNode
fun AbstractInsnNode.getIndices() =
if (isSuccessors) controlFlowGraph.getSuccessorsIndices(this)
else controlFlowGraph.getPredecessorsIndices(this)
val visited = mutableSetOf<AbstractInsnNode>()
fun dfs(insn: AbstractInsnNode) {
if (insn in visited) return
visited += insn
if (!insn.isMeaningful()) {
for (succIndex in insn.getIndices()) {
dfs(methodNode.instructions[succIndex])
}
}
}
for (succIndex in getIndices()) {
dfs(methodNode.instructions[succIndex])
}
return visited.filter { it.isMeaningful() }
}
fun replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks() {
val isReferenceMap =
popsBeforeSafeUnitInstances.associateWith { (frames[methodNode.instructions.indexOf(it)]?.top()?.isReference == true) }
for (pop in popsBeforeSafeUnitInstances) {
if (isReferenceMap[pop] == true) {
val label = Label()
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
ifacmpne(label)
areturn(AsmTypes.OBJECT_TYPE)
mark(label)
})
}
}
}
fun allSuspensionPointsAreTailCalls(suspensionPoints: List<SuspensionPoint>): Boolean {
val safelyReachableReturns = findSafelyReachableReturns()
val instructions = methodNode.instructions
return suspensionPoints.all { suspensionPoint ->
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
val tryBlockStartIndex = instructions.indexOf(block.start)
val tryBlockEndIndex = instructions.indexOf(block.end)
beginIndex in tryBlockStartIndex until tryBlockEndIndex
}
if (insideTryBlock) return@all false
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
frames[returnIndex]?.top().sure {
"There must be some value on stack to return"
} is FromSuspensionPointValue
} ?: false
}
}
/**
* Let's call an instruction safe if its execution is always invisible: stack modifications, branching, variable insns (invisible in debug)
*
* For some instruction `insn` define the result as following:
* - if there is a path leading to the non-safe instruction then result is `null`
* - Otherwise result contains all the reachable ARETURN indices
*
* @return indices of safely reachable returns for each instruction in the method node
*/
private fun findSafelyReachableReturns(): Array<Set<Int>?> {
val insns = methodNode.instructions
val reachableReturnsIndices = Array(insns.size()) init@{ index ->
val insn = insns[index]
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
return@init setOf(index)
}
// Since POP, PUSH Unit, ARETURN behaves like normal return in terms of tail-call optimization, set return index to POP
if (insn.isPopBeforeSafeUnitInstance()) {
return@init setOf(index)
}
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) || isInlineMarker(insn)
|| insn.isSafeUnitInstance() || insn.isAreturnAfterSafeUnitInstance()
) {
setOf()
} else null
}
var changed: Boolean
do {
changed = false
for (index in 0 until insns.size()) {
if (insns[index].opcode == Opcodes.ARETURN) continue
@Suppress("RemoveExplicitTypeArguments")
val newResult =
controlFlowGraph
.getSuccessorsIndices(index).plus(index)
.map(reachableReturnsIndices::get)
.fold<Set<Int>?, Set<Int>?>(mutableSetOf<Int>()) { acc, successorsResult ->
if (acc != null && successorsResult != null) acc + successorsResult else null
}
if (newResult != reachableReturnsIndices[index]) {
reachableReturnsIndices[index] = newResult
changed = true
}
}
} while (changed)
return reachableReturnsIndices
}
}
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
val insns = methodNode.instructions
val index = insns.indexOf(this)
return (this is VarInsnNode && methodNode.localVariables.none {
it.index == `var` && index in it.start.let(insns::indexOf)..it.end.let(insns::indexOf)
})
}
private val SAFE_OPCODES =
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
private object FromSuspensionPointValue : BasicValue(AsmTypes.OBJECT_TYPE) {
override fun equals(other: Any?): Boolean = other is FromSuspensionPointValue
}
private fun BasicValue?.toFromSuspensionPoint(): BasicValue? = if (this?.type?.sort == Type.OBJECT) FromSuspensionPointValue else this
private class TcoInterpreter(private val suspensionPoints: List<SuspensionPoint>) : BasicInterpreter(Opcodes.API_VERSION) {
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
return super.copyOperation(insn, value).convert(insn)
}
private fun BasicValue?.convert(insn: AbstractInsnNode): BasicValue? = if (insn in suspensionPoints) toFromSuspensionPoint() else this
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out BasicValue?>?): BasicValue? {
return super.naryOperation(insn, values).convert(insn)
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: BasicValue?, value2: BasicValue?, value3: BasicValue?): BasicValue? {
return super.ternaryOperation(insn, value1, value2, value3).convert(insn)
}
override fun merge(value1: BasicValue?, value2: BasicValue?): BasicValue {
return if (value1 is FromSuspensionPointValue || value2 is FromSuspensionPointValue) FromSuspensionPointValue
else super.merge(value1, value2)
}
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
return super.unaryOperation(insn, value).convert(insn)
}
override fun binaryOperation(insn: AbstractInsnNode, value1: BasicValue?, value2: BasicValue?): BasicValue? {
return super.binaryOperation(insn, value1, value2).convert(insn)
}
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
return super.newOperation(insn).convert(insn)
}
}

View File

@@ -17,22 +17,20 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.types.*
import java.util.*
/**
* Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
*/
fun createFreeFakeLambdaDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
return createFreeDescriptor(descriptor)
fun createFreeFakeLambdaDescriptor(descriptor: FunctionDescriptor, typeApproximator: TypeApproximator?): FunctionDescriptor {
return createFreeDescriptor(descriptor, typeApproximator)
}
private fun <D : CallableMemberDescriptor> createFreeDescriptor(descriptor: D): D {
private fun <D : CallableMemberDescriptor> createFreeDescriptor(descriptor: D, typeApproximator: TypeApproximator?): D {
@Suppress("UNCHECKED_CAST")
val builder = descriptor.newCopyBuilder() as CallableMemberDescriptor.CopyBuilder<D>
@@ -43,14 +41,82 @@ private fun <D : CallableMemberDescriptor> createFreeDescriptor(descriptor: D):
while (container != null) {
if (container is ClassDescriptor) {
typeParameters.addAll(container.declaredTypeParameters)
}
else if (container is CallableDescriptor && container !is ConstructorDescriptor) {
} else if (container is CallableDescriptor && container !is ConstructorDescriptor) {
typeParameters.addAll(container.typeParameters)
}
container = container.containingDeclaration
}
return if (typeParameters.isEmpty()) descriptor else builder.build()!!
val approximated = typeApproximator?.approximate(descriptor, builder) ?: false
return if (typeParameters.isEmpty() && !approximated) descriptor else builder.build()!!
}
private fun TypeApproximator.approximate(descriptor: CallableMemberDescriptor, builder: CallableMemberDescriptor.CopyBuilder<*>): Boolean {
var approximated = false
val returnType = descriptor.returnType
if (returnType != null) {
// unwrap to avoid instances of DeferredType
val approximatedType = approximate(returnType.unwrap(), toSuper = true)
if (approximatedType != null) {
builder.setReturnType(approximatedType)
approximated = true
}
}
if (builder !is FunctionDescriptor.CopyBuilder<*>) return approximated
val extensionReceiverParameter = descriptor.extensionReceiverParameter
if (extensionReceiverParameter != null) {
val approximatedExtensionReceiver = approximate(extensionReceiverParameter.type.unwrap(), toSuper = false)
if (approximatedExtensionReceiver != null) {
builder.setExtensionReceiverParameter(
extensionReceiverParameter.substituteTopLevelType(approximatedExtensionReceiver)
)
approximated = true
}
}
var valueParameterApproximated = false
val newParameters = descriptor.valueParameters.map {
val approximatedType = approximate(it.type.unwrap(), toSuper = false)
if (approximatedType != null) {
valueParameterApproximated = true
// invoking constructor explicitly as substitution on value parameters is not supported
ValueParameterDescriptorImpl(
it.containingDeclaration, it.original, it.index, it.annotations,
it.name, outType = approximatedType, it.declaresDefaultValue(),
it.isCrossinline, it.isNoinline, it.varargElementType, it.source
)
} else {
it
}
}
if (valueParameterApproximated) {
builder.setValueParameters(newParameters)
approximated = true
}
return approximated
}
private fun ReceiverParameterDescriptor.substituteTopLevelType(newType: KotlinType): ReceiverParameterDescriptor? {
val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance): KotlinType = newType
}
return substitute(TypeSubstitutor.create(wrappedSubstitution))
}
private fun TypeApproximator.approximate(type: UnwrappedType, toSuper: Boolean): KotlinType? {
if (type.arguments.isEmpty() && type.constructor.isDenotable) return null
return if (toSuper)
approximateToSuperType(type, TypeApproximatorConfiguration.PublicDeclaration)
else
approximateToSubType(type, TypeApproximatorConfiguration.PublicDeclaration)
}
/**
@@ -58,26 +124,31 @@ private fun <D : CallableMemberDescriptor> createFreeDescriptor(descriptor: D):
* when using reflection on that local variable at runtime.
* Only members used by [DescriptorSerializer.propertyProto] are implemented correctly in this property descriptor.
*/
fun createFreeFakeLocalPropertyDescriptor(descriptor: LocalVariableDescriptor): PropertyDescriptor {
fun createFreeFakeLocalPropertyDescriptor(descriptor: LocalVariableDescriptor, typeApproximator: TypeApproximator?): PropertyDescriptor {
val property = PropertyDescriptorImpl.create(
descriptor.containingDeclaration, descriptor.annotations, Modality.FINAL, descriptor.visibility, descriptor.isVar,
descriptor.name, CallableMemberDescriptor.Kind.DECLARATION, descriptor.source, false, descriptor.isConst,
false, false, false, @Suppress("DEPRECATION") descriptor.isDelegated
descriptor.containingDeclaration, descriptor.annotations, Modality.FINAL, descriptor.visibility, descriptor.isVar,
descriptor.name, CallableMemberDescriptor.Kind.DECLARATION, descriptor.source, false, descriptor.isConst,
false, false, false, @Suppress("DEPRECATION") descriptor.isDelegated
)
property.setType(
descriptor.type, descriptor.typeParameters,
descriptor.dispatchReceiverParameter, descriptor.extensionReceiverParameter
)
property.setType(descriptor.type, descriptor.typeParameters, descriptor.dispatchReceiverParameter, descriptor.extensionReceiverParameter)
property.initialize(
descriptor.getter?.run {
PropertyGetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source).apply {
descriptor.getter?.run {
PropertyGetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source)
.apply {
initialize(this@run.returnType)
}
},
descriptor.setter?.run {
PropertySetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source).apply {
},
descriptor.setter?.run {
PropertySetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source)
.apply {
initialize(this@run.valueParameters.single())
}
}
}
)
return createFreeDescriptor(property)
return createFreeDescriptor(property, typeApproximator)
}

View File

@@ -42,8 +42,7 @@ class AnonymousObjectTransformer(
private val fieldNames = hashMapOf<String, MutableList<String>>()
private var constructor: MethodNode? = null
private var sourceInfo: String? = null
private var debugInfo: String? = null
private lateinit var sourceMap: SMAP
private lateinit var sourceMapper: SourceMapper
private val languageVersionSettings = inliningContext.state.languageVersionSettings
@@ -56,6 +55,8 @@ class AnonymousObjectTransformer(
val methodsToTransform = ArrayList<MethodNode>()
val metadataReader = ReadKotlinClassHeaderAnnotationVisitor()
lateinit var superClassName: String
var sourceInfo: String? = null
var debugInfo: String? = null
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
@@ -113,22 +114,12 @@ class AnonymousObjectTransformer(
override fun visitEnd() {}
}, ClassReader.SKIP_FRAMES)
if (!inliningContext.isInliningLambda) {
sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) {
SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!))
} else {
//seems we can't do any clever mapping cause we don't know any about original class name
IdenticalSourceMapper
}
if (sourceInfo != null && !GENERATE_SMAP) {
classBuilder.visitSource(sourceInfo!!, debugInfo)
}
} else {
if (sourceInfo != null) {
classBuilder.visitSource(sourceInfo!!, debugInfo)
}
sourceMapper = IdenticalSourceMapper
}
// When regenerating objects in inline lambdas, keep the old SMAP and don't remap the line numbers to
// save time. The result is effectively the same anyway.
val debugInfoToParse = if (inliningContext.isInliningLambda) null else debugInfo
val (firstLine, lastLine) = (methodsToTransform + listOfNotNull(constructor)).lineNumberRange()
sourceMap = SMAPParser.parseOrCreateDefault(debugInfoToParse, sourceInfo, oldObjectType.internalName, firstLine, lastLine)
sourceMapper = SourceMapper(sourceMap.fileMappings.firstOrNull { it.name == sourceInfo }?.toSourceInfo())
val allCapturedParamBuilder = ParametersBuilder.newBuilder()
val constructorParamBuilder = ParametersBuilder.newBuilder()
@@ -183,7 +174,11 @@ class AnonymousObjectTransformer(
}
}
classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
if (GENERATE_SMAP && !inliningContext.isInliningLambda) {
classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
} else if (sourceInfo != null) {
classBuilder.visitSource(sourceInfo!!, debugInfo)
}
val visitor = classBuilder.visitor
innerClassNodes.forEach { node ->
@@ -296,7 +291,7 @@ class AnonymousObjectTransformer(
remapper,
isSameModule,
"Transformer for " + transformationInfo.oldClassName,
sourceMapper,
SourceMapCopier(sourceMapper, sourceMap),
InlineCallSiteInfo(
transformationInfo.oldClassName,
sourceNode.name,

View File

@@ -30,14 +30,14 @@ import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getLoadStoreArgSize;
public class InlineAdapter extends InstructionAdapter {
private final SourceMapper sourceMapper;
private final SourceMapCopier sourceMapper;
private final List<CatchBlock> blocks = new ArrayList<>();
private boolean isLambdaInlining = false;
private int nextLocalIndex = 0;
private int nextLocalIndexBeforeInline = -1;
public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) {
public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapCopier sourceMapper) {
super(Opcodes.API_VERSION, mv);
this.nextLocalIndex = localsSize;
this.sourceMapper = sourceMapper;

View File

@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -24,7 +25,9 @@ import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
@@ -72,7 +75,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
var activeLambda: LambdaInfo? = null
protected set
private val defaultSourceMapper = sourceCompiler.lazySourceMapper
private val sourceMapper = sourceCompiler.lazySourceMapper
protected var delayedHiddenWriting: Function0<Unit>? = null
@@ -208,7 +211,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean, isCallOfFunctionInCorrespondingDefaultDispatch: Boolean): InlineResult {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
val node = nodeAndSmap.node
if (inlineDefaultLambda) {
for (lambda in extractDefaultLambdas(node)) {
@@ -230,11 +232,13 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
)
val sourceInfo = sourceMapper.sourceInfo!!
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.source, sourceInfo.pathOrCleanFQN)
val inliner = MethodInliner(
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + sourceCompiler.callElementText,
NestedSourceMapper(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo,
if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, callSite.takeIf { !isCallOfFunctionInCorrespondingDefaultDispatch }),
info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
!isInlinedToInlineFunInKotlinRuntime()
) //with captured
@@ -269,9 +273,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
if (shouldSpillStack) {
addInlineMarker(codegen.v, false)
}
if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = null
return result
}
@@ -616,7 +617,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
callableDescriptor.name.asString() == "arrayOf" -> IntrinsicArrayConstructors.generateArrayOfBody(asmMethod)
else -> throw UnsupportedOperationException("Not an array intrinsic: $callableDescriptor")
}
return SMAPAndMethodNode(body, SMAP(listOf(FileMapping.SKIP)))
return SMAPAndMethodNode(body, SMAP(listOf()))
}
assert(callableDescriptor is DescriptorWithContainerSource) { "Not a deserialized function or proper: $callableDescriptor" }
@@ -631,8 +632,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
}
val methodNode =
getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, AsmUtil.asmTypeByClassId(containerId)) ?: return null
val methodNode = getMethodNodeInner(containerId, bytes, asmMethod, callableDescriptor) ?: return null
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
@@ -643,6 +643,28 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return methodNode
}
private fun getMethodNodeInner(
containerId: ClassId,
bytes: ByteArray,
asmMethod: Method,
callableDescriptor: CallableMemberDescriptor
): SMAPAndMethodNode? {
val classType = AsmUtil.asmTypeByClassId(containerId)
var methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType)
if (methodNode == null && requiresFunctionNameManglingForReturnType(callableDescriptor)) {
val nameWithoutManglingSuffix = asmMethod.name.stripManglingSuffixOrNull()
if (nameWithoutManglingSuffix != null) {
methodNode = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType)
}
}
return methodNode
}
private fun String.stripManglingSuffixOrNull(): String? {
val dashIndex = indexOf('-')
return if (dashIndex < 0) null else substring(0, dashIndex)
}
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
if (callableDescriptor is FictitiousArrayConstructor) return true
val name = callableDescriptor.name.asString()

View File

@@ -42,7 +42,7 @@ class InlineCodegenForDefaultBody(
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
)
val childSourceMapper = NestedSourceMapper(sourceMapper, nodeAndSmap.classSMAP, sameFile = true)
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)
val node = nodeAndSmap.node
val transformedMethod = MethodNode(

View File

@@ -54,7 +54,7 @@ class MethodInliner(
private val nodeRemapper: FieldRemapper,
private val isSameModule: Boolean,
private val errorPrefix: String,
private val sourceMapper: SourceMapper,
private val sourceMapper: SourceMapCopier,
private val inlineCallSiteInfo: InlineCallSiteInfo,
private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root
private val shouldPreprocessApiVersionCalls: Boolean = false
@@ -278,7 +278,7 @@ class MethodInliner(
visitInsn(Opcodes.NOP)
}
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info)
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info, sourceMapper.parent)
addInlineMarker(this, true)
val lambdaParameters = info.addAllParameters(nodeRemapper)
@@ -288,20 +288,14 @@ class MethodInliner(
)
setLambdaInlining(true)
val lambdaSMAP = info.node.classSMAP
val childSourceMapper =
if (inliningContext.classRegeneration && !inliningContext.isInliningLambda)
NestedSourceMapper(sourceMapper, lambdaSMAP)
else
NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP, sameFile = info !is DefaultLambda)
val callSite = sourceMapper.callSite.takeIf { info is DefaultLambda }
val inliner = MethodInliner(
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
newCapturedRemapper,
if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/,
"Lambda inlining " + info.lambdaClassType.internalName,
childSourceMapper, inlineCallSiteInfo, null
SourceMapCopier(sourceMapper.parent, info.node.classSMAP, callSite), inlineCallSiteInfo, null
)
val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift)

View File

@@ -47,7 +47,7 @@ class PsiInlineIntrinsicsSupport(private val state: GenerationState) : ReifiedTy
v.aconst(descriptor.arity)
generateCallableReferenceDeclarationContainerClass(v, descriptor, state)
v.aconst(descriptor.name.asString())
generateCallableReferenceSignature(v, descriptor, state)
generateFunctionReferenceSignature(v, descriptor, state)
v.aconst(getCallableReferenceTopLevelFlag(descriptor))
v.invokespecial(
FUNCTION_REFERENCE_IMPL.internalName, "<init>",

View File

@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.codegen.inline
import gnu.trove.TIntIntHashMap
import org.jetbrains.kotlin.codegen.SourceInfo
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
import kotlin.math.max
@@ -17,185 +16,100 @@ const val KOTLIN_DEBUG_STRATA_NAME = "KotlinDebug"
object SMAPBuilder {
fun build(fileMappings: List<FileMapping>, backwardsCompatibleSyntax: Boolean): String? {
val realMappings = fileMappings.filter { it.lineMappings.isNotEmpty() && it != FileMapping.SKIP }
if (realMappings.isEmpty()) {
if (fileMappings.isEmpty()) {
return null
}
val defaultStrata = generateDefaultStrata(realMappings)
val debugStrata = generateDebugStrata(realMappings)
val debugMappings = linkedMapOf<Pair<String, String>, FileMapping>()
for (fileMapping in fileMappings) {
for ((_, dest, range, callSite) in fileMapping.lineMappings) {
callSite?.let { (line, file, path) ->
debugMappings.getOrPut(file to path) { FileMapping(file, path) }.mapNewInterval(line, dest, range)
}
}
}
// Old versions of kotlinc and the IDEA plugin have incorrect implementations of SMAPParser:
// 1. they require *E between strata, which is not correct syntax according to JSR-045;
// 2. in KotlinDebug, they use `1#2,3:4` to mean "map lines 4..6 to line 1 of #2", when in reality (and in
// the non-debug stratum) this maps lines 4..6 to lines 1..3. The correct syntax is `1#2:4,3`.
val defaultStrata = fileMappings.toSMAP(KOTLIN_STRATA_NAME, mapToFirstLine = false)
val debugStrata = debugMappings.values.toSMAP(KOTLIN_DEBUG_STRATA_NAME, mapToFirstLine = !backwardsCompatibleSyntax)
if (backwardsCompatibleSyntax && defaultStrata.isNotEmpty() && debugStrata.isNotEmpty()) {
// Old versions of kotlinc might fail if there is no END between defaultStrata and debugStrata.
// This is not actually correct syntax according to JSR-045.
return "SMAP\n${fileMappings[0].name}\n$KOTLIN_STRATA_NAME\n$defaultStrata${SMAP.END}\n$debugStrata${SMAP.END}\n"
}
return "SMAP\n${fileMappings[0].name}\n$KOTLIN_STRATA_NAME\n$defaultStrata$debugStrata${SMAP.END}\n"
}
private fun generateDefaultStrata(realMappings: List<FileMapping>): String {
val fileData = realMappings.mapIndexed { id, file -> file.toSMAPFile(id + 1) }.joinToString("")
val lineData = realMappings.mapIndexed { id, file -> file.toSMAPMapping(id + 1) }.joinToString("")
return "${SMAP.STRATA_SECTION} $KOTLIN_STRATA_NAME\n${SMAP.FILE_SECTION}\n$fileData${SMAP.LINE_SECTION}\n$lineData"
}
private fun Collection<FileMapping>.toSMAP(stratumName: String, mapToFirstLine: Boolean): String = if (isEmpty()) "" else
"${SMAP.STRATA_SECTION} $stratumName\n" +
"${SMAP.FILE_SECTION}\n${mapIndexed { id, file -> file.toSMAPFile(id + 1) }.joinToString("")}" +
"${SMAP.LINE_SECTION}\n${mapIndexed { id, file -> file.toSMAPMapping(id + 1, mapToFirstLine) }.joinToString("")}"
private fun generateDebugStrata(realMappings: List<FileMapping>): String {
val combinedMapping = FileMapping(realMappings[0].name, realMappings[0].path)
for (fileMapping in realMappings) {
for ((_, dest, range, callSiteMarker) in fileMapping.lineMappings) {
callSiteMarker?.let { combinedMapping.mapNewInterval(it.lineNumber, dest, range) }
}
}
if (combinedMapping.lineMappings.isEmpty()) return ""
val fileData = combinedMapping.toSMAPFile(1)
// TODO: this generates entries like `1#2,3:4` which means "map lines 4..6 to lines 1..3 of file #2".
// What we want is `1#2:4,3`, i.e. "map lines 4..6 to line 1 of #2", but currently IDEA cannot handle that.
val lineData = combinedMapping.toSMAPMapping(1)
return "${SMAP.STRATA_SECTION} $KOTLIN_DEBUG_STRATA_NAME\n${SMAP.FILE_SECTION}\n$fileData${SMAP.LINE_SECTION}\n$lineData"
}
private fun RangeMapping.toSMAP(fileId: Int): String =
if (range == 1) "$source#$fileId:$dest\n" else "$source#$fileId,$range:$dest\n"
private fun RangeMapping.toSMAP(fileId: Int, oneLine: Boolean): String =
if (range == 1) "$source#$fileId:$dest\n" else if (oneLine) "$source#$fileId:$dest,$range\n" else "$source#$fileId,$range:$dest\n"
private fun FileMapping.toSMAPFile(id: Int): String =
"+ $id $name\n$path\n"
private fun FileMapping.toSMAPMapping(id: Int): String =
lineMappings.joinToString("") { it.toSMAP(id) }
private fun FileMapping.toSMAPMapping(id: Int, mapToFirstLine: Boolean): String =
lineMappings.joinToString("") { it.toSMAP(id, mapToFirstLine) }
}
class NestedSourceMapper(
override val parent: SourceMapper, private val smap: SMAP, private val sameFile: Boolean = false
) : DefaultSourceMapper(smap.sourceInfo) {
class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, val callSite: SourcePosition? = null) {
private val visitedLines = TIntIntHashMap()
private var lastVisitedRange: RangeMapping? = null
override fun mapLineNumber(lineNumber: Int): Int {
if (lineNumber in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) {
return lineNumber
}
if (sameFile && lineNumber <= smap.sourceInfo.linesInFile) {
// assuming the parent source mapper is for the same file, this line number does not need remapping
return lineNumber
}
fun mapLineNumber(lineNumber: Int): Int {
val mappedLineNumber = visitedLines.get(lineNumber)
if (mappedLineNumber > 0) {
return mappedLineNumber
}
val range = lastVisitedRange?.takeIf { lineNumber in it }
?: smap.findRange(lineNumber)
?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}")
val sourceLineNumber = range.mapDestToSource(lineNumber)
val newLineNumber = if (sameFile)
parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path, range.callSiteMarker)
else
parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path)
if (newLineNumber > 0) {
visitedLines.put(lineNumber, newLineNumber)
}
val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) ?: return -1
lastVisitedRange = range
val newLineNumber = parent.mapLineNumber(range.mapDestToSource(lineNumber), callSite ?: range.callSite)
visitedLines.put(lineNumber, newLineNumber)
return newLineNumber
}
}
interface SourceMapper {
val resultMappings: List<FileMapping>
val parent: SourceMapper?
get() = null
data class SourcePosition(val line: Int, val file: String, val path: String)
fun mapLineNumber(lineNumber: Int): Int
fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int =
mapLineNumber(source, sourceName, sourcePath, null)
fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int
companion object {
fun createFromSmap(smap: SMAP): SourceMapper {
return DefaultSourceMapper(smap.sourceInfo, smap.fileMappings)
}
}
}
object IdenticalSourceMapper : SourceMapper {
override val resultMappings: List<FileMapping>
get() = emptyList()
override val parent: SourceMapper?
get() = null
override fun mapLineNumber(lineNumber: Int) = lineNumber
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int =
throw UnsupportedOperationException(
"IdenticalSourceMapper#mapLineNumber($source, $sourceName, $sourcePath)\n"
+ "This mapper should not encounter a line number out of range of the current file.\n"
+ "This indicates that SMAP generation is missed somewhere."
)
}
data class CallSiteMarker(val lineNumber: Int)
open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper {
private var maxUsedValue: Int = sourceInfo.linesInFile
class SourceMapper(val sourceInfo: SourceInfo?) {
private var maxUsedValue: Int = sourceInfo?.linesInFile ?: 0
private var fileMappings: LinkedHashMap<Pair<String, String>, FileMapping> = linkedMapOf()
var callSiteMarker: CallSiteMarker? = null
override val resultMappings: List<FileMapping>
val resultMappings: List<FileMapping>
get() = fileMappings.values.toList()
init {
// Explicitly map the file to itself.
getOrRegisterNewSource(sourceInfo.source, sourceInfo.pathOrCleanFQN).mapNewInterval(1, 1, sourceInfo.linesInFile)
}
constructor(sourceInfo: SourceInfo, fileMappings: List<FileMapping>) : this(sourceInfo) {
// The first mapping is already created in the `init` block above.
fileMappings.asSequence().drop(1)
.forEach { fileMapping ->
val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path)
fileMapping.lineMappings.forEach {
newFileMapping.mapNewInterval(it.source, it.dest, it.range)
maxUsedValue = max(it.maxDest, maxUsedValue)
}
}
}
private fun getOrRegisterNewSource(name: String, path: String): FileMapping {
return fileMappings.getOrPut(name to path) { FileMapping(name, path) }
}
//TODO maybe add assertion that linenumber contained in fileMappings
override fun mapLineNumber(lineNumber: Int): Int = lineNumber
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int =
mapLineNumber(source, sourceName, sourcePath, callSiteMarker)
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int {
if (source < 0) {
//no source information, so just skip this linenumber
return -1
sourceInfo?.let {
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges.
getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile)
}
val fileMapping = getOrRegisterNewSource(sourceName, sourcePath)
val mappedLineIndex = fileMapping.mapNewLineNumber(source, maxUsedValue, callSiteMarker)
}
val isTrivial: Boolean
get() = maxUsedValue == 0 || maxUsedValue == sourceInfo?.linesInFile
private fun getOrRegisterNewSource(name: String, path: String): FileMapping =
fileMappings.getOrPut(name to path) { FileMapping(name, path) }
fun mapLineNumber(inlineSource: SourcePosition, inlineCallSite: SourcePosition?): Int {
val fileMapping = getOrRegisterNewSource(inlineSource.file, inlineSource.path)
val mappedLineIndex = fileMapping.mapNewLineNumber(inlineSource.line, maxUsedValue, inlineCallSite)
maxUsedValue = max(maxUsedValue, mappedLineIndex)
return mappedLineIndex
}
fun mapSyntheticLineNumber(id: Int): Int {
return mapLineNumber(SourcePosition(id, "fake.kt", "kotlin/jvm/internal/FakeKt"), null)
}
}
class SMAP(val fileMappings: List<FileMapping>) {
val sourceInfo: SourceInfo = run {
assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" }
val defaultFile = fileMappings.first()
val defaultRange = defaultFile.lineMappings.first()
SourceInfo(defaultFile.name, defaultFile.path, defaultRange.source + defaultRange.range - 1)
}
// assuming disjoint line mappings (otherwise binary search can't be used anyway)
private val intervals = fileMappings.flatMap { it.lineMappings }.sortedBy { it.dest }
@@ -217,54 +131,40 @@ data class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP)
class FileMapping(val name: String, val path: String) {
val lineMappings = arrayListOf<RangeMapping>()
fun mapNewLineNumber(source: Int, currentIndex: Int, callSiteMarker: CallSiteMarker?): Int {
var mapping = lineMappings.lastOrNull()
if (mapping != null && mapping.callSiteMarker == callSiteMarker &&
(source - mapping.source) in 0 until mapping.range + (if (mapping.maxDest == currentIndex) 10 else 0)
) {
// Save some space in the SMAP by reusing (or extending if it's the last one) the existing range.
mapping.range = max(mapping.range, source - mapping.source + 1)
} else {
mapping = mapNewInterval(source, currentIndex + 1, 1, callSiteMarker)
}
fun toSourceInfo(): SourceInfo =
SourceInfo(name, path, lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) })
fun mapNewLineNumber(source: Int, currentIndex: Int, callSite: SourcePosition?): Int {
// Save some space in the SMAP by reusing (or extending if it's the last one) the existing range.
// TODO some *other* range may already cover `source`; probably too slow to check them all though.
// Maybe keep the list ordered by `source` and use binary search to locate the closest range on the left?
val mapping = lineMappings.lastOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSite) }
?: lineMappings.firstOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSite) }
?: mapNewInterval(source, currentIndex + 1, 1, callSite)
mapping.range = max(mapping.range, source - mapping.source + 1)
return mapping.mapSourceToDest(source)
}
fun mapNewInterval(source: Int, dest: Int, range: Int, callSiteMarker: CallSiteMarker? = null): RangeMapping =
RangeMapping(source, dest, range, callSiteMarker, parent = this).also { lineMappings.add(it) }
private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: SourcePosition?): Boolean =
callSite == newCallSite && (newSource - source) in 0 until range + (if (globalMaxDest in this) 10 else 0)
companion object {
val SKIP = FileMapping("no-source-info", "no-source-info").apply {
mapNewInterval(-1, -1, 1)
}
}
fun mapNewInterval(source: Int, dest: Int, range: Int, callSite: SourcePosition? = null): RangeMapping =
RangeMapping(source, dest, range, callSite, parent = this).also { lineMappings.add(it) }
}
data class RangeMapping(
val source: Int, val dest: Int, var range: Int, val callSiteMarker: CallSiteMarker?,
val parent: FileMapping
) {
private val skip = source == -1 && dest == -1
data class RangeMapping(val source: Int, val dest: Int, var range: Int, val callSite: SourcePosition?, val parent: FileMapping) {
operator fun contains(destLine: Int): Boolean =
dest <= destLine && destLine < dest + range
val maxDest: Int
get() = dest + range - 1
fun hasMappingForSource(sourceLine: Int): Boolean =
source <= sourceLine && sourceLine < source + range
operator fun contains(destLine: Int): Boolean {
return skip || (dest <= destLine && destLine < dest + range)
}
fun mapDestToSource(destLine: Int): SourcePosition =
SourcePosition(source + (destLine - dest), parent.name, parent.path)
fun hasMappingForSource(sourceLine: Int): Boolean {
return skip || (source <= sourceLine && sourceLine < source + range)
}
fun mapDestToSource(destLine: Int): Int {
return if (skip) -1 else source + (destLine - dest)
}
fun mapSourceToDest(sourceLine: Int): Int {
return if (skip) -1 else dest + (sourceLine - source)
}
fun mapSourceToDest(sourceLine: Int): Int =
dest + (sourceLine - source)
}
val RangeMapping.toRange: IntRange
get() = this.dest..this.maxDest
get() = dest until dest + range

View File

@@ -21,60 +21,64 @@ object SMAPParser {
@JvmStatic
fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
if (mappingInfo != null && mappingInfo.isNotEmpty()) {
return parse(mappingInfo)
parseOrNull(mappingInfo)?.let { return it }
}
if (source == null || source.isEmpty() || methodStartLine > methodEndLine) {
return SMAP(listOf())
}
val mapping = FileMapping(source, path).apply {
mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)
}
val mapping =
if (source == null || source.isEmpty() || methodStartLine > methodEndLine)
FileMapping.SKIP
else
FileMapping(source, path).apply {
if (methodStartLine <= methodEndLine) {
//one to one
mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)
}
}
return SMAP(listOf(mapping))
}
@JvmStatic
fun parse(mappingInfo: String): SMAP {
fun parseOrNull(mappingInfo: String): SMAP? =
parseStratum(mappingInfo, KOTLIN_STRATA_NAME, parseStratum(mappingInfo, KOTLIN_DEBUG_STRATA_NAME, null))
private fun parseStratum(mappingInfo: String, stratum: String, callSites: SMAP?): SMAP? {
val fileMappings = linkedMapOf<Int, FileMapping>()
val iterator = mappingInfo.lineSequence().dropWhile { it != "${SMAP.STRATA_SECTION} $stratum" }.drop(1).iterator()
// JSR-045 allows the line section to come before the file section, but we don't generate SMAPs like this.
if (!iterator.hasNext() || iterator.next() != SMAP.FILE_SECTION) return null
// Assuming we want the first stratum (which should be "Kotlin" for Kotlin classes, though you never know).
// Also, JSR-045 allows the line section to come before the file section, but we don't generate SMAPs like this.
val iterator = mappingInfo.lineSequence().dropWhile { it.trim() != SMAP.FILE_SECTION }.drop(1).iterator()
while (iterator.hasNext()) {
val fileDeclaration = iterator.next().trim()
if (fileDeclaration == SMAP.LINE_SECTION) break
if (!fileDeclaration.startsWith('+')) {
throw AssertionError("File declaration should be in extended form, but: $fileDeclaration in $mappingInfo")
for (line in iterator) {
when {
line == SMAP.LINE_SECTION -> break
line == SMAP.FILE_SECTION || line == SMAP.END || line.startsWith(SMAP.STRATA_SECTION) -> return null
}
val indexAndFileInternalName = fileDeclaration.substringAfter("+ ").trim()
val indexAndFileInternalName = if (line.startsWith("+ ")) line.substring(2) else line
val fileIndex = indexAndFileInternalName.substringBefore(' ').toInt()
val fileName = indexAndFileInternalName.substringAfter(' ')
val path = iterator.next().trim()
val path = if (line.startsWith("+ ")) iterator.next() else fileName
fileMappings[fileIndex] = FileMapping(fileName, path)
}
for (lineMapping in iterator) {
// The stratum is terminated either by *E or another stratum.
if (lineMapping.trim().startsWith("*")) break
/*only simple mapping now*/
val targetSplit = lineMapping.indexOf(':')
val originalPart = lineMapping.substring(0, targetSplit)
val rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it }
for (line in iterator) {
when {
line == SMAP.LINE_SECTION || line == SMAP.FILE_SECTION -> return null
line == SMAP.END || line.startsWith(SMAP.STRATA_SECTION) -> break
}
val fileSeparator = lineMapping.indexOf('#')
val originalIndex = originalPart.substring(0, fileSeparator).toInt()
val range = if (rangeSeparator == targetSplit) 1 else originalPart.substring(rangeSeparator + 1, targetSplit).toInt()
// <source>#<file>,<sourceRange>:<dest>,<destMultiplier>
val fileSeparator = line.indexOf('#')
if (fileSeparator < 0) return null
val destSeparator = line.indexOf(':', fileSeparator)
if (destSeparator < 0) return null
val sourceRangeSeparator = line.indexOf(',').let { if (it !in fileSeparator..destSeparator) destSeparator else it }
val destMultiplierSeparator = line.indexOf(',', destSeparator).let { if (it < 0) line.length else it }
val fileIndex = lineMapping.substring(fileSeparator + 1, rangeSeparator).toInt()
val targetIndex = lineMapping.substring(targetSplit + 1).toInt()
fileMappings[fileIndex]!!.mapNewInterval(originalIndex, targetIndex, range)
val file = fileMappings[line.substring(fileSeparator + 1, sourceRangeSeparator).toInt()] ?: return null
val source = line.substring(0, fileSeparator).toInt()
val dest = line.substring(destSeparator + 1, destMultiplierSeparator).toInt()
val range = when {
// These two fields have a different meaning, but for compatibility we treat them the same. See `SMAPBuilder`.
destMultiplierSeparator != line.length -> line.substring(destMultiplierSeparator + 1).toInt()
sourceRangeSeparator != destSeparator -> line.substring(sourceRangeSeparator + 1, destSeparator).toInt()
else -> 1
}
// Here we assume that each range in `Kotlin` is entirely within at most one range in `KotlinDebug`.
file.mapNewInterval(source, dest, range, callSites?.findRange(dest)?.let { it.mapDestToSource(it.dest) })
}
return SMAP(fileMappings.values.toList())

View File

@@ -46,7 +46,7 @@ interface SourceCompilerForInline {
val inlineCallSiteInfo: InlineCallSiteInfo
val lazySourceMapper: DefaultSourceMapper
val lazySourceMapper: SourceMapper
fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode
@@ -212,18 +212,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
}
return createSMAPWithDefaultMapping(expression, parentCodegen.orCreateSourceMapper.resultMappings)
}
private fun createSMAPWithDefaultMapping(
declaration: KtExpression,
mappings: List<FileMapping>
): SMAP {
val containingFile = declaration.containingFile
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in $containingFile")
return SMAP(mappings)
return SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
}
@Suppress("UNCHECKED_CAST")
@@ -310,7 +299,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
)
createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
} else {
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
}

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil
import jdk.internal.org.objectweb.asm.Type
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.coroutines.*
import org.jetbrains.kotlin.codegen.inline.*
@@ -14,12 +15,14 @@ import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
const val FOR_INLINE_SUFFIX = "\$\$forInline"
@@ -187,8 +190,7 @@ fun markNoinlineLambdaIfSuspend(mv: MethodVisitor, info: FunctionalArgument?) {
}
}
private fun Frame<SourceValue>.getSource(offset: Int): AbstractInsnNode? =
getStack(stackSize - offset - 1)?.insns?.singleOrNull()
private fun Frame<BasicValue>.getSource(offset: Int): AbstractInsnNode? = (getStack(stackSize - offset - 1) as? PossibleLambdaLoad)?.insn
fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode) {
val markers = node.instructions.asSequence().filter {
@@ -196,14 +198,14 @@ fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode) {
}.toList()
if (markers.isEmpty()) return
val sourceFrames = MethodTransformer.analyze("fake", node, SourceInterpreter())
val sourceFrames = MethodTransformer.analyze("fake", node, CapturedLambdaInterpreter())
val loads = markers.map { marker ->
val arity = (marker.next as MethodInsnNode).owner.removePrefix(NUMBERED_FUNCTION_PREFIX).toInt()
var receiver = sourceFrames[node.instructions.indexOf(marker) + 1].getSource(arity)
// Navigate the ALOAD+GETFIELD+... chain to the first instruction. We need to insert a stack
// spilling marker before it starts.
while (receiver?.opcode == Opcodes.GETFIELD) {
receiver = sourceFrames[node.instructions.indexOf(receiver)].getSource(0)
receiver = receiver.previous
}
receiver
}
@@ -244,3 +246,39 @@ fun FieldInsnNode.isSuspendLambdaCapturedByOuterObjectOrLambda(inliningContext:
}
return isCapturedSuspendLambda(container, name, inliningContext.state.bindingContext)
}
// Interpreter, that keeps track of captured functional arguments
private class PossibleLambdaLoad(val insn: AbstractInsnNode) : BasicValue(AsmTypes.OBJECT_TYPE)
private class CapturedLambdaInterpreter : BasicInterpreter(Opcodes.API_VERSION) {
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
if (insn.opcode == Opcodes.GETSTATIC) {
insn.fieldLoad()?.let { return it }
}
return super.newOperation(insn)
}
private fun AbstractInsnNode.fieldLoad(): PossibleLambdaLoad? {
if (this !is FieldInsnNode) return null
if (desc.startsWith('L') && Type.getType(desc).internalName.isNumberedFunctionInternalName()) {
if ((opcode == Opcodes.GETSTATIC && name.startsWith(CAPTURED_FIELD_FOLD_PREFIX + CAPTURED_FIELD_PREFIX)) ||
(opcode == Opcodes.GETFIELD && isCapturedFieldName(name))
) return PossibleLambdaLoad(this)
}
return null
}
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
if (insn.opcode == Opcodes.ALOAD) PossibleLambdaLoad(insn) else super.copyOperation(insn, value)
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
if (insn.opcode == Opcodes.GETFIELD) {
insn.fieldLoad()?.let { return it }
}
return super.unaryOperation(insn, value)
}
override fun merge(v: BasicValue?, w: BasicValue?): BasicValue? =
if (v is PossibleLambdaLoad && w is PossibleLambdaLoad && v.insn == w.insn) v else super.merge(v, w)
}

View File

@@ -92,12 +92,8 @@ internal fun getMethodNode(
val cr = ClassReader(classData)
var node: MethodNode? = null
val debugInfo = arrayOfNulls<String>(2)
val lines = IntArray(2)
lines[0] = Integer.MAX_VALUE
lines[1] = Integer.MIN_VALUE
cr.accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitSource(source: String?, debug: String?) {
super.visitSource(source, debug)
debugInfo[0] = source
@@ -123,16 +119,8 @@ internal fun getMethodNode(
node?.let { existing ->
throw AssertionError("Can't find proper '$name' method for inline: ambiguity between '${existing.name + existing.desc}' and '${name + desc}'")
}
return object : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
override fun visitLineNumber(line: Int, start: Label) {
super.visitLineNumber(line, start)
lines[0] = min(lines[0], line)
lines[1] = max(lines[1], line)
}
}.also {
node = it
}
node = MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions)
return node!!
}
}, ClassReader.SKIP_FRAMES or if (GENERATE_SMAP) 0 else ClassReader.SKIP_DEBUG)
@@ -140,10 +128,25 @@ internal fun getMethodNode(
return null
}
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, lines[0], lines[1])
val (first, last) = listOfNotNull(node).lineNumberRange()
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, first, last)
return SMAPAndMethodNode(node!!, smap)
}
internal fun Collection<MethodNode>.lineNumberRange(): Pair<Int, Int> {
var minLine = Int.MAX_VALUE
var maxLine = Int.MIN_VALUE
for (node in this) {
for (insn in node.instructions.asSequence()) {
if (insn is LineNumberNode) {
minLine = min(minLine, insn.line)
maxLine = max(maxLine, insn.line)
}
}
}
return minLine to maxLine
}
internal fun findVirtualFile(state: GenerationState, classId: ClassId): VirtualFile? {
return VirtualFileFinder.getInstance(state.project, state.module).findVirtualFileWithHeader(classId)
}
@@ -202,11 +205,12 @@ private fun getInlineName(
}
internal fun isInvokeOnLambda(owner: String, name: String): Boolean {
return OperatorNameConventions.INVOKE.asString() == name &&
owner.startsWith(NUMBERED_FUNCTION_PREFIX) &&
owner.substring(NUMBERED_FUNCTION_PREFIX.length).isInteger()
return OperatorNameConventions.INVOKE.asString() == name && owner.isNumberedFunctionInternalName()
}
internal fun String.isNumberedFunctionInternalName(): Boolean =
startsWith(NUMBERED_FUNCTION_PREFIX) && substring(NUMBERED_FUNCTION_PREFIX.length).isInteger()
internal fun isAnonymousConstructorCall(internalName: String, methodName: String): Boolean =
isConstructor(methodName) && isAnonymousClass(internalName)
@@ -538,7 +542,11 @@ internal fun isThis0(name: String): Boolean = AsmUtil.CAPTURED_THIS_FIELD == nam
class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
private val callLineNumber = codegen.lastLineNumber
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo) {
companion object {
const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1
}
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo, smap: SourceMapper) {
val firstLine = info.node.node.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
if (callLineNumber >= 0 && firstLine == callLineNumber) {
// We want the debugger to be able to break both on the inline call itself, plus on each
@@ -549,7 +557,7 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
// number that is remapped by the SMAP to a line that does not exist.
val label = Label()
mv.visitLabel(label)
mv.visitLineNumber(JvmAbi.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER, label)
mv.visitLineNumber(smap.mapSyntheticLineNumber(LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER), label)
}
}
@@ -562,22 +570,6 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
}
}
fun initDefaultSourceMappingIfNeeded(
context: CodegenContext<*>, codegen: MemberCodegen<*>, state: GenerationState
) {
if (state.isInlineDisabled) return
var parentContext: CodegenContext<*>? = context.parentContext
while (parentContext != null) {
if (parentContext.isInlineMethodContext) {
//just init default one to one mapping
codegen.orCreateSourceMapper
break
}
parentContext = parentContext.parentContext
}
}
fun MethodNode.preprocessSuspendMarkers(forInline: Boolean, keepFakeContinuation: Boolean = true) {
if (instructions.first == null) return
if (!keepFakeContinuation) {

View File

@@ -51,10 +51,11 @@ private constructor(
private val INT_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Int", Type.INT_TYPE)
private val LONG_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Long", Type.LONG_TYPE)
private val UINT_PROGRESSION_ITERATOR_VALUE =
ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt"))
private val ULONG_PROGRESSION_ITERATOR_VALUE =
ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong"))
// TODO functions returning inline classes are mangled now, should figure out how to work with UInt/ULong iterators here
// private val UINT_PROGRESSION_ITERATOR_VALUE =
// ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt"))
// private val ULONG_PROGRESSION_ITERATOR_VALUE =
// ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong"))
private val PROGRESSION_CLASS_NAME_TO_ITERATOR_VALUE: Map<String, ProgressionIteratorBasicValue> =
hashMapOf(
@@ -64,10 +65,10 @@ private constructor(
INT_PROGRESSION_FQN to INT_PROGRESSION_ITERATOR_VALUE,
LONG_RANGE_FQN to LONG_PROGRESSION_ITERATOR_VALUE,
LONG_PROGRESSION_FQN to LONG_PROGRESSION_ITERATOR_VALUE,
UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE,
ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE
// UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
// UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
// ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE,
// ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE
)
fun byProgressionClassType(progressionClassType: Type): ProgressionIteratorBasicValue? =

View File

@@ -0,0 +1,11 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>

View File

@@ -0,0 +1,11 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>

View File

@@ -60,7 +60,7 @@ fun analyzeLiveness(node: MethodNode): List<VariableLivenessFrame> {
private fun analyzeVisibleByDebuggerVariables(
node: MethodNode,
typeAnnotatedFrames: Array<Frame<BasicValue>?>
typeAnnotatedFrames: TypeAnnotatedFrames
): Array<BitSet> {
val res = Array(node.instructions.size()) { BitSet(node.maxLocals) }
for (local in node.localVariables) {

View File

@@ -34,16 +34,13 @@ abstract class AbstractForInProgressionLoopGenerator(
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
protected var incrementVar: Int = -1
protected val asmLoopRangeType: Type
protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!!
protected val asmLoopRangeType: Type = codegen.asmType(rangeKotlinType)
private val rangeElementKotlinType = getRangeOrProgressionElementType(rangeKotlinType)
?: throw AssertionError("Unexpected loop range type: $rangeKotlinType")
private val incrementKotlinType: KotlinType
protected val incrementType: Type
init {
asmLoopRangeType = codegen.asmType(rangeKotlinType)
val incrementProp = rangeKotlinType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND)
assert(incrementProp.size == 1) { rangeKotlinType.toString() + " " + incrementProp.size }
incrementKotlinType = incrementProp.single().type

View File

@@ -17,8 +17,12 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
@@ -28,6 +32,8 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
private var loopParameter: StackValue? = null
protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!!
init {
assert(
asmElementType.sort == Type.INT ||
@@ -36,7 +42,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
asmElementType.sort == Type.CHAR ||
asmElementType.sort == Type.LONG
) {
"Unexpected range element type: " + asmElementType
"Unexpected range element type: $asmElementType"
}
}
@@ -48,7 +54,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
protected fun checkPostCondition(loopExit: Label) {
assert(endVar != -1) {
"endVar must be allocated, endVar = " + endVar
"endVar must be allocated, endVar = $endVar"
}
loopParameter().put(asmElementType, elementType, v)
v.load(endVar, asmElementType)
@@ -64,4 +70,14 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
protected fun loopParameter(): StackValue =
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
protected fun KotlinType.getPropertyGetterName(propertyName: String): String {
// In case of unsigned ranges, getter methods for corresponding range/progression properties would be mangled.
val propertyDescriptor = memberScope.getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND)
.singleOrNull()
?: throw AssertionError("No '$propertyName' in member scope of type $this")
val getter = propertyDescriptor.getter
?: throw AssertionError("Property has no getter: $propertyDescriptor")
return codegen.typeMapper.mapFunctionName(getter, OwnerKind.IMPLEMENTATION)
}
}

View File

@@ -31,8 +31,12 @@ class ForInProgressionExpressionLoopGenerator(
v.dup()
v.dup()
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar)
val firstName = rangeKotlinType.getPropertyGetterName("first")
val lastName = rangeKotlinType.getPropertyGetterName("last")
val stepName = rangeKotlinType.getPropertyGetterName("step")
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, stepName, incrementType, incrementType, incrementVar)
}
}

View File

@@ -17,9 +17,13 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.types.KotlinType
class ForInRangeInstanceLoopGenerator(
codegen: ExpressionCodegen,
@@ -30,18 +34,21 @@ class ForInRangeInstanceLoopGenerator(
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1, comparisonGenerator) {
override fun storeRangeStartAndEnd() {
val loopRangeType = codegen.bindingContext.getType(rangeExpression)!!
val asmLoopRangeType = codegen.asmType(loopRangeType)
codegen.gen(rangeExpression, asmLoopRangeType, loopRangeType)
val asmLoopRangeType = codegen.asmType(rangeKotlinType)
codegen.gen(rangeExpression, asmLoopRangeType, rangeKotlinType)
v.dup()
val firstName = rangeKotlinType.getPropertyGetterName("first")
val lastName = rangeKotlinType.getPropertyGetterName("last")
// ranges inherit first and last from corresponding progressions
if (reversed) {
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, asmElementType, endVar)
} else {
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar)
}
}
}

View File

@@ -32,6 +32,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.DescriptorSerializer.Companion.writeVersionRequirement
import org.jetbrains.kotlin.serialization.SerializerExtension
@@ -54,8 +56,10 @@ class JvmSerializerExtension @JvmOverloads constructor(
private val languageVersionSettings = state.languageVersionSettings
private val isParamAssertionsDisabled = state.isParamAssertionsDisabled
private val unifiedNullChecks = state.unifiedNullChecks
private val functionsWithInlineClassReturnTypesMangled = state.functionsWithInlineClassReturnTypesMangled
override val metadataVersion = state.metadataVersion
private val jvmDefaultMode = state.jvmDefaultMode
private val approximator = state.typeApproximator
override fun shouldUseTypeTable(): Boolean = useTypeTable
override fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean {
@@ -75,17 +79,17 @@ class JvmSerializerExtension @JvmOverloads constructor(
}
override fun serializeClass(
descriptor: ClassDescriptor,
proto: ProtoBuf.Class.Builder,
versionRequirementTable: MutableVersionRequirementTable,
childSerializer: DescriptorSerializer
descriptor: ClassDescriptor,
proto: ProtoBuf.Class.Builder,
versionRequirementTable: MutableVersionRequirementTable,
childSerializer: DescriptorSerializer
) {
if (moduleName != JvmProtoBufUtil.DEFAULT_MODULE_NAME) {
proto.setExtension(JvmProtoBuf.classModuleName, stringTable.getStringIndex(moduleName))
}
//TODO: support local delegated properties in new defaults scheme
val containerAsmType =
if (DescriptorUtils.isInterface(descriptor)) typeMapper.mapDefaultImpls(descriptor) else typeMapper.mapClass(descriptor)
if (isInterface(descriptor)) typeMapper.mapDefaultImpls(descriptor) else typeMapper.mapClass(descriptor)
writeLocalProperties(proto, containerAsmType, JvmProtoBuf.classLocalVariable)
writeVersionRequirementForJvmDefaultIfNeeded(descriptor, proto, versionRequirementTable)
@@ -135,7 +139,7 @@ class JvmSerializerExtension @JvmOverloads constructor(
val localVariables = CodegenBinding.getLocalDelegatedProperties(codegenBinding, classAsmType) ?: return
for (localVariable in localVariables) {
val propertyDescriptor = createFreeFakeLocalPropertyDescriptor(localVariable)
val propertyDescriptor = createFreeFakeLocalPropertyDescriptor(localVariable, approximator)
val serializer = DescriptorSerializer.createForLambda(this)
proto.addExtension(extension, serializer.propertyProto(propertyDescriptor)?.build() ?: continue)
}
@@ -198,6 +202,13 @@ class JvmSerializerExtension @JvmOverloads constructor(
if (descriptor.needsInlineParameterNullCheckRequirement()) {
versionRequirementTable?.writeInlineParameterNullCheckRequirement(proto::addVersionRequirement)
}
if (requiresFunctionNameManglingForReturnType(descriptor) &&
!DescriptorUtils.hasJvmNameAnnotation(descriptor) &&
!requiresFunctionNameManglingForParameterTypes(descriptor)
) {
versionRequirementTable?.writeFunctionNameManglingForReturnTypeRequirement(proto::addVersionRequirement)
}
}
private fun MutableVersionRequirementTable.writeInlineParameterNullCheckRequirement(add: (Int) -> Unit) {
@@ -208,6 +219,12 @@ class JvmSerializerExtension @JvmOverloads constructor(
}
}
private fun MutableVersionRequirementTable.writeFunctionNameManglingForReturnTypeRequirement(add: (Int) -> Unit) {
if (functionsWithInlineClassReturnTypesMangled) {
add(writeVersionRequirement(1, 4, 0, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, this))
}
}
private fun FunctionDescriptor.needsInlineParameterNullCheckRequirement(): Boolean =
isInline && !isSuspend && !isParamAssertionsDisabled &&
!Visibilities.isPrivate(visibility) &&
@@ -253,6 +270,10 @@ class JvmSerializerExtension @JvmOverloads constructor(
if (getter?.needsInlineParameterNullCheckRequirement() == true || setter?.needsInlineParameterNullCheckRequirement() == true) {
versionRequirementTable?.writeInlineParameterNullCheckRequirement(proto::addVersionRequirement)
}
if (!DescriptorUtils.hasJvmNameAnnotation(descriptor) && requiresFunctionNameManglingForReturnType(descriptor)) {
versionRequirementTable?.writeFunctionNameManglingForReturnTypeRequirement(proto::addVersionRequirement)
}
}
private fun PropertyDescriptor.isJvmFieldPropertyInInterfaceCompanion(): Boolean {
@@ -262,7 +283,7 @@ class JvmSerializerExtension @JvmOverloads constructor(
if (!DescriptorUtils.isCompanionObject(container)) return false
val grandParent = (container as ClassDescriptor).containingDeclaration
return DescriptorUtils.isInterface(grandParent) || DescriptorUtils.isAnnotationClass(grandParent)
return isInterface(grandParent) || DescriptorUtils.isAnnotationClass(grandParent)
}
override fun serializeErrorType(type: KotlinType, builder: ProtoBuf.Type.Builder) {

View File

@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeApproximator
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
import java.io.File
@@ -251,6 +252,8 @@ class GenerationState private constructor(
val isInlineDisabled: Boolean = configuration.getBoolean(CommonConfigurationKeys.DISABLE_INLINE)
val useTypeTableInSerializer: Boolean = configuration.getBoolean(JVMConfigurationKeys.USE_TYPE_TABLE)
val unifiedNullChecks: Boolean = languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4
val functionsWithInlineClassReturnTypesMangled: Boolean =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
val rootContext: CodegenContext<*> = RootContext(this)
@@ -283,6 +286,12 @@ class GenerationState private constructor(
lateinit var irBasedMapAsmMethod: (FunctionDescriptor) -> Method
var mapInlineClass: (ClassDescriptor) -> Type = { descriptor -> typeMapper.mapType(descriptor.defaultType) }
val typeApproximator: TypeApproximator? =
if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
TypeApproximator(module.builtIns)
else
null
init {
this.interceptedBuilderFactory = builderFactory
.wrapWith(

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String>?

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String?>?

View File

@@ -364,39 +364,29 @@ class KotlinTypeMapper @JvmOverloads constructor(
// and, more importantly, returns 'kotlin.Any' (so that it can return as a reference value or a special COROUTINE_SUSPENDED object).
// This also causes boxing of primitives and inline class values.
// If we have a function returning an inline class value that is mapped to a reference type, we want to avoid boxing.
// However, we have to do that consistently both on declaration site and on call site in case of covariant overrides.
// However, we have to do that consistently both on declaration site and on call site.
if (!functionDescriptor.isSuspend) return null
val originalSuspendFunction = functionDescriptor.unwrapInitialDescriptorForSuspendFunction()
val originalReturnType = originalSuspendFunction.returnType!!
if (!originalReturnType.isInlineClassType()) return null
if (!originalReturnType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn()) {
return originalSuspendFunction.module.builtIns.nullableAnyType
// Force boxing for primitives
if (AsmUtil.isPrimitive(mapType(originalReturnType))) {
return functionDescriptor.builtIns.nullableAnyType
}
// Lambdas, callable references, and function literals implicitly override corresponding generic method from a base class.
// NB we don't have suspend function literals so far, but we support it in back-end, just in case.
if (isFunctionLiteral(originalSuspendFunction) || isFunctionExpression(originalSuspendFunction)) {
return originalSuspendFunction.module.builtIns.nullableAnyType
}
// NB JVM view of a Kotlin function overrides JVM views of corresponding overridden functions
val originalOverridden = getAllOverriddenDeclarations(functionDescriptor).map {
it.unwrapInitialDescriptorForSuspendFunction().original
}
if (originalOverridden.any { !it.returnType!!.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn() }) {
return originalSuspendFunction.module.builtIns.nullableAnyType
// Force boxing for nullable inline class types with nullable underlying type
if (originalReturnType.isMarkedNullable && originalReturnType.isNullableUnderlyingType()) {
return functionDescriptor.builtIns.nullableAnyType
}
// Don't box other inline classes
return originalReturnType
}
private fun KotlinType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn(): Boolean =
isInlineClassType() && !AsmUtil.isPrimitive(mapType(this)) && (!isMarkedNullable || !isNullableUnderlyingType())
@JvmOverloads
fun mapToCallableMethod(
descriptor: FunctionDescriptor,
@@ -410,7 +400,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
val owner = mapOwner(descriptor)
val originalDescriptor = descriptor.original
return CallableMethod(
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).descriptor }, method, INVOKESPECIAL,
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL,
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false
)
}
@@ -571,7 +561,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
return CallableMethod(
owner, ownerForDefaultImpl,
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).descriptor },
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)) },
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType,
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
@@ -629,6 +619,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
}
private val shouldMangleByReturnType =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
private fun mangleMemberNameIfRequired(
name: String,
descriptor: CallableMemberDescriptor,
@@ -663,11 +656,16 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
}
val suffix = getInlineClassSignatureManglingSuffix(descriptor)
if (suffix != null) {
newName += suffix
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS
// Skip inline class mangling for property reference signatures,
// so that we don't have to repeat the same logic in reflection
// in case of properties without getter methods.
if (kind !== OwnerKind.PROPERTY_REFERENCE_SIGNATURE || descriptor.isPropertyWithGetterSignaturePresent()) {
val suffix = getManglingSuffixBasedOnKotlinSignature(descriptor, shouldMangleByReturnType)
if (suffix != null) {
newName += suffix
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS
}
}
newName = sanitizeNameIfNeeded(newName, languageVersionSettings)
@@ -688,6 +686,16 @@ class KotlinTypeMapper @JvmOverloads constructor(
} else newName
}
private fun CallableMemberDescriptor.isPropertyWithGetterSignaturePresent(): Boolean {
val propertyDescriptor = when (this) {
is PropertyDescriptor -> this
is PropertyAccessorDescriptor -> correspondingProperty
else -> return false
}
return PropertyCodegen.isReferenceablePropertyWithGetter(propertyDescriptor)
}
private fun getModuleName(descriptor: CallableMemberDescriptor): String {
return getJvmModuleNameForDeserializedDescriptor(descriptor) ?: moduleName
}
@@ -696,6 +704,10 @@ class KotlinTypeMapper @JvmOverloads constructor(
return mapSignature(descriptor).asmMethod
}
fun mapPropertyReferenceSignature(descriptor: FunctionDescriptor): Method {
return mapSignature(descriptor, OwnerKind.PROPERTY_REFERENCE_SIGNATURE, true).asmMethod
}
fun mapAsmMethod(descriptor: FunctionDescriptor, kind: OwnerKind): Method {
return mapSignature(descriptor, kind, true).asmMethod
}
@@ -966,12 +978,12 @@ class KotlinTypeMapper @JvmOverloads constructor(
// implicitly override generic 'invoke' from a corresponding base class.
if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true
return isJvmPrimitiveOrInlineClass(returnType) &&
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitiveOrInlineClass(it.returnType!!) }
return isJvmPrimitive(returnType) &&
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitive(it.returnType!!) }
}
private fun isJvmPrimitiveOrInlineClass(kotlinType: KotlinType) =
KotlinBuiltIns.isPrimitiveType(kotlinType) || kotlinType.isInlineClassType()
private fun isJvmPrimitive(kotlinType: KotlinType) =
KotlinBuiltIns.isPrimitiveType(kotlinType)
private fun isBoxMethodForInlineClass(descriptor: FunctionDescriptor): Boolean {
val containingDeclaration = descriptor.containingDeclaration

View File

@@ -83,7 +83,7 @@ class SignatureDumpingBuilderFactory(
super.defineClass(origin, version, access, name, signature, superName, interfaces)
}
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor {
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: JvmMethodExceptionTypes): MethodVisitor {
signatures += RawSignature(name, desc, MemberKind.METHOD) to origin.descriptor?.let {
if (it is CallableDescriptor) it.unwrapInitialDescriptorForSuspendFunction() else it
}

View File

@@ -5,33 +5,51 @@
package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.jvm.*
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
import java.security.MessageDigest
import java.util.*
fun getInlineClassSignatureManglingSuffix(descriptor: CallableMemberDescriptor): String? {
fun getManglingSuffixBasedOnKotlinSignature(
descriptor: CallableMemberDescriptor,
shouldMangleByReturnType: Boolean
): String? {
if (descriptor !is FunctionDescriptor) return null
if (descriptor is ConstructorDescriptor) return null
if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null
val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
// Don't mangle functions with '@JvmName' annotation.
// Some stdlib functions ('Result.success', 'Result.failure') are annotated with '@JvmName' as a workaround for forward compatibility.
if (DescriptorUtils.hasJvmNameAnnotation(descriptor)) return null
return getInlineClassSignatureManglingSuffix(actualValueParameterTypes)
// If a function accepts inline class parameters, mangle its name.
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
return "-" + md5base64(collectSignatureForMangling(descriptor))
}
// If a class member function returns inline class value, mangle its name.
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
// should unwrap it and take original return type instead.
if (shouldMangleByReturnType) {
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
return "-" + md5base64(":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!))
}
}
return null
}
private fun getInlineClassSignatureManglingSuffix(valueParameterTypes: List<KotlinType>) =
if (requiresFunctionNameMangling(valueParameterTypes))
"-" + md5base64(collectSignatureForMangling(valueParameterTypes))
else
null
private fun collectSignatureForMangling(types: List<KotlinType>) =
types.joinToString { getSignatureElementForMangling(it) }
private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor): String {
val types = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
return types.joinToString { getSignatureElementForMangling(it) }
}
private fun getSignatureElementForMangling(type: KotlinType): String = buildString {
val descriptor = type.constructor.declarationDescriptor ?: return ""

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 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.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.serialization.builtins
@@ -97,10 +86,10 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(Buil
fqName ->
val packageView = module.getPackage(fqName)
PackageSerializer(
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
packageView.fqName,
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
packageView.fqName,
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
).run()
}
}

View File

@@ -38,19 +38,12 @@ import kotlin.system.exitProcess
abstract class CLITool<A : CommonToolArguments> {
fun exec(errStream: PrintStream, vararg args: String): ExitCode {
val rendererType = System.getProperty(MessageRenderer.PROPERTY_KEY)
val messageRenderer = when (rendererType) {
MessageRenderer.XML.name -> MessageRenderer.XML
MessageRenderer.GRADLE_STYLE.name -> MessageRenderer.GRADLE_STYLE
MessageRenderer.WITHOUT_PATHS.name -> MessageRenderer.WITHOUT_PATHS
MessageRenderer.PLAIN_FULL_PATHS.name -> MessageRenderer.PLAIN_FULL_PATHS
else -> MessageRenderer.PLAIN_RELATIVE_PATHS
}
return exec(errStream, Services.EMPTY, messageRenderer, args)
return exec(errStream, Services.EMPTY, defaultMessageRenderer(), args)
}
fun exec(errStream: PrintStream, messageRenderer: MessageRenderer, vararg args: String): ExitCode
= exec(errStream, Services.EMPTY, messageRenderer, args)
protected fun exec(
errStream: PrintStream,
services: Services,
@@ -192,6 +185,16 @@ abstract class CLITool<A : CommonToolArguments> {
abstract fun executableScriptFileName(): String
companion object {
private fun defaultMessageRenderer(): MessageRenderer =
when (System.getProperty(MessageRenderer.PROPERTY_KEY)) {
MessageRenderer.XML.name -> MessageRenderer.XML
MessageRenderer.GRADLE_STYLE.name -> MessageRenderer.GRADLE_STYLE
MessageRenderer.WITHOUT_PATHS.name -> MessageRenderer.WITHOUT_PATHS
MessageRenderer.PLAIN_FULL_PATHS.name -> MessageRenderer.PLAIN_FULL_PATHS
else -> MessageRenderer.PLAIN_RELATIVE_PATHS
}
/**
* Useful main for derived command line tools
*/
@@ -215,8 +218,13 @@ abstract class CLITool<A : CommonToolArguments> {
}
@JvmStatic
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode = try {
compiler.exec(System.err, *args)
@JvmOverloads
fun doMainNoExit(
compiler: CLITool<*>,
args: Array<String>,
messageRenderer: MessageRenderer = defaultMessageRenderer()
): ExitCode = try {
compiler.exec(System.err, messageRenderer, *args)
} catch (e: CompileEnvironmentException) {
System.err.println(e.message)
ExitCode.INTERNAL_ERROR

View File

@@ -550,8 +550,6 @@ class KotlinCoreEnvironment private constructor(
CollectAdditionalSourcesExtension.registerExtensionPoint(project)
ExtraImportsProviderExtension.registerExtensionPoint(project)
IrGenerationExtension.registerExtensionPoint(project)
@Suppress("DEPRECATION_ERROR")
org.jetbrains.kotlin.backend.common.extensions.PureIrGenerationExtension.registerExtensionPoint(project)
ScriptEvaluationExtension.registerExtensionPoint(project)
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)

View File

@@ -45,24 +45,29 @@ import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.common.output.writeAll
import org.jetbrains.kotlin.cli.common.toLogger
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.DefaultCodegenFactory
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmClassCodegen
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.extensions.extensionsService
import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.registerExtensions
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc
@@ -319,7 +324,7 @@ object KotlinToJVMBytecodeCompiler {
}
val moduleInfo = FirJvmModuleInfo(module.getModuleName())
val session: FirSession = FirJavaModuleBasedSession(moduleInfo, provider, scope).also {
val session: FirSession = FirJavaModuleBasedSession.create(moduleInfo, provider, scope).also {
val dependenciesInfo = FirJvmModuleInfo(Name.special("<dependencies>"))
moduleInfo.dependencies.add(dependenciesInfo)
val librariesScope = ProjectScope.getLibrariesScope(project)
@@ -327,18 +332,18 @@ object KotlinToJVMBytecodeCompiler {
dependenciesInfo, provider, librariesScope,
project, environment.createPackagePartProvider(librariesScope)
)
it.extensionsService.registerExtensions(FirExtensionRegistrar.RegisteredExtensions.EMPTY)
it.extensionService.registerExtensions(BunchOfRegisteredExtensions.empty())
}
val firProvider = (session.firProvider as FirProviderImpl)
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, stubMode = false)
val resolveTransformer = FirTotalResolveTransformer()
val resolveTransformer = FirTotalResolveProcessor(session)
val firFiles = ktFiles.map {
val firFile = builder.buildFirFile(it)
firProvider.recordFile(firFile)
firFile
}.also {
try {
resolveTransformer.processFiles(it)
resolveTransformer.process(it)
} catch (e: Exception) {
throw e
}
@@ -346,11 +351,12 @@ object KotlinToJVMBytecodeCompiler {
val signaturer = IdSignatureDescriptor(JvmManglerDesc())
val (moduleFragment, symbolTable, sourceManager) =
val (moduleFragment, symbolTable, sourceManager, components) =
Fir2IrConverter.createModuleFragment(
session, resolveTransformer.scopeSession, firFiles,
moduleConfiguration.languageVersionSettings, signaturer = signaturer,
generatorExtensions = JvmGeneratorExtensions()
generatorExtensions = JvmGeneratorExtensions(),
mangler = FirJvmKotlinMangler(session)
)
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
@@ -367,6 +373,8 @@ object KotlinToJVMBytecodeCompiler {
createOutputFilesFlushingCallbackIfPossible(moduleConfiguration)
).isIrBackend(
true
).jvmBackendClassResolver(
FirJvmBackendClassResolver(components)
).build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()

View File

@@ -9,7 +9,7 @@ import com.intellij.core.CoreApplicationEnvironment
import com.intellij.openapi.extensions.ExtensionsArea
import java.io.File
// BUNCH: 193
// FIX ME WHEN BUNCH 193 REMOVED
fun registerExtensionPointAndExtensionsEx(pluginFile: File, fileName: String, area: ExtensionsArea) {
@Suppress("MissingRecentApi")
CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginFile, fileName, area)

View File

@@ -10,7 +10,7 @@ import com.intellij.openapi.extensions.ExtensionsArea
import java.io.File
import java.nio.file.FileSystems
// BUNCH: 193
// FIX ME WHEN BUNCH 193 REMOVED
fun registerExtensionPointAndExtensionsEx(pluginFile: File, fileName: String, area: ExtensionsArea) {
val pluginRoot = FileSystems.getDefault().getPath(pluginFile.path)
@Suppress("MissingRecentApi")

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cli.metadata
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.buildKoltinLibrary
import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
@@ -83,7 +83,7 @@ internal class K2MetadataKlibSerializer(private val metadataVersion: BuiltInsBin
irVersion = null
)
buildKoltinLibrary(
buildKotlinLibrary(
emptyList(),
serializedMetadata,
null,
@@ -91,6 +91,7 @@ internal class K2MetadataKlibSerializer(private val metadataVersion: BuiltInsBin
destDir.absolutePath,
configuration[CommonConfigurationKeys.MODULE_NAME]!!,
nopack = true,
perFile = false,
manifestProperties = null,
dataFlowGraph = null,
builtInsPlatform = BuiltInsPlatform.COMMON
@@ -244,4 +245,4 @@ private val MetadataFactories =
{ DefaultBuiltIns.Instance },
NullFlexibleTypeDeserializer,
NativeTypeTransformer()
)
)

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 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.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cli.metadata

View File

@@ -24,15 +24,9 @@ dependencies {
runtime(project(":kotlin-reflect"))
embedded(project(":daemon-common")) { isTransitive = false }
embedded(project(":daemon-common-new")) { isTransitive = false }
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) {
isTransitive = false
}
compile(commonDep("io.ktor", "ktor-network")) {
ktorExcludesForDaemon.forEach { (group, module) ->
exclude(group = group, module = module)
}
}
}
sourceSets {

View File

@@ -76,8 +76,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
val compilerClassPath = listOf(
File(compilerLibDir, "kotlin-compiler.jar"),
File(compilerLibDir, "kotlin-daemon.jar"),
File(compilerLibDir, "ktor-network-1.0.1.jar")
File(compilerLibDir, "kotlin-daemon.jar")
)
val scriptRuntimeClassPath = listOf(
File(compilerLibDir, "kotlin-runtime.jar"),

View File

@@ -97,9 +97,8 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
)
val daemonClientClassPath = listOf(
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-daemon-client-new.jar"),
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler.jar"),
File(KotlinIntegrationTestBase.getCompilerLib(), "ktor-network-1.0.1.jar")
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-daemon-client.jar"),
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler.jar")
)
val compilerId by lazy(LazyThreadSafetyMode.NONE) { CompilerId.makeCompilerId(compilerClassPath) }

View File

@@ -0,0 +1,4 @@
public abstract interface F : R|kotlin/Any| {
public abstract fun R|kotlin/String|.f(x: R|kotlin/Int|): R|kotlin/Unit|
}

View File

@@ -27,10 +27,10 @@ FILE: lambdaInLambda.kt
R|/buildString|(<L> = buildString@fun R|StringBuilder|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|/insert|<R|StringBuilder|, R|KDocTemplate|>(R|/KDocTemplate.KDocTemplate|(), <L> = insert@fun R|KDocTemplate|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|/KDocTemplate.definition|(<L> = definition@fun R|StringBuilder|.<anonymous>(): R|kotlin/Unit| {
^ R|<local>/ordinal|?.R|kotlin/let|<R|kotlin/Int|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
R|<local>/ordinal|?.{ $subj$.R|kotlin/let|<R|kotlin/Int|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
^@let Unit
}
)
) }
}
)
}

View File

@@ -8,7 +8,7 @@ FILE: main.kt
}
public final fun test(): R|kotlin/Unit| {
lval processor: R|AdapterProcessor<ft<PsiMethod, PsiMethod?>!, ft<PsiClass, PsiClass?>!>| = R|/AdapterProcessor.AdapterProcessor|<R|ft<PsiMethod, PsiMethod?>!|, R|ft<PsiClass, PsiClass?>!|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>!|, R|PsiClass?|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|PsiClass?| {
^ R|<local>/method|?.R|/PsiMethod.containingClass|
^ R|<local>/method|?.{ $subj$.R|/PsiMethod.containingClass| }
}
))
}

View File

@@ -8,7 +8,7 @@ FILE: bareTypes.kt
public abstract interface MutableString : R|MutableA<kotlin/String>| {
}
public final fun test(a: R|A<kotlin/String>|): R|kotlin/Unit| {
(R|<local>/a| as? R|MutableA<kotlin/String>|)?.R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String())
(R|<local>/a| as? R|MutableA<kotlin/String>|)?.{ $subj$.R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String()) }
(R|<local>/a| as R|MutableA<kotlin/String>|).R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String())
}
public final fun test2(a: R|A<kotlin/String>|): R|kotlin/Unit| {

View File

@@ -0,0 +1,9 @@
interface A
fun test_1(a: A?, convert: A.() -> String) {
val s = a?.convert()
}
fun test_2(a: A, convert: A.() -> String) {
val s = a.convert()
}

View File

@@ -0,0 +1,9 @@
FILE: extensionInvokeAfterSafeCall.kt
public abstract interface A : R|kotlin/Any| {
}
public final fun test_1(a: R|A?|, convert: R|A.() -> kotlin/String|): R|kotlin/Unit| {
lval s: R|kotlin/String?| = R|<local>/a|?.{ R|<local>/convert|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|($subj$) }
}
public final fun test_2(a: R|A|, convert: R|A.() -> kotlin/String|): R|kotlin/Unit| {
lval s: R|kotlin/String| = R|<local>/convert|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|(R|<local>/a|)
}

View File

@@ -0,0 +1,7 @@
typealias MyTypeAlias = (() -> String?)?
fun foo(x: MyTypeAlias) {
x?.let { y -> y()?.let { result -> bar(result) } }
}
fun bar(x: String) = x

View File

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

View File

@@ -62,7 +62,7 @@ digraph initBlockAndInPlaceLambda_kt {
}
26 [label="Call arguments union" style="filled" fillcolor=yellow];
24 [label="Postponed exit from lambda"];
25 [label="Function call: R|<local>/a|.R|/A.b|?.R|kotlin/let|<R|B|, R|C|>(...)"];
25 [label="Function call: $subj$.R|kotlin/let|<R|B|, R|C|>(...)"];
22 [label="Exit safe call"];
27 [label="Variable declaration: lval c: R|C?|"];
28 [label="Exit block"];

View File

@@ -12,10 +12,10 @@ FILE: initBlockAndInPlaceLambda.kt
}
init {
lval c: R|C?| = R|<local>/a|.R|/A.b|?.R|kotlin/let|<R|B|, R|C|>(<L> = let@fun <anonymous>(it: R|B|): R|C| <kind=EXACTLY_ONCE> {
lval c: R|C?| = R|<local>/a|.R|/A.b|?.{ $subj$.R|kotlin/let|<R|B|, R|C|>(<L> = let@fun <anonymous>(it: R|B|): R|C| <kind=EXACTLY_ONCE> {
^ R|/C.C|(R|<local>/a|, R|<local>/it|)
}
)
) }
}
}

View File

@@ -47,7 +47,7 @@ FILE: localClassesWithImplicit.kt
}
lval x: R|anonymous| = object : R|kotlin/Any| {
private constructor(): R|anonymous| {
private[local] constructor(): R|anonymous| {
super<R|kotlin/Any|>()
}

View File

@@ -62,10 +62,10 @@ digraph safeCalls_kt {
16 [label="Enter function test_1" style="filled" fillcolor=red];
18 [label="Access variable R|<local>/x|"];
19 [label="Enter safe call"];
21 [label="Function call: R|<local>/x|?.R|/A.foo|()"];
21 [label="Function call: $subj$.R|/A.foo|()"];
20 [label="Exit safe call"];
22 [label="Enter safe call"];
24 [label="Function call: R|<local>/x|?.R|/A.foo|()?.R|/A.bar|()"];
24 [label="Function call: $subj$.R|/A.bar|()"];
23 [label="Exit safe call"];
17 [label="Exit function test_1" style="filled" fillcolor=red];
}

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