Compare commits

..

302 Commits

Author SHA1 Message Date
Ilya Kirillov
5918bbde21 Wizard: change new wizard title 2020-01-24 09:22:48 +03:00
Ilya Kirillov
9c467c01d9 Wizard: make new wizard to be second in the Kotlin group 2020-01-24 09:22:47 +03:00
Ilya Kirillov
ca0a398a31 Wizard: add FUS statistic collection 2020-01-24 09:22:45 +03:00
Ilya Kirillov
339fd2ae58 Wizard: allow simple js template to be used with JsSingleplatformModuleConfigurator 2020-01-24 09:22:44 +03:00
Ilya Kirillov
ebd825ac8c Wizard: fix removing template in UI 2020-01-24 09:22:43 +03:00
Ilya Kirillov
c87d48eedd Wizard: allow enabling new wizard in UI 2020-01-24 09:22:41 +03:00
Ilya Kirillov
f83f48c803 Wizard: fix tests 2020-01-24 09:22:40 +03:00
Ilya Kirillov
e2f81ee85b Wizard: fix adding dependencies to targets 2020-01-24 09:22:39 +03:00
Ilya Kirillov
0d63c35ee0 Wizard: temporary hide sourcesets editing for users 2020-01-24 09:22:38 +03:00
Ilya Kirillov
ef675dba06 Wizard: fix incorrectly added classpath dependency for Android with Groovy dsl 2020-01-24 09:22:36 +03:00
Ilya Kirillov
70d26bff46 Wizard: put pluginManagement section in the beginning of settings.gradle file 2020-01-24 09:22:35 +03:00
Ilya Kirillov
7da178c345 Wizard: add support of creating run configurations
#KT-36043 fixed
2020-01-24 09:22:33 +03:00
Ilya Kirillov
c2b02afe29 Wizard: add support of react js to the js template 2020-01-24 09:22:32 +03:00
Ilya Kirillov
8882c2e958 Wizard: fix not added dependencies for MPP modules 2020-01-24 09:22:31 +03:00
Ilya Kirillov
9c6e561349 Wizard: fix text of module configurators which is shown in module editor 2020-01-24 09:22:29 +03:00
Ilya Kirillov
6309710c0e Wizard: add support of JS singleplatform projects 2020-01-24 09:22:28 +03:00
Ilya Kirillov
d2602cd5bf Wizard: automatically determine Kotlin version based on Kotlin plugin version
For snapshot plugin just take the latest eap or stable version
2020-01-24 09:22:26 +03:00
Ilya Kirillov
142600f91f Wizard: remove empty border from module settings 2020-01-24 09:22:25 +03:00
Ilya Kirillov
5efb9934a3 Wizard: remove unused function 2020-01-24 09:22:24 +03:00
Ilya Kirillov
36bd7791b2 Wizard: fix incorrectly added modules to the tree 2020-01-24 09:22:23 +03:00
Ilya Kirillov
c6b6f07d3d Wizard: move "validation error" string from message to title 2020-01-24 09:22:21 +03:00
Ilya Kirillov
5e08272f25 Wizard: add validation for project name 2020-01-24 09:22:20 +03:00
Ilya Kirillov
15469c4f8d Wizard: do not suggest invalid groupId 2020-01-24 09:22:19 +03:00
Ilya Kirillov
12a18a8860 Wizard: do not show expert panel form wizard 2020-01-24 09:22:18 +03:00
Ilya Kirillov
46b824ade3 Wizard: remove duplicated string validator 2020-01-24 09:22:16 +03:00
Ilya Kirillov
d2175822e8 Wizard: add validators for POM data 2020-01-24 09:22:15 +03:00
Ilya Kirillov
0faa152537 Wizard: Show message when module has no configurable settings 2020-01-24 09:22:14 +03:00
Ilya Kirillov
051d6afae6 Wizard: Move test framework settings to module configurators 2020-01-24 09:22:12 +03:00
Ilya Kirillov
d4c458e77a Wizard: Move module templates to modules: separate SourcetModuleIR to MultiplatformModuleIR & SourcesetIR 2020-01-24 09:22:11 +03:00
Ilya Kirillov
b864bfe08f Wizard: move module templates to modules 2020-01-24 09:22:10 +03:00
Ilya Kirillov
cf2fa7f27a Wizard: add module dependencies for JPS 2020-01-24 09:22:08 +03:00
Ilya Kirillov
fabb1fed09 Wizard: add kotlin native console application template 2020-01-24 09:22:07 +03:00
Ilya Kirillov
f8ca0d031f Wizard: do not print binaries specification for all native targets
#KT-35719 fixed
2020-01-24 09:22:06 +03:00
Ilya Kirillov
0b8af7d6f8 Wizard: sort & distinct imports in Gradle build files 2020-01-24 09:22:04 +03:00
Ilya Kirillov
78f4a35317 Wizard: move fqName to import in NativeTargetConfigurator 2020-01-24 09:22:03 +03:00
Ilya Kirillov
dfa09aa5ba Wizard: add irs for build files from targets 2020-01-24 09:21:59 +03:00
Ilya Kirillov
540aabc357 Wizard: do not add empty gradle project to settings.gradle 2020-01-24 09:21:58 +03:00
Ilya Kirillov
bd2ed53e33 Wizard: use settings.gradle instead of .kts for Groovy DSL Gradle projects
#KT-35694 fixed
2020-01-24 09:21:57 +03:00
Ilya Kirillov
1450c0ad83 Wizard: print repositories for Maven
#KT-35715 fixed
2020-01-24 09:21:55 +03:00
Ilya Kirillov
3b74c305c8 Wizard: retrieve repositories from artifacts 2020-01-24 09:21:54 +03:00
Ilya Kirillov
ad359f0198 Wizard: correctly add Kotlin dependencies to singleplatform modules with gradle dsl build system
#KT-35695 fixed
2020-01-24 09:21:53 +03:00
Ilya Kirillov
0413c73574 Wizard: fix adding invalid dependencies for maven build files
#KT-35711 fixed
2020-01-24 09:21:52 +03:00
Ilya Kirillov
259d85fdbb Wizard: allow dashes for module names
#KT-35584 fixed
2020-01-24 09:21:51 +03:00
Ilya Kirillov
8c5c5345ff Wizard: Use default Java source roots for JPS projects
#KT-35710 fixed
2020-01-24 09:21:49 +03:00
Ilya Kirillov
c14152eeb0 Wizard: rework UI components for settings
#KT-35712 fixed
2020-01-24 09:21:48 +03:00
Ilya Kirillov
b3ca8308d9 Wizard: fix incorrect ktor repository
#KT-35718 fixed
2020-01-24 09:21:47 +03:00
Ilya Kirillov
bad2a3a946 Wizard: remove redundant return in native target configuration
#KT-35720 fixed
2020-01-24 09:21:42 +03:00
Ilya Kirillov
ab47d3d508 Wizard: fix swapped artifactId and groupId fields titles
#KT-35690 fixed
2020-01-24 09:21:41 +03:00
Ilya Kirillov
59537803d5 Wizard: do not overwrite existing artifactId & groupId settings
#KT-35713 fixed
2020-01-24 09:21:40 +03:00
Ilya Kirillov
2acafe32d0 Fix 191 & as35 compilation
(cherry picked from commit c311a66e5e)
2020-01-24 09:21:20 +03:00
Ilya Kirillov
586a1d3c8f Fix "Protected function call from public-API inline function is prohibited" error
(cherry picked from commit d6daaf14f8)
2020-01-24 09:21:19 +03:00
Ilya Kirillov
d0634d2b6f Fix compilation for AS
(cherry picked from commit 06dc2caf41)
2020-01-24 09:21:18 +03:00
Nikolay Krasko
9cf23713fd Allow @author usage in ...projectWizard.settings.version.maven package
(cherry picked from commit 1f878049eb)
2020-01-24 09:18:51 +03:00
Ilya Kirillov
8815f67511 Fix class not found exception in gradle wizard tests
(cherry picked from commit 830f0c6137)
2020-01-24 09:18:22 +03:00
Ilya Kirillov
a275716dd6 Wizard: introduce unit test mode
(cherry picked from commit 1ab405a86c)
2020-01-24 09:18:21 +03:00
Ilya Kirillov
3b83af751a Wizard: fix android tests
(cherry picked from commit 1c30572844)
2020-01-24 09:18:20 +03:00
Ilya Kirillov
845251f2da Wizard: fix wrong checking for project kind in UI
(cherry picked from commit b2166dc40d)
2020-01-24 09:18:19 +03:00
Ilya Kirillov
a927841af1 Wizard: disable abbility to switch between targets in existing module
(cherry picked from commit c1ce215b5d)
2020-01-24 09:18:18 +03:00
Ilya Kirillov
e47bfec05e Wizard: add suggested module names for js targets
(cherry picked from commit 7204ab091a)
2020-01-24 09:18:17 +03:00
Ilya Kirillov
820a90c3bc Wizard: do not allow to create more than one target of each type
(cherry picked from commit fc9f63d49f)
2020-01-24 09:18:16 +03:00
Ilya Kirillov
a7099c6c30 Wizard: add additional applicability checker for template
(cherry picked from commit aa2992e84a)
2020-01-24 09:18:15 +03:00
Ilya Kirillov
c7e97c2861 Wizard: remove unused android service
(cherry picked from commit 40367635cc)
2020-01-24 09:18:13 +03:00
Ilya Kirillov
1e2c56380a Wizard: format templates code
(cherry picked from commit af174b4f74)
2020-01-24 09:18:12 +03:00
Ilya Kirillov
83c559cf49 Wizard: add simple js template
(cherry picked from commit b29e6d0c69)
2020-01-24 09:18:11 +03:00
Ilya Kirillov
09a771dad0 Wizard: do not print duplicated repositories
(cherry picked from commit 5d56f3d28b)
2020-01-24 09:18:09 +03:00
Ilya Kirillov
d80512dd98 Wizard: introduce interceptors for module templates
(cherry picked from commit 32a151f561)
2020-01-24 09:18:07 +03:00
Ilya Kirillov
d8df582975 Wizard: add simple JS client template
(cherry picked from commit 8bf9c31880)
2020-01-24 09:18:05 +03:00
Ilya Kirillov
a1ece3b529 Wizard: add basic ktor server template
(cherry picked from commit 56fccce305)
2020-01-24 09:18:02 +03:00
Ilya Kirillov
388668edf7 Wizard: introduce ServicesManager & correctly handle disabled gradle & maven Idea plugins
(cherry picked from commit f927fb3471)
2020-01-24 09:18:00 +03:00
Ilya Kirillov
03c1eee25d Wizard: change wizard title to experimental
(cherry picked from commit 9011eecfdf)
2020-01-24 09:17:59 +03:00
Ilya Kirillov
24fc714e01 Wizard: Create parent group for current and experimental project wizard
(cherry picked from commit b10e157147)
2020-01-24 09:17:57 +03:00
Ilya Kirillov
aad67ddbda Wizard: show experimental new project wizard only by registry flag
(cherry picked from commit 8684b0d6c1)
2020-01-24 09:17:56 +03:00
Ilya Kirillov
aeab899542 Wizard: Add initial version of the new project wizard
(cherry picked from commit aca193ddd2)
2020-01-24 09:17:55 +03:00
Abduqodiri Qurbonzoda
cdf89677fb Optimize ArrayDeque tests run time
(cherry picked from commit e89893b6fd)
2020-01-24 05:57:18 +03:00
Ilya Gorbunov
d17908b9ce ArrayDeque: avoid triggering JDK 1.6 bug in tests
Use System.arraycopy instead of Arrays.copyOfRange to
avoid triggering JDK-7174363 bug in copyOfRange.

Fix package of ArrayDequeTest

(cherry picked from commit 8733d5f9ed)
2020-01-24 05:56:54 +03:00
Abduqodiri Qurbonzoda
a00c12d876 Add removeFirst(OrNull) and removeLast(OrNull) methods to MutableList
(cherry picked from commit e459542e6f)
2020-01-24 05:56:25 +03:00
Abduqodiri Qurbonzoda
d8193a5a9f Common ArrayDeque
(cherry picked from commit b6849efd47)
2020-01-24 05:56:02 +03:00
Vladimir Dolzhenko
2af2140f70 Track changes of non physical files with incOutOfBlockModificationCount
To invalidate synthetic file cache have to increment
incOutOfBlockModificationCount on valuable psi changes

#KT-35186 Fixed

(cherry picked from commit 6352cded1b)
2020-01-23 21:24:16 +01:00
Vladimir Dolzhenko
20f5ad2be5 Track changes of non physical files with incOutOfBlockModificationCount
To invalidate synthetic file cache have to increment
incOutOfBlockModificationCount on valuable psi changes

#KT-35186 Fixed

(cherry picked from commit 6352cded1b)
2020-01-23 21:22:38 +01:00
Andrey Uskov
9eb8700d3a Added FUS extensions and new metrics for reporting statistics from gradle 2020-01-23 20:36:47 +03:00
Andrey Uskov
b5202dc104 Added tests to gradle statistics reporter 2020-01-23 20:36:36 +03:00
Andrey Uskov
937a8947cd Metric description and anonymization rules added
Added metrics and their anonymization rules added. Persisted gradle
statistical information will not contain any sensitive information.
#KT-33404 Fixed
2020-01-23 20:36:28 +03:00
Andrey Uskov
ae1be18241 Collecting performance information in Gradle plugin supported
The build performance information is collected during the build
when the Kotlin Gradle plugin is applied. Only hashed values are
saved if they may contain sensitive information. Numeric metrics
obtained on the basis of user's project are saved with random seed.
Persisted information is saved in gradleUserHomeDir.

#KT-33404 Fixed
2020-01-23 20:36:23 +03:00
Andrey Uskov
c0d1b76b62 Open files leak on incremental compilation fixed
#KT-25206 Fixed
2020-01-23 20:36:18 +03:00
Andrey Uskov
0db48ed660 Do not show warnings when some projects are not generated before import
#KT-35442 Fixed
2020-01-23 20:36:14 +03:00
Vladimir Ilmov
765dc2dc28 AsyncStackTraceContext extra logging removed 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
35f4dc57a1 Coroutine debugger starting even if registry key set to false - fixed 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
9a23886042 [coroutine] ComboBox disabled as in progress 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
823cc41123 [coroutine] Exception fixed for SUSPEND coroutines. 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
21ba1f2455 Flaky ConcurrentModificationException in NewMultiplatformProjectImportingTest.testFileCollectionDependency fixed 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
0fac6d2d50 POC coroutine panel removed 2020-01-23 15:26:47 +01:00
Vladimir Ilmov
0903e0dcdc [debug] coroutine's stack frame locations pre-calculated on initialization 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
cd39237566 CodeConformanceTest @author mention in sources fixed 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
a934b348e1 Coroutine as35 compatibility patch also added to 191. 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
abd956c123 CoroutineAsyncStackTraceProvider stack corruption fix 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
ab727cbfbf coroutine debugger toolbar added 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
9f1d8f38a3 coroutine debugger logic moved to jvm-debugger-coroutine module 2020-01-23 15:26:46 +01:00
Vladimir Ilmov
58bbf6a57a [coroutine][debugger] implementation basing on X-* approach
XCoroutine view added for direct comparison with Coroutines
2020-01-23 15:26:46 +01:00
Vladimir Ilmov
8ed20ce667 [coroutine][debugger] refactoring being done
X-view approach added for review, thread groups added
2020-01-23 15:26:46 +01:00
Leonid Startsev
90fe752ae9 Do not include annotations and KDoc into NO_EXPLICIT_VISIBILITY_IN_API_MODE report range
Rename positioning strategy to better reflect its behavior.
#KT-36021 Fixed

(cherry picked from commit 43858e8169)
2020-01-23 17:17:15 +03:00
Leonid Startsev
7b82c0e90b Fix unavailable 'Specify visibility explicitly' quickfix
in explicit API mode due to incorrect cast.
Add tests for applying this quickfix.
#KT-36020 Fixed

(cherry picked from commit 4285c6045a)
2020-01-23 17:17:05 +03:00
Leonid Startsev
dcb5df4f48 Search for standard serializers in both internal and root packages
To allow graduate migration of some classes (e.g. IntSerializer)
from kotlinx.serialization.internal.* to kotlinx.serialization.*

(cherry picked from commit 9e8f21cc20)
2020-01-23 12:42:30 +03:00
Leonid Startsev
38965ccf51 Pass actual serializable properties count in the generated code
to SerialClassDescImpl.
This is needed to optimize space allocation.

(cherry picked from commit db4273d677)
2020-01-23 12:42:06 +03:00
Leonid Startsev
b695f2b8fe Refactor plugin-generated call to EnumSerializer():
support new values() argument.
Get rid of old @JvmOverloads requirements in runtime.

(cherry picked from commit 9558538d15)
2020-01-23 12:41:54 +03:00
Vladimir Dolzhenko
f0535a787f Put a proper version of ProgressIndicatorUtils.kt.192
Relates to #KT-33939
2020-01-23 08:57:56 +01:00
Vladimir Dolzhenko
f95d9ca024 Handle kdoc case for Introduce import alias inspection
#EA-210889 Fixed
2020-01-22 22:26:01 +01:00
Vladimir Dolzhenko
59df5711aa Show Review Added Imports on paste action
Fixed multi-caret selection in kotlin-to-kotlin copy-paste processor

Relates to #KT-33939

(cherry picked from commit db8b0a6593)
2020-01-22 17:23:05 +01:00
Vladimir Dolzhenko
036f88424a Fixed ProgressIndicatorUtils.kt for 201
#KT-36008 Fixed
Relates to #KT-33939

(cherry picked from commit 1911cbb077)
2020-01-22 17:22:49 +01:00
Vladimir Dolzhenko
b49b795bd2 ProgressIndicatorUtils.kt for 191 is added
Relates to #KT-33939

(cherry picked from commit c0c929c449)
2020-01-22 17:22:09 +01:00
Vladimir Dolzhenko
ce829cb220 Reworked k2k copy-paste action.
Get rid of resolve from copy phase, paste phase performs resolve in bg

#KT-33939 Fixed

(cherry picked from commit 5730a21e7b)
2020-01-22 17:22:00 +01:00
Ilya Matveev
4ec1ec7fd9 Gradle, native: Allow setting destination directory for binaries
Issue #KT-29395 fixed
2020-01-22 17:41:00 +07:00
Ilya Matveev
0611e79d98 Gradle, native: Don't pass to compiler missing klib files
We don't compile a klib if there are no sources for it (NO-SOURCE
checks). So, we need to take this fact into account and don't
pass such libraries to compiler in dependent modules. See also:
GH-2617 in the K/N repo.

This patch checks that a klib file exists before passing it to the
compiler.
2020-01-22 17:40:59 +07:00
Ilya Matveev
90ef8f9b55 Gradle, tests: Skip building in native binaries test for Groovy DSL
This test is one of the most time-consuming tests because
it builds a lot of final native binaries. Moreover, it exists
in two versions: for Groovy DSL and for Kotlin DSL. The only
difference between these versions is build script DSL.

This patch disables project building for the Groovy DSL version to
reduce total test execution time. Now this test only checks that
project configuration is successful. But it's enough to detect DSL
problems.
2020-01-22 17:40:58 +07:00
Ilya Matveev
9b5bd0dd5d Gradle, native: Support exporting dependencies for static and shared libs
Issue #KT-35352 fixed
2020-01-22 17:40:57 +07:00
Yaroslav Chernyshev
17d3f1d075 [Gradle, Native] Implement custom name for generated framework for XCode
(cherry picked from commit 401baa35ab)
2020-01-22 10:53:21 +03:00
Natalia Selezneva
1af05fd600 Fix script configurations for gradle project without source roots in 193 and as40
GradleKtsImportTest:testEmpty fixed
(cherry picked from commit b38836c488)
2020-01-22 09:51:48 +03:00
Natalia Selezneva
9a36ec0219 KotlinDslScriptModel request shouldn't fail the gradle build
(cherry picked from commit f0cb51a5bc)
2020-01-22 09:51:48 +03:00
Natalia Selezneva
f3bb45c59c as36: Update to AS 3.6 RC (192.7142.36.36.6071332)
^KT-36005 Fixed

(cherry picked from commit 606279b462)
2020-01-22 09:51:48 +03:00
Natalia Selezneva
a9ba149554 Remove unnecessary bunch file for AS4.0
(cherry picked from commit 4699ba758e)
2020-01-22 09:51:48 +03:00
Natalia Selezneva
521d3eee70 Scripting: do not call getConfiguration inside ScriptClassRootsCache
We already have all configurations inside `all` property.
If script doesn't have loaded configuration getting script sdk - ask for configuration explicitly to avoid situations when configuration is already loaded but not yet saved in memory cache

Looks related to KT-35590
^KT-35590

(cherry picked from commit a24e62eaf7)
2020-01-22 09:51:47 +03:00
Vladimir Dolzhenko
195104f7cf Store addUnambiguousImportsOnTheFly in kotlin code insight settings
store optimizeImportsOnTheFly in kotlin code insight workspace settings

#KT-36034 Fixed
2020-01-21 17:56:18 +01:00
Alexander Podkhalyuzin
a1ec739727 Now using Kotlin setting instead of Java one in 191 as well 2020-01-21 17:55:49 +01:00
Ilya Chernikov
8e812c2685 Add only non-jdk classpath entries from the compiler to script
remove unnecessary manifest classpath entries in the saved compiled
script jar
2020-01-21 15:12:03 +01:00
Ilya Chernikov
19ddcc0895 Use scripting cache earlier in the pipeline:
before initializing compiler and processing callbacks
2020-01-21 15:12:03 +01:00
Ilya Chernikov
6b25f14bfd Speed up REPL package member declaration provider
about 10-15% on specific test
also preparing test infrastructure for it
2020-01-21 15:12:03 +01:00
Ilya Chernikov
794c22b758 [minor] fix typo in function name 2020-01-21 15:12:03 +01:00
Ilya Chernikov
401f659734 Immplement default cache in main-kts 2020-01-21 15:12:03 +01:00
Ilya Chernikov
874d08b04e Get rid of kotlinx.coroutines usage in saved script runner
to reduce dpendencies for the save dscipt running
2020-01-21 15:12:03 +01:00
Ilya Chernikov
995699cc36 Fix ivy mapping to the maven repos in main-kts 2020-01-21 15:12:03 +01:00
Ilya Chernikov
c9d0e97eaf Implement automatic loading of .main.kts scripts support
also fix discovery from ScriptDefinitionsProvider
2020-01-21 15:12:03 +01:00
Ilya Chernikov
afed7fde01 Check REPL snippet syntax before calling analysis
restores the behaviour of the GenericRepl implementation and fixes
issues then invalid code is being compiled
#KT-34888 fixed
2020-01-21 15:12:02 +01:00
Ilya Gorbunov
464c8782c2 Rename Clock to TimeSource, ClockMark to TimeMark
Step 2: rename classes and interfaces.
Provide deprecated typealiases to smooth migration.

(cherry picked from commit 1336da8453)
2020-01-21 16:07:52 +03:00
Ilya Gorbunov
57c5d0ee83 Rename Clock to TimeSource, ClockMark to TimeMark
Step 1: rename files

(cherry picked from commit a11a25087a)
2020-01-21 16:07:52 +03:00
Elena Lepilkina
2abdeaf365 Update K/N version 2020-01-21 14:05:59 +03:00
Zalim Bashorov
c544749e14 [Build] Remove the property to skip JS IR BE tests
It's no longer needed since we going to start building libraries using the new BE,
so we have to be sure that everything works well in releases branches too.

(cherry picked from commit 9cf1a2b404)
2020-01-21 00:09:36 +03:00
Zalim Bashorov
86441a95c4 [JS BE] Fix is check with Function
#KT-33149 fixed

(cherry picked from commit ee06678484)
2020-01-21 00:09:36 +03:00
Igor Chevdar
2c2aa081e4 [kotlin-native-plugin] Enabled compiler daemon 2020-01-20 18:43:14 +03:00
Leonid Startsev
7993a02d9f Support SerializerFactory in Native
kotlinx.serialization plugin now adds additional function to companions
of generic classes in order to overcome lack of reflection. This
helps retrieving generic serializers from KType.

(cherry picked from commit 137c500e3a)
2020-01-20 14:57:12 +03:00
Nikolay Krasko
5db3ae7680 Switch to 193 platform 2020-01-20 13:46:44 +03:00
Nikolay Krasko
7e3ba2f976 Update 193 to 193.6015.22-EAP-SNAPSHOT 2020-01-20 13:44:42 +03:00
Nikolay Krasko
3d632163d8 Advance version to 193.5662.53
(cherry picked from commit 80d5723a07)
2020-01-20 13:44:42 +03:00
Nikolay Krasko
7562bc44d2 Mute TCServiceMessageOutputStreamHandlerTest for 193 platform (KT-35938)
(cherry picked from commit b4ae1645ec)
2020-01-20 13:44:42 +03:00
Nikolay Krasko
513f8b26d5 JUnit 4 runner for ignoring muted tests
(cherry picked from commit fd8ff463bb)
2020-01-20 13:44:42 +03:00
Nikolay Krasko
059b0b4e8c Run tests in kotlin-gradle-plugin in repository working dir
Unify with other modules and make GradleNodeModuleBuilderTest work under
JPS.

(cherry picked from commit 6963c81b40)
2020-01-20 13:44:42 +03:00
Mikhael Bogdanov
6100899487 Minor. Convert test
(cherry picked from commit 52ac8d788d)
2020-01-20 10:57:47 +01:00
Mikhael Bogdanov
01b1567723 Don't generate type annotations on synthetic accessors
#KT-35843 Fixed

(cherry picked from commit 70d71f0f07)
2020-01-20 10:57:35 +01:00
Mikhael Bogdanov
3bb25c889a Support field type annotations
#KT-35843 Fixed

(cherry picked from commit 1032e3a17c)
2020-01-20 10:57:22 +01:00
Mikhael Bogdanov
a4b3912ea7 Support type annotations
#KT-35843 Fixed

(cherry picked from commit 2ed0cb2a89)
2020-01-20 10:57:06 +01:00
victor.petukhov
04ad28046a Fix isNegated psi method in KtWhenConditionInRange
^KT-34395 Fixed

(cherry picked from commit fc7b836151)
2020-01-17 19:26:17 +03:00
Victor Petukhov
982d86b4a3 Workaround an inliner problem upon which the compiler code itself stumbled
^KT-35856 Fixed

(cherry picked from commit 5917591205)
2020-01-17 19:26:07 +03:00
Sergey Igushkin
c5fdddb719 Support serializing a module's own descriptors without dependencies
The KlibMetadataSerializer used to serialize all package fragments that a module
could provide, including those coming from the module's dependencies. In order
to produce a klib from a module that is analyzed by the K2MetadataCompiler, the
serializer needs to take just the own package fragments of the module, excluding
those of the dependencies.

(cherry picked from commit 1129b2d3eb)
2020-01-17 18:51:11 +03:00
Sergey Igushkin
65b4680521 Support generating a klib from common code with K2MetadataCompiler
(cherry picked from commit ed6034e449)
2020-01-17 18:51:10 +03:00
Sergey Igushkin
820be03e25 Allow not providing IR to serialize a klib with just the frontend metadata
(cherry picked from commit 28e0089259)
2020-01-17 18:51:08 +03:00
Sergey Igushkin
a1909b10ef Fix non-existing files passed in classpath to Kotlin/JS compiler
(cherry picked from commit 38feadcfe8)
2020-01-17 18:31:51 +03:00
Nikolay Krasko
f184c4d2ac Simplify adding Kotlin sdk by inlining internals of ProjectSdksModel
Because of using cloning sdks inside ProjectSdksModel tests fail with sdk leaked errors.

(cherry picked from commit c7d39b612c)
2020-01-17 18:25:08 +03:00
Nikolay Krasko
48cd03a66c Better fix for compiler plugin test initialization
The previous one didn't work in 191.
Also revert changes in tests-common module.

(cherry picked from commit 70067bc9bf)
2020-01-17 18:25:08 +03:00
Nikolay Krasko
919092558c Mute flaky JavaAgainstKotlin.testUsingMutableInterfaces
(cherry picked from commit ddda93ad96)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
1d1453197b Enable mute tests feature for BuiltInDecompilerTest
(cherry picked from commit e20c66011a)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
7e0e94736e Mute flaky step over tests on Android Studio
(cherry picked from commit 28e23f0aa8)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
4c89c4bccc Mute GradleMigrateTest.testMigrateStdlib in AS
(cherry picked from commit 11e4b710b5)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
44fd8a8a16 Mute tests for preferring JDK classes in completion and auto-import in 191 and 192 (KT-35709)
BasicCompletionWeigherTestGenerated.testPreferFromJdk
AutoImports.testAmbiguousNamePreferFromJdk

(cherry picked from commit 77edfed764)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
a64f0366b1 Fix test data for QuickFixTestGenerated.SupertypeInitialization in 191
(cherry picked from commit 74e2c98426)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
be7ae53b40 Mute JavaToKotlinConverterSingleFileTestGenerated in 191
(cherry picked from commit 0d48855333)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
d4bb1f3f42 Fix UpdateConfigurationQuickFixTest.testEnableCoroutinesFacet test
(cherry picked from commit 28eb6a223d)
2020-01-17 18:25:07 +03:00
Nikolay Krasko
e9d6cce9a3 Split tests to common and platform parts
(cherry picked from commit 4c28e0dec3)
2020-01-17 18:25:06 +03:00
Nikolay Krasko
2e436a2c25 Minor: sort tests in mute database
(cherry picked from commit 570b522e8e)
2020-01-17 18:25:06 +03:00
Nikolay Krasko
ad0884e0cb Port muting database from master
(cherry picked from commit 8014a6509e)
(cherry picked from commit 482cb07420)
(cherry picked from commit 9d54d1ec40)
(cherry picked from commit c5d4213a5c)
(cherry picked from commit c935078f05)
(cherry picked from commit c848212ae9)
(cherry picked from commit 08ade450ff)
(cherry picked from commit f41b588f70)
(cherry picked from commit 712517a02e)
(cherry picked from commit 5f25242cbf)
(cherry picked from commit 3520d5b81d)
(cherry picked from commit 18b1d64adc)
(cherry picked from commit c11f36cf1d)
(cherry picked from commit 84604b91bf)
(cherry picked from commit 1058f04c53)
(cherry picked from commit 1e3736ec1e)
(cherry picked from commit 6613b73657)
(cherry picked from commit dca5ff10c7)
(cherry picked from commit d80fdf307f)
(cherry picked from commit d2909814c2)
(cherry picked from commit 03bd80b1ba)
(cherry picked from commit 3210e1d44c)
(cherry picked from commit 1682ace428)
(cherry picked from commit 9206f1cfb2)
(cherry picked from commit 1e14c48742)
(cherry picked from commit 0884681662)
(cherry picked from commit c372dc7f0a)
(cherry picked from commit 9b68008208)
(cherry picked from commit d575df56e9)
(cherry picked from commit 1b9bae0cca)
(cherry picked from commit bf79b660c4)
(cherry picked from commit 2f129ea435)
(cherry picked from commit 7a94b1d88b)
(cherry picked from commit 5583b57ed7)
(cherry picked from commit 70ff3d36d0)
2020-01-17 18:25:06 +03:00
Yan Zhulanow
899d1c844e Remove changelog for previous releases 2020-01-17 21:10:16 +09:00
Dmitry Gridin
cabe30f973 idea: cleanup code
(cherry picked from commit 8dbbd64beb)
2020-01-17 17:29:23 +07:00
Ilya Matveev
5585074266 Gradle, native: Don't use an arg file when compiler daemon is enabled
We pass compiler flags using an arg file if the compiler is executed
in a separate process because Windows limits maximal command line
length (see https://github.com/JetBrains/kotlin-native/issues/1999).

But for the compiler daemon we pass the args directly to the compiler
entry point method. So we can abandon using an arg file here.
2020-01-17 12:45:50 +07:00
Ilya Matveev
fd89b9000b Gradle, native: Escape spaces in K/N compiler args
We use an argument file to pass arguments to the K/N compiler.
Earlier each line of such a file was treated by the compiler
as a separate argument. But this logic was updated some time
ago and now content for this file is treated as a space separated
list of arguments.

This patch takes this into account at the Gradle side and quotes
arguments written to the arg file.

Issue #KT-35934 Fixed
2020-01-17 12:45:49 +07:00
Abduqodiri Qurbonzoda
96059aead3 Create method Collection.randomOrNull() #KT-35347
(cherry picked from commit 3cad1bbb51)
2020-01-16 22:56:28 +03:00
Sergey Rostov
db8be3fc8a AbstractScriptConfigurationLoadingTest: add asserting messages
(cherry picked from commit 07041574da)
2020-01-16 19:17:42 +03:00
Sergey Rostov
287cbd8382 .gralde.kts: optimize getAffectedGradleProjectFiles (EA-220597 fixed)
(cherry picked from commit 40914e79ee)
2020-01-16 19:17:41 +03:00
Alexander Udalov
13aea1382e Revert "JVM/JVM_IR: fix mapping of KClass in annotation classes"
This reverts commit 7cd55c85e6.

Since we don't have much time for carrying out the deprecation policy,
KT-35207 will be supported since 1.4-M1.
2020-01-16 17:02:06 +01:00
Alexander Udalov
8f09dcbe9b Keep annotation FQ name in experimental API diagnostics
This fixes compilation of ExperimentalFixesFactory where this FQ name
is used to construct a correct quick fix instance.

(cherry picked from commit b5afdc7553)
2020-01-16 17:01:06 +01:00
Alexander Udalov
f9f286dd8c Deprecate Experimental/UseExperimental in favor of RequiresOptIn/OptIn
(cherry picked from commit 514bf3eec0)
2020-01-16 17:01:06 +01:00
Alexander Udalov
fd879cb4f5 Support custom message in RequiresOptIn
#KT-34648 Fixed

(cherry picked from commit f954a6c812)
2020-01-16 17:01:05 +01:00
Alexander Udalov
73d3b7632c Rename UseExperimental->OptIn, Experimental->RequiresOptIn in quickfix and IDE tests
(cherry picked from commit 9187a85aaf)
2020-01-16 17:01:05 +01:00
Alexander Udalov
82b18c9291 Fix compiler and IDE tests on Experimental/RequiresOptIn
See cdbabf224f, e009c7064e

(cherry picked from commit 16db3a8b5f)
2020-01-16 17:01:05 +01:00
Alexander Udalov
cd668eae98 Rename UseExperimental->OptIn, Experimental->RequiresOptIn in Gradle plugin
(cherry picked from commit da077b5353)
2020-01-16 17:01:05 +01:00
Alexander Udalov
e821a7c516 Rename UseExperimental->OptIn, Experimental->RequiresOptIn in stdlib kdocs
(cherry picked from commit 8f94a2bb75)
2020-01-16 17:01:05 +01:00
Alexander Udalov
e35f1c4bbc Rename UseExperimental->OptIn, Experimental->RequiresOptIn in compiler tests
(cherry picked from commit 7742a3b697)
2020-01-16 17:01:04 +01:00
Alexander Udalov
834fc4d457 Rename Experimental/UseExperimental in compiler diagnostic messages
#KT-34647

(cherry picked from commit b839b905b5)
2020-01-16 17:01:04 +01:00
Alexander Udalov
deced92e8d Fix NPE in ExperimentalUsageChecker in corner case
Since there's no nullability assertion, null could end up in this list
and cause NPE further at `reportNotAcceptedExperimentalities`. This
could happen if a declaration was annotated with WasExperimental, the
marker was annotated with the new RequiresOptIn, and API version 1.2 was
used.

No new tests are added because 1.2 is obsolete and WasExperimental is
internal.

(cherry picked from commit d547af00aa)
2020-01-16 17:01:04 +01:00
Alexander Udalov
1c047daeae Add -Xopt-in command line argument
As per https://github.com/Kotlin/KEEP/pull/201

(cherry picked from commit e009c7064e)
2020-01-16 17:01:04 +01:00
Alexander Udalov
adec550d1a Introduce RequiresOptIn and OptIn annotations
RequiresOptIn should be used now instead of Experimental, OptIn instead
of UseExperimental. See https://github.com/Kotlin/KEEP/pull/201.

This change adds the new declarations only to the stdlib, and supports
them in the compiler. Because of the way compiler loads annotations, we
need to bootstrap it first before deprecating the old annotations and
updating tests.

 #KT-34647 Fixed

(cherry picked from commit cdbabf224f)
2020-01-16 17:01:04 +01:00
Alexander Udalov
35258657af Deprecate -Xexperimental compiler argument
This option is not widely used and its implementation relies on a
complicated mechanism of a module-wide metadata, which is not properly
supported in the IDE (see IdeModuleAnnotationsResolver).

 #KT-34649 Fixed

(cherry picked from commit 33bc3db144)
2020-01-16 17:01:03 +01:00
Vyacheslav Gerasimov
6d8148f64b Build: Add missing com.github.node-gradle.node plugin versions
(cherry picked from commit fa1c6c9697)
2020-01-16 18:52:25 +03:00
Vyacheslav Gerasimov
5ca2a9b79f Build: Add kotlinPluginPublication to idea-gradle-tooling-api
(cherry picked from commit a0e73bffa0)
2020-01-16 18:52:14 +03:00
Dmitry Gridin
fb10a6de3a KtScratchExecutionSession: fix compilation for 191
(cherry picked from commit 09acdb655d)
2020-01-16 18:40:12 +07:00
Dmitry Gridin
353404705f KotlinDebuggerCaches: fix INRE
#EA-219472 Fixed

(cherry picked from commit 898308c7ba)
2020-01-16 18:40:09 +07:00
Dmitry Gridin
33251ee2ee KotlinConsoleRunner: fix INRE
#EA-219478 Fixed

(cherry picked from commit 3f500c6e92)
2020-01-16 18:40:07 +07:00
Dmitry Gridin
2dcf96cd71 IDEKotlinAsJavaSupport: fix INRE
#EA-213321 Fixed

(cherry picked from commit 02beb72ab1)
2020-01-16 18:38:09 +07:00
Dmitry Gridin
c82520e1bf KotlinFunctionBreakpoint: fix INRE
#KT-35316 Fixed
#EA-219418 Fixed

(cherry picked from commit 4d7fe78a51)
2020-01-16 18:38:05 +07:00
Dmitry Gridin
286149efe5 KotlinNativeModuleConfigurator: fix INRE
#EA-219416 Fixed

(cherry picked from commit 09bcfab047)
2020-01-16 18:38:04 +07:00
Dmitry Gridin
4be844bbe7 KtScratchExecutionSession: fix INRE
#EA-218701 Fixed

(cherry picked from commit 86f9253fa0)
2020-01-16 18:38:01 +07:00
Dmitry Gridin
de7f8c34c8 KotlinVariableInplaceIntroducer: fix PIEAE
#EA-209820 Fixed

(cherry picked from commit 78f7ed2c27)
2020-01-16 18:37:58 +07:00
Dmitry Gridin
6b4d2ed7db JavaToKotlinAction: fix KNPE
#EA-215300 Fixed

(cherry picked from commit 580885245d)
2020-01-16 18:36:50 +07:00
Dmitry Gridin
83ed2150a5 idea: fix some ControlFlowException
#EA-219412 Fixed

(cherry picked from commit 34dcc72e7f)
2020-01-16 18:36:47 +07:00
Dmitry Gridin
327acd5f5f PerModulePackageCacheService: fix NPE for code injection
#KT-35208 Fixed

(cherry picked from commit 7c9826b60b)
2020-01-16 18:35:05 +07:00
Nicolay Mitropolsky
b31f88a51d 191: Uast: fix compilation for 191
(cherry picked from commit ed57a53ad6)
2020-01-16 10:24:02 +03:00
Nicolay Mitropolsky
72a7bc2beb Uast: KotlinIDERenderLogTest for running UAST tests with ULC
In case of result difference the `-ide`-suffixed testdata is used.
Actually the difference in results is more likely to be a bug
but currently we are fixating at least some behaviour to protect from
 unexpected regressions in Ultra Light Classes.

`object Local` were removed because there is no local objects in actual
 Kotlin syntax

(cherry picked from commit 54285d328f)
2020-01-16 10:24:00 +03:00
Mikhail Zarechenskiy
589a07494d Add feature that allows references to synthetic properties with warning
See KT-35933 for details
2020-01-16 09:46:00 +03:00
Natalia Selezneva
9e3ed92e26 Scripting: use VFS events instead of document changes to track changes outside of IDE (KT-35557)
^KT-35557 Fixed

(cherry picked from commit a653feb2dc)
2020-01-16 09:38:05 +03:00
Natalia Selezneva
bdf3543ebf Simplify check for that gradle script configurations is up to date
Get time stamp for script inputs before gradle import

(cherry picked from commit 6bf0e4b1a9)
2020-01-16 09:38:04 +03:00
Natalia Selezneva
cf3c505097 Implement persistent storage for time stamps of files that affect build script configuration (KT-3556)
^KT-3556 Fixed

(cherry picked from commit 3dfbd824e4)
2020-01-16 09:38:04 +03:00
Natalia Selezneva
426815b8ae Scripting: extract API to check if script is related to any gradle project
KT-35268 cannot be implemented without explicit action for loading configurations for script outside of project model

^KT-35268
^KT-34625

(cherry picked from commit ecb05ace91)
2020-01-16 09:38:04 +03:00
Natalia Selezneva
d3bcbcc7eb Tests: switch off script configuration update in MutlifileRefactoringTests
(cherry picked from commit feda832eb7)
2020-01-16 09:38:04 +03:00
Natalia Selezneva
0ef8ecea02 Scripting: remove unexpected cache clear
(cherry picked from commit 233d400e93)
2020-01-16 09:38:04 +03:00
Sergey Igushkin
b9888d160b Deprecate 1.2.x MPP Gradle plugins
Issue #KT-31570 Fixed
2020-01-16 00:00:28 +03:00
Sergey Igushkin
0cb15d8c88 Support Gradle instant execution for Kapt tasks
* In the Kotlin/JVM tasks, move the compiler arguments setup logic to
  a separate class, so that it can be reused by the Kapt tasks without
  directly referencing the Kotlin/JVM tasks

* In the Kapt tasks, carefully capture the values using the Provider API
  so that the task can be serialized for Instant Execution and then
  deserialized and executed without relying on the project model

Issue #KT-35181 Fixed

(cherry picked from commit f9acc0ab88)
2020-01-15 23:55:49 +03:00
Ilmir Usmanov
0ddeb3975c Unconditionally remove $$forInline suffix from enclosing method
when transforming objects with suspend functions/lambdas, which
capture crossinline suspend lambdas. Since functions with the
suffix have a counterpart without the suffix, for java interop
and reflection call purposes, it is safe change.
 #KT-31242 Fixed
2020-01-15 15:12:57 +01:00
Ilya Kirillov
bbb0788e4a New J2K: fix exception when met PsiLambdaParameterType
#KT-35431 fixed

(cherry picked from commit a10f37dd50)
2020-01-15 14:18:25 +03:00
Ilya Kirillov
0dcec158ec New J2K: fix converting multiline comment with /* inside
#KT-18001 fixed
#KT-35081 fixed

(cherry picked from commit 5be80be74d)
2020-01-15 14:18:24 +03:00
Ilya Kirillov
b3654b7d03 New J2K: add missing line break between property and getter
#KT-35739 fixed

(cherry picked from commit a87de01c74)
2020-01-15 14:18:24 +03:00
Ilya Kirillov
47ee2452aa New J2K: fix incorrectly removed line break before constructor comment
That caused class body brace to be under the comment

#KT-35478 fixed

(cherry picked from commit b83a529b77)
2020-01-15 14:18:23 +03:00
Ilya Kirillov
3990d7337a New J2K: correctly convert compound Java assignment expression
#KT-35476 fixed

(cherry picked from commit 7bfad12e6a)
2020-01-15 14:18:23 +03:00
Ilya Kirillov
0b7f44d5ea New J2K: fix UninitializedPropertyAccessException when calculating type of anonymous class
#KT-35395 fixed

(cherry picked from commit 6a8a68a263)
2020-01-15 14:18:22 +03:00
Ilya Kirillov
62eaad300a New J2K: Fix SOE in nj2k Java declarations printer
(cherry picked from commit 7882f566be)
2020-01-15 14:18:22 +03:00
Ilya Kirillov
77cc29b42d New J2K: remove initializer from property without backing field
#KT-33637 fixed

(cherry picked from commit 14a8d3726d)
2020-01-15 14:18:21 +03:00
Leonid Startsev
85dd870693 Supply correct Native platform for module descriptor while compiling from CLI
(cherry picked from commit 9bd966c123)
2020-01-15 12:51:07 +03:00
Leonid Startsev
dddab06b9f Support .decodeSequentially call on JVM and Native and remove READ_ALL handling from all platforms
Fix codegen test

Ignore JVM IR codegen test for a while since it requires updated kotlinx-serialization-runtime in classpath

(cherry picked from commit f2026a49bb)
2020-01-15 12:50:49 +03:00
Yaroslav Chernyshev
49f7aa38ea [Gradle, Native] Added subspecs support in CocoaPods plugin
#KT-32750 fixed
2020-01-15 15:42:59 +07:00
Alexander Gorshenev
797dd80ee5 Allow parallel access to klib zip filesystem 2020-01-14 19:12:30 +03:00
Nicolay Mitropolsky
2d8701a2d9 Uast: fake light method for uast is created only when containing class exists (KT-35310, EA-219604)
(cherry picked from commit 23c2a5c830)
2020-01-14 17:05:29 +03:00
Nicolay Mitropolsky
3330db8c7b Uast: the returnType support for light methods for reified functions (KT-35610)
(cherry picked from commit ed4e73c8e9)
2020-01-14 17:05:27 +03:00
Nicolay Mitropolsky
c54f55d460 Uast: properly handling annotations on destructured variables (KT-35673, EA-220128)
(cherry picked from commit c04ba009e6)
2020-01-14 17:05:26 +03:00
Vladimir Dolzhenko
6aa9fe6def IAE: RangeMarkerImpl.<init>
#EA-141884 Fixed
2020-01-14 13:11:22 +01:00
Vladimir Dolzhenko
e972901b9c Access index under runReadActionInSmartMode in ProbablyContractedCallableNamesImpl
#EA-219476 Fixed
2020-01-14 13:11:10 +01:00
Vladimir Dolzhenko
c5a669ead4 Improve investigation info in KtDotQualifiedExpression
Relates to #EA-212081
2020-01-14 13:11:01 +01:00
Vladimir Dolzhenko
5d4ab93db3 Access index under runReadActionInSmartMode in KotlinRuntimeLibraryUtil
#EA-220414 Fixed
2020-01-14 13:10:52 +01:00
Vladimir Dolzhenko
550d057fc8 Edit kdoc reference in Introducing import alias
#KT-35837 Fixed
2020-01-14 13:10:41 +01:00
Vladimir Dolzhenko
c26522dfd2 Handle kdoc case for Introduce import alias inspection
#EA-210889 Fixed
2020-01-14 13:10:30 +01:00
Vladimir Dolzhenko
5f6f2f8af9 Module info has to be read under readAction in KotlinConfigurationCheckerComponent
#EA-209610 Fixed
2020-01-14 13:09:57 +01:00
Vladimir Dolzhenko
bc5ffe14a9 Improve investigation info in PackageCodegenImpl
Relates to #EA-218779
2020-01-14 13:09:46 +01:00
Vladimir Dolzhenko
dc8b3ffd8a Handle \r line endings in plaintext j2k
#KT-35831 #EA-209568 Fixed
2020-01-14 13:09:35 +01:00
Vladimir Dolzhenko
e1beebde08 Handle java ctor case for Introduce import alias inspection
#KT-35824 #EA-218654 Fixed
2020-01-14 13:09:23 +01:00
Vladimir Dolzhenko
edfe97a165 Add more investigation info to diagnoseUnknownModuleInfo
Relates to #EA-220276
2020-01-14 13:09:08 +01:00
Vladimir Dolzhenko
0e66b5ed9d Add disposable to document listener in ScratchEditorSyncHighlighter
#EA-220382 Fixed
2020-01-14 13:08:32 +01:00
Vladimir Dolzhenko
803df7d7a1 Fix renaming class according to a file name when file name has no name (but extension)
#EA-219715 Fixed
2020-01-14 13:08:23 +01:00
Vladimir Dolzhenko
4f3e26e7be Commit documents before createResourceReference in KotlinAndroidAddStringResource
#EA-127016 Fixed
2020-01-14 13:08:09 +01:00
Vladimir Dolzhenko
87477fe15a Add more investigation info to getFilesForElements
Relates to #EA-209630
2020-01-14 13:08:00 +01:00
Vladimir Dolzhenko
175d0da3e8 Module info has to be read under readAction in scriptDefinitionsFromDependencies
#EA-220355 Fixed
2020-01-14 13:07:46 +01:00
Vladimir Dolzhenko
3eb3e55d6f Module info has to be read under readAction in KotlinNativeABICompatibilityChecker
#EA-220356 Fixed
2020-01-14 13:07:37 +01:00
Ilya Gorbunov
85b931b64a Rewrite UnderMigration and MigrationStatus in Java
to remove dependency on kotlin-stdlib.

#KT-33141

(cherry picked from commit 0764a065e8)
2020-01-14 14:34:08 +03:00
Miguel Serra
5a9e771197 KT-20357: Add samples for linkedSetOf
(cherry picked from commit 4fa5e2d85c)
2020-01-14 14:34:08 +03:00
Tillmann Berg
94b82080bc KT-20357: Add sample for reduce, reduceRight and their indexed counterparts
(cherry picked from commit 95300ae31d)
2020-01-14 14:34:08 +03:00
Ilya Gorbunov
cd7a6989ec Add more reduceOrNull tests
- Test for unsigned arrays
- Update binary api dump with the new functions

(cherry picked from commit 6d092b5f71)
2020-01-14 14:34:08 +03:00
Alfredo Delli Bovi
5bfc9ad010 Add sample for reduceOrNull and reduceRightOrNull
(cherry picked from commit 9546307243)
2020-01-14 14:34:07 +03:00
Alfredo Delli Bovi
f28c13bdcc KT-33761 Add reduceRightOrNull
(cherry picked from commit 06008c40ab)
2020-01-14 14:34:07 +03:00
Alfredo Delli Bovi
773cdf314f KT-33761 Add reduceOrNull
(cherry picked from commit f5d696d3c4)
2020-01-14 14:34:07 +03:00
Abduqodiri Qurbonzoda
cc8dcef9aa Rename Appendable methods parameters
(cherry picked from commit b868e6f8da)
2020-01-14 14:34:07 +03:00
Ilmir Usmanov
16d78e45a7 Disable tail-call optimization for suspend functions with Unit return type
if it overrides functions with another return type.
Otherwise, we cannot determine on call site that the function returns Unit
and cannot { POP, PUSH Unit } in order to avoid the situation when callee's
continuation resumes with non-unit result. The observed behavior is that
suspend function, which should return Unit, suddenly returns other value.
 #KT-35262: Fixed
2020-01-14 12:21:23 +01:00
Ilya Matveev
4d0c015575 IDEA plugin: Don't create iOS test in the share lib project template
Since 1.3.70 an iOS simulator test task is created by the MPP Gradle
plugin out of the box. So we stop creating such a task manually in
the shared library project template.

Issue #KT-35560 Fixed.
2020-01-14 17:44:08 +07:00
Vladimir Dolzhenko
787192fc0d Drop UNREACHABLE_CODE eager text range calculation
#KT-35242 Fixed

(cherry picked from commit 272ca002d7)
2020-01-14 11:25:00 +01:00
Ilya Chernikov
49791a3207 Allow only single expression eval in cli compiler and kotlin runner
#KT-35740 fixed
also add tests and drop logger usage in the cli dependencies manager:
the logger is normally unitialized in the usage scenarios, but related
warnings are annoying.

(cherry picked from commit 995c6a32b8)
2020-01-14 07:59:51 +01:00
Ilya Chernikov
8c24a860c1 [minor] "fix" fir testdata for KT-30245 test, todo: fix problems in fir accordingly
(cherry picked from commit 9da536c202)
2020-01-14 07:59:51 +01:00
Ilya Chernikov
a014725187 [NI] Convert extension lambda to the non-extension one, if needed
#KT-30245 fixed
2020-01-14 07:59:51 +01:00
Ilya Goncharov
7fa0f15a11 [Gradle, JS] Actualize node and yarn version
#KT-35599 fixed

(cherry picked from commit 74889ef3ad)
2020-01-13 19:17:09 +03:00
Ilya Goncharov
f05288848c [Gradle, JS] Add check on run and dist task
- Check existence of compile output file to prevent fail in case of NO-SOURCE

#KT-31894 fixed

(cherry picked from commit 24e3310393)
2020-01-13 19:17:09 +03:00
Vyacheslav Gerasimov
4efebea5db Build: Specify version explicitly for com.github.node-gradle.node 2020-01-13 15:48:10 +03:00
Yan Zhulanow
804c57d90a Update Changelog: add entries for 1.3.70 EAP 1 2020-01-13 17:33:30 +09:00
Yan Zhulanow
464076b5d1 Update Changelog: add entries from 1.3.60/61 2020-01-13 17:31:48 +09:00
nikita.movshin
116e34a0ae Update K/N version 2019-12-26 19:46:21 +03:00
Vyacheslav Gerasimov
0d60f2b5b9 as40: Minor: Fix copyright header in AbstractModelBuilderTest.java
(cherry picked from commit 5a9070b6da)
2019-12-26 16:40:55 +03:00
Vyacheslav Gerasimov
21c3050e96 as40: Fix duplicate registration of kotlin-copyright
(cherry picked from commit 3d79e4609e)
2019-12-26 16:40:55 +03:00
Vyacheslav Gerasimov
ba57ab531b Build: Fix android-wizardTemplate-plugin dependencies
Present only in AS 3.6

(cherry picked from commit 7b1c4e72ba)
2019-12-26 16:40:55 +03:00
Vyacheslav Gerasimov
4ca8140d50 as40: Fix test compilation for AS 4.0 C7 2019-12-26 16:40:54 +03:00
Vyacheslav Gerasimov
e2edf54c86 as40: Fix KotlinDslScriptModelProvider and KotlinDslScriptModelResolver for AS 4.0 C7 2019-12-26 16:40:54 +03:00
Vyacheslav Gerasimov
923c1b1bf0 as40: Upgrade to AS 4.0 C7 2019-12-26 16:40:54 +03:00
Vyacheslav Gerasimov
675806569a Build: Use tar.gz extension for linux AS distributions 2019-12-26 16:40:54 +03:00
Vyacheslav Gerasimov
1e1ffcc4b4 Build: Add Ide.AS40 constant
(cherry picked from commit eda27ab298)
2019-12-26 16:40:54 +03:00
Vyacheslav Gerasimov
04a63cc87b Build: Add as40 to .bunch
(cherry picked from commit 19233ee120)
2019-12-26 16:40:54 +03:00
Alexander Gorshenev
c07d04e459 Don't search for expects when not given -Xmpp-klibs 2019-12-26 11:34:56 +03:00
nikita.movshin
0c71dde729 Update K/N version 2019-12-25 17:37:06 +03:00
Igor Chevdar
15384c9230 [native-gradle-plugin] Disabled cache building for iOS devices 2019-12-25 15:52:06 +05:00
nikita.movshin
415750c393 Update K/N version 2019-12-24 11:31:25 +03:00
Igor Chevdar
14f670f058 [kotlin-native-plugin] Disabled compiler daemon for now 2019-12-23 16:24:20 +03:00
Igor Chevdar
6886f1390d [kotlin-native-plugin] Two fixes:
* Added property to select the cache kind (none, dynamic, static)
* Fixed the check if the cache needs to be rebuilt
2019-12-23 13:32:03 +03:00
Mikhail Zarechenskiy
23c61dfb54 Fix ambiguity between Java and Kotlin SAM candidates
Because of incorrect flag we generated synthetic SAM candidates and got ambiguity when feature `SamConversionPerArgument` was enabled (Gradle case) because candidates for Java were duplicated

 #KT-35579 Fixed
2019-12-23 12:48:43 +03:00
Igor Yakovlev
895f2d609b Fix allopen call from UL methods
Fixed #KT-35577
2019-12-20 18:28:50 +03:00
Ilya Kirillov
1feda25af3 New J2K: Fix not converted jetbrains nullability annotations for types
it became broken after annotation started to be assigned to type elements
instead of declarations after 4da7d11

#KT-34987 fixed

(cherry picked from commit 92f8432b1e)
2019-12-20 13:05:34 +03:00
Roman Artemev
e4c06a63e7 Update bootstrap to #1.3.70-eap-17 2019-12-19 15:30:47 +03:00
nikita.movshin
7887cfdf99 Update K/N version 2019-12-19 14:39:39 +03:00
nikita.movshin
ae87b0a83e Update K/N version 2019-12-19 11:00:57 +03:00
Igor Chevdar
2cf6f0b00d [IR Serialization] Removed native-specific hack in mangler 2019-12-18 14:48:03 +03:00
Zalim Bashorov
2427764a87 [IDE, klib] Support in IDE klibs with dynamic type 2019-12-17 22:05:08 +03:00
Alexander Gorshenev
ae996c4819 Properly mute (and unmute) tests for unrelated backends 2019-12-17 20:57:39 +03:00
Alexander Gorshenev
c97abf79fc Reconciled -Xklib-mpp with commonizer 2019-12-17 20:57:39 +03:00
Alexander Gorshenev
5525b1cef5 Expect/actual support in klibs under -Xklib-mpp 2019-12-17 20:57:39 +03:00
Roman Artemev
c397da5e3f [KLIB] Fix references to type made from TypeParameter in KotlinMangler
- promote ABI version

(cherry picked from commit cad3cb1bbe)
2019-12-17 19:37:53 +03:00
Svyatoslav Kuzmich
a71f272b59 [JS IR BE] Support typeOf 2019-12-17 19:17:28 +03:00
Svyatoslav Kuzmich
644d25e3e5 [JS IR] Properly report compiler errors
Report compiler errors using message collector
Instead of crashing with stack trace
2019-12-17 19:17:28 +03:00
Roman Artemev
85949ab82d [JS IR] Fix external fields naming
(cherry picked from commit 0b7c11c96e)
2019-12-17 17:37:24 +03:00
Roman Artemev
d8e6937891 [JS IR] Fix state machine builder
(cherry picked from commit 02db5ea0eb)
2019-12-17 17:37:24 +03:00
Roman Golyshev
ea7b929543 Add ML completion jar to the resulting plugin jar
- Without it, ML completion jar will not be present in the runtime, causing errors when ML completion is enabled
- This step should have been done in 28ec74648e commit

(cherry picked from commit 8e53ccb852)
2019-12-17 16:35:38 +03:00
Dmitry Gridin
3365dfa5ae KotlinImportOptimizer: should use with isIndeterminate=false
#KT-34928 Fixed

(cherry picked from commit cdabff1941)
2019-12-17 20:20:39 +07:00
Igor Chevdar
33c7df6457 [IR] Remapped some forgotten types during IR copying 2019-12-17 15:50:45 +03:00
Mikhael Bogdanov
3e219f4ebf Keep original casts during reification to avoid VerifyError
#KT-26435 Fixed

(cherry picked from commit 03c2350e79)
2019-12-17 12:48:16 +01:00
Igor Chevdar
eb0ba37e88 [gradle-native-plugin] Build static caches instead of dynamic 2019-12-17 14:38:38 +03:00
Natalia Selezneva
759d1da0df Fix configuration for AS 3.5
(cherry picked from commit e77d8657f4)
2019-12-17 09:30:02 +03:00
20726 changed files with 246571 additions and 512919 deletions

3
.bunch
View File

@@ -1,7 +1,8 @@
193
201
192
191_192
183_191_192
as34_183_191_192
as35_191_192
as36_192
as40

2
.gitattributes vendored
View File

@@ -1,6 +1,4 @@
**/testData/** linguist-vendored
*Generated.java linguist-generated=true
* text=auto
* eol=lf
compiler/cli/bin/* eol=lf
compiler/cli/bin/*.bat eol=crlf

4
.gitignore vendored
View File

@@ -1,9 +1,8 @@
.DS_Store
.idea/shelf
/android.tests.dependencies
/confluence/target
/dependencies/repo
/android.tests.dependencies
/dependencies/android.tests.dependencies
/dist
/local
/gh-pages
@@ -18,7 +17,6 @@ workspace.xml
/jps-plugin/testData/kannotator
/js/js.translator/testData/out/
/js/js.translator/testData/out-min/
/js/js.translator/testData/out-pir/
.gradle/
build/
!**/src/**/build

View File

@@ -2,8 +2,6 @@
<dictionary name="4u7">
<words>
<w>bintray</w>
<w>cacheability</w>
<w>cacheable</w>
<w>cidr</w>
<w>foldable</w>
<w>instrumentator</w>

View File

@@ -1,7 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="sergey.igushkin">
<words>
<w>klib</w>
</words>
</dictionary>
</component>

View File

@@ -6,7 +6,6 @@
<w>destructured</w>
<w>hacky</w>
<w>impls</w>
<w>inlined</w>
<w>kapt</w>
<w>kotlinc</w>
<w>mutators</w>

View File

@@ -99,6 +99,7 @@
<option name="problems">
<list>
<Problem reference="com.intellij.util.JdomKt#element" reason="Removed in 191" />
<Problem reference="com.intellij.execution.JavaRunConfigurationExtensionManager#getInstance" reason="Can't be used in Kotlin, because method was replaced with property after J2K in 183. Use JavaRunConfigurationExtensionManagerUtil instead." />
<Problem reference="org.jetbrains.kotlin.idea.reporter.ITNReporterCompat#submit" reason="parentComponent is nullable in AS" />
<Problem reference="com.intellij.diagnostic.ITNReporter#submit" reason="parentComponent is nullable in AS" />
</list>

10
.idea/misc.xml generated
View File

@@ -12,8 +12,14 @@
<item index="2" class="java.lang.String" itemvalue="org.gradle.api.tasks.options.Option" />
</list>
</component>
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
<component name="FacetAutodetectingManager">
<autodetection-disabled>
<facet-type id="Python">
<modules>
<module name="Jet" />
</modules>
</facet-type>
</autodetection-disabled>
</component>
<component name="IdProvider" IDEtalkID="71A301FF1940049D6D82F12C40F1E1D5" />
<component name="JavadocGenerationManager">

View File

@@ -12,7 +12,6 @@
<list>
<option value=":compiler:generateTests" />
<option value=":compiler:tests-java8:generateTests" />
<option value=":compiler:tests-against-klib:generateTests" />
<option value=":js:js.tests:generateTests" />
<option value=":core:descriptors.runtime:generateTests" />
</list>

4
.idea/vcs.xml generated
View File

@@ -2,10 +2,8 @@
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="BodyLimit" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GrazieCommit" enabled="true" level="TYPO" enabled_by_default="true" />
<inspection_tool class="SubjectBodySeparation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GrazieCommit" enabled="true" level="TYPO" enabled_by_default="true" />
</profile>
</component>
<component name="IssueNavigationConfiguration">

10222
ChangeLog.md

File diff suppressed because it is too large Load Diff

View File

@@ -37,9 +37,9 @@ In order to build Kotlin distribution you need to have:
JDK_18="path to JDK 1.8"
JDK_9="path to JDK 9"
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 1.8 and JDK 9 installed, and to point `JDK_16` and `JDK_17` environment variables to your JDK 1.8 installation.
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 1.8 and JDK 9 installed, and to point JDK_16 and JDK_17 environment variables to your JDK 1.8 installation.
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties) to setup `JDK_*` variables.
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties) to setup JDK_* variables.
> Note: The JDK 6 for MacOS is not available on Oracle's site. You can [download it here](https://support.apple.com/kb/DL1572).
@@ -73,7 +73,7 @@ command line parameters on the first run:
- `clean` - clean build results
- `dist` - assembles the compiler distribution into `dist/kotlinc/` folder
- `ideaPlugin` - assembles the Kotlin IDEA plugin distribution into `dist/artifacts/ideaPlugin/Kotlin/` folder
- `ideaPlugin` - assembles the Kotlin IDEA plugin distribution into `dist/artifacts/Kotlin` folder
- `install` - build and install all public artifacts into local maven repository
- `runIde` - build IDEA plugin and run IDEA with it
- `coreLibsTest` - build and run stdlib, reflect and kotlin-test tests
@@ -106,39 +106,28 @@ bunch switch 191
Working with the Kotlin project requires at least IntelliJ IDEA 2019.1. You can download IntelliJ IDEA 2019.1 [here](https://www.jetbrains.com/idea/download).
After cloning the project, to import the project in IntelliJ choose the project directory in the Open project dialog. Then, after project opened, select
`File` -> `New` -> `Module from Existing Sources...` in the menu, and select `build.gradle.kts` file in the project's root folder.
After cloning the project, to import the project in Intellij choose the project directory in the Open project dialog. Then, after project opened, Select
`File` -> `New...` -> `Module from Existing Sources` in the menu, and select `build.gradle.kts` file in the project's root folder.
In the import dialog, select `use default gradle wrapper`.
To be able to run tests from IntelliJ easily, check `Delegate IDE build/run actions to Gradle` and choose `Gradle Test Runner` in the Gradle runner settings after importing the project.
At this time, you can use the latest released `1.3.x` version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use `Tools` -> `Kotlin` -> `Configure Kotlin Plugin Updates`.
At this time, you can use the latest released 1.3.x version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use Tools | Kotlin | Configure Kotlin Plugin Updates and press "Check for updates now".
### Compiling and running
From this root project there are Run/Debug Configurations for running `IDEA` or the `Generate Compiler Tests` for example; so if you want to try out the latest and greatest IDEA plugin
From this root project there are Run/Debug Configurations for running IDEA or the Compiler Tests for example; so if you want to try out the latest and greatest IDEA plugin
* `VCS` -> `Git` -> `Pull`
* Run the `IDEA` run configuration in the project
* A child IntelliJ IDEA with the Kotlin plugin will then startup
* VCS -> Git -> Pull
* Run the "IDEA" run configuration in the project
* a child IntelliJ IDEA with the Kotlin plugin will then startup
### Including into composite build
To include kotlin compiler into [composite build](https://docs.gradle.org/current/userguide/composite_builds.html) you need to define `dependencySubstitution` for `kotlin-compiler` module in `settings.gradle.kts`
To include kotlin compiler into [composite build](https://docs.gradle.org/current/userguide/composite_builds.html) you need to define `dependencySubstitution` for `kotlin-compiler` module in `settings.gradle`
```Kotlin
includeBuild("/path/to/kotlin") {
dependencySubstitution {
substitute(module("org.jetbrains.kotlin:kotlin-compiler"))
.with(project(":include:kotlin-compiler"))
}
}
```
or in `settings.gradle`
```Groovy
includeBuild('/path/to/kotlin') {
dependencySubstitution {
substitute module('org.jetbrains.kotlin:kotlin-compiler') with project(':include:kotlin-compiler')

View File

@@ -75,21 +75,6 @@ benchmark {
include("CommonCallsBenchmark")
//include("InferenceBaselineCallsBenchmark")
}
register("ni") {
warmups = 10
iterations = 10
iterationTime = 1
iterationTimeUnit = "sec"
param("useNI", true)
param("isIR", false)
param("size", 1000)
include("InferenceBaselineCallsBenchmark")
include("InferenceExplicitArgumentsCallsBenchmark")
include("InferenceForInApplicableCandidate")
include("InferenceFromArgumentCallsBenchmark")
include("InferenceFromReturnTypeCallsBenchmark")
}
}
targets {
register("main")

View File

@@ -74,7 +74,7 @@ private val LANGUAGE_FEATURE_SETTINGS =
private fun newConfiguration(useNewInference: Boolean): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration.put(CommonConfigurationKeys.MODULE_NAME, "benchmark")
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, "../compiler/cli/cli-common/resources")
configuration.put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, "../idea/resources")
configuration.addJvmClasspathRoot(JDK_PATH)
configuration.addJvmClasspathRoot(RUNTIME_JAR)
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
@@ -161,11 +161,10 @@ abstract class AbstractSimpleFileBenchmark {
val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile))
.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 builder = RawFirBuilder(session, stubMode = false)
val totalTransformer = FirTotalResolveTransformer()
val firFile = builder.buildFirFile(file).also(firProvider::recordFile)
val firFile = builder.buildFirFile(file).also((session.firProvider as FirProviderImpl)::recordFile)
for (transformer in totalTransformer.transformers) {
transformer.transformFile(firFile, null)

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class ManyImplicitReceiversBenchmark : AbstractSimpleFileBenchmark() {
@Param("1", "10", "50")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText(): String {
return buildString {
appendln("inline fun <T, R> with(receiver: T, block: T.() -> R): R = block()")
for (i in 1..size) {
appendln("interface A$i {")
appendln(" fun foo$i()")
appendln("}")
appendln()
}
appendln()
append("fun test(")
append((1..size).joinToString(", ") { "a$it: A$it" })
appendln(" {")
for (i in 1..size) {
appendln("with(a$i) {")
}
for (i in 1..size) {
appendln("foo$i()")
}
for (i in 1..size) {
appendln("}")
}
appendln("}")
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.benchmarks
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class PlusAssignOperatorDesugaringBenchmark : AbstractInferenceBenchmark() {
@Param("9", "10", "11", "12", "13", "14")
private var size: Int = 0
@Benchmark
fun benchmark(bh: Blackhole) {
analyzeGreenFile(bh)
}
override fun buildText(): String = buildString {
appendln(
"""
class A {
operator fun <T : Number> plus(other: (Int) -> T): A = this
operator fun <T : CharSequence> plusAssign(other: (String) -> T) {}
}
""".trimIndent()
)
appendln("fun test() {")
appendln("var a = A()")
for (i in 1..size) {
appendln("a += {")
}
for (i in 1..size) {
appendln(
"""
it.inc()
1
}
""".trimIndent())
}
appendln()
}
}

View File

@@ -1,3 +1,4 @@
description = "Kotlin Build Common"
plugins {
@@ -11,7 +12,7 @@ dependencies {
compileOnly(project(":compiler:cli-common"))
compileOnly(project(":compiler:frontend.java"))
compileOnly(project(":js:js.serializer"))
compileOnly(project(":js:js.config"))
compileOnly(project(":js:js.frontend"))
compileOnly(project(":kotlin-util-klib-metadata"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(intellijDep()) { includeJars("asm-all", "trove4j", "util", rootProject = rootProject) }
@@ -22,9 +23,8 @@ dependencies {
testCompile(commonDep("junit:junit"))
testCompile(protobufFull())
testCompile(kotlinStdlib())
Platform[193].orLower {
testCompileOnly(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
}
testCompileOnly(intellijDep()) { includeJars("openapi") }
testRuntime(project(":kotlin-reflect"))
}

View File

@@ -83,17 +83,6 @@ open class IncrementalJsCache(
dirtySources.addAll(removedAndCompiledSources)
}
fun compare(translatedFiles: Map<File, TranslationResultValue>, changesCollector: ChangesCollector) {
for ((srcFile, data) in translatedFiles) {
val oldProtoMap = translationResults[srcFile]?.metadata?.let { protoData(srcFile, it) } ?: emptyMap()
val newProtoMap = protoData(srcFile, data.metadata)
for (classId in oldProtoMap.keys + newProtoMap.keys) {
changesCollector.collectProtoChanges(oldProtoMap[classId], newProtoMap[classId])
}
}
}
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
val translatedFiles = incrementalResults.packageParts
@@ -128,8 +117,8 @@ open class IncrementalJsCache(
}
for ((srcFile, irData) in incrementalResults.irFileData) {
val (fileData, types, signatures, strings, declarations, bodies, fqn) = irData
irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn)
val (fileData, symbols, types, strings, declarations, bodies, fqn) = irData
irTranslationResults.put(srcFile, fileData, symbols, types, strings, declarations, bodies, fqn)
}
}
@@ -240,8 +229,8 @@ private class TranslationResultMap(
private object IrTranslationResultValueExternalizer : DataExternalizer<IrTranslationResultValue> {
override fun save(output: DataOutput, value: IrTranslationResultValue) {
output.writeArray(value.fileData)
output.writeArray(value.symbols)
output.writeArray(value.types)
output.writeArray(value.signatures)
output.writeArray(value.strings)
output.writeArray(value.declarations)
output.writeArray(value.bodies)
@@ -262,14 +251,14 @@ private object IrTranslationResultValueExternalizer : DataExternalizer<IrTransla
override fun read(input: DataInput): IrTranslationResultValue {
val fileData = input.readArray()
val symbols = input.readArray()
val types = input.readArray()
val signatures = input.readArray()
val strings = input.readArray()
val declarations = input.readArray()
val bodies = input.readArray()
val fqn = input.readArray()
return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn)
return IrTranslationResultValue(fileData, symbols, types, strings, declarations, bodies, fqn)
}
}
@@ -280,8 +269,8 @@ private class IrTranslationResultMap(
BasicStringMap<IrTranslationResultValue>(storageFile, IrTranslationResultValueExternalizer) {
override fun dumpValue(value: IrTranslationResultValue): String =
"Filedata: ${value.fileData.md5()}, " +
"Symbols: ${value.symbols.md5()}, " +
"Types: ${value.types.md5()}, " +
"Signatures: ${value.signatures.md5()}, " +
"Strings: ${value.strings.md5()}, " +
"Declarations: ${value.declarations.md5()}, " +
"Bodies: ${value.bodies.md5()}"
@@ -289,15 +278,15 @@ private class IrTranslationResultMap(
fun put(
sourceFile: File,
newFiledata: ByteArray,
newSymbols: ByteArray,
newTypes: ByteArray,
newSignatures: ByteArray,
newStrings: ByteArray,
newDeclarations: ByteArray,
newBodies: ByteArray,
fqn: ByteArray
) {
storage[pathConverter.toPath(sourceFile)] =
IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn)
IrTranslationResultValue(newFiledata, newSymbols, newTypes, newStrings, newDeclarations, newBodies, fqn)
}
operator fun get(sourceFile: File): IrTranslationResultValue? =

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2018 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.
@@ -206,11 +206,6 @@ open class ProtoCompareGenerated(
if (!checkStringEquals(old.getExtension(JvmProtoBuf.anonymousObjectOriginName), new.getExtension(JvmProtoBuf.anonymousObjectOriginName))) return false
}
if (old.hasExtension(JvmProtoBuf.jvmClassFlags) != new.hasExtension(JvmProtoBuf.jvmClassFlags)) return false
if (old.hasExtension(JvmProtoBuf.jvmClassFlags)) {
if (old.getExtension(JvmProtoBuf.jvmClassFlags) != new.getExtension(JvmProtoBuf.jvmClassFlags)) return false
}
if (old.getExtensionCount(JsProtoBuf.classAnnotation) != new.getExtensionCount(JsProtoBuf.classAnnotation)) {
return false
}
@@ -269,7 +264,6 @@ open class ProtoCompareGenerated(
JVM_EXT_CLASS_MODULE_NAME,
JVM_EXT_CLASS_LOCAL_VARIABLE_LIST,
JVM_EXT_ANONYMOUS_OBJECT_ORIGIN_NAME,
JVM_EXT_JVM_CLASS_FLAGS,
JS_EXT_CLASS_ANNOTATION_LIST,
JS_EXT_CLASS_CONTAINING_FILE_ID,
JAVA_EXT_IS_PACKAGE_PRIVATE_CLASS,
@@ -338,11 +332,6 @@ open class ProtoCompareGenerated(
if (!checkStringEquals(old.getExtension(JvmProtoBuf.anonymousObjectOriginName), new.getExtension(JvmProtoBuf.anonymousObjectOriginName))) result.add(ProtoBufClassKind.JVM_EXT_ANONYMOUS_OBJECT_ORIGIN_NAME)
}
if (old.hasExtension(JvmProtoBuf.jvmClassFlags) != new.hasExtension(JvmProtoBuf.jvmClassFlags)) result.add(ProtoBufClassKind.JVM_EXT_JVM_CLASS_FLAGS)
if (old.hasExtension(JvmProtoBuf.jvmClassFlags)) {
if (old.getExtension(JvmProtoBuf.jvmClassFlags) != new.getExtension(JvmProtoBuf.jvmClassFlags)) result.add(ProtoBufClassKind.JVM_EXT_JVM_CLASS_FLAGS)
}
if (old.getExtensionCount(JsProtoBuf.classAnnotation) != new.getExtensionCount(JsProtoBuf.classAnnotation)) {
result.add(ProtoBufClassKind.JS_EXT_CLASS_ANNOTATION_LIST)
}
@@ -1746,10 +1735,6 @@ fun ProtoBuf.Class.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) ->
hashCode = 31 * hashCode + stringIndexes(getExtension(JvmProtoBuf.anonymousObjectOriginName))
}
if (hasExtension(JvmProtoBuf.jvmClassFlags)) {
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.jvmClassFlags)
}
for(i in 0..getExtensionCount(JsProtoBuf.classAnnotation) - 1) {
hashCode = 31 * hashCode + getExtension(JsProtoBuf.classAnnotation, i).hashCode(stringIndexes, fqNameIndexes, typeById)
}

View File

@@ -28,8 +28,9 @@ import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.synthetic.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
import org.jetbrains.kotlin.utils.keysToMap
import java.io.File
import java.util.*
import kotlin.collections.HashSet

View File

@@ -273,10 +273,6 @@ class DifferenceCalculatorForClass(
isClassAffected = true
areSubclassesAffected = true
}
ProtoBufClassKind.JVM_EXT_JVM_CLASS_FLAGS -> {
isClassAffected = true
areSubclassesAffected = true
}
}
}

View File

@@ -1,106 +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.KeyDescriptor
import com.intellij.util.io.PersistentHashMap
import java.io.File
class NonCachingLazyStorage<K, V>(
private val storageFile: File,
private val keyDescriptor: KeyDescriptor<K>,
private val valueExternalizer: DataExternalizer<V>
) : LazyStorage<K, 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!!
}
override val keys: Collection<K>
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
}
@Synchronized
override fun clean() {
try {
storage?.close()
} catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
storage = null
}
@Synchronized
override fun flush(memoryCachesOnly: Boolean) {
val existingStorage = storage ?: return
if (memoryCachesOnly) {
if (existingStorage.isDirty) {
existingStorage.dropMemoryCaches()
}
} else {
existingStorage.force()
}
}
@Synchronized
override fun close() {
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
}

View File

@@ -22,13 +22,11 @@ data class BuildLogFinder(
private val isDataContainerBuildLogEnabled: Boolean = false,
private val isGradleEnabled: Boolean = false,
private val isJsEnabled: Boolean = false,
private val isJsIrEnabled: Boolean = false, // TODO rename as it is used for metadata-only test
private val isScopeExpansionEnabled: Boolean = false
private val isJsIrEnabled: Boolean = false // TODO rename as it is used for metadata-only test
) {
companion object {
private const val JS_LOG = "js-build.log"
private const val JS_IR_LOG = "js-ir-build.log"
private const val SCOPE_EXPANDING_LOG = "build-with-scope-expansion.log"
private const val GRADLE_LOG = "gradle-build.log"
private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
const val JS_JPS_LOG = "js-jps-build.log"
@@ -42,7 +40,6 @@ data class BuildLogFinder(
val names = dir.list() ?: arrayOf()
val files = names.filter { File(dir, it).isFile }.toSet()
val matchedName = when {
isScopeExpansionEnabled && SCOPE_EXPANDING_LOG in files -> SCOPE_EXPANDING_LOG
isJsIrEnabled && JS_IR_LOG in files -> JS_IR_LOG
isJsEnabled && JS_LOG in files -> JS_LOG
isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG

View File

@@ -10100,7 +10100,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
boolean hasFlags();
@@ -10117,7 +10116,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
int getFlags();
@@ -10855,7 +10853,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public boolean hasFlags() {
@@ -10874,7 +10871,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public int getFlags() {
@@ -12246,7 +12242,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public boolean hasFlags() {
@@ -12265,7 +12260,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public int getFlags() {
@@ -12284,7 +12278,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public Builder setFlags(int value) {
@@ -12306,7 +12299,6 @@ public final class DebugProtoBuf {
*isExternal
*isExpect
*isInline
*isFun
* </pre>
*/
public Builder clearFlags() {

View File

@@ -18,7 +18,6 @@ public final class DebugJvmProtoBuf {
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.classModuleName);
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.classLocalVariable);
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.anonymousObjectOriginName);
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.jvmClassFlags);
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.packageModuleName);
registry.add(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.packageLocalVariable);
}
@@ -4651,21 +4650,6 @@ public final class DebugJvmProtoBuf {
.newFileScopedGeneratedExtension(
java.lang.Integer.class,
null);
public static final int JVM_CLASS_FLAGS_FIELD_NUMBER = 104;
/**
* <code>extend .org.jetbrains.kotlin.metadata.Class { ... }</code>
*
* <pre>
* isFunctionBodyInInterface: 0 if actual body generated in DefaultImpl, 1 - otherwise (in interface default method)
* </pre>
*/
public static final
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
org.jetbrains.kotlin.metadata.DebugProtoBuf.Class,
java.lang.Integer> jvmClassFlags = org.jetbrains.kotlin.protobuf.GeneratedMessage
.newFileScopedGeneratedExtension(
java.lang.Integer.class,
null);
public static final int PACKAGE_MODULE_NAME_FIELD_NUMBER = 101;
/**
* <code>extend .org.jetbrains.kotlin.metadata.Package { ... }</code>
@@ -4774,13 +4758,12 @@ public final class DebugJvmProtoBuf {
"\'.org.jetbrains.kotlin.metadata.Property",
":P\n\034anonymous_object_origin_name\022$.org.j" +
"etbrains.kotlin.metadata.Class\030g \001(\005B\004\230\265" +
"\030\001:@\n\017jvm_class_flags\022$.org.jetbrains.ko" +
"tlin.metadata.Class\030h \001(\005:\0010:I\n\023package_" +
"module_name\022&.org.jetbrains.kotlin.metad" +
"ata.Package\030e \001(\005B\004\230\265\030\001:o\n\026package_local" +
"_variable\022&.org.jetbrains.kotlin.metadat" +
"a.Package\030f \003(\0132\'.org.jetbrains.kotlin.m" +
"etadata.PropertyB\022B\020DebugJvmProtoBuf"
"\030\001:I\n\023package_module_name\022&.org.jetbrain" +
"s.kotlin.metadata.Package\030e \001(\005B\004\230\265\030\001:o\n" +
"\026package_local_variable\022&.org.jetbrains." +
"kotlin.metadata.Package\030f \003(\0132\'.org.jetb" +
"rains.kotlin.metadata.PropertyB\022B\020DebugJ" +
"vmProtoBuf"
};
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
@@ -4837,9 +4820,8 @@ public final class DebugJvmProtoBuf {
classModuleName.internalInit(descriptor.getExtensions().get(8));
classLocalVariable.internalInit(descriptor.getExtensions().get(9));
anonymousObjectOriginName.internalInit(descriptor.getExtensions().get(10));
jvmClassFlags.internalInit(descriptor.getExtensions().get(11));
packageModuleName.internalInit(descriptor.getExtensions().get(12));
packageLocalVariable.internalInit(descriptor.getExtensions().get(13));
packageModuleName.internalInit(descriptor.getExtensions().get(11));
packageLocalVariable.internalInit(descriptor.getExtensions().get(12));
org.jetbrains.kotlin.protobuf.ExtensionRegistry registry =
org.jetbrains.kotlin.protobuf.ExtensionRegistry.newInstance();
registry.add(org.jetbrains.kotlin.metadata.DebugExtOptionsProtoBuf.stringIdInTable);

View File

@@ -1,12 +1,14 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import proguard.gradle.ProGuardTask
buildscript {
extra["defaultSnapshotVersion"] = "1.3-SNAPSHOT"
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap(kotlinBuildProperties.kotlinBootstrapVersion!!, cacheRedirectorEnabled))
kotlinBootstrapFrom(BootstrapOption.BintrayBootstrap("1.3.70-eap-17", cacheRedirectorEnabled))
repositories {
bootstrapKotlinRepo?.let(::maven)
@@ -26,17 +28,13 @@ buildscript {
dependencies {
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
classpath("com.gradle.publish:plugin-publish-plugin:0.11.0")
classpath("com.gradle.publish:plugin-publish-plugin:0.9.7")
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
classpath("net.sf.proguard:proguard-gradle:6.1.0")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
}
}
if (kotlinBuildProperties.buildScanServer != null) {
apply(from = "gradle/buildScanUserData.gradle")
}
plugins {
idea
id("jps-compatible")
@@ -53,7 +51,6 @@ pill {
}
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val includeStdlibJsIr by extra(project.kotlinBuildProperties.includeStdlibJsIr)
val configuredJdks: List<JdkId> =
getConfiguredJdks().also {
@@ -66,7 +63,7 @@ val defaultSnapshotVersion: String by extra
val buildNumber by extra(findProperty("build.number")?.toString() ?: defaultSnapshotVersion)
val kotlinVersion by extra(findProperty("deployVersion")?.toString() ?: buildNumber)
val kotlinLanguageVersion by extra("1.4")
val kotlinLanguageVersion by extra("1.3")
allprojects {
group = "org.jetbrains.kotlin"
@@ -144,8 +141,6 @@ rootProject.apply {
from(rootProject.file("gradle/report.gradle.kts"))
from(rootProject.file("gradle/javaInstrumentation.gradle.kts"))
from(rootProject.file("gradle/jps.gradle.kts"))
from(rootProject.file("gradle/checkArtifacts.gradle.kts"))
from(rootProject.file("gradle/checkCacheability.gradle.kts"))
}
IdeVersionConfigurator.setCurrentIde(project)
@@ -170,17 +165,13 @@ extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0"
extra["versions.markdown"] = "0.1.25"
extra["versions.trove4j"] = "1.0.20181211"
extra["versions.completion-ranking-kotlin"] = "0.1.2"
extra["versions.r8"] = "1.5.70"
val immutablesVersion = "0.3.1"
extra["versions.kotlinx-collections-immutable"] = immutablesVersion
extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
extra["versions.completion-ranking-kotlin"] = "0.0.2"
// NOTE: please, also change KTOR_NAME in pathUtil.kt and all versions in corresponding jar names in daemon tests.
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.4-M2-dev-15123"
extra["versions.kotlin-native"] = "1.3.70-eap-14141"
}
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
@@ -198,17 +189,15 @@ extra["IntellijCoreDependencies"] =
"jdom",
"jna",
"log4j",
if (Platform[201].orHigher()) null else "picocontainer",
"picocontainer",
"snappy-in-java",
"streamex",
"trove4j"
).filterNotNull()
)
extra["compilerModules"] = arrayOf(
":compiler:util",
":compiler:config",
":compiler:config.jvm",
":compiler:container",
":compiler:resolution",
":compiler:serialization",
@@ -233,20 +222,15 @@ extra["compilerModules"] = arrayOf(
":compiler:backend",
":compiler:plugin-api",
":compiler:light-classes",
":compiler:javac-wrapper",
":compiler:cli",
":compiler:cli-js",
":compiler:incremental-compilation-impl",
":compiler:compiler.version",
":js:js.ast",
":js:js.serializer",
":js:js.parser",
":js:js.config",
":js:js.frontend",
":js:js.translator",
":js:js.dce",
":native:frontend.native",
":native:kotlin-native-utils",
":compiler",
":kotlin-build-common",
":core:metadata",
@@ -260,35 +244,26 @@ extra["compilerModules"] = arrayOf(
":compiler:fir:cones",
":compiler:fir:resolve",
":compiler:fir:tree",
":compiler:fir:raw-fir:fir-common",
":compiler:fir:raw-fir:psi2fir",
":compiler:fir:raw-fir:light-tree2fir",
":compiler:fir:psi2fir",
":compiler:fir:lightTree",
":compiler:fir:fir2ir",
":compiler:fir:fir2ir:jvm-backend",
":compiler:fir:java",
":compiler:fir:jvm",
":compiler:fir:checkers",
":compiler:fir:analysis-tests"
":compiler:fir:java"
)
val coreLibProjects = listOfNotNull(
":kotlin-stdlib",
":kotlin-stdlib-common",
":kotlin-stdlib-js",
// Exclude JS IR from core libs because it depends on local compiler build, which
// in turn depends on local JVM stdlib. It slows down library testing.
":kotlin-stdlib-js-ir".takeIf { includeStdlibJsIr },
":kotlin-stdlib-js-ir",
":kotlin-stdlib-jdk7",
":kotlin-stdlib-jdk8",
":kotlin-test:kotlin-test-annotations-common",
":kotlin-test:kotlin-test-common",
":kotlin-test:kotlin-test-jvm",
":kotlin-test:kotlin-test-junit",
":kotlin-test:kotlin-test-junit5",
":kotlin-test:kotlin-test-testng",
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
":kotlin-reflect",
":kotlin-coroutines-experimental-compat"
":kotlin-reflect"
)
val gradlePluginProjects = listOf(
@@ -326,7 +301,7 @@ fun Task.listConfigurationContents(configName: String) {
val defaultJvmTarget = "1.8"
val defaultJavaHome = jdkPath(defaultJvmTarget)
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
val ignoreTestFailures by extra(project.findProperty("ignoreTestFailures")?.toString()?.toBoolean() ?: project.hasProperty("teamcity"))
allprojects {
@@ -352,7 +327,6 @@ allprojects {
maven("https://dl.bintray.com/kotlin/ktor")
maven("https://kotlin.bintray.com/kotlin-dependencies")
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies")
maven("https://dl.google.com/dl/android/maven2")
bootstrapKotlinRepo?.let(::maven)
internalKotlinRepo?.let(::maven)
}
@@ -360,11 +334,9 @@ allprojects {
configureJvmProject(javaHome!!, jvmTarget!!)
val commonCompilerArgs = listOfNotNull(
"-Xopt-in=kotlin.RequiresOptIn",
"-Xuse-experimental=kotlin.Experimental",
"-Xread-deserialized-contracts",
"-Xjvm-default=compatibility",
"-Xno-optimized-callable-references",
"-Xno-kotlin-nothing-value-exception",
"-progressive".takeIf { hasProperty("test.progressive.mode") }
)
@@ -394,23 +366,6 @@ allprojects {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
tasks.withType<AbstractArchiveTask> {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
tasks.withType<Test> {
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KT-37089") { true }
}
normalization {
runtimeClasspath {
ignore("META-INF/MANIFEST.MF")
ignore("META-INF/compiler.version")
ignore("META-INF/plugin.xml")
}
}
tasks {
register("listArchives") { listConfigurationContents("archives") }
@@ -455,18 +410,23 @@ allprojects {
// Aggregate task for build related checks
tasks.register("checkBuild")
apply(from = "$rootDir/gradle/cacheRedirector.gradle.kts")
}
}
gradle.taskGraph.whenReady {
fun Boolean.toOnOff(): String = if (this) "on" else "off"
val profile = if (isTeamcityBuild) "CI" else "Local"
logger.warn("$profile build profile is active (proguard is ${kotlinBuildProperties.proguard.toOnOff()}" +
", jar compression is ${kotlinBuildProperties.jarCompression.toOnOff()})." +
" Use -Pteamcity=<true|false> to reproduce CI/local build")
if (isTeamcityBuild) {
logger.warn("CI build profile is active (IC is off, proguard is on). Use -Pteamcity=false to reproduce local build")
for (task in allTasks) {
when (task) {
is AbstractKotlinCompile<*> -> task.incremental = false
is JavaCompile -> task.options.isIncremental = false
}
}
} else {
logger.warn("Local build profile is active (IC is on, proguard is off). Use -Pteamcity=true to reproduce TC build")
}
allTasks.filterIsInstance<org.gradle.jvm.tasks.Jar>().forEach { task ->
task.entryCompression = if (kotlinBuildProperties.jarCompression)
@@ -538,8 +498,7 @@ tasks {
":compiler:test",
":compiler:container:test",
":compiler:tests-java8:test",
":compiler:tests-spec:test",
":compiler:tests-against-klib:test"
":compiler:tests-spec:remoteRunTests"
)
dependsOn(":plugins:jvm-abi-gen:test")
}
@@ -557,31 +516,16 @@ tasks {
}
register("wasmCompilerTest") {
// TODO: fix once
// dependsOn(":js:js.tests:wasmTest")
}
register("nativeCompilerTest") {
dependsOn(":native:kotlin-native-utils:test")
dependsOn(":js:js.tests:wasmTest")
}
register("firCompilerTest") {
dependsOn(":compiler:fir:raw-fir:psi2fir:test")
dependsOn(":compiler:fir:raw-fir:light-tree2fir:test")
dependsOn(":compiler:fir:analysis-tests:test")
dependsOn(":compiler:fir:psi2fir:test")
dependsOn(":compiler:fir:resolve:test")
dependsOn(":compiler:fir:fir2ir:test")
dependsOn(":compiler:fir:lightTree:test")
}
register("firAllTest") {
dependsOn(
":compiler:fir:raw-fir:psi2fir:test",
":compiler:fir:raw-fir:light-tree2fir:test",
":compiler:fir:analysis-tests:test",
":compiler:fir:fir2ir:test",
":idea:idea-fir:test"
)
}
register("compilerFrontendVisualizerTest") {
dependsOn("compiler:visualizer:test")
}
@@ -600,17 +544,14 @@ tasks {
// dependsOn(":kotlin-scripting-jvm-host-test:embeddableTest")
dependsOn(":kotlin-scripting-jsr223-test:embeddableTest")
dependsOn(":kotlin-main-kts-test:test")
dependsOn(":kotlin-scripting-ide-services-test:test")
}
register("compilerTest") {
dependsOn("jvmCompilerTest")
dependsOn("jsCompilerTest")
dependsOn("wasmCompilerTest")
dependsOn("nativeCompilerTest")
dependsOn("firCompilerTest")
dependsOn(":compiler:daemon:daemon-tests:test")
dependsOn("scriptingTest")
dependsOn(":kotlin-build-common:test")
dependsOn(":compiler:incremental-compilation-impl:test")
@@ -621,7 +562,6 @@ tasks {
register("toolsTest") {
dependsOn(":tools:kotlinp:test")
dependsOn(":native:kotlin-klib-commonizer:test")
}
register("examplesTest") {
@@ -652,6 +592,14 @@ tasks {
dependsOn(":jps-plugin:test")
}
register("konan-tests") {
dependsOn("dist")
dependsOn(
":kotlin-native:kotlin-native-library-reader:test",
":kotlin-native:commonizer:test"
)
}
register("idea-plugin-main-tests") {
dependsOn("dist")
dependsOn(":idea:test")
@@ -669,37 +617,24 @@ tasks {
":idea:jvm-debugger:jvm-debugger-evaluation:test",
":idea:jvm-debugger:jvm-debugger-sequence:test",
":idea:jvm-debugger:eval4j:test",
":idea:scripting-support:test",
":idea:idea-fir:test"
":idea:scripting-support:test"
)
}
if (Ide.IJ()) {
register("idea-new-project-wizard-tests") {
dependsOn("dist")
dependsOn(
":libraries:tools:new-project-wizard:test",
":libraries:tools:new-project-wizard:new-project-wizard-cli:test",
":idea:idea-new-project-wizard:test"
)
}
register("idea-new-project-wizard-tests") {
dependsOn("dist")
dependsOn(
":libraries:tools:new-project-wizard:test",
":libraries:tools:new-project-wizard:new-project-wizard-cli:test"
)
}
register("idea-plugin-tests") {
dependsOn("dist")
dependsOn(
"idea-plugin-main-tests",
"idea-plugin-additional-tests"
)
if (Ide.IJ()) {
dependsOn("idea-new-project-wizard-tests")
}
}
register("idea-plugin-performance-tests") {
dependsOn("dist")
dependsOn(
":idea:performanceTests:performanceTest"
"idea-plugin-additional-tests",
"idea-new-project-wizard-tests"
)
}
@@ -716,6 +651,7 @@ tasks {
dependsOn("dist")
dependsOn(
":kotlin-annotation-processing:test",
":kotlin-source-sections-compiler-plugin:test",
":kotlin-allopen-compiler-plugin:test",
":kotlin-noarg-compiler-plugin:test",
":kotlin-sam-with-receiver-compiler-plugin:test",
@@ -732,6 +668,7 @@ tasks {
dependsOn(
"idea-plugin-tests",
"jps-tests",
"konan-tests",
"plugins-tests",
"android-ide-tests",
":generators:test"
@@ -774,7 +711,6 @@ val zipStdlibTests by task<Zip> {
archiveFileName.set("kotlin-stdlib-tests.zip")
from("libraries/stdlib/common/test") { into("common") }
from("libraries/stdlib/test") { into("test") }
from("libraries/kotlin.test/common/src/test/kotlin") { into("kotlin-test") }
doLast {
logger.lifecycle("Stdlib tests are packed to ${archiveFile.get()}")
}
@@ -803,15 +739,18 @@ val zipPlugin by task<Zip> {
}
val destPath = project.findProperty("pluginZipPath") as String?
val dest = File(destPath ?: "$buildDir/kotlin-plugin.zip")
destinationDirectory.set(dest.parentFile)
archiveFileName.set(dest.name)
destinationDir = dest.parentFile
archiveName = dest.name
doFirst {
if (destPath == null) throw GradleException("Specify target zip path with 'pluginZipPath' property")
}
from(src)
into("Kotlin")
setExecutablePermissions()
doLast {
logger.lifecycle("Plugin artifacts packed to $archiveFile")
logger.lifecycle("Plugin artifacts packed to $archivePath")
}
}
@@ -822,8 +761,7 @@ configure<IdeaModel> {
commonLocalDataDir,
".gradle",
"dependencies",
"dist",
"tmp"
"dist"
).toSet()
}
}

View File

@@ -1,12 +1,11 @@
extra["versions.shadow"] = "4.0.3"
extra["versions.native-platform"] = "0.14"
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))
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
repositories {
if (cacheRedirectorEnabled) {
@@ -17,29 +16,27 @@ buildscript {
maven("https://kotlin.bintray.com/kotlin-dependencies")
}
project.bootstrapKotlinRepo?.let {
buildSrcKotlinRepo?.let {
maven(url = it)
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.6")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion")
}
}
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
logger.info("buildSrcKotlinVersion: " + extra["bootstrapKotlinVersion"])
logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"])
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
apply {
plugin("kotlin")
plugin("kotlin-sam-with-receiver")
from("../gradle/checkCacheability.gradle.kts")
}
plugins {
@@ -49,6 +46,10 @@ plugins {
gradlePlugin {
plugins {
register("pill-configurable") {
id = "pill-configurable"
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
}
register("jps-compatible") {
id = "jps-compatible"
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
@@ -56,10 +57,6 @@ gradlePlugin {
}
}
kotlinDslPluginOptions {
experimentalWarning.set(false)
}
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
val v = it.toString()
if (v.isBlank()) true
@@ -75,11 +72,10 @@ val intellijUltimateEnabled by extra(kotlinBuildProperties.intellijUltimateEnabl
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"
extra["versions.intellijSdk"]?.toString()?.endsWith("SNAPSHOT") == true -> "nightly"
else -> "releases"
}
extra["intellijReleaseType"] = if (extra["versions.intellijSdk"]?.toString()?.endsWith("SNAPSHOT") == true)
"snapshots"
else
"releases"
extra["versions.androidDxSources"] = "5.0.0_r2"
@@ -91,22 +87,21 @@ repositories {
maven("https://kotlin.bintray.com/kotlin-dependencies")
gradlePluginPortal()
extra["bootstrapKotlinRepo"]?.let {
extra["buildSrcKotlinRepo"]?.let {
maven(url = it)
}
}
dependencies {
implementation(kotlin("stdlib", embeddedKotlinVersion))
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.6")
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
implementation("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
implementation("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
implementation("com.jakewharton.dex:dex-method-list:3.0.0")
implementation("com.github.jengelman.gradle.plugins:shadow:${rootProject.extra["versions.shadow"]}")
implementation("net.sf.proguard:proguard-gradle:6.2.2")
implementation("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
implementation("org.jetbrains.intellij.deps:asm-all:7.0.1")
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")

View File

@@ -0,0 +1,8 @@
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

@@ -9,9 +9,6 @@ import java.text.SimpleDateFormat
import java.util.*
import javax.xml.stream.XMLOutputFactory
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
plugins {
base
}
@@ -108,7 +105,7 @@ val nodeJSPlugin by configurations.creating
val intellijRuntimeAnnotations = "intellij-runtime-annotations"
val dependenciesDir = (findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
?: rootProject.rootDir.parentFile.resolve("dependencies")
val customDepsRepoDir = dependenciesDir.resolve("repo")
@@ -145,29 +142,14 @@ 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)
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
from(repoDir.resolve("intellij-core/$intellijVersion/artifacts/annotations.jar"))
val targetDir = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath][intellijVersion].use()
val targetDir = File(repoDir, "$intellijRuntimeAnnotations/$intellijVersion")
into(targetDir)
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
@@ -189,8 +171,6 @@ val makeIntellijAnnotations by tasks.registering(Copy::class) {
val mergeSources by tasks.creating(Jar::class.java) {
dependsOn(sources)
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
from(provider { sources.map(::zipTree) })
destinationDirectory.set(File(repoDir, sources.name))
archiveBaseName.set("intellij")
@@ -201,20 +181,20 @@ val mergeSources by tasks.creating(Jar::class.java) {
val sourcesFile = mergeSources.outputs.files.singleFile
val makeIde = if (androidStudioBuild != null) {
buildIvyRepositoryTaskAndRegisterCleanupTask(
buildIvyRepositoryTask(
androidStudio,
customDepsOrg,
customDepsRepoDir,
if (androidStudioOs == "mac")
::skipContentsDirectory
else
::skipContentsDirectory
else
::skipToplevelDirectory
)
} 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 +204,8 @@ val makeIde = if (androidStudioBuild != null) {
task
}
val buildJpsStandalone = buildIvyRepositoryTaskAndRegisterCleanupTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
val buildNodeJsPlugin = buildIvyRepositoryTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") {
dependsOn(
@@ -234,16 +215,11 @@ tasks.named("build") {
makeIntellijAnnotations
)
if (installIntellijUltimate) {
dependsOn(buildNodeJsPlugin)
}
}
if (installIntellijUltimate) {
val buildNodeJsPlugin =
buildIvyRepositoryTaskAndRegisterCleanupTask(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")
@@ -251,114 +227,93 @@ tasks.register<Delete>("cleanLegacy") {
}
tasks.named<Delete>("clean") {
//TODO specify repos to clean? Use CleanDataTask
delete(customDepsRepoDir)
}
fun buildIvyRepositoryTaskAndRegisterCleanupTask(
fun buildIvyRepositoryTask(
configuration: Configuration,
organization: String,
repoDirectory: File,
pathRemap: ((String) -> String)? = null,
sources: File? = null
): TaskProvider<Task> {
fun ResolvedArtifact.storeDirectory(): CleanableStore =
CleanableStore[repoDirectory.resolve("$organization/${moduleVersion.id.name}").absolutePath]
) = tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
fun ResolvedArtifact.moduleDirectory(): File =
storeDirectory()[moduleVersion.id.version].use()
File(repoDirectory, "$organization/${moduleVersion.id.name}/${moduleVersion.id.version}")
val buildIvyRepositoryTask = tasks.register("buildIvyRepositoryFor${configuration.name.capitalize()}") {
dependsOn(configuration)
inputs.files(configuration)
dependsOn(configuration)
inputs.files(configuration)
if (verifyDependencyOutput) {
outputs.dir(
provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory()
if (verifyDependencyOutput) {
outputs.dir(provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory()
})
} else {
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
}
doFirst {
configuration.resolvedConfiguration.resolvedArtifacts.single().run {
val moduleDirectory = moduleDirectory()
val artifactsDirectory = File(moduleDirectory(), "artifacts")
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
copy {
val fileTree = when (extension) {
"tar.gz" -> tarTree(file)
"zip" -> zipTree(file)
else -> error("Unsupported artifact extension: $extension")
}
from(fileTree.matching {
exclude("**/plugins/Kotlin/**")
})
into(artifactsDirectory)
if (pathRemap != null) {
eachFile {
path = pathRemap(path)
}
}
includeEmptyDirs = false
}
writeIvyXml(
organization,
moduleVersion.id.name,
moduleVersion.id.version,
moduleVersion.id.name,
File(artifactsDirectory, "lib"),
File(artifactsDirectory, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
} else {
outputs.upToDateWhen {
configuration.resolvedConfiguration.resolvedArtifacts.single()
.moduleDirectory()
.exists()
}
}
doFirst {
configuration.resolvedConfiguration.resolvedArtifacts.single().run {
val moduleDirectory = moduleDirectory()
val artifactsDirectory = File(moduleDirectory(), "artifacts")
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
copy {
val fileTree = when (extension) {
"tar.gz" -> tarTree(file)
"zip" -> zipTree(file)
else -> error("Unsupported artifact extension: $extension")
val pluginsDirectory = File(artifactsDirectory, "plugins")
if (pluginsDirectory.exists()) {
file(File(artifactsDirectory, "plugins"))
.listFiles { file: File -> file.isDirectory }
.forEach {
writeIvyXml(
organization,
it.name,
moduleVersion.id.version,
it.name,
File(it, "lib"),
File(it, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
}
from(
fileTree.matching {
exclude("**/plugins/Kotlin/**")
}
)
into(artifactsDirectory)
if (pathRemap != null) {
eachFile {
path = pathRemap(path)
}
}
includeEmptyDirs = false
}
writeIvyXml(
organization,
moduleVersion.id.name,
moduleVersion.id.version,
moduleVersion.id.name,
File(artifactsDirectory, "lib"),
File(artifactsDirectory, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
val pluginsDirectory = File(artifactsDirectory, "plugins")
if (pluginsDirectory.exists()) {
file(File(artifactsDirectory, "plugins"))
.listFiles { file: File -> file.isDirectory }
.forEach {
writeIvyXml(
organization,
it.name,
moduleVersion.id.version,
it.name,
File(it, "lib"),
File(it, "lib"),
File(moduleDirectory, "ivy"),
*listOfNotNull(sources).toTypedArray()
)
}
}
}
}
}
val cleanupIvyRepositoryTask = tasks.register<CleanDataTask>("cleanupIvyRepositoryFor${configuration.name.capitalize()}") {
cleanableStoreProvider = provider {
configuration.resolvedConfiguration.resolvedArtifacts.single().storeDirectory()
}
}
cleanupDependencies {
dependsOn(cleanupIvyRepositoryTask)
}
return buildIvyRepositoryTask
}
fun writeIvyXml(
@@ -380,7 +335,7 @@ fun writeIvyXml(
val ivyFile = targetDir.resolve("$fileName.ivy.xml")
ivyFile.parentFile.mkdirs()
with(XMLWriter(ivyFile.writer())) {
with(XMLWriter(FileWriter(ivyFile))) {
document("UTF-8", "1.0") {
element("ivy-module") {
attribute("version", "2.0")
@@ -404,24 +359,24 @@ fun writeIvyXml(
}
element("publications") {
artifactDir.listFiles()
?.filter(::shouldIncludeIntellijJar)
?.sortedBy { it.name.toLowerCase() }
?.forEach { jarFile ->
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
emptyElement("artifact") {
attributes(
"name" to relativeName,
"type" to "jar",
"ext" to "jar",
"conf" to "default"
)
}
artifactDir.listFiles()?.filter(::shouldIncludeIntellijJar)?.forEach { jarFile ->
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
emptyElement("artifact") {
attributes(
"name" to relativeName,
"type" to "jar",
"ext" to "jar",
"conf" to "default"
)
}
}
sourcesJar.forEach { jarFile ->
emptyElement("artifact") {
val sourcesArtifactName = jarFile.name.substringBefore("-$version")
val sourcesArtifactName = jarFile.name
.substringBeforeLast("-")
.substringBeforeLast("-")
attributes(
"name" to sourcesArtifactName,
"type" to "jar",

View File

@@ -20,55 +20,33 @@ buildscript {
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.6")
}
}
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")
def target_AndroidStudio = buildProperties.includeCidrPlugins && projectVersions.contains("versions.androidStudioRelease")
def target_IdeaUltimate = buildProperties.includeUltimate
if (target_AppCode_Clion) {
logger.info("Including modules for AC and CL in buildSrc/settings.gradle")
if (buildProperties.includeCidrPlugins) {
logger.info("Including CIDR plugins in buildSrc/settings.gradle")
include ":prepare-deps:kotlin-native-platform-deps"
include ":prepare-deps:native-debug-plugin"
project(":prepare-deps:kotlin-native-platform-deps").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/kotlin-native-platform-deps")
project(":prepare-deps:native-debug-plugin").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin")
} else if (target_AndroidStudio) {
logger.info("Including modules for AS (mobile plugin) in buildSrc/settings.gradle")
include ":prepare-deps:cocoa-common-binaries"
include ":prepare-deps:lldb-framework"
include ":prepare-deps:lldb-frontend"
project(":prepare-deps:cocoa-common-binaries").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/cocoa-common-binaries")
project(":prepare-deps:lldb-framework").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-framework")
project(":prepare-deps:lldb-frontend").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend")
} else if (target_IdeaUltimate) {
logger.info("Including modules for IU in buildSrc/settings.gradle")
} else {
logger.info("NOT including CIDR plugins in buildSrc/settings.gradle")
}
if (buildProperties.includeUltimate) {
logger.info("Including extension for IJ Ultimate in buildSrc/settings.gradle")
include ":prepare-deps:lldb-frontend"
include ":prepare-deps:native-debug-plugin"
project(":prepare-deps:lldb-frontend").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend")
project(":prepare-deps:native-debug-plugin").projectDir =
file("${buildProperties.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin")
} else {
logger.info("Not including extra modules in buildSrc/settings.gradle")
}
logger.info("Not including extension for IJ Ultimate in buildSrc/settings.gradle")
}

View File

@@ -0,0 +1,114 @@
@file:Suppress("unused") // usages in build scripts are not tracked properly
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
import java.net.URI
var Project.bootstrapKotlinVersion: String
get() = this.property("bootstrapKotlinVersion") as String
private set(value) {
this.extra["bootstrapKotlinVersion"] = value
}
var Project.bootstrapKotlinRepo: String?
get() = this.property("bootstrapKotlinRepo") as String?
private set(value) {
this.extra["bootstrapKotlinRepo"] = value
}
val Project.internalKotlinRepo: String?
get() = "https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Compiler),number:$bootstrapKotlinVersion," +
"branch:default:any/artifacts/content/internal/repo"
fun Project.kotlinBootstrapFrom(defaultSource: BootstrapOption) {
val customVersion = project.findProperty("bootstrap.kotlin.version") as String?
val customRepo = project.findProperty("bootstrap.kotlin.repo") as String?
val teamCityVersion = project.findProperty("bootstrap.teamcity.kotlin.version") as String?
val teamCityBuild = project.findProperty("bootstrap.teamcity.build.number") as String?
val teamCityProject = project.findProperty("bootstrap.teamcity.project") as String?
val bootstrapSource = when {
project.hasProperty("bootstrap.local") -> BootstrapOption.Local(
project.findProperty("bootstrap.local.version") as String?,
project.findProperty("bootstrap.local.path") as String?
)
teamCityVersion != null -> BootstrapOption.TeamCity(
teamCityVersion,
teamCityBuild,
projectExtId = teamCityProject,
onlySuccessBootstrap = false
)
customVersion != null -> BootstrapOption.Custom(kotlinVersion = customVersion, repo = customRepo)
else -> defaultSource
}
bootstrapSource.applyToProject(project)
project.logger.lifecycle("Using kotlin bootstrap version $bootstrapKotlinVersion from repo $bootstrapKotlinRepo")
}
sealed class BootstrapOption {
abstract fun applyToProject(project: Project)
/** Manual repository and version specification.
*
* If [repo] is not specified the default buildscript and project repositories are used
*/
open class Custom(val kotlinVersion: String, val repo: String?, val cacheRedirector: Boolean = false) : BootstrapOption() {
override fun applyToProject(project: Project) {
project.bootstrapKotlinVersion = kotlinVersion
project.bootstrapKotlinRepo = if (cacheRedirector)
repo?.let { URI(it) }?.let { "https://cache-redirector.jetbrains.com/${it.host}/${it.path}" }
else
repo
}
}
/** Get bootstrap from kotlin-dev bintray repo */
class BintrayDev(kotlinVersion: String, cacheRedirector: Boolean = false) :
Custom(kotlinVersion, "https://dl.bintray.com/kotlin/kotlin-dev", cacheRedirector)
/** Get bootstrap from kotlin-bootstrap bintray repo, where bootstraps are published */
class BintrayBootstrap(kotlinVersion: String, cacheRedirector: Boolean = false) :
Custom(kotlinVersion, "https://dl.bintray.com/kotlin/kotlin-bootstrap", cacheRedirector)
/** Get bootstrap from teamcity maven artifacts of the specified build configuration
*
* [kotlinVersion] the version of maven artifacts
* [buildNumber] build number of a teamcity build, by default the same as [kotlinVersion],
* [projectExtId] extId of a teamcity build configuration, by default "Kotlin_dev_Compiler",
* [onlySuccessBootstrap] allow artifacts only from success builds of the default branch tagged with 'bootstrap' tag
*/
class TeamCity(
val kotlinVersion: String,
val buildNumber: String? = null,
val projectExtId: String? = null,
val onlySuccessBootstrap: Boolean = true,
val teamcityUrl: String = "https://teamcity.jetbrains.com"
) : BootstrapOption() {
override fun applyToProject(project: Project) {
val query = if (onlySuccessBootstrap) "status:SUCCESS,tag:bootstrap,pinned:true" else "branch:default:any"
project.bootstrapKotlinRepo = "$teamcityUrl/guestAuth/app/rest/builds/buildType:(id:${projectExtId
?: "Kotlin_dev_Compiler"}),number:${buildNumber ?: kotlinVersion},$query/artifacts/content/maven/"
project.bootstrapKotlinVersion = kotlinVersion
}
}
/**
* Use previously published local artifacts from the build/repo maven repository
*
* [kotlinVersion] version of artifacts, by default the snapshot version of project is used
* [localPath] the path to local repository, if specified it is resolved with respect or project dir
*/
class Local(val kotlinVersion: String? = null, val localPath: String? = null) : BootstrapOption() {
override fun applyToProject(project: Project) {
val repoPath = if (localPath != null)
project.projectDir.resolve(localPath).canonicalFile
else
project.buildDir.resolve("repo")
project.bootstrapKotlinRepo = repoPath.toURI().toString()
project.bootstrapKotlinVersion = kotlinVersion ?: project.property("defaultSnapshotVersion") as String
}
}
}

View File

@@ -1,22 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
val KotlinBuildProperties.includeJava9: Boolean
get() = !isInJpsBuildIdeaSync && getBoolean("kotlin.build.java9", true)
val KotlinBuildProperties.useBootstrapStdlib: Boolean
get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false)
val KotlinBuildProperties.postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true)
val KotlinBuildProperties.relocation: Boolean get() = postProcessing
val KotlinBuildProperties.proguard: Boolean get() = postProcessing && getBoolean("kotlin.build.proguard", isTeamcityBuild)
val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.build.jar.compression", isTeamcityBuild)
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
val KotlinBuildProperties.includeStdlibJsIr: Boolean get() = getBoolean("include.stdlib.js.ir", isTeamcityBuild)

View File

@@ -1,385 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import groovy.lang.Closure
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import org.gradle.internal.jvm.Jvm
import org.gradle.internal.jvm.inspection.JvmVersionDetector
import proguard.ClassSpecification
import java.io.File
import javax.inject.Inject
@CacheableTask
open class CacheableProguardTask @Inject constructor(
private val jvmVersionDetector: JvmVersionDetector
) : proguard.gradle.ProGuardTask() {
@Internal
var jdkHome: File? = null
@get:Optional
@get:Input
internal val jdkMajorVersion: String?
get() = jdkHome?.let { jvmVersionDetector.getJavaVersion(Jvm.forHome(jdkHome)) }?.majorVersion
@CompileClasspath
override fun getLibraryJarFileCollection(): FileCollection = super.getLibraryJarFileCollection().filter { libraryFile ->
jdkHome?.let { !libraryFile.absoluteFile.startsWith(it.absoluteFile) } ?: true
}
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)
override fun getConfigurationFileCollection(): FileCollection = super.getConfigurationFileCollection()
@InputFiles
@Classpath
override fun getInJarFileCollection(): FileCollection = super.getInJarFileCollection()
@Optional
@OutputFiles
override fun getOutJarFileCollection(): FileCollection = super.getOutJarFileCollection()
@get:Optional
@get:OutputFile
internal val printConfigurationFile: File?
get() = configuration.printConfiguration?.takeIf { it.path.isNotEmpty() }
@Input
override fun getOutJarFilters(): MutableList<Any?> = super.getOutJarFilters()
@Input
override fun getInJarFilters(): MutableList<Any?> = super.getInJarFilters()
@Input
override fun getLibraryJarFilters(): MutableList<Any?> = super.getLibraryJarFilters()
@Internal
override fun getOutJarFiles(): MutableList<Any?> = super.getOutJarFiles()
@Internal
override fun getInJarFiles(): MutableList<Any?> = super.getInJarFiles()
@Internal
override fun getInJarCounts(): MutableList<Any?> = super.getInJarCounts()
@Internal
override fun getLibraryJarFiles(): MutableList<Any?> = super.getLibraryJarFiles()
/*
* Inputs properly declared these methods so we don't override them
*
* configuration(configurationFiles: Any?)
* libraryjars(libraryJarFiles: Any?)
* libraryjars(filterArgs: MutableMap<Any?, Any?>?, libraryJarFiles: Any?)
* injars(inJarFiles: Any?)
* injars(filterArgs: MutableMap<Any?, Any?>?, inJarFiles: Any?)
* outjars(outJarFiles: Any?)
* outjars(filterArgs: MutableMap<Any?, Any?>?, outJarFiles: Any?)
* printconfiguration()
* printconfiguration(printConfiguration: Any?)
*/
override fun renamesourcefileattribute() = throw NotImplementedError()
override fun renamesourcefileattribute(newSourceFileAttribute: String?) = throw NotImplementedError()
override fun dontshrink() = throw NotImplementedError()
override fun assumenosideeffects(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenosideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepnames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepnames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun printmapping() = throw NotImplementedError()
override fun printmapping(printMapping: Any?) = throw NotImplementedError()
override fun keep(classSpecificationString: String?) = throw NotImplementedError()
override fun keep(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepdirectories() = throw NotImplementedError()
override fun keepdirectories(filter: String?) = throw NotImplementedError()
override fun dontpreverify() = throw NotImplementedError()
override fun dontnote() = throw NotImplementedError()
override fun dontnote(filter: String?) = throw NotImplementedError()
@Internal
override fun getrenamesourcefileattribute(): Any? = throw NotImplementedError()
override fun useuniqueclassmembernames() = throw NotImplementedError()
override fun overloadaggressively() = throw NotImplementedError()
@Internal
override fun getprintusage(): Any? = throw NotImplementedError()
@Internal
override fun getforceprocessing(): Any? = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationString: String?) = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun obfuscationdictionary(obfuscationDictionary: Any?) = throw NotImplementedError()
override fun adaptclassstrings() = throw NotImplementedError()
override fun adaptclassstrings(filter: String?) = throw NotImplementedError()
override fun applymapping(applyMapping: Any?) = throw NotImplementedError()
override fun mergeinterfacesaggressively() = throw NotImplementedError()
@Internal
override fun getdontwarn(): Any? = throw NotImplementedError()
override fun ignorewarnings() = throw NotImplementedError()
@Internal
override fun getaddconfigurationdebugging(): Any? = throw NotImplementedError()
override fun field(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
@Internal
override fun getallowaccessmodification(): Any? = throw NotImplementedError()
override fun constructor(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun dontusemixedcaseclassnames() = throw NotImplementedError()
@Internal
override fun getignorewarnings(): Any? = throw NotImplementedError()
@Internal
override fun getkeepdirectories(): Any? = throw NotImplementedError()
override fun classobfuscationdictionary(classObfuscationDictionary: Any?) = throw NotImplementedError()
override fun verbose() = throw NotImplementedError()
override fun optimizations(filter: String?) = throw NotImplementedError()
@Internal
override fun getuseuniqueclassmembernames(): Any? = throw NotImplementedError()
@Internal
override fun getmicroedition(): Any? = throw NotImplementedError()
override fun assumenoescapingparameters(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoescapingparameters(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getandroid(): Any? = throw NotImplementedError()
override fun keeppackagenames() = throw NotImplementedError()
override fun keeppackagenames(filter: String?) = throw NotImplementedError()
@Internal
override fun getoverloadaggressively(): Any? = throw NotImplementedError()
override fun skipnonpubliclibraryclasses() = throw NotImplementedError()
@Internal
override fun getdontusemixedcaseclassnames(): Any? = throw NotImplementedError()
@Internal
override fun getdontnote(): Any? = throw NotImplementedError()
override fun assumenoexternalreturnvalues(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoexternalreturnvalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun target(targetClassVersion: String?) = throw NotImplementedError()
override fun keepattributes() = throw NotImplementedError()
override fun keepattributes(filter: String?) = throw NotImplementedError()
override fun keepclassmembernames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getdontpreverify(): Any? = throw NotImplementedError()
@Internal
override fun getverbose(): Any? = throw NotImplementedError()
@Internal
override fun getskipnonpubliclibraryclasses(): Any? = throw NotImplementedError()
@Internal
override fun getdontoptimize(): Any? = throw NotImplementedError()
override fun keepclasseswithmembernames(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun keepclasseswithmembers(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getdump(): Any? = throw NotImplementedError()
override fun printseeds() = throw NotImplementedError()
override fun printseeds(printSeeds: Any?) = throw NotImplementedError()
override fun dontoptimize() = throw NotImplementedError()
override fun dontobfuscate() = throw NotImplementedError()
override fun extendClassSpecifications(
classSpecifications: MutableList<Any?>?,
classSpecification: ClassSpecification?
): MutableList<Any?> = throw NotImplementedError()
override fun allowaccessmodification() = throw NotImplementedError()
@Internal
override fun getdontobfuscate(): Any? = throw NotImplementedError()
@Internal
override fun getprintmapping(): Any? = throw NotImplementedError()
override fun flattenpackagehierarchy() = throw NotImplementedError()
override fun flattenpackagehierarchy(flattenPackageHierarchy: String?) = throw NotImplementedError()
override fun android() = throw NotImplementedError()
override fun dump() = throw NotImplementedError()
override fun dump(dump: Any?) = throw NotImplementedError()
@Internal
override fun getdontshrink(): Any? = throw NotImplementedError()
@Internal
override fun getkeepattributes(): Any? = throw NotImplementedError()
override fun microedition() = throw NotImplementedError()
override fun keepparameternames() = throw NotImplementedError()
override fun addconfigurationdebugging() = throw NotImplementedError()
override fun packageobfuscationdictionary(packageObfuscationDictionary: Any?) = throw NotImplementedError()
@Internal
override fun getdontskipnonpubliclibraryclassmembers(): Any? = throw NotImplementedError()
override fun dontskipnonpubliclibraryclassmembers() = throw NotImplementedError()
@Internal
override fun getprintconfiguration(): Any? = throw NotImplementedError()
override fun forceprocessing() = throw NotImplementedError()
override fun keepclassmembers(classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
@Internal
override fun getmergeinterfacesaggressively(): Any? = throw NotImplementedError()
@Internal
override fun getConfigurationFiles(): MutableList<Any?> = throw NotImplementedError()
@Internal
override fun getkeeppackagenames(): Any? = throw NotImplementedError()
override fun assumevalues(classSpecificationString: String?) = throw NotImplementedError()
override fun assumevalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun printusage() = throw NotImplementedError()
override fun printusage(printUsage: Any?) = throw NotImplementedError()
@Internal
override fun getprintseeds(): Any? = throw NotImplementedError()
@Internal
override fun getadaptresourcefilenames(): Any? = throw NotImplementedError()
override fun assumenoexternalsideeffects(classSpecificationString: String?) = throw NotImplementedError()
override fun assumenoexternalsideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
override fun dontwarn() = throw NotImplementedError()
override fun dontwarn(filter: String?) = throw NotImplementedError()
@Internal
override fun getrepackageclasses(): Any? = throw NotImplementedError()
@Internal
override fun getadaptresourcefilecontents(): Any? = throw NotImplementedError()
@Internal
override fun getflattenpackagehierarchy(): Any? = throw NotImplementedError()
override fun optimizationpasses(optimizationPasses: Int) = throw NotImplementedError()
override fun adaptresourcefilenames() = throw NotImplementedError()
override fun adaptresourcefilenames(filter: String?) = throw NotImplementedError()
override fun method(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
@Internal
override fun getadaptclassstrings(): Any? = throw NotImplementedError()
override fun repackageclasses() = throw NotImplementedError()
override fun repackageclasses(repackageClasses: String?) = throw NotImplementedError()
@Internal
override fun getkeepparameternames(): Any? = throw NotImplementedError()
override fun adaptresourcefilecontents() = throw NotImplementedError()
override fun adaptresourcefilecontents(filter: String?) = throw NotImplementedError()
}

View File

@@ -7,12 +7,10 @@ import org.gradle.api.Task
import org.gradle.api.file.CopySourceSpec
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.SourceSetOutput
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.kotlin.dsl.*
import proguard.gradle.ProGuardTask
import java.io.File
import java.util.concurrent.Callable
@@ -58,7 +56,6 @@ fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaE
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
main = fqName
workingDir = rootDir
systemProperty("line.separator", "\n")
}
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
@@ -72,11 +69,3 @@ inline fun CopySourceSpec.from(crossinline filesProvider: () -> Any?): CopySourc
fun Project.javaPluginConvention(): JavaPluginConvention = the()
fun Project.findJavaPluginConvention(): JavaPluginConvention? = convention.findByType() ?: convention.findPlugin()
fun JavaExec.pathRelativeToWorkingDir(file: File): String = file.relativeTo(workingDir).invariantSeparatorsPath
fun Task.singleOutputFile(): File = when (this) {
is AbstractArchiveTask -> archiveFile.get().asFile
is ProGuardTask -> project.file(outJarFiles.single()!!)
else -> outputs.files.singleFile
}

View File

@@ -26,12 +26,10 @@ fun CompatibilityPredicate.or(other: CompatibilityPredicate): CompatibilityPredi
}
enum class Platform : CompatibilityPredicate {
P183, P191, P192, P193, P201;
P183, P191, P192, P193;
val version: Int = name.drop(1).toInt()
val displayVersion: String = "20${name.drop(1).dropLast(1)}.${name.last()}"
override fun matches(ide: Ide) = ide.platform == this
companion object {
@@ -43,11 +41,12 @@ enum class Platform : CompatibilityPredicate {
}
enum class Ide(val platform: Platform) : CompatibilityPredicate {
IJ183(Platform.P183),
IJ191(Platform.P191),
IJ192(Platform.P192),
IJ193(Platform.P193),
IJ201(Platform.P201),
AS34(Platform.P183),
AS35(Platform.P183),
AS36(Platform.P192),
AS40(Platform.P193);
@@ -55,11 +54,6 @@ enum class Ide(val platform: Platform) : CompatibilityPredicate {
val kind = Kind.values().first { it.shortName == name.take(2) }
val version = name.dropWhile { !it.isDigit() }.toInt()
val displayVersion: String = when (kind) {
Kind.IntelliJ -> "IJ${platform.displayVersion}"
Kind.AndroidStudio -> "Studio${name.substringAfter("AS").toCharArray().joinToString(separator = ".")}"
}
override fun matches(ide: Ide) = ide == this
enum class Kind(val shortName: String) {

View File

@@ -64,8 +64,6 @@ fun Project.runtimeJarArtifactBy(task: Task, artifactRef: Any, body: Configurabl
}
}
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> = runtimeJar(getOrCreateTask("jar", body), { })
fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {}): TaskProvider<T> {
tasks.named<Jar>("jar").configure {
removeArtifacts(configurations.getOrCreate("archives"), this)
@@ -85,6 +83,8 @@ fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {})
return task
}
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> = runtimeJar(getOrCreateTask("jar", body), { })
fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
val task = tasks.register<Jar>("sourcesJar") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

View File

@@ -2,25 +2,21 @@
// usages in build scripts are not tracked properly
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.AbstractCopyTask
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import java.io.File
private val Project.isEAPIntellij get() = rootProject.extra["versions.intellijSdk"].toString().contains("-EAP-")
private val Project.isNightlyIntellij get() = rootProject.extra["versions.intellijSdk"].toString().endsWith("SNAPSHOT") && !isEAPIntellij
val Project.isSnapshotIntellij get() = rootProject.extra["versions.intellijSdk"].toString().endsWith("SNAPSHOT")
val Project.intellijRepo get() =
when {
isEAPIntellij -> "https://www.jetbrains.com/intellij-repository/snapshots"
isNightlyIntellij -> "https://www.jetbrains.com/intellij-repository/nightly"
else -> "https://www.jetbrains.com/intellij-repository/releases"
}
val Project.intellijRepo get() = "https://www.jetbrains.com/intellij-repository/" + if (isSnapshotIntellij) "snapshots" else "releases"
fun Project.commonDep(coord: String): String {
val parts = coord.split(':')
@@ -133,12 +129,6 @@ fun Project.firstFromJavaHomeThatExists(vararg paths: String, jdkHome: File = Fi
logger.warn("Cannot find file by paths: ${paths.toList()} in $jdkHome")
}
fun Project.toolsJarApi(): Any =
if (kotlinBuildProperties.isInJpsBuildIdeaSync)
files(toolsJarFile() ?: error("tools.jar is not found!"))
else
dependencies.project(":dependencies:tools-jar-api")
fun Project.toolsJar(): FileCollection = files(toolsJarFile() ?: error("tools.jar is not found!"))
fun Project.toolsJarFile(jdkHome: File = File(this.property("JDK_18") as String)): File? =

View File

@@ -11,20 +11,17 @@ import java.io.File
val kotlinEmbeddableRootPackage = "org.jetbrains.kotlin"
val packagesToRelocate =
listOf(
"com.intellij",
"com.google",
"com.sampullara",
"org.apache",
"org.jdom",
"org.picocontainer",
"org.jline",
"org.fusesource",
"kotlinx.coroutines",
"net.jpountz",
"one.util.streamex",
"kotlinx.collections.immutable"
)
listOf( "com.intellij",
"com.google",
"com.sampullara",
"org.apache",
"org.jdom",
"org.picocontainer",
"org.jline",
"org.fusesource",
"kotlinx.coroutines",
"net.jpountz",
"one.util.streamex")
// The shaded compiler "dummy" is used to rewrite dependencies in projects that are used with the embeddable compiler
// on the runtime and use some shaded dependencies from the compiler

View File

@@ -24,14 +24,11 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.*
import java.io.File
private fun Project.kotlinBuildLocalDependenciesDir(): File =
(findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
(findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File) ?: project.rootDir.absoluteFile.resolve("dependencies")
private fun Project.kotlinBuildLocalRepoDir(): File = kotlinBuildLocalDependenciesDir().resolve("repo")
@@ -177,17 +174,12 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
"-Didea.debug.mode=true",
"-Didea.system.path=$ideaSandboxDir",
"-Didea.config.path=$ideaSandboxConfigDir",
"-Didea.tooling.debug=true",
"-Dapple.laf.useScreenMenuBar=true",
"-Dapple.awt.graphics.UseQuartz=true",
"-Dsun.io.useCanonCaches=false",
"-Dplugin.path=${ideaPluginDir.absolutePath}"
)
if (Platform[201].orHigher()) {
jvmArgs("-Didea.platform.prefix=Idea")
}
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
jvmArgs("-Didea.platform.prefix=AndroidStudio")
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Plugin
import org.gradle.api.Project
@Suppress("unused")
class JpsCompatiblePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.configurations.maybeCreate(EmbeddedComponents.CONFIGURATION_NAME)
project.extensions.create("pill", PillExtension::class.java)
// 'jpsTest' does not require the 'tests-jar' artifact
project.configurations.create("jpsTest")
if (project == project.rootProject) {
project.tasks.create("pill") {
dependsOn(":pill:pill-importer:pill")
if (System.getProperty("pill.android.tests", "false") == "true") {
TaskUtils.useAndroidSdk(this)
TaskUtils.useAndroidJar(this)
}
}
project.tasks.create("unpill") {
dependsOn(":pill:pill-importer:unpill")
}
}
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
open class PillExtension {
enum class Variant {
// Default variant (./gradlew pill)
BASE() {
override val includes = setOf(BASE)
},
// Full variant (./gradlew pill -Dpill.variant=full)
FULL() {
override val includes = setOf(BASE, FULL)
},
// Do not import the project to JPS model, but set some options for it
NONE() {
override val includes = emptySet<Variant>()
},
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
DEFAULT() {
override val includes = emptySet<Variant>()
};
abstract val includes: Set<Variant>
}
open var variant: Variant = Variant.DEFAULT
open var excludedDirs: List<File> = emptyList()
@Suppress("unused")
fun Project.excludedDirs(vararg dirs: String) {
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
}
@Suppress("unused")
fun serialize() = mapOf<String, Any?>(
"variant" to variant.name,
"excludedDirs" to excludedDirs
)
}

View File

@@ -0,0 +1,33 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
class DependencyMapper(val predicate: (ResolvedArtifact) -> Boolean, val mapping: (ResolvedArtifact) -> MappedDependency?) {
companion object {
fun forProject(path: String, mapping: (ResolvedArtifact) -> MappedDependency?): DependencyMapper {
return DependencyMapper(
predicate = { artifact ->
val identifier = artifact.id.componentIdentifier as? ProjectComponentIdentifier
identifier?.projectPath == path
},
mapping = mapping
)
}
fun forModule(group: String, module: String, version: String?, mapping: (ResolvedArtifact) -> MappedDependency?): DependencyMapper {
return DependencyMapper(
predicate = { artifact ->
val identifier = artifact.id.componentIdentifier as? ModuleComponentIdentifier
identifier?.group == group && identifier?.module == module && (version == null || identifier?.version == version)
},
mapping = mapping
)
}
}
}
class MappedDependency(val main: PDependency?, val deferred: List<PDependency> = emptyList())
class ParserContext(val dependencyMappers: List<DependencyMapper>, val variant: PillExtension.Variant)

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2010-2019 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.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSet
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
data class PDependencies(val main: List<PDependency>, val deferred: List<PDependency>) {
fun join(): List<PDependency> {
return main + deferred
}
}
fun Project.resolveDependencies(
configuration: Configuration,
forTests: Boolean,
dependencyMappers: List<DependencyMapper>,
withEmbedded: Boolean = false
): PDependencies {
val dependencies = mutableListOf<PDependency>()
val deferred = mutableListOf<PDependency>()
nextArtifact@ for (artifact in configuration.resolvedConfiguration.resolvedArtifacts) {
val identifier = artifact.id.componentIdentifier
for (mapper in dependencyMappers) {
if (mapper.predicate(artifact)) {
val mapped = mapper.mapping(artifact)
if (mapped != null) {
mapped.main?.let { dependencies += it }
deferred += mapped.deferred
}
continue@nextArtifact
}
}
fun addProjectDependency(projectPath: String) {
val project = rootProject.findProject(projectPath) ?: error("Cannot find project $projectPath")
fun addSourceSet(name: String, suffix: String): Boolean {
val sourceSet = project.sourceSets?.findByName(name)?.takeIf { !it.allSource.isEmpty() } ?: return false
dependencies += PDependency.Module(project.pillModuleName + '.' + suffix)
return true
}
if (forTests && artifact.classifier == "tests") {
addSourceSet(SourceSet.TEST_SOURCE_SET_NAME, "test") || addSourceSet(SourceSet.MAIN_SOURCE_SET_NAME, "src")
} else {
addSourceSet(SourceSet.MAIN_SOURCE_SET_NAME, "src")
}
if (withEmbedded) {
val embeddedConfiguration = project.configurations.findByName(EmbeddedComponents.CONFIGURATION_NAME)
if (embeddedConfiguration != null) {
dependencies += resolveDependencies(embeddedConfiguration, forTests, dependencyMappers, withEmbedded).join()
}
}
}
when (identifier) {
is ProjectComponentIdentifier -> addProjectDependency(identifier.projectPath)
is LibraryBinaryIdentifier -> addProjectDependency(identifier.projectPath)
is ModuleComponentIdentifier -> {
val file = artifact.file
val library = PLibrary(file.name, classes = listOf(file))
dependencies += PDependency.ModuleLibrary(library)
}
}
}
val existingFiles = mutableSetOf<File>()
for (dependency in configuration.dependencies) {
if (dependency !is SelfResolvingDependency) {
continue
}
val files = dependency.resolve().filter { it !in existingFiles }.takeIf { it.isNotEmpty() } ?: continue
existingFiles.addAll(files)
val library = PLibrary(dependency.name, classes = files.toList())
deferred += PDependency.ModuleLibrary(library)
}
return PDependencies(dependencies, deferred)
}

View File

@@ -0,0 +1,39 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
import org.gradle.api.Project
open class PillExtension {
enum class Variant {
// Default variant (./gradlew pill)
BASE() { override val includes = setOf(BASE) },
// Full variant (./gradlew pill -Dpill.variant=full)
FULL() { override val includes = setOf(BASE, FULL) },
// Do not import the project to JPS model, but set some options for it
NONE() { override val includes = emptySet<Variant>() },
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
DEFAULT() { override val includes = emptySet<Variant>() };
abstract val includes: Set<Variant>
}
open var variant: Variant = Variant.DEFAULT
open var importAsLibrary: Boolean = false
open var excludedDirs: List<File> = emptyList()
fun Project.excludedDirs(vararg dirs: String) {
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
}
open var libraryPath: File? = null
set(v) {
importAsLibrary = true
field = v
}
}

View File

@@ -0,0 +1,182 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.internal.file.copy.SingleParentCopySpec
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Copy
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.extra
import org.jetbrains.kotlin.pill.ArtifactElement.*
import org.jetbrains.kotlin.pill.POrderRoot.*
import java.io.File
class PArtifact(val artifactName: String, val outputDir: File, private val contents: ArtifactElement.Root) {
fun render(context: PathContext) = xml("component", "name" to "ArtifactManager") {
xml("artifact", "name" to artifactName) {
xml("output-path") {
raw(context(outputDir))
}
add(contents.renderRecursively(context))
}
}
}
sealed class ArtifactElement {
private val myChildren = mutableListOf<ArtifactElement>()
val children get() = myChildren
fun add(child: ArtifactElement) {
myChildren += child
}
fun add(children: List<ArtifactElement>) {
myChildren += children
}
abstract fun render(context: PathContext): xml
fun renderRecursively(context: PathContext): xml {
return render(context).apply {
children.forEach { add(it.renderRecursively(context)) }
}
}
fun getDirectory(path: String): ArtifactElement {
if (path.isEmpty()) {
return this
}
var current: ArtifactElement = this
for (segment in path.split("/")) {
val existing = current.children.firstOrNull { it is Directory && it.name == segment }
if (existing != null) {
current = existing
continue
}
current = Directory(segment).also { current.add(it) }
}
return current
}
class Root : ArtifactElement() {
override fun render(context: PathContext) = xml("root", "id" to "root")
}
data class Directory(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "directory", "name" to name)
}
data class Archive(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "archive", "name" to name)
}
data class ModuleOutput(val moduleName: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "module-output", "name" to moduleName)
}
data class FileCopy(val source: File, val outputFileName: String? = null) : ArtifactElement() {
override fun render(context: PathContext): xml {
val args = mutableListOf("id" to "file-copy", "path" to context(source))
if (outputFileName != null) {
args += "output-file-name" to outputFileName
}
return xml("element", *args.toTypedArray())
}
}
data class DirectoryCopy(val source: File) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "dir-copy", "path" to context(source))
}
data class ProjectLibrary(val name: String) : ArtifactElement() {
override fun render(context: PathContext) = xml("element", "id" to "library", "level" to "project", "name" to name)
}
data class ExtractedDirectory(val archive: File, val pathInJar: String = "/") : ArtifactElement() {
override fun render(context: PathContext) =
xml("element", "id" to "extracted-dir", "path" to context(archive), "path-in-jar" to pathInJar)
}
}
fun generateKotlinPluginArtifactFile(rootProject: Project, dependencyMappers: List<DependencyMapper>): PFile {
val root = Root()
fun Project.getProject(name: String) = findProject(name) ?: error("Cannot find project $name")
val prepareIdeaPluginProject = rootProject.getProject(":prepare:idea-plugin")
root.add(Directory("kotlinc").apply {
val kotlincDirectory = rootProject.extra["distKotlinHomeDir"].toString()
add(DirectoryCopy(File(kotlincDirectory)))
})
root.add(Directory("lib").apply {
val librariesConfiguration = prepareIdeaPluginProject.configurations.getByName("libraries")
add(getArtifactElements(rootProject, librariesConfiguration, dependencyMappers, false))
add(Directory("jps").apply {
val prepareJpsPluginProject = rootProject.getProject(":kotlin-jps-plugin")
add(Archive(prepareJpsPluginProject.name + ".jar").apply {
val jpsPluginConfiguration = prepareIdeaPluginProject.configurations.getByName("jpsPlugin")
add(getArtifactElements(rootProject, jpsPluginConfiguration, dependencyMappers, true))
})
})
add(Archive("kotlin-plugin.jar").apply {
add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties")))
val embeddedConfiguration = prepareIdeaPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME)
add(getArtifactElements(rootProject, embeddedConfiguration, dependencyMappers, true))
})
})
val artifact = PArtifact("KotlinPlugin", File(rootProject.projectDir, "out/artifacts/Kotlin"), root)
return PFile(
File(rootProject.projectDir, ".idea/artifacts/${artifact.artifactName}.xml"),
artifact.render(ProjectContext(rootProject))
)
}
private fun getArtifactElements(
rootProject: Project,
configuration: Configuration,
dependencyMappers: List<DependencyMapper>,
extractDependencies: Boolean
): List<ArtifactElement> {
val dependencies = rootProject.resolveDependencies(configuration, false, dependencyMappers, withEmbedded = true).join()
val artifacts = mutableListOf<ArtifactElement>()
for (dependency in dependencies) {
when (dependency) {
is PDependency.Module -> {
val moduleOutput = ModuleOutput(dependency.name)
if (extractDependencies) {
artifacts += moduleOutput
} else {
artifacts += Archive(dependency.name + ".jar").apply {
add(moduleOutput)
}
}
}
is PDependency.Library -> artifacts += ProjectLibrary(dependency.name)
is PDependency.ModuleLibrary -> {
val files = dependency.library.classes
if (extractDependencies) files.mapTo(artifacts) { ExtractedDirectory(it) }
else files.mapTo(artifacts) { FileCopy(it) }
}
}
}
return artifacts
}

View File

@@ -0,0 +1,421 @@
/*
* Copyright 2010-2018 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.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Project
import org.gradle.api.artifacts.*
import org.gradle.api.tasks.*
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.kotlin.dsl.configure
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.HasConvention
import org.gradle.api.internal.file.copy.CopySpecInternal
import org.gradle.api.internal.file.copy.SingleParentCopySpec
import org.gradle.language.jvm.tasks.ProcessResources
import org.jetbrains.kotlin.pill.POrderRoot.*
import org.jetbrains.kotlin.pill.PSourceRoot.*
import org.jetbrains.kotlin.pill.PillExtension.*
import java.io.File
import java.util.LinkedList
data class PProject(
val name: String,
val rootDirectory: File,
val modules: List<PModule>,
val libraries: List<PLibrary>
)
data class PModule(
val name: String,
val rootDirectory: File,
val moduleFile: File,
val contentRoots: List<PContentRoot>,
val orderRoots: List<POrderRoot>,
val moduleForProductionSources: PModule? = null
)
data class PContentRoot(
val path: File,
val forTests: Boolean,
val sourceRoots: List<PSourceRoot>,
val excludedDirectories: List<File>
)
data class PSourceRoot(
val path: File,
val kind: Kind,
val kotlinOptions: PSourceRootKotlinOptions?
) {
enum class Kind { PRODUCTION, TEST, RESOURCES, TEST_RESOURCES }
}
data class PSourceRootKotlinOptions(
val noStdlib: Boolean?,
val noReflect: Boolean?,
val moduleName: String?,
val apiVersion: String?,
val languageVersion: String?,
val jvmTarget: String?,
val extraArguments: List<String>
) {
fun intersect(other: PSourceRootKotlinOptions) = PSourceRootKotlinOptions(
if (noStdlib == other.noStdlib) noStdlib else null,
if (noReflect == other.noReflect) noReflect else null,
if (moduleName == other.moduleName) moduleName else null,
if (apiVersion == other.apiVersion) apiVersion else null,
if (languageVersion == other.languageVersion) languageVersion else null,
if (jvmTarget == other.jvmTarget) jvmTarget else null,
extraArguments.intersect(other.extraArguments).toList()
)
}
data class POrderRoot(
val dependency: PDependency,
val scope: Scope,
val isExported: Boolean = false,
val isProductionOnTestDependency: Boolean = false
) {
enum class Scope { COMPILE, TEST, RUNTIME, PROVIDED }
}
sealed class PDependency {
data class Module(val name: String) : PDependency()
data class Library(val name: String) : PDependency()
data class ModuleLibrary(val library: PLibrary) : PDependency()
}
data class PLibrary(
val name: String,
val classes: List<File>,
val javadoc: List<File> = emptyList(),
val sources: List<File> = emptyList(),
val annotations: List<File> = emptyList(),
val dependencies: List<PLibrary> = emptyList(),
val originalName: String = name
) {
fun attachSource(file: File): PLibrary {
return this.copy(sources = this.sources + listOf(file))
}
}
fun parse(project: Project, libraries: List<PLibrary>, context: ParserContext): PProject = with (context) {
if (project != project.rootProject) {
error("$project is not a root project")
}
fun Project.matchesSelectedVariant(): Boolean {
val extension = this.extensions.findByType(PillExtension::class.java) ?: return true
val projectVariant = extension.variant.takeUnless { it == Variant.DEFAULT } ?: Variant.BASE
return projectVariant in context.variant.includes
}
val (includedProjects, excludedProjects) = project.allprojects
.partition { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) && it.matchesSelectedVariant() }
val modules = includedProjects.flatMap { parseModules(it, excludedProjects) }
return PProject("Kotlin", project.projectDir, modules, libraries)
}
/*
Ordering here and below is significant.
Placing 'runtime' configuration dependencies on the top make 'idea' tests to run normally.
('idea' module has 'intellij-core' as transitive dependency, and we really need to get rid of it.)
*/
private val CONFIGURATION_MAPPING = mapOf(
listOf("runtimeClasspath") to Scope.RUNTIME,
listOf("compile", "embedded") to Scope.COMPILE,
listOf("compileOnly") to Scope.PROVIDED
)
private val TEST_CONFIGURATION_MAPPING = mapOf(
listOf("runtimeClasspath", "testRuntimeClasspath") to Scope.RUNTIME,
listOf("compile", "testCompile") to Scope.COMPILE,
listOf("compileOnly", "testCompileOnly") to Scope.PROVIDED,
listOf("jpsTest") to Scope.TEST
)
private fun ParserContext.parseModules(project: Project, excludedProjects: List<Project>): List<PModule> {
val (productionContentRoots, testContentRoots) = parseContentRoots(project).partition { !it.forTests }
val modules = mutableListOf<PModule>()
fun getJavaExcludedDirs() = project.plugins.findPlugin(IdeaPlugin::class.java)
?.model?.module?.excludeDirs?.toList() ?: emptyList()
fun getPillExcludedDirs() = project.extensions.getByType(PillExtension::class.java).excludedDirs
val allExcludedDirs = getPillExcludedDirs() + getJavaExcludedDirs() + project.buildDir +
(if (project == project.rootProject) excludedProjects.map { it.buildDir } else emptyList())
var productionSourcesModule: PModule? = null
fun getModuleFile(suffix: String = ""): File {
val relativePath = File(project.projectDir, project.pillModuleName + suffix + ".iml")
.toRelativeString(project.rootProject.projectDir)
return File(project.rootProject.projectDir, ".idea/modules/$relativePath")
}
for ((nameSuffix, roots) in mapOf(".src" to productionContentRoots, ".test" to testContentRoots)) {
if (roots.isEmpty()) {
continue
}
val mainRoot = roots.first()
var dependencies = parseDependencies(project, mainRoot.forTests)
if (productionContentRoots.isNotEmpty() && mainRoot.forTests) {
val productionModuleDependency = PDependency.Module(project.pillModuleName + ".src")
dependencies += POrderRoot(productionModuleDependency, Scope.COMPILE, true)
}
val module = PModule(
project.pillModuleName + nameSuffix,
mainRoot.path,
getModuleFile(nameSuffix),
roots,
dependencies,
productionSourcesModule
)
modules += module
if (!mainRoot.forTests) {
productionSourcesModule = module
}
}
val mainModuleFileRelativePath = when (project) {
project.rootProject -> File(project.rootProject.projectDir, project.rootProject.name + ".iml")
else -> getModuleFile()
}
modules += PModule(
project.pillModuleName,
project.projectDir,
mainModuleFileRelativePath,
listOf(PContentRoot(project.projectDir, false, emptyList(), allExcludedDirs)),
if (modules.isEmpty()) parseDependencies(project, false) else emptyList()
)
return modules
}
private fun parseContentRoots(project: Project): List<PContentRoot> {
val sourceRoots = parseSourceRoots(project).groupBy { it.kind }
fun getRoots(kind: PSourceRoot.Kind) = sourceRoots[kind] ?: emptyList()
val productionSourceRoots = getRoots(Kind.PRODUCTION) + getRoots(Kind.RESOURCES)
val testSourceRoots = getRoots(Kind.TEST) + getRoots(Kind.TEST_RESOURCES)
fun createContentRoots(sourceRoots: List<PSourceRoot>, forTests: Boolean): List<PContentRoot> {
return sourceRoots.map { PContentRoot(it.path, forTests, listOf(it), emptyList()) }
}
return createContentRoots(productionSourceRoots, forTests = false) +
createContentRoots(testSourceRoots, forTests = true)
}
private fun parseSourceRoots(project: Project): List<PSourceRoot> {
if (!project.plugins.hasPlugin(JavaPlugin::class.java)) {
return emptyList()
}
val kotlinTasksBySourceSet = project.tasks.names
.filter { it.startsWith("compile") && it.endsWith("Kotlin") }
.map { project.tasks.getByName(it) }
.associateBy { it.invokeInternal("getSourceSetName") }
val sourceRoots = mutableListOf<PSourceRoot>()
val sourceSets = project.sourceSets
if (sourceSets != null) {
for (sourceSet in sourceSets) {
val kotlinCompileTask = kotlinTasksBySourceSet[sourceSet.name]
val kind = if (sourceSet.isTestSourceSet) Kind.TEST else Kind.PRODUCTION
fun Any.getKotlin(): SourceDirectorySet {
val kotlinMethod = javaClass.getMethod("getKotlin")
val oldIsAccessible = kotlinMethod.isAccessible
try {
kotlinMethod.isAccessible = true
return kotlinMethod(this) as SourceDirectorySet
} finally {
kotlinMethod.isAccessible = oldIsAccessible
}
}
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
.plugins["kotlin"]?.getKotlin()?.srcDirs
?: emptySet()
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
.filter { it.exists() }
.takeIf { it.isNotEmpty() }
?: continue
val kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it) }
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
if (!resourceRoot.exists() || resourceRoot in directories) {
continue
}
val resourceRootKind = when (kind) {
Kind.PRODUCTION -> Kind.RESOURCES
Kind.TEST -> Kind.TEST_RESOURCES
else -> error("Invalid source root kind $kind")
}
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind, kotlinOptions)
}
for (directory in directories) {
sourceRoots += PSourceRoot(directory, kind, kotlinOptions)
}
for (root in parseResourceRootsProcessedByProcessResourcesTask(project, sourceSet)) {
if (sourceRoots.none { it.path == root.path }) {
sourceRoots += root
}
}
}
}
return sourceRoots
}
private fun parseResourceRootsProcessedByProcessResourcesTask(project: Project, sourceSet: SourceSet): List<PSourceRoot> {
val isMainSourceSet = sourceSet.name == SourceSet.MAIN_SOURCE_SET_NAME
val resourceRootKind = if (sourceSet.isTestSourceSet) PSourceRoot.Kind.TEST_RESOURCES else PSourceRoot.Kind.RESOURCES
val taskNameBase = "processResources"
val taskName = if (isMainSourceSet) taskNameBase else sourceSet.name + taskNameBase.capitalize()
val task = project.tasks.findByName(taskName) as? ProcessResources ?: return emptyList()
val roots = mutableListOf<File>()
fun collectRoots(spec: CopySpecInternal) {
if (spec is SingleParentCopySpec && spec.children.none()) {
roots += spec.sourcePaths.map { File(project.projectDir, it.toString()) }.filter { it.exists() }
return
}
spec.children.forEach(::collectRoots)
}
collectRoots(task.rootSpec)
return roots.map { PSourceRoot(it, resourceRootKind, null) }
}
private val SourceSet.isTestSourceSet: Boolean
get() = name == SourceSet.TEST_SOURCE_SET_NAME
|| name.endsWith("Test")
|| name.endsWith("Tests")
private fun getKotlinOptions(kotlinCompileTask: Any): PSourceRootKotlinOptions? {
val compileArguments = run {
val method = kotlinCompileTask::class.java.getMethod("getSerializedCompilerArguments")
method.isAccessible = true
method.invoke(kotlinCompileTask) as List<String>
}
fun parseBoolean(name: String) = compileArguments.contains("-$name")
fun parseString(name: String) = compileArguments.dropWhile { it != "-$name" }.drop(1).firstOrNull()
fun isOptionForScriptingCompilerPlugin(option: String)
= option.startsWith("-Xplugin=") && option.contains("kotlin-scripting-compiler")
val extraArguments = compileArguments.filter {
it.startsWith("-X") && !isOptionForScriptingCompilerPlugin(it)
}
return PSourceRootKotlinOptions(
parseBoolean("no-stdlib"),
parseBoolean("no-reflect"),
parseString("module-name"),
parseString("api-version"),
parseString("language-version"),
parseString("jvm-target"),
extraArguments
)
}
private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() }
val oldIsAccessible = method.isAccessible
try {
method.isAccessible = true
return method.invoke(instance)
} finally {
method.isAccessible = oldIsAccessible
}
}
private fun ParserContext.parseDependencies(project: Project, forTests: Boolean): List<POrderRoot> {
val configurations = project.configurations
val configurationMapping = if (forTests) TEST_CONFIGURATION_MAPPING else CONFIGURATION_MAPPING
val mainRoots = mutableListOf<POrderRoot>()
val deferredRoots = mutableListOf<POrderRoot>()
for ((configurationNames, scope) in configurationMapping) {
for (configurationName in configurationNames) {
val configuration = configurations.findByName(configurationName) ?: continue
val (main, deferred) = project.resolveDependencies(configuration, forTests, dependencyMappers)
mainRoots += main.map { POrderRoot(it, scope) }
deferredRoots += deferred.map { POrderRoot(it, scope) }
}
}
return removeDuplicates(mainRoots + deferredRoots)
}
fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
val dependenciesByScope = roots.groupBy { it.scope }.mapValues { it.value.mapTo(mutableSetOf()) { it.dependency } }
fun dependenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
val result = mutableSetOf<POrderRoot>()
for (root in roots.distinct()) {
val scope = root.scope
val dependency = root.dependency
if (root in result) {
continue
}
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in dependenciesFor(Scope.COMPILE)) {
continue
}
if (scope == Scope.PROVIDED && dependency in dependenciesFor(Scope.RUNTIME)) {
result += POrderRoot(dependency, Scope.COMPILE)
continue
}
if (scope == Scope.RUNTIME && dependency in dependenciesFor(Scope.PROVIDED)) {
result += POrderRoot(dependency, Scope.COMPILE)
continue
}
result += root
}
return result.toList()
}
val Project.pillModuleName: String
get() = path.removePrefix(":").replace(':', '.')
val Project.sourceSets: SourceSetContainer?
get() {
val convention = project.convention.findPlugin(JavaPluginConvention::class.java) ?: return null
return convention.sourceSets
}

View File

@@ -0,0 +1,54 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Project
import java.io.File
private val USER_HOME_DIR_PATH = System.getProperty("user.home").withSlash()
private fun replacePrefix(path: String, prefix: String, variableName: String): String {
if (path.startsWith(prefix)) {
return "$" + variableName + "$/" + path.drop(prefix.length)
}
return path
}
private fun simplifyUserHomeDirPath(path: String): String {
return replacePrefix(path, USER_HOME_DIR_PATH, "USER_HOME")
}
interface PathContext {
operator fun invoke(file: File): String
fun url(file: File): Pair<String, String> {
val path = when {
file.isFile && file.extension.toLowerCase() == "jar" -> "jar://" + this(file) + "!/"
else -> "file://" + this(file)
}
return Pair("url", path)
}
}
class ProjectContext private constructor(private val projectDir: File) : PathContext {
constructor(project: PProject) : this(project.rootDirectory)
constructor(project: Project) : this(project.projectDir)
override fun invoke(file: File): String {
return simplifyUserHomeDirPath(replacePrefix(file.absolutePath, projectDir.absolutePath.withSlash(), "PROJECT_DIR"))
}
}
class ModuleContext(val project: PProject, val module: PModule) : PathContext {
override fun invoke(file: File): String {
if (!file.startsWith(project.rootDirectory)) {
return simplifyUserHomeDirPath(file.absolutePath)
}
return "\$MODULE_DIR\$/" + file.toRelativeString(module.moduleFile.parentFile)
}
}
fun String.withSlash() = if (this.endsWith("/")) this else (this + "/")
fun String.withoutSlash() = this.trimEnd('/')

View File

@@ -0,0 +1,338 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.kotlin.dsl.extra
import shadow.org.jdom2.input.SAXBuilder
import shadow.org.jdom2.*
import shadow.org.jdom2.output.Format
import shadow.org.jdom2.output.XMLOutputter
import java.io.File
class PillConfigurablePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.configurations.maybeCreate(EmbeddedComponents.CONFIGURATION_NAME)
project.extensions.create("pill", PillExtension::class.java)
}
}
class JpsCompatiblePlugin : Plugin<Project> {
companion object {
private fun getDependencyMappers(projectLibraries: List<PLibrary>): List<DependencyMapper> {
val mappersForKotlinLibrariesExeptStdlib = projectLibraries
.filter { it.name != "kotlin-stdlib" }
.map { DependencyMapper.forProject(it.originalName) { MappedDependency(PDependency.Library(it.name)) } }
val disabledModuleMappers = listOf(
":kotlin-stdlib-common",
":core:builtins",
":kotlin-compiler",
":kotlin-compiler-embeddable",
":kotlin-test:kotlin-test-common",
":kotlin-test:kotlin-test-annotations-common"
).map { DependencyMapper.forProject(it) { null } }
return listOf(
DependencyMapper.forProject(":kotlin-stdlib") {
MappedDependency(
PDependency.Library("kotlin-stdlib"),
listOf(PDependency.Library("annotations-13.0"))
)
},
DependencyMapper.forProject(":kotlin-test:kotlin-test-jvm") { MappedDependency(PDependency.Library("kotlin-test-jvm")) },
DependencyMapper.forProject(":kotlin-reflect-api") { MappedDependency(PDependency.Library("kotlin-reflect")) }
) + mappersForKotlinLibrariesExeptStdlib + disabledModuleMappers
}
fun getProjectLibraries(rootProject: Project): List<PLibrary> {
val distLibDir = File(rootProject.extra["distLibDir"].toString())
fun distJar(name: String) = File(rootProject.projectDir, "dist/kotlinc/lib/$name.jar")
val libraries = rootProject.allprojects
.mapNotNull { library ->
val libraryExtension = library.extensions.findByType(PillExtension::class.java)
?.takeIf { it.importAsLibrary }
?: return@mapNotNull null
val libraryPath = libraryExtension.libraryPath ?: distLibDir
val archivesBaseName = library.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName ?: library.name
fun List<File>.filterExisting() = filter { it.exists() }
PLibrary(
library.name,
classes = listOf(File(libraryPath, "$archivesBaseName.jar")).filterExisting(),
sources = listOf(File(libraryPath, "$archivesBaseName-sources.jar")).filterExisting(),
originalName = library.path
)
}
return libraries + PLibrary("annotations-13.0", classes = listOf(distJar("annotations-13.0")))
}
}
override fun apply(project: Project) {
project.plugins.apply(PillConfigurablePlugin::class.java)
// 'jpsTest' does not require the 'tests-jar' artifact
project.configurations.create("jpsTest")
if (project == project.rootProject) {
project.tasks.create("pill") {
doLast { pill(project) }
if (System.getProperty("pill.android.tests", "false") == "true") {
TaskUtils.useAndroidSdk(this)
TaskUtils.useAndroidJar(this)
}
}
project.tasks.create("unpill") {
doLast { unpill(project) }
}
}
}
private lateinit var projectDir: File
private lateinit var platformVersion: String
private lateinit var platformBaseNumber: String
private lateinit var platformDir: File
private lateinit var intellijCoreDir: File
private var isAndroidStudioPlatform: Boolean = false
private fun initEnvironment(project: Project) {
projectDir = project.projectDir
platformVersion = project.extensions.extraProperties.get("versions.intellijSdk").toString()
platformBaseNumber = platformVersion.substringBefore(".", "").takeIf { it.isNotEmpty() }
?: platformVersion.substringBefore("-", "").takeIf { it.isNotEmpty() }
?: error("Invalid platform version: $platformVersion")
platformDir = IntellijRootUtils.getIntellijRootDir(project)
intellijCoreDir = File(platformDir.parentFile.parentFile.parentFile, "intellij-core")
isAndroidStudioPlatform = project.extensions.extraProperties.has("versions.androidStudioRelease")
}
private fun pill(rootProject: Project) {
initEnvironment(rootProject)
val variantOptionValue = System.getProperty("pill.variant", "base").toUpperCase()
val variant = PillExtension.Variant.values().firstOrNull { it.name == variantOptionValue }
?: run {
rootProject.logger.error("Invalid variant name: $variantOptionValue")
return
}
rootProject.logger.lifecycle("Pill: Setting up project for the '${variant.name.toLowerCase()}' variant...")
if (variant == PillExtension.Variant.NONE || variant == PillExtension.Variant.DEFAULT) {
rootProject.logger.error("'none' and 'default' should not be passed as a Pill variant property value")
return
}
val projectLibraries = getProjectLibraries(rootProject)
val dependencyMappers = getDependencyMappers(projectLibraries)
val parserContext = ParserContext(dependencyMappers, variant)
val jpsProject = parse(rootProject, projectLibraries, parserContext)
.mapLibraries(this::attachPlatformSources, this::attachAsmSources)
val files = render(jpsProject)
removeExistingIdeaLibrariesAndModules()
removeJpsAndPillRunConfigurations()
removeAllArtifactConfigurations()
generateKotlinPluginArtifactFile(rootProject, dependencyMappers).write()
copyRunConfigurations()
setOptionsForDefaultJunitRunConfiguration(rootProject)
files.forEach { it.write() }
}
private fun unpill(project: Project) {
initEnvironment(project)
removeExistingIdeaLibrariesAndModules()
removeJpsAndPillRunConfigurations()
removeAllArtifactConfigurations()
}
private fun removeExistingIdeaLibrariesAndModules() {
File(projectDir, ".idea/libraries").deleteRecursively()
File(projectDir, ".idea/modules").deleteRecursively()
}
private fun removeJpsAndPillRunConfigurations() {
File(projectDir, ".idea/runConfigurations")
.walk()
.filter { (it.name.startsWith("JPS_") || it.name.startsWith("Pill_")) && it.extension.toLowerCase() == "xml" }
.forEach { it.delete() }
}
private fun removeAllArtifactConfigurations() {
File(projectDir, ".idea/artifacts")
.walk()
.filter { it.extension.toLowerCase() == "xml" }
.forEach { it.delete() }
}
private fun copyRunConfigurations() {
val runConfigurationsDir = File(projectDir, "buildSrc/src/main/resources/runConfigurations")
val targetDir = File(projectDir, ".idea/runConfigurations")
val platformDirProjectRelative = "\$PROJECT_DIR\$/" + platformDir.toRelativeString(projectDir)
val additionalIdeaArgs = if (isAndroidStudioPlatform) "-Didea.platform.prefix=AndroidStudio" else ""
targetDir.mkdirs()
fun substitute(text: String): String {
return text
.replace("\$IDEA_HOME_PATH\$", platformDirProjectRelative)
.replace("\$ADDITIONAL_IDEA_ARGS\$", additionalIdeaArgs)
}
runConfigurationsDir.listFiles()
.filter { it.extension == "xml" }
.map { it.name to substitute(it.readText()) }
.forEach { File(targetDir, it.first).writeText(it.second) }
}
/*
This sets a proper (project root) working directory and a "idea.home.path" property to the default JUnit configuration,
so one does not need to make these changes manually.
*/
private fun setOptionsForDefaultJunitRunConfiguration(project: Project) {
val workspaceFile = File(projectDir, ".idea/workspace.xml")
if (!workspaceFile.exists()) {
project.logger.warn("${workspaceFile.name} does not exist, JUnit default run configuration was not modified")
return
}
val document = SAXBuilder().build(workspaceFile)
val rootElement = document.rootElement
fun Element.getOrCreateChild(name: String, vararg attributes: Pair<String, String>): Element {
for (child in getChildren(name)) {
if (attributes.all { (attribute, value) -> child.getAttributeValue(attribute) == value }) {
return child
}
}
return Element(name).apply {
for ((attributeName, value) in attributes) {
setAttribute(attributeName, value)
}
this@getOrCreateChild.addContent(this@apply)
}
}
val platformDirProjectRelative = "\$PROJECT_DIR\$/" + platformDir.toRelativeString(projectDir)
val runManagerComponent = rootElement.getOrCreateChild("component", "name" to "RunManager")
val junitConfiguration = runManagerComponent.getOrCreateChild(
"configuration",
"default" to "true",
"type" to "JUnit",
"factoryName" to "JUnit"
)
junitConfiguration.apply {
getOrCreateChild("option", "name" to "WORKING_DIRECTORY").setAttribute("value", "file://\$PROJECT_DIR\$")
getOrCreateChild("option", "name" to "VM_PARAMETERS").also { vmParams ->
var options = vmParams.getAttributeValue("value", "")
.split(' ')
.map { it.trim() }
.filter { it.isNotEmpty() }
fun addOrReplaceOptionValue(name: String, value: Any?) {
val optionsWithoutNewValue = options.filter { !it.startsWith("-D$name=") }
options = if (value == null) optionsWithoutNewValue else (optionsWithoutNewValue + listOf("-D$name=$value"))
}
val robolectricClasspath = project.rootProject
.project(":plugins:android-extensions-compiler")
.configurations.getByName("robolectricClasspath")
.files.joinToString(File.pathSeparator)
if (options.none { it == "-ea" }) {
options += "-ea"
}
addOrReplaceOptionValue("idea.home.path", platformDirProjectRelative)
addOrReplaceOptionValue("ideaSdk.androidPlugin.path", platformDirProjectRelative + "/plugins/android/lib")
addOrReplaceOptionValue("robolectric.classpath", robolectricClasspath)
addOrReplaceOptionValue("use.jps", "true")
addOrReplaceOptionValue("kotlinVersion", project.rootProject.extra["kotlinVersion"].toString())
val isAndroidStudioBunch = project.findProperty("versions.androidStudioRelease") != null
addOrReplaceOptionValue("idea.platform.prefix", if (isAndroidStudioBunch) "AndroidStudio" else null)
val androidJarPath = project.configurations.findByName("androidJar")?.singleFile
val androidSdkPath = project.configurations.findByName("androidSdk")?.singleFile
if (androidJarPath != null && androidSdkPath != null) {
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
}
vmParams.setAttribute("value", options.joinToString(" "))
}
}
val output = XMLOutputter().also {
it.format = Format.getPrettyFormat().apply {
setEscapeStrategy { Verifier.isHighSurrogate(it) || it == '"' }
setIndent(" ")
setTextMode(Format.TextMode.TRIM)
setOmitEncoding(false)
setOmitDeclaration(false)
}
}
val postProcessedXml = output.outputString(document)
.replace("&#x22;", "&quot;")
.replace("&#xA;", "&#10;")
.replace("&#xC;", "&#13;")
workspaceFile.writeText(postProcessedXml)
}
private fun attachPlatformSources(library: PLibrary): PLibrary {
val platformSourcesJar = File(platformDir, "../../../sources/intellij-$platformVersion-sources.jar")
if (library.classes.any { it.startsWith(platformDir) || it.startsWith(intellijCoreDir) }) {
return library.attachSource(platformSourcesJar)
}
return library
}
private fun attachAsmSources(library: PLibrary): PLibrary {
val asmSourcesJar = File(platformDir, "../asm-shaded-sources/asm-src-$platformBaseNumber.jar")
val asmAllJar = File(platformDir, "lib/asm-all.jar")
if (library.classes.any { it == asmAllJar }) {
return library.attachSource(asmSourcesJar)
}
return library
}
private fun PProject.mapLibraries(vararg mappers: (PLibrary) -> PLibrary): PProject {
fun mapLibrary(root: POrderRoot): POrderRoot {
val dependency = root.dependency
if (dependency is PDependency.ModuleLibrary) {
val newLibrary = mappers.fold(dependency.library) { lib, mapper -> mapper(lib) }
return root.copy(dependency = dependency.copy(library = newLibrary))
}
return root
}
val modules = this.modules.map { it.copy(orderRoots = it.orderRoots.map(::mapLibrary)) }
return this.copy(modules = modules)
}
}

View File

@@ -1,21 +1,17 @@
/*
* 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.
*/
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import java.io.File
class PFile(val path: File, private val text: String) {
constructor(path: File, xml: XmlNode) : this(path, xml.toString())
class PFile(val path: File, val text: String) {
fun write() {
path.parentFile.mkdirs()
path.writeText(text)
}
}
fun PFile(path: File, xml: xml) = PFile(path, xml.toString())
fun render(project: PProject): List<PFile> {
val files = mutableListOf<PFile>()
@@ -44,8 +40,7 @@ private fun renderModulesFile(project: PProject) = PFile(
private fun renderModule(project: PProject, module: PModule) = PFile(
module.moduleFile,
xml(
"module",
xml("module",
"type" to "JAVA_MODULE",
"version" to 4
) {
@@ -54,7 +49,12 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
xml("component", "name" to "TestModuleProperties", "production-module" to moduleForProductionSources.name)
}
val kotlinCompileOptions = module.kotlinOptions
val kotlinCompileOptionsList = module.contentRoots.flatMap { it.sourceRoots }.mapNotNull { it.kotlinOptions }
var kotlinCompileOptions = kotlinCompileOptionsList.firstOrNull()
for (otherOptions in kotlinCompileOptionsList.drop(1)) {
kotlinCompileOptions = kotlinCompileOptions?.intersect(otherOptions)
}
val pathContext = ModuleContext(project, module)
val platformVersion = (kotlinCompileOptions?.jvmTarget ?: "1.8")
@@ -93,18 +93,17 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
}
}
xml(
"component",
xml("component",
"name" to "NewModuleRootManager",
"LANGUAGE_LEVEL" to "JDK_${platformVersion.replace('.', '_')}",
"inherit-compiler-output" to "true"
) {
xml("exclude-output")
for (contentRoot in module.contentRoots.filter { it.path.exists() }) {
for (contentRoot in module.contentRoots) {
xml("content", pathContext.url(contentRoot.path)) {
for (sourceRoot in contentRoot.sourceRoots) {
var args = arrayOf(pathContext.url(sourceRoot.directory))
var args = arrayOf(pathContext.url(sourceRoot.path))
args += when (sourceRoot.kind) {
PSourceRoot.Kind.PRODUCTION -> ("isTestSource" to "false")
@@ -180,7 +179,7 @@ private fun renderLibrary(project: PProject, library: PLibrary): PFile {
})
}
private fun renderLibraryToXml(library: PLibrary, pathContext: PathContext, named: Boolean = true): XmlNode {
private fun renderLibraryToXml(library: PLibrary, pathContext: PathContext, named: Boolean = true): xml {
val args = if (named) arrayOf("name" to library.renderName()) else emptyArray()
return xml("library", *args) {

View File

@@ -0,0 +1,61 @@
@file:Suppress("PackageDirectoryMismatch")
package org.jetbrains.kotlin.pill
import shadow.org.jdom2.Document
import shadow.org.jdom2.Element
import shadow.org.jdom2.output.Format
import shadow.org.jdom2.output.XMLOutputter
class xml(val name: String, private vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
private companion object {
fun makeXml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}): xml {
return xml(name, *args, block = block)
}
}
private val children = mutableListOf<xml>()
private var value: Any? = null
init {
@Suppress("UNUSED_EXPRESSION")
block()
}
fun xml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}) {
children += makeXml(name, *args, block = block)
}
fun add(xml: xml) {
children += xml
}
fun raw(text: String) {
value = text
}
private fun toElement(): Element {
val element = Element(name)
for (arg in args) {
element.setAttribute(arg.first, arg.second.toString())
}
require(value == null || children.isEmpty())
value?.let { value ->
element.addContent(value.toString())
}
for (child in children) {
element.addContent(child.toElement())
}
return element
}
override fun toString(): String {
val document = Document().also { it.rootElement = toElement() }
val output = XMLOutputter().also { it.format = Format.getPrettyFormat() }
return output.outputString(document)
}
}

View File

@@ -5,12 +5,10 @@
import com.jakewharton.dex.*
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.*
import org.gradle.jvm.tasks.Jar
import java.io.File
@CacheableTask
open class DexMethodCount : DefaultTask() {
data class Counts(
@@ -21,23 +19,34 @@ open class DexMethodCount : DefaultTask() {
val byClass: Map<String, Int>
)
@Classpath
init {
outputs.upToDateWhen { !shouldPrintTeamCityStatistics } // always execute when teamCityStatistics output is required
}
@InputFile
lateinit var jarFile: File
@Optional
@Input
@Optional
var ownPackages: List<String>? = null
@Internal
// ##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='62362']
@Input
@Optional
var teamCityStatistics: Boolean? = null
private val shouldPrintTeamCityStatistics = teamCityStatistics ?: project.hasProperty("teamcity")
@Input
@Optional
var artifactName: String? = null
@get:Input
val artifactOrArchiveName: String
get() = artifactName ?: project.name
private val artifactOrArchiveName get() = artifactName ?: project.name
fun from(jar: Jar) {
jarFile = jar.archiveFile.get().asFile
artifactName = jar.archiveBaseName.orNull
jarFile = jar.archivePath
artifactName = jar.baseName
dependsOn(jar)
}
@@ -45,13 +54,16 @@ open class DexMethodCount : DefaultTask() {
lateinit var counts: Counts
@get:OutputFile
val detailOutputFile: File
get() = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
val detailOutputFile: File get() = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
@TaskAction
fun invoke() {
val methods = dexMethods(jarFile)
val counts = methods.getCounts().also { this.counts = it }
printTotals(counts)
printTCStats(counts)
outputDetails(counts)
}
@@ -59,7 +71,7 @@ open class DexMethodCount : DefaultTask() {
val byPackage = this.groupingBy { it.`package` }.eachCount()
val byClass = this.groupingBy { it.declaringType }.eachCount()
val ownPackages = ownPackages?.map { "$it." }
val ownPackages = ownPackages?.map { it + '.' }
val byOwnPackages = if (ownPackages != null) {
this.partition { method -> ownPackages.any { method.declaringType.startsWith(it) } }.let {
it.first.size to it.second.size
@@ -75,6 +87,26 @@ open class DexMethodCount : DefaultTask() {
)
}
private fun printTotals(counts: Counts) {
logger.lifecycle("Artifact $artifactOrArchiveName, total methods: ${counts.total}")
ownPackages?.let { packages ->
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from packages ${packages.joinToString { "$it.*" }}: ${counts.totalOwnPackages}")
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from other packages: ${counts.totalOtherPackages}")
}
}
private fun printTCStats(counts: Counts) {
if (shouldPrintTeamCityStatistics) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='${counts.total}']")
counts.totalOwnPackages?.let { value ->
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$value']")
}
counts.totalOtherPackages?.let { value ->
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OtherPackages' value='$value']")
}
}
}
private fun outputDetails(counts: Counts) {
detailOutputFile.printWriter().use { writer ->
writer.println("${counts.total.padRight()}\tTotal methods")
@@ -94,67 +126,9 @@ open class DexMethodCount : DefaultTask() {
}
}
}
}
open class DexMethodCountStats : DefaultTask() {
@Internal
lateinit var from: TaskProvider<DexMethodCount>
@get:InputFile
internal val inputFile
get() = from.get().detailOutputFile
@TaskAction
private fun printStats() {
val artifactOrArchiveName = from.get().artifactOrArchiveName
inputFile.reader().useLines { lines ->
fun String.getStatValue() = substringBefore("\t").trim()
val ownPackages = from.get().ownPackages
val statsLineCount = if (ownPackages == null) 1 else 3
val stats = lines.take(statsLineCount).map { it.getStatValue() }.toList()
val total = stats[0]
logger.lifecycle("Artifact $artifactOrArchiveName, total methods: $total")
if (project.kotlinBuildProperties.isTeamcityBuild) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='$total']")
}
ownPackages?.let { packages ->
val totalOwnPackages = stats[1]
val totalOtherPackages = stats[2]
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from packages ${packages.joinToString { "$it.*" }}: $totalOwnPackages")
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from other packages: $totalOtherPackages")
if (project.kotlinBuildProperties.isTeamcityBuild) {
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$totalOwnPackages']")
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OtherPackages' value='$totalOtherPackages']")
}
}
}
}
}
fun Project.printStats(dexMethodCount: TaskProvider<DexMethodCount>) {
val dexMethodCountStats = tasks.register("dexMethodCountStats", DexMethodCountStats::class.java) {
dependsOn(dexMethodCount)
from = dexMethodCount
}
dexMethodCount.configure {
finalizedBy(dexMethodCountStats)
}
}
fun Project.dexMethodCount(action: DexMethodCount.() -> Unit): TaskProvider<DexMethodCount> {
val dexMethodCount = tasks.register("dexMethodCount", DexMethodCount::class.java, action)
printStats(dexMethodCount)
tasks.getByName("check").dependsOn(dexMethodCount)
return dexMethodCount
}
private val DexMethod.`package`: String get() = declaringType.substringBeforeLast('.')
private fun Int.padRight() = toString().padStart(5, ' ')

View File

@@ -5,17 +5,14 @@ import org.jetbrains.org.objectweb.asm.*
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.*
import java.util.jar.JarFile
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
private val CONSTANT_TIME_FOR_ZIP_ENTRIES = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis
/**
* Removes @kotlin.Metadata annotations from compiled Kotlin classes
*/
fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFile: File, preserveFileTimestamps: Boolean = true) {
fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFile: File) {
val classRegex = classNamePattern.toRegex()
assert(inFile.exists()) { "Input file not found at $inFile" }
@@ -52,9 +49,6 @@ fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFil
}
val newEntry = ZipEntry(entry.name)
if (!preserveFileTimestamps) {
newEntry.time = CONSTANT_TIME_FOR_ZIP_ENTRIES
}
outJar.putNextEntry(newEntry)
outJar.write(outBytes)
outJar.closeEntry()

View File

@@ -154,10 +154,6 @@ object TaskUtils {
fun useAndroidJar(task: Task) {
task.useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
}
fun useAndroidEmulator(task: Task) {
task.useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidEmulator")
}
}
private fun Task.useAndroidConfiguration(systemPropertyName: String, configName: String) {

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.jps=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.pill=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.jps=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.pill=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="PASS_PARENT_ENVS" value="true" />

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="[Pill] IDEA" type="Application" factoryName="Application" singleton="true">
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<module name="idea-runner.main" />
<module name="idea-runner" />
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin $ADDITIONAL_IDEA_ARGS$" />
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
<RunnerSettings RunnerId="Debug">

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="[Pill] IDEA (No ProcessCanceledException)" type="Application" factoryName="Application" singleton="true">
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<module name="idea-runner.main" />
<module name="idea-runner" />
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Didea.ProcessCanceledException=disabled $ADDITIONAL_IDEA_ARGS$" />
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
<RunnerSettings RunnerId="Debug">

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="[Pill] IDEA Ultimate" type="Application" factoryName="Application" singleton="true">
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<module name="kotlin-ultimate.ultimate.ultimate-runner.main" />
<module name="kotlin-ultimate.ultimate.ultimate-runner" />
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin $ADDITIONAL_IDEA_ARGS$" />
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
<RunnerSettings RunnerId="Debug">

View File

@@ -7,7 +7,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -Djna.nosys=true -Duse.jps=true -Dkotlin.js.skipMinificationTest=false" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -Djna.nosys=true -Duse.pill=true -Dkotlin.js.skipMinificationTest=false" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="PASS_PARENT_ENVS" value="true" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.jps=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.pill=true -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="PASS_PARENT_ENVS" value="true" />

View File

@@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.jps=true -Dkotlin.colors.enabled=false -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true -Duse.pill=true -Dkotlin.colors.enabled=false -Didea.home.path=$IDEA_HOME_PATH$" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="PASS_PARENT_ENVS" value="true" />

View File

@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
ext {
isD8Enabled = project.findProperty('android.enableD8').toBoolean()
}
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:3.3.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
apply plugin: 'com.android.application'
@@ -19,7 +19,7 @@ repositories {
}
android {
compileSdkVersion 26
compileSdkVersion 19
buildToolsVersion "28.0.3"
defaultConfig {
@@ -51,7 +51,7 @@ android {
dexOptions {
dexInProcess false
javaMaxHeapSize "1500m"
javaMaxHeapSize "1200m"
maxProcessCount 4
additionalParameters "--debug"
}
@@ -60,42 +60,17 @@ android {
resultsDir = "build/test/results"
}
if (isD8Enabled) {
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
flavorDimensions "box"
productFlavors {
common0 {
ktest0 {
dimension "box"
}
common1 {
ktest1 {
dimension "box"
}
common2 {
dimension "box"
}
reflect0 {
dimension "box"
}
if (isD8Enabled) {
jvm80 {
dimension "box"
}
reflectjvm80 {
dimension "box"
}
}
}
}
@@ -103,9 +78,9 @@ android {
task jarTestFolders() {
println "Jar folders..."
new File("${projectDir}/libs/").listFiles().each { File file ->
if (file.isDirectory()) {
if (file.isDirectory() && !file.name.equals("test")) {
println "Jar '${file.name}' folder..."
ant.jar(basedir: "libs/${file.name}/", destfile: "libs/" + file.name + ".jar")
ant.jar(basedir: "libs/${file.name}/", destfile: "libs/test/" + file.name + ".jar")
}
}
}
@@ -115,18 +90,10 @@ tasks.withType(JavaCompile) {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['kotlin-test.jar', 'kotlin-stdlib.jar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
android.applicationVariants.all { variant ->
variant.productFlavors.each {
def configuration = configurations.getByName(it.name + 'Implementation').name
add(configuration, project.fileTree(dir: 'libs', include: [it.name + ".jar"]))
if (it.name.startsWith("reflect")) {
add(configuration, project.fileTree(dir: 'libs', include: ['kotlin-reflect.jar']))
}
}
}
ktest0Implementation fileTree(dir: 'libs/test', include: ['libtest0.jar'])
ktest1Implementation fileTree(dir: 'libs/test', include: ['libtest1.jar'])
}

View File

@@ -1,3 +1,3 @@
#don't try to download android specific tools within gradle: licence acceptance will be required
android.builder.sdkDownload=false
android.enableD8=true
android.enableD8=false

View File

@@ -8,5 +8,5 @@
# For customization when using a Version Control System, please read the
# header note.
#sdk.dir=compiler/android-tests/android-module/android-sdk/android-sdk-windows
sdk.dir=../../../dependencies/android.tests.dependencies/android-sdk
sdk.dir=../../../android.tests.dependencies/android-sdk

View File

@@ -1,4 +1,3 @@
import TaskUtils.useAndroidEmulator
plugins {
kotlin("jvm")
@@ -14,10 +13,7 @@ dependencies {
compile(project(":kotlin-reflect"))
compile(projectTests(":compiler:tests-common"))
compile(commonDep("junit:junit"))
Platform[193].orLower {
compileOnly(intellijDep()) { includeJars("openapi") }
}
compileOnly(intellijDep()) { includeJars("openapi") }
testCompile(project(":compiler:incremental-compilation-impl"))
testCompile(project(":core:descriptors"))
@@ -25,11 +21,7 @@ dependencies {
testCompile(project(":compiler:frontend.java"))
testCompile(projectTests(":jps-plugin"))
testCompile(commonDep("junit:junit"))
Platform[193].orLower {
testCompile(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
}
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
testCompile(intellijDep()) { includeJars("openapi", "util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
Platform[191].orLower {
testCompile(intellijDep()) { includeJars("jps-builders") }
}
@@ -60,10 +52,9 @@ projectTest {
}
workingDir = rootDir
useAndroidEmulator(this)
}
val generateAndroidTests by generator("org.jetbrains.kotlin.android.tests.CodegenTestsOnAndroidGenerator")
val generateTests by generator("org.jetbrains.kotlin.android.tests.CodegenTestsOnAndroidGenerator")
generateAndroidTests.workingDir = rootDir
generateAndroidTests.dependsOn(rootProject.tasks.named("dist"))
generateTests.workingDir = rootDir
generateTests.dependsOn(rootProject.tasks.named("dist"))

View File

@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.android.tests
import com.intellij.util.PlatformUtils
import junit.framework.TestCase
import junit.framework.TestSuite
import org.jetbrains.kotlin.android.tests.download.SDKDownloader
import org.jetbrains.kotlin.android.tests.emulator.Emulator
import org.jetbrains.kotlin.android.tests.gradle.GradleRunner
import org.jetbrains.kotlin.android.tests.run.PermissionManager
import org.junit.Assert
import org.w3c.dom.Element
import org.xml.sax.SAXException
@@ -37,6 +39,8 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
private fun runTestsInEmulator(): TestSuite {
val rootSuite = TestSuite("Root")
downloadDependencies()
val emulatorType = if (isTeamcity) Emulator.ARM else Emulator.X86
println("Using $emulatorType emulator!")
val emulator = Emulator(pathManager, emulatorType)
@@ -52,16 +56,16 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
try {
emulator.waitEmulatorStart()
runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply {
runTestsOnEmulator(gradleRunner, TestSuite("Dex")).apply {
rootSuite.addTest(this)
}
renameFlavorFolder()
enableD8(false)
runTestsOnEmulator(gradleRunner, TestSuite("DX")).apply {
enableD8(true)
runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply {
(0 until this.countTestCases()).forEach {
val testCase = testAt(it) as TestCase
testCase.name += "_DX"
testCase.name += "_D8"
}
rootSuite.addTest(this)
}
@@ -102,14 +106,14 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
testCases.forEach { aCase -> suite.addTest(aCase) }
Assert.assertNotEquals("There is no test results in report", 0, testCases.size.toLong())
}
} catch (e: Throwable) {
} catch (e: Exception) {
throw RuntimeException("Can't parse test results in $reportFolder\n$resultOutput", e)
}
}
private fun renameFlavorFolder() {
val reportFolder = File(flavorFolder())
reportFolder.renameTo(File(reportFolder.parentFile, reportFolder.name + "_d8"))
reportFolder.renameTo(File(reportFolder.parentFile, reportFolder.name + "_dex"))
}
private fun flavorFolder() = pathManager.tmpFolder + "/build/test/results/connected/flavors"
@@ -130,6 +134,18 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
}
private fun downloadDependencies() {
val rootForAndroidDependencies = File(pathManager.dependenciesRoot)
if (!rootForAndroidDependencies.exists()) {
rootForAndroidDependencies.mkdirs()
}
val downloader = SDKDownloader(pathManager)
downloader.downloadAll()
downloader.unzipAll()
PermissionManager.setPermissions(pathManager)
}
companion object {
@JvmStatic

View File

@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.android.tests;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.android.tests.download.SDKDownloader;
import java.io.File;
@@ -35,7 +35,7 @@ public class PathManager {
}
public String getAndroidAvdRoot() {
String androidEmulatorRoot = getAndroidSdkRoot() + "/compiler_box_test_avd";
String androidEmulatorRoot = getAndroidSdkRoot() + "/emulatoravd";
new File(androidEmulatorRoot).mkdirs();
return androidEmulatorRoot;
}
@@ -52,8 +52,12 @@ public class PathManager {
return getAndroidSdkRoot() + "/emulator";
}
public String getOutputForCompiledFiles(String flavor) {
return tmpFolder + "/libs/" + flavor;
public String getBuildToolsFolderInAndroidSdk() {
return getAndroidSdkRoot() + "/build-tools";
}
public String getOutputForCompiledFiles(int index) {
return tmpFolder + "/libs/libtest" + index;
}
public String getLibsFolderInAndroidTmpFolder() {
@@ -69,7 +73,19 @@ public class PathManager {
}
public String getAndroidSdkRoot() {
return KotlinTestUtils.getAndroidSdkSystemIndependentPath();
return getDependenciesRoot() + "/android-sdk";
}
public String getDependenciesRoot() {
return rootFolder + "/android.tests.dependencies";
}
public String getGradleBinFolder() {
return getDependenciesRoot() + "/gradle-" + SDKDownloader.GRADLE_VERSION + "/bin";
}
public String getRootForDownload() {
return getDependenciesRoot() + "/download";
}
public String getAndroidModuleRoot() {

View File

@@ -0,0 +1,269 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.android.tests.download;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.kotlin.android.tests.PathManager;
import org.jetbrains.kotlin.android.tests.run.RunUtils;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class SDKDownloader {
private final String platformZipPath;
private final String armImage;
private final String x86Image;
private final String platformToolsZipPath;
private final String skdToolsZipPath;
private final String buildToolsZipPath;
private final String gradleZipPath;
private final String emulatorZipPath;
private final PathManager pathManager;
private static final String PLATFORM_TOOLS = "28.0.1";
private static final String SDK_TOOLS = "4333796"; //"26.1.1";
public static final String BUILD_TOOLS = "28.0.3";
private static final int ANDROID_VERSION = 19;
public static final String GRADLE_VERSION = "5.1.1";
public static final String EMULATOR_TOOLS_VERSION = "5264690"; //"28.0.23";
public SDKDownloader(PathManager pathManager) {
this.pathManager = pathManager;
platformZipPath = pathManager.getRootForDownload() + "/platform" + ANDROID_VERSION + ".zip";
armImage = pathManager.getRootForDownload() + "/arm-image.zip";
x86Image = pathManager.getRootForDownload() + "/x86-image.zip";
platformToolsZipPath = pathManager.getRootForDownload() + "/platform-tools" + PLATFORM_TOOLS + ".zip";
skdToolsZipPath = pathManager.getRootForDownload() + "/sdk-tools" + SDK_TOOLS + ".zip";
buildToolsZipPath = pathManager.getRootForDownload() + "/build-tools" + BUILD_TOOLS + ".zip";
gradleZipPath = pathManager.getRootForDownload() + "/gradle" + GRADLE_VERSION + ".zip";
emulatorZipPath = pathManager.getRootForDownload() + "/emulator" + EMULATOR_TOOLS_VERSION + ".zip";
}
public void downloadPlatform() {
download("https://dl-ssl.google.com/android/repository/android-" + ANDROID_VERSION + "_r04.zip", platformZipPath); //Same for all platforms
}
private void downloadAbi() {
download("https://dl.google.com/android/repository/sys-img/android/armeabi-v7a-" + ANDROID_VERSION + "_r05.zip", armImage); //Same for all platforms
download("https://dl.google.com/android/repository/sys-img/android/x86-" + ANDROID_VERSION + "_r06.zip", x86Image); //Same for all platforms
}
public void downloadPlatformTools() {
download(getDownloadUrl("https://dl-ssl.google.com/android/repository/platform-tools_r" + PLATFORM_TOOLS), platformToolsZipPath);
}
public void downloadSdkTools() {
download("https://dl.google.com/android/repository/sdk-tools-" + getPlatformName() + "-" + SDK_TOOLS + ".zip",
skdToolsZipPath);
}
public void downloadBuildTools() {
download(getDownloadUrl("https://dl.google.com/android/repository/build-tools_r" + BUILD_TOOLS), buildToolsZipPath);
}
public void downloadEmulator() {
download("https://dl.google.com/android/repository/emulator-" + getPlatformName() + "-" + EMULATOR_TOOLS_VERSION + ".zip",
emulatorZipPath);
}
public void downloadGradle() {
download("https://services.gradle.org/distributions/gradle-" + GRADLE_VERSION + "-bin.zip", gradleZipPath);
}
private static String getDownloadUrl(String prefix) {
String suffix;
if (SystemInfo.isWindows) {
suffix = "-windows.zip";
}
else if (SystemInfo.isMac) {
suffix = "-macosx.zip";
}
else if (SystemInfo.isUnix) {
suffix = "-linux.zip";
}
else {
throw new IllegalStateException("Your operating system isn't supported yet.");
}
return prefix + suffix;
}
private static String getPlatformName() {
if (SystemInfo.isWindows) {
return "windows";
}
else if (SystemInfo.isMac) {
return "darwin";
}
else if (SystemInfo.isUnix) {
return "linux";
}
else {
throw new IllegalStateException("Your operating system isn't supported yet.");
}
}
public void downloadAll() {
downloadSdkTools();
downloadAbi();
downloadPlatform();
downloadPlatformTools();
downloadBuildTools();
downloadGradle();
downloadEmulator();
}
public void unzipAll() {
String androidSdkRoot = pathManager.getAndroidSdkRoot();
unzip(platformZipPath, pathManager.getPlatformFolderInAndroidSdk());
new File(pathManager.getPlatformFolderInAndroidSdk() + "/android-4.4.2").renameTo(new File(pathManager.getPlatformFolderInAndroidSdk() + "/android-" + ANDROID_VERSION));
unzip(armImage, androidSdkRoot + "/system-images/android-" + ANDROID_VERSION + "/default/");
unzip(x86Image, androidSdkRoot + "/system-images/android-" + ANDROID_VERSION + "/default/");
unzip(platformToolsZipPath, androidSdkRoot);
unzip(skdToolsZipPath, androidSdkRoot);
unzip(gradleZipPath, pathManager.getDependenciesRoot());
//BUILD TOOLS
String buildTools = androidSdkRoot + "/build-tools/";
unzip(buildToolsZipPath, buildTools);
unzip(emulatorZipPath, androidSdkRoot);
}
public void deleteAll() {
delete(platformZipPath);
delete(platformToolsZipPath);
delete(skdToolsZipPath);
delete(buildToolsZipPath);
delete(armImage);
delete(x86Image);
delete(gradleZipPath);
}
private static void download(String urlString, String output) {
System.out.println("Start downloading: " + urlString + " to " + output);
OutputStream outStream = null;
URLConnection urlConnection;
InputStream is;
try {
URL Url;
byte[] buf;
int read;
//int written = 0;
Url = new URL(urlString);
File outputFile = new File(output);
outputFile.getParentFile().mkdirs();
if (outputFile.exists()) {
System.out.println("File was already downloaded: " + output);
return;
}
outputFile.createNewFile();
FileOutputStream outputStream = new FileOutputStream(outputFile);
outStream = new BufferedOutputStream(outputStream);
urlConnection = Url.openConnection();
is = urlConnection.getInputStream();
buf = new byte[1024];
while ((read = is.read(buf)) != -1) {
outStream.write(buf, 0, read);
//written += read;
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
RunUtils.close(outStream);
}
System.out.println("Finish downloading: " + urlString + " to " + output);
}
protected void unzip(String pathToFile, String outputFolder) {
System.out.println("Start unzipping: " + pathToFile + " to " + outputFolder);
String pathToUnzip;
if (outputFolder.equals(pathManager.getPlatformFolderInAndroidSdk())) {
pathToUnzip = outputFolder;
}
else {
pathToUnzip = outputFolder + "/" + FileUtil.getNameWithoutExtension(new File(pathToFile));
}
if (new File(pathToUnzip).listFiles() != null) {
System.out.println("File was already unzipped: " + pathToFile);
return;
}
try {
byte[] buf = new byte[1024];
ZipEntry zipEntry = null;
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(pathToFile))) {
zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String entryName = zipEntry.getName();
int n;
File outputFile = new File(outputFolder + "/" + entryName);
if (zipEntry.isDirectory()) {
outputFile.mkdirs();
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
continue;
}
else {
File parentFile = outputFile.getParentFile();
if (parentFile != null && !parentFile.exists()) {
parentFile.mkdirs();
}
outputFile.createNewFile();
}
try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
while ((n = zipInputStream.read(buf, 0, 1024)) > -1) {
fileOutputStream.write(buf, 0, n);
}
}
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
}
}
catch (IOException e) {
if (zipEntry != null) {
System.err.println("Entry name: " + zipEntry.getName());
}
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finish unzipping: " + pathToFile + " to " + outputFolder);
}
private static void delete(String filePath) {
new File(filePath).delete();
}
}

View File

@@ -48,8 +48,8 @@ public class Emulator {
private GeneralCommandLine getCreateCommand() {
GeneralCommandLine commandLine = new GeneralCommandLine();
String androidCmdName = SystemInfo.isWindows ? "avdmanager.bat" : "avdmanager";
commandLine.setExePath(pathManager.getToolsFolderInAndroidSdk() + "/bin/" + androidCmdName);
String androidCmdName = SystemInfo.isWindows ? "android.bat" : "android";
commandLine.setExePath(pathManager.getToolsFolderInAndroidSdk() + "/" + androidCmdName);
commandLine.addParameter("create");
commandLine.addParameter("avd");
commandLine.addParameter("--force");

View File

@@ -31,8 +31,8 @@ public class GradleRunner {
public GradleRunner(PathManager pathManager) {
listOfCommands = new ArrayList<>();
String cmdName = SystemInfo.isWindows ? "gradlew.bat" : "gradlew";
listOfCommands.add(pathManager.getTmpFolder() + "/" + cmdName);
String cmdName = SystemInfo.isWindows ? "gradle.bat" : "gradle";
listOfCommands.add(pathManager.getGradleBinFolder() + "/" + cmdName);
listOfCommands.add("--no-daemon");
listOfCommands.add("--build-file");
listOfCommands.add(pathManager.getTmpFolder() + "/build.gradle");

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.android.tests.run;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.kotlin.android.tests.PathManager;
import org.jetbrains.kotlin.android.tests.download.SDKDownloader;
import java.io.File;
public class PermissionManager {
private PermissionManager() {
}
public static void setPermissions(PathManager pathManager) {
if (!SystemInfo.isWindows) {
setExecPermissionForSimpleNamedFiles(new File(pathManager.getToolsFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getBuildToolsFolderInAndroidSdk() + "/" + SDKDownloader.BUILD_TOOLS));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getPlatformToolsFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getToolsFolderInAndroidSdk() +"/bin"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/bin"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/bin64"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/qemu/linux-x86_64"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getAndroidSdkRoot() + "/system-images/android-19/default/armeabi-v7a/"));
RunUtils.execute(generateChmodCmd(pathManager.getGradleBinFolder() + "/gradle"));
}
}
private static void setExecPermissionForSimpleNamedFiles(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile() && !file.getName().contains(".")) {
RunUtils.execute(generateChmodCmd(file.getAbsolutePath()));
}
}
}
}
private static GeneralCommandLine generateChmodCmd(String path) {
GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath("chmod");
commandLine.addParameter("a+x");
commandLine.addParameter(path);
return commandLine;
}
}

View File

@@ -41,7 +41,7 @@ public class AndroidJpsBuildTestCase extends BaseKotlinJpsBuildTestCase {
}
@Override
protected void runTest() {
protected void runTest() throws Throwable {
doTest();
}

View File

@@ -17,10 +17,10 @@
package org.jetbrains.kotlin.android.tests
import com.intellij.openapi.util.Ref
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.test.KotlinBaseTest
import java.io.File
import java.util.regex.Pattern
@@ -34,7 +34,7 @@ private data class OldPackageAndNew(val oldFqName: FqName, val newFqName: FqName
internal fun patchFilesAndAddTest(
testFile: File,
testFiles: List<KotlinBaseTest.TestFile>,
testFiles: List<CodegenTestCase.TestFile>,
filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter
): FqName? {
if (testFiles.any { it.name.endsWith(".java") }) {
@@ -46,21 +46,18 @@ internal fun patchFilesAndAddTest(
val newPackagePrefix = testFile.path.replace("\\\\|-|\\.|/".toRegex(), "_")
val oldPackage = Ref<FqName>()
val isJvmName = Ref<Boolean>(false)
val isSingle = testFiles.size == 1
val resultFiles = testFiles.map {
val fileName = if (isSingle) it.name else testFile.name.substringBeforeLast(".kt") + "/" + it.name
TestClassInfo(
fileName,
changePackage(newPackagePrefix, it.content, oldPackage, isJvmName),
changePackage(newPackagePrefix, it.content, oldPackage),
oldPackage.get(),
isJvmName.get(),
getGeneratedClassName(File(fileName), it.content, newPackagePrefix, oldPackage.get())
)
}
val packages =
resultFiles.map { OldPackageAndNew(it.oldPackage, it.newPackagePartClassId.parent()) }
.sortedByDescending { it.oldFqName.asString().length }
resultFiles.map { OldPackageAndNew(it.oldPackage, it.newClassId.parent()) }.sortedByDescending { it.oldFqName.asString().length }
//If files contain any val or var declaration with same name as any package name
// then use old conservative renaming scheme, otherwise use aggressive one
@@ -97,7 +94,7 @@ internal fun patchFilesAndAddTest(
/*replace all Class.forName*/
resultFiles.forEach { file ->
file.content = resultFiles.fold(file.content) { r, param ->
patchClassForName(param.newPackagePartClassId, param.oldPackage, r, conservativeRenameScheme)
patchClassForName(param.newClassId, param.oldPackage, r, conservativeRenameScheme)
}
}
@@ -106,13 +103,6 @@ internal fun patchFilesAndAddTest(
file.content = file.content.patchSelfImports(file.newPackage)
}
//patch root package parts usages in strings
resultFiles.forEach { file ->
file.content = resultFiles.fold(file.content) { r, param ->
patchRootPartNamesInStrings(param.newPackagePartClassId, param.oldPackage, param.isJvmName, r)
}
}
val boxFiles = resultFiles.filter { hasBoxMethod(it.content) }
if (boxFiles.size != 1) {
println("Several box methods in $testFile")
@@ -120,22 +110,22 @@ internal fun patchFilesAndAddTest(
filesHolder.addTest(
resultFiles.filter { resultFile -> resultFile.name.endsWith(".kt") || resultFile.name.endsWith(".kts") },
TestInfo("", boxFiles.last().newPackagePartClassId, testFile)
TestInfo("", boxFiles.last().newClassId, testFile)
)
return boxFiles.last().newPackagePartClassId
return boxFiles.last().newClassId
}
private fun hasBoxMethod(text: String): Boolean {
return text.contains("fun box()")
}
class TestClassInfo(val name: String, var content: String, val oldPackage: FqName, val isJvmName: Boolean, val newPackagePartClassId: FqName) {
val newPackage = newPackagePartClassId.parent()
class TestClassInfo(val name: String, var content: String, val oldPackage: FqName, val newClassId: FqName) {
val newPackage = newClassId.parent()
}
private fun changePackage(newPackagePrefix: String, text: String, oldPackage: Ref<FqName>, isJvmName: Ref<Boolean>): String {
private fun changePackage(newPackagePrefix: String, text: String, oldPackage: Ref<FqName>): String {
val matcher = packagePattern.matcher(text)
if (matcher.find()) {
val oldPackageName = matcher.toMatchResult().group(1)
@@ -147,7 +137,6 @@ private fun changePackage(newPackagePrefix: String, text: String, oldPackage: Re
if (text.contains("@file:")) {
val index = text.lastIndexOf("@file:")
val packageDirectiveIndex = text.indexOf("\n", index)
isJvmName.set(true)
return text.substring(0, packageDirectiveIndex + 1) + packageDirective + text.substring(packageDirectiveIndex + 1)
} else {
return packageDirective + text
@@ -180,19 +169,6 @@ private fun patchClassForName(className: FqName, oldPackage: FqName, text: Strin
)
}
private fun patchRootPartNamesInStrings(
className: FqName,
oldPackage: FqName,
isJvmName: Boolean,
text: String
): String {
if (!oldPackage.isRoot || isJvmName) return text
return text.replace(
("\"" + oldPackage.child(className.shortName()).asString()).toRegex(),
"\"" + className.asString()
)
}
private fun patchPackages(newPackage: FqName, oldPackage: FqName, text: String): String {
if (oldPackage.isRoot) return text

View File

@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.android.tests
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.kotlin.cli.common.output.writeAllTo
@@ -19,100 +17,50 @@ import org.jetbrains.kotlin.codegen.GenerationUtils
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.*
import org.junit.Assert
import org.junit.Ignore
import java.io.File
import java.io.FileWriter
import java.io.IOException
import kotlin.test.assertTrue
data class ConfigurationKey(val kind: ConfigurationKind, val jdkKind: TestJdkKind, val configuration: String)
class CodegenTestsOnAndroidGenerator private constructor(private val pathManager: PathManager) {
@Ignore
class CodegenTestsOnAndroidGenerator private constructor(private val pathManager: PathManager) : CodegenTestCase() {
private var writtenFilesCount = 0
private var currentModuleIndex = 1
private val pathFilter: String? = System.getProperties().getProperty("kotlin.test.android.path.filter")
private val pendingUnitTestGenerators = hashMapOf<String, UnitTestFileWriter>()
private val pendingUnitTestGenerators = hashMapOf<Int, UnitTestFileWriter>()
//keep it globally to avoid test grouping on TC
private val generatedTestNames = hashSetOf<String>()
private val COMMON = FlavorConfig("common", 3);
private val REFLECT = FlavorConfig("reflect", 1);
private val JVM8 = FlavorConfig("jvm8", 1);
private val JVM8REFLECT = FlavorConfig("reflectjvm8", 1);
class FlavorConfig(private val prefix: String, val limit: Int) {
private var writtenFilesCount = 0
fun printStatistics() {
println("FlavorTestCompiler: $prefix, generated file count: $writtenFilesCount")
}
fun getFlavorForNewFiles(newFilesCount: Int): String {
writtenFilesCount += newFilesCount
//2500 files per folder that would be used by flavor to avoid multidex usage,
// each folder would be jared by build.gradle script
val index = writtenFilesCount / 2500
return getFlavorName(index, prefix).also {
assertTrue("Please Add new flavor in build.gradle for $it") { index < limit }
}
}
private fun getFlavorName(index: Int, prefix: String): String {
return prefix + index
}
fun getFlavorUnitTestFilePath(index: Int): String {
return pathManager.srcFolderInAndroidTmpFolder + "/androidTestKtest$index/java/" + testClassPackage.replace(
".",
"/"
) + "/" + testClassName + "$index.java"
}
private fun prepareAndroidModuleAndGenerateTests(skipSdkDirWriting: Boolean) {
prepareAndroidModule(skipSdkDirWriting)
private fun prepareAndroidModuleAndGenerateTests() {
prepareAndroidModule()
generateTestsAndFlavourSuites()
}
private fun prepareAndroidModule(skipSdkDirWriting: Boolean) {
private fun prepareAndroidModule() {
FileUtil.copyDir(File(pathManager.androidModuleRoot), File(pathManager.tmpFolder))
if (!skipSdkDirWriting) {
writeAndroidSkdToLocalProperties(pathManager)
}
writeAndroidSkdToLocalProperties(pathManager)
println("Copying kotlin-stdlib.jar and kotlin-reflect.jar in android module...")
copyKotlinRuntimeJars()
copyGradleWrapperAndPatch()
}
private fun copyGradleWrapperAndPatch() {
val projectRoot = File(pathManager.tmpFolder)
val target = File(projectRoot, "gradle/wrapper")
File("./gradle/wrapper/").copyRecursively(target)
val gradlew = File(projectRoot, "gradlew")
File("./gradlew").copyTo(gradlew).also {
if (!SystemInfo.isWindows) {
it.setExecutable(true)
}
}
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
}.let { lines ->
FileWriter(file).use { fw ->
lines.forEach { line ->
fw.write("$line\n")
}
}
}
}
private fun copyKotlinRuntimeJars() {
FileUtil.copy(
ForTestCompileRuntime.runtimeJarForTests(),
@@ -148,15 +96,9 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
holders.values.forEach {
it.writeFilesOnDisk()
}
COMMON.printStatistics()
REFLECT.printStatistics()
JVM8.printStatistics()
JVM8REFLECT.printStatistics()
}
internal inner class FilesWriter(
private val flavorConfig: FlavorConfig,
private val configuration: CompilerConfiguration
) {
private val rawFiles = arrayListOf<TestClassInfo>()
@@ -171,40 +113,38 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}
fun writeFilesOnDisk() {
val disposable = Disposer.newDisposable()
val disposable = TestDisposable()
val environment = KotlinCoreEnvironment.createForTests(
disposable,
configuration.copy().apply { put(CommonConfigurationKeys.MODULE_NAME, "android-module-" + currentModuleIndex++) },
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
try {
writeFiles(
rawFiles.map {
try {
CodegenTestFiles.create(it.name, it.content, environment.project).psiFile
} catch (e: Throwable) {
throw RuntimeException("Error on processing ${it.name}:\n${it.content}", e)
}
}, environment, unitTestDescriptions
)
} finally {
rawFiles.clear()
unitTestDescriptions.clear()
Disposer.dispose(disposable)
}
writeFiles(
rawFiles.map {
try {
CodegenTestFiles.create(it.name, it.content, environment.project).psiFile
} catch (e: Throwable) {
throw RuntimeException("Error on processing ${it.name}:\n${it.content}", e)
}
}, environment
)
Disposer.dispose(disposable)
rawFiles.clear()
unitTestDescriptions.clear()
}
private fun writeFiles(
filesToCompile: List<KtFile>,
environment: KotlinCoreEnvironment,
unitTestDescriptions: ArrayList<TestInfo>
) {
private fun writeFiles(filesToCompile: List<KtFile>, environment: KotlinCoreEnvironment) {
if (filesToCompile.isEmpty()) return
val flavorName = flavorConfig.getFlavorForNewFiles(filesToCompile.size)
//3000 files per folder that would be used by flavor to avoid multidex usage,
// each folder would be jared by build.gradle script
writtenFilesCount += filesToCompile.size
val index = writtenFilesCount / 3000
val outputDir = File(pathManager.getOutputForCompiledFiles(index))
assertTrue("Add flavors for ktest$index", index < 2)
val outputDir = File(pathManager.getOutputForCompiledFiles(flavorName))
println("Generating ${filesToCompile.size} files into ${outputDir.name}, configuration: '${environment.configuration}'...")
val outputFiles = GenerationUtils.compileFiles(filesToCompile, environment).run { destroy(); factory }
@@ -213,10 +153,10 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
outputDir.mkdirs()
}
Assert.assertTrue("Cannot create directory for compiled files", outputDir.exists())
val unitTestFileWriter = pendingUnitTestGenerators.getOrPut(flavorName) {
val unitTestFileWriter = pendingUnitTestGenerators.getOrPut(index) {
UnitTestFileWriter(
getFlavorUnitTestFolder(flavorName),
flavorName,
getFlavorUnitTestFilePath(index),
index,
generatedTestNames
)
}
@@ -224,12 +164,6 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
outputFiles.writeAllTo(outputDir)
}
private fun getFlavorUnitTestFolder(flavourName: String): String {
return pathManager.srcFolderInAndroidTmpFolder +
"/androidTest${flavourName.capitalize()}/java/" +
testClassPackage.replace(".", "/") + "/"
}
fun addTest(testFiles: List<TestClassInfo>, info: TestInfo) {
rawFiles.addAll(testFiles)
unitTestDescriptions.add(info)
@@ -246,6 +180,9 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}
for (file in files) {
if (SpecialFiles.getExcludedFiles().contains(file.name)) {
continue
}
if (file.isDirectory) {
val listFiles = file.listFiles()
if (listFiles != null) {
@@ -258,9 +195,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
continue
}
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file) ||
InTextDirectivesUtils.isIgnoredTarget(TargetBackend.ANDROID, file)
) {
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file)) {
continue
}
@@ -276,32 +211,23 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
if (fullFileText.contains("@file:JvmPackageName(")) continue
// TODO: Support jvm assertions
if (fullFileText.contains("// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm")) continue
val targets = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fullFileText, "// JVM_TARGET:")
.also { it.remove(JvmTarget.JVM_1_6.description) }
val isJvm8Target =
if (targets.isEmpty()) false
else if (targets.contains(JvmTarget.JVM_1_8.description) && targets.size == 1) true
else continue //TODO: support other targets on Android
// TODO: support JVM 8 test with D8
if (fullFileText.contains("// JVM_TARGET")) continue
// TODO: support SKIP_JDK6 on new platforms
if (fullFileText.contains("// SKIP_JDK6")) continue
if (hasBoxMethod(fullFileText)) {
val testFiles = createTestFiles(file, fullFileText)
val kind = KotlinBaseTest.extractConfigurationKind(testFiles)
val jdkKind = KotlinBaseTest.getTestJdkKind(testFiles)
val kind = extractConfigurationKind(testFiles)
val jdkKind = getJdkKind(testFiles)
val keyConfiguration = CompilerConfiguration()
CodegenTestCase.updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
val key = ConfigurationKey(kind, jdkKind, keyConfiguration.toString())
val compiler = if (isJvm8Target) {
if (kind.withReflection) JVM8REFLECT else JVM8
} else if (kind.withReflection) REFLECT else COMMON
val filesHolder = holders.getOrPut(key) {
FilesWriter(compiler, KotlinTestUtils.newConfiguration(kind, jdkKind, KotlinTestUtils.getAnnotationsJar()).apply {
FilesWriter(KotlinTestUtils.newConfiguration(kind, jdkKind, KotlinTestUtils.getAnnotationsJar()).apply {
println("Creating new configuration by $key")
CodegenTestCase.updateConfigurationByDirectivesInTestFiles(testFiles, this)
updateConfigurationByDirectivesInTestFiles(testFiles, this)
})
}
@@ -311,11 +237,19 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}
}
private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> =
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM)
private fun createTestFiles(file: File, expectedText: String): List<TestFile> =
TestFiles.createTestFiles(
file.name,
expectedText,
object : TestFiles.TestFileFactoryNoModules<TestFile>() {
override fun create(fileName: String, text: String, directives: Map<String, String>): TestFile {
return TestFile(fileName, text)
}
}, false,
"kotlin.coroutines"
)
companion object {
const val GRADLE_VERSION = "5.6.4"
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
const val testClassName = "CodegenTestCaseOnAndroid"
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
@@ -323,11 +257,10 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
const val generatorName = "CodegenTestsOnAndroidGenerator"
@JvmOverloads
@JvmStatic
@Throws(Throwable::class)
fun generate(pathManager: PathManager, skipSdkDirWriting: Boolean = false) {
CodegenTestsOnAndroidGenerator(pathManager).prepareAndroidModuleAndGenerateTests(skipSdkDirWriting)
fun generate(pathManager: PathManager) {
CodegenTestsOnAndroidGenerator(pathManager).prepareAndroidModuleAndGenerateTests()
}
private fun hasBoxMethod(text: String): Boolean {
@@ -336,7 +269,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
@Throws(IOException::class)
internal fun writeAndroidSkdToLocalProperties(pathManager: PathManager) {
val sdkRoot = KotlinTestUtils.getAndroidSdkSystemIndependentPath()
val sdkRoot = File(pathManager.androidSdkRoot).invariantSeparatorsPath
println("Writing android sdk to local.properties: $sdkRoot")
val file = File(pathManager.tmpFolder + "/local.properties")
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
@@ -348,8 +281,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
println("Created temporary folder for android tests: " + tmpFolder.absolutePath)
val rootFolder = File("")
val pathManager = PathManager(rootFolder.absolutePath, tmpFolder.absolutePath)
generate(pathManager, true)
println("Android test project is generated into " + tmpFolder.absolutePath + " folder")
generate(pathManager)
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.android.tests;
import java.util.HashSet;
import java.util.Set;
public class SpecialFiles {
private static final Set<String> excludedFiles = new HashSet<>();
static {
fillExcludedFiles();
}
public static Set<String> getExcludedFiles() {
return excludedFiles;
}
private static void fillExcludedFiles() {
// Reflection
excludedFiles.add("enclosing");
excludedFiles.add("kt10259.kt");
excludedFiles.add("simpleClassLiteral.kt");
//UnsatisfiedLinkError
excludedFiles.add("nativePropertyAccessors.kt");
excludedFiles.add("topLevel.kt");
//Test with no reflection at runtime
excludedFiles.add("noReflectAtRuntime");
excludedFiles.add("noReflect");
excludedFiles.add("functionNtoStringNoReflect.kt");
excludedFiles.add("getDelegateWithoutReflection.kt");
// "IOOBE: Invalid index 4, size is 4" for java.lang.reflect.ParameterizedType on Android
excludedFiles.add("innerGenericTypeArgument.kt");
// Cannot change package name
excludedFiles.add("kt6990.kt");
excludedFiles.add("typeParameters.kt");
excludedFiles.add("kt13133.kt");
// StackOverflow with StringBuilder (escape())
excludedFiles.add("kt684.kt");
// Wrong enclosing info or signature after package renaming
excludedFiles.add("enclosingInfo");
excludedFiles.add("signature");
// Some classes are not visible on android
excludedFiles.add("classpath.kt");
// Out of memory
excludedFiles.add("manyNumbers.kt");
// Native methods
excludedFiles.add("external");
// Additional nested class in 'Thread' class on Android
excludedFiles.add("nestedClasses.kt");
// KT-8120
excludedFiles.add("closureOfInnerLocalClass.kt");
excludedFiles.add("closureWithSelfInstantiation.kt");
excludedFiles.add("quotedClassName.kt");
//wrong function resolution after package renaming
excludedFiles.add("apiVersionAtLeast1.kt");
//special symbols in names
excludedFiles.add("nameWithWhitespace.kt");
}
private SpecialFiles() {
}
}

View File

@@ -15,11 +15,7 @@ import java.io.FileWriter
class TestInfo(val name: String, val fqName: FqName, val file: File)
class UnitTestFileWriter(
private val flavourFolder: String,
private val flavourName: String,
private val generatedTestNames: MutableSet<String>
) {
class UnitTestFileWriter(private val fileName: String, private val index: Int, private val generatedTestNames: MutableSet<String>) {
private val infos = arrayListOf<TestInfo>()
fun addTests(info: List<TestInfo>) {
@@ -27,7 +23,7 @@ class UnitTestFileWriter(
}
fun generate() {
FileWriter(File(flavourFolder, flavourName.capitalize() + ".java").also { it.parentFile.mkdirs() }).use { suite ->
FileWriter(File(fileName).also { it.parentFile.mkdirs() }).use { suite ->
val p = Printer(suite)
p.println(
"""package ${CodegenTestsOnAndroidGenerator.testClassPackage};
@@ -35,7 +31,7 @@ class UnitTestFileWriter(
|import ${CodegenTestsOnAndroidGenerator.baseTestClassPackage}.${CodegenTestsOnAndroidGenerator.baseTestClassName};
|
|/* This class is generated by ${CodegenTestsOnAndroidGenerator.generatorName}. DO NOT MODIFY MANUALLY */
|public class ${flavourName.capitalize()} extends ${CodegenTestsOnAndroidGenerator.baseTestClassName} {
|public class ${CodegenTestsOnAndroidGenerator.testClassName}$index extends ${CodegenTestsOnAndroidGenerator.baseTestClassName} {
|
""".trimMargin()
)

View File

@@ -8,6 +8,7 @@ dependencies {
compile(project(":core:descriptors"))
compile(project(":compiler:util"))
compile(project(":compiler:frontend"))
compile(project(":compiler:ir.tree"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
}

View File

@@ -18,16 +18,15 @@ package org.jetbrains.kotlin.backend.common.bridges
import org.jetbrains.kotlin.utils.DFS
import java.util.*
import kotlin.collections.LinkedHashMap
interface FunctionHandle {
val isDeclaration: Boolean
val isAbstract: Boolean
/** On finding concrete super declaration we should distinguish non-abstract java8/js default methods from
* class ones (see [findConcreteSuperDeclaration] method in bridges.kt).
* Note that interface methods with body compiled to jvm 8 target are assumed to be non-abstract in bridges method calculation
* (more details in [DescriptorBasedFunctionHandle.isBodyOwner] comment).*/
* class ones (see [findConcreteSuperDeclaration] method in bridges.kt).
* Note that interface methods with body compiled to jvm 8 target are assumed to be non-abstract in bridges method calculation
* (more details in [DescriptorBasedFunctionHandle.isBodyOwner] comment).*/
val mayBeUsedAsSuperImplementation: Boolean
fun getOverridden(): Iterable<FunctionHandle>
@@ -35,19 +34,18 @@ interface FunctionHandle {
val mightBeIncorrectCode: Boolean get() = false
}
data class Bridge<out Signature, out Function : FunctionHandle>(
val from: Signature,
val to: Signature,
val originalFunctions: Set<Function>
data class Bridge<out Signature>(
val from: Signature,
val to: Signature
) {
override fun toString() = "$from -> $to"
}
fun <Function : FunctionHandle, Signature> generateBridges(
function: Function,
signature: (Function) -> Signature
): Set<Bridge<Signature, Function>> {
function: Function,
signature: (Function) -> Signature
): Set<Bridge<Signature>> {
// If it's an abstract function, no bridges are needed: when an implementation will appear in some concrete subclass, all necessary
// bridges will be generated there
if (function.isAbstract) return setOf()
@@ -60,7 +58,7 @@ fun <Function : FunctionHandle, Signature> generateBridges(
val implementation = findConcreteSuperDeclaration(function) ?: return setOf()
val bridgesToGenerate = findAllReachableDeclarations(function).groupByTo(LinkedHashMap(), signature)
val bridgesToGenerate = findAllReachableDeclarations(function).mapTo(LinkedHashSet<Signature>(), signature)
if (fake) {
// If it's a concrete fake override, some of the bridges may be inherited from the super-classes. Specifically, bridges for all
@@ -69,20 +67,14 @@ fun <Function : FunctionHandle, Signature> generateBridges(
@Suppress("UNCHECKED_CAST")
for (overridden in function.getOverridden() as Iterable<Function>) {
if (!overridden.isAbstract) {
for (reachable in findAllReachableDeclarations(overridden)) {
bridgesToGenerate.remove(signature(reachable))
}
bridgesToGenerate.removeAll(findAllReachableDeclarations(overridden).map(signature))
}
}
}
val method = signature(implementation)
bridgesToGenerate.remove(method)
return bridgesToGenerate.entries
.map { (overriddenSignature, overriddenFunctions) ->
Bridge(overriddenSignature, method, overriddenFunctions.toSet())
}
.toSet()
return bridgesToGenerate.map { Bridge(it, method) }.toSet()
}
fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function): MutableSet<Function> {
@@ -103,7 +95,7 @@ fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function)
* The implementation is guaranteed to exist because if it wouldn't, the given function would've been abstract
*/
fun <Function : FunctionHandle> findConcreteSuperDeclaration(function: Function): Function? {
require(!function.isAbstract) { "Only concrete functions have implementations: $function" }
require(!function.isAbstract, { "Only concrete functions have implementations: $function" })
if (function.isDeclaration) return function

View File

@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor,
signature: (FunctionDescriptor) -> Signature
): Set<Bridge<Signature, DescriptorBasedFunctionHandle>> {
): Set<Bridge<Signature>> {
return generateBridges(DescriptorBasedFunctionHandle(descriptor), { signature(it.descriptor) })
}

View File

@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
@@ -39,6 +38,8 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
private final List<FileMapping> fileMappings = new ArrayList<>();
private String sourceName;
private String debugInfo;
@@ -105,7 +106,15 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
@Override
public void done() {
getVisitor().visitSource(sourceName, debugInfo);
if (!fileMappings.isEmpty() && GENERATE_SMAP) {
FileMapping origin = fileMappings.get(0);
assert sourceName == null || origin.getName().equals(sourceName) : "Error " + origin.getName() + " != " + sourceName;
getVisitor().visitSource(origin.getName(), new SMAPBuilder(origin.getName(), origin.getPath(), fileMappings).build());
}
else {
getVisitor().visitSource(sourceName, debugInfo);
}
getVisitor().visitEnd();
}
@@ -125,21 +134,10 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
@Override
public void visitSource(@NotNull String name, @Nullable String debug) {
assert sourceName == null || sourceName.equals(name) : "inconsistent file name: " + sourceName + " vs " + name;
sourceName = name;
debugInfo = debug;
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
if (!GENERATE_SMAP) return;
List<FileMapping> fileMappings = smap.getResultMappings();
if (fileMappings.isEmpty()) return;
visitSource(fileMappings.get(0).getName(), SMAPBuilder.INSTANCE.build(fileMappings, backwardsCompatibleSyntax));
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getVisitor().visitOuterClass(owner, name, desc);
@@ -156,4 +154,9 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
assert thisName != null : "This name isn't set";
return thisName;
}
@Override
public void addSMAP(FileMapping mapping) {
fileMappings.add(mapping);
}
}

View File

@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.types.FlexibleType;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext;
import org.jetbrains.org.objectweb.asm.*;
import java.lang.annotation.*;
@@ -676,9 +675,9 @@ public abstract class AnnotationCodegen {
return;
}
Iterable<TypePathInfo<AnnotationDescriptor>> infos =
new PsiTypeAnnotationCollector().collectTypeAnnotations(type);
for (TypePathInfo<AnnotationDescriptor> info : infos) {
Iterable<TypePathInfo> infos =
new TypeAnnotationCollector().collectTypeAnnotations(type, TypeReference.METHOD_FORMAL_PARAMETER);
for (TypePathInfo info : infos) {
for (AnnotationDescriptor annotationDescriptor : info.getAnnotations()) {
genAnnotation(annotationDescriptor, info.getPath(), true);
}

View File

@@ -22,7 +22,10 @@ import org.jetbrains.kotlin.codegen.intrinsics.HashCode;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.config.ApiVersion;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -43,7 +46,6 @@ import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.*;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
@@ -67,6 +69,7 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineWithReified;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -306,10 +309,9 @@ public class AsmUtil {
return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes));
}
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind, JvmDefaultMode jvmDefaultMode) {
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
return (functionDescriptor.getModality() == Modality.ABSTRACT ||
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !JvmAnnotationUtilKt
.isCompiledToJvmDefault(functionDescriptor, jvmDefaultMode)))
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor)))
&& !isStaticMethod(kind, functionDescriptor);
}
@@ -324,15 +326,10 @@ public class AsmUtil {
}
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind, GenerationState state) {
return getMethodAsmFlags(functionDescriptor, kind, state.getDeprecationProvider(), state.getJvmDefaultMode());
return getMethodAsmFlags(functionDescriptor, kind, state.getDeprecationProvider());
}
public static int getMethodAsmFlags(
FunctionDescriptor functionDescriptor,
OwnerKind kind,
DeprecationResolver deprecationResolver,
JvmDefaultMode jvmDefaultMode
) {
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind, DeprecationResolver deprecationResolver) {
int flags = getCommonCallableFlags(functionDescriptor, kind, deprecationResolver);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.METHOD_FLAGS) {
@@ -360,7 +357,7 @@ public class AsmUtil {
flags |= ACC_STATIC;
}
if (isAbstractMethod(functionDescriptor, kind, jvmDefaultMode)) {
if (isAbstractMethod(functionDescriptor, kind)) {
flags |= ACC_ABSTRACT;
}
@@ -1026,7 +1023,9 @@ public class AsmUtil {
}
value.put(asmType, v);
v.visitLdcInsn(name);
String methodName = state.getUnifiedNullChecks() ? "checkNotNullParameter" : "checkParameterIsNotNull";
String methodName = state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0
? "checkNotNullParameter"
: "checkParameterIsNotNull";
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false);
}
}
@@ -1049,7 +1048,9 @@ public class AsmUtil {
if (innerType.getSort() == Type.OBJECT || innerType.getSort() == Type.ARRAY) {
v.dup();
v.visitLdcInsn(runtimeAssertionInfo.getMessage());
String methodName = state.getUnifiedNullChecks() ? "checkNotNullExpressionValue" : "checkExpressionValueIsNotNull";
String methodName = state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0
? "checkNotNullExpressionValue"
: "checkExpressionValueIsNotNull";
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false);
}
StackValue.coerce(innerType, innerKotlinType, type, kotlinType, v);
@@ -1080,23 +1081,27 @@ public class AsmUtil {
}
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
v.visitInsn(defaultValueOpcode(type));
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
v.aconst(null);
}
else {
pushDefaultPrimitiveValueOnStack(type, v);
}
}
public static int defaultValueOpcode(@NotNull Type type) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return ACONST_NULL;
}
public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
if (type.getSort() == Type.FLOAT) {
return FCONST_0;
v.fconst(0);
}
if (type.getSort() == Type.DOUBLE) {
return DCONST_0;
else if (type.getSort() == Type.DOUBLE) {
v.dconst(0);
}
if (type.getSort() == Type.LONG) {
return LCONST_0;
else if (type.getSort() == Type.LONG) {
v.lconst(0);
}
else {
v.iconst(0);
}
return ICONST_0;
}
public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) {

View File

@@ -6,8 +6,6 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.coroutines.createCustomCopy
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.config.JVMAssertionsMode
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
@@ -21,15 +19,12 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
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.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
const val ASSERTIONS_DISABLED_FIELD_NAME = "\$assertionsDisabled"
@@ -135,7 +130,7 @@ private fun inlineAlwaysInlineAssert(resolvedCall: ResolvedCall<*>, codegen: Exp
)
}
fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, clInitBuilder: MethodVisitor, className: String) {
fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, clInitBuilder: MethodVisitor) {
classBuilder.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC, ASSERTIONS_DISABLED_FIELD_NAME,
"Z", null, null
@@ -144,7 +139,7 @@ fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, cl
val elseLabel = Label()
with(InstructionAdapter(clInitBuilder)) {
mark(Label())
aconst(Type.getObjectType(className))
aconst(Type.getObjectType(classBuilder.thisName))
invokevirtual("java/lang/Class", "desiredAssertionStatus", "()Z", false)
ifne(thenLabel)
iconst(1)
@@ -158,16 +153,6 @@ fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, cl
}
}
fun rewriteAssertionsDisabledFieldInitialization(methodNode: MethodNode, className: String) {
InsnSequence(methodNode.instructions).firstOrNull {
it is FieldInsnNode && it.opcode == Opcodes.PUTSTATIC && it.name == ASSERTIONS_DISABLED_FIELD_NAME
}?.findPreviousOrNull {
it is MethodInsnNode && it.opcode == Opcodes.INVOKEVIRTUAL
&& it.owner == "java/lang/Class" && it.name == "desiredAssertionStatus" && it.desc == "()Z"
}?.previous?.safeAs<LdcInsnNode>()?.cst =
Type.getObjectType(className)
}
private fun <D : FunctionDescriptor> ResolvedCall<D>.replaceAssertWithAssertInner(): ResolvedCall<D> {
val newCandidateDescriptor = resultingDescriptor.createCustomCopy {
setName(Name.identifier(ALWAYS_ENABLED_ASSERT_FUNCTION_NAME))

View File

@@ -47,7 +47,7 @@ interface BaseExpressionCodegen {
functionReferenceReceiver: StackValue?
)
fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean)
fun markLineNumberAfterInlineIfNeeded()
fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker)

View File

@@ -240,9 +240,8 @@ class ObjectCompare(
companion object {
fun getObjectCompareOpcode(opToken: IElementType): Int = when (opToken) {
// "==" and "!=" are here because enum values are compared using reference equality.
KtTokens.EQEQEQ, KtTokens.EQEQ -> IF_ACMPNE
KtTokens.EXCLEQEQEQ, KtTokens.EXCLEQ -> IF_ACMPEQ
KtTokens.EQEQEQ -> IF_ACMPNE
KtTokens.EXCLEQEQEQ -> IF_ACMPEQ
else -> throw UnsupportedOperationException("don't know how to generate this condjump")
}
}

View File

@@ -37,7 +37,7 @@ interface Callable {
fun invokeMethodWithArguments(resolvedCall: ResolvedCall<*>, receiver: StackValue, codegen: ExpressionCodegen): StackValue {
// it's important to use unsubstituted return type here to unbox value if it comes from type variable
return StackValue.functionCall(returnType, returnKotlinType ?: resolvedCall.resultingDescriptor.original.returnType) {
return StackValue.functionCall(returnType, resolvedCall.resultingDescriptor.original.returnType) {
codegen.invokeMethodWithArguments(this, resolvedCall, receiver)
}
}

View File

@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
@@ -37,6 +36,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
@@ -222,11 +222,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
FunctionDescriptor interfaceFun = entry.getKey();
//skip java 8 default methods
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) &&
!JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(
DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(interfaceFun), state.getJvmDefaultMode()
)
) {
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !hasJvmDefaultAnnotation(interfaceFun)) {
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
}
}

View File

@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
@@ -72,12 +71,12 @@ public interface ClassBuilder {
void visitSource(@NotNull String name, @Nullable String debug);
void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax);
void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc);
void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access);
@NotNull
String getThisName();
void addSMAP(FileMapping mapping);
}

View File

@@ -12,7 +12,6 @@ import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.ClosureContext;
@@ -33,11 +32,9 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.metadata.ProtoBuf;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
@@ -67,16 +64,12 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
private final SamType samType;
private final KotlinType superClassType;
private final List<KotlinType> superInterfaceTypes;
private final ResolvedCall<FunctionDescriptor> functionReferenceCall;
private final FunctionDescriptor functionReferenceTarget;
private final FunctionGenerationStrategy strategy;
protected final CalculatedClosure closure;
protected final Type asmType;
protected final int visibilityFlag;
private final boolean shouldHaveBoundReferenceReceiver;
private final boolean isLegacyFunctionReference;
private final boolean isOptimizedFunctionReference;
private final boolean isAdaptedFunctionReference;
private Method constructor;
protected Type superClassAsmType;
@@ -86,7 +79,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@NotNull KtElement element,
@Nullable SamType samType,
@NotNull ClosureContext context,
@Nullable ResolvedCall<FunctionDescriptor> functionReferenceCall,
@Nullable FunctionDescriptor functionReferenceTarget,
@NotNull FunctionGenerationStrategy strategy,
@NotNull MemberCodegen<?> parentCodegen,
@NotNull ClassBuilder classBuilder
@@ -96,8 +89,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
this.funDescriptor = context.getFunctionDescriptor();
this.classDescriptor = context.getContextDescriptor();
this.samType = samType;
this.functionReferenceCall = functionReferenceCall;
this.functionReferenceTarget = functionReferenceCall != null ? functionReferenceCall.getResultingDescriptor() : null;
this.functionReferenceTarget = functionReferenceTarget;
this.strategy = strategy;
if (samType == null) {
@@ -128,17 +120,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
this.shouldHaveBoundReferenceReceiver = CallableReferenceUtilKt.isForBoundCallableReference(closure);
ClassifierDescriptor superClassDescriptor = superClassType.getConstructor().getDeclarationDescriptor();
this.isLegacyFunctionReference =
functionReferenceTarget != null &&
superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReference();
this.isOptimizedFunctionReference =
functionReferenceTarget != null &&
superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReferenceImpl();
this.isAdaptedFunctionReference =
functionReferenceTarget != null &&
superClassDescriptor == state.getJvmRuntimeTypes().getAdaptedFunctionReference();
this.asmType = typeMapper.mapClass(classDescriptor);
visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor);
@@ -199,7 +180,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
protected void generateClosureBody() {
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), funDescriptor, strategy);
if (isLegacyFunctionReference) {
if (functionReferenceTarget != null) {
generateFunctionReferenceMethods(functionReferenceTarget);
}
@@ -249,8 +230,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
erasedInterfaceFunction.getValueParameters(), erasedInterfaceFunction.getReturnType(),
Modality.OPEN, erasedInterfaceFunction.getVisibility());
descriptorForBridges.setSuspend(descriptor.isSuspend());
DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, erasedInterfaceFunction);
codegen.generateBridges(descriptorForBridges);
}
@@ -304,7 +283,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
);
}
private void generateBridge(
protected void generateBridge(
@NotNull Method bridge,
@NotNull List<KotlinType> bridgeParameterKotlinTypes,
@Nullable KotlinType bridgeReturnType,
@@ -415,8 +394,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
}
// Returns false if null was generated.
public static boolean generateCallableReferenceDeclarationContainerClass(
public static void generateCallableReferenceDeclarationContainer(
@NotNull InstructionAdapter iv,
@NotNull CallableDescriptor descriptor,
@NotNull GenerationState state
@@ -440,20 +418,15 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
else {
iv.aconst(null);
return false;
return;
}
return true;
}
boolean isContainerPackage =
descriptor instanceof LocalVariableDescriptor
? DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class) == null
: container instanceof PackageFragmentDescriptor;
public static void generateCallableReferenceDeclarationContainer(
@NotNull InstructionAdapter iv,
@NotNull CallableDescriptor descriptor,
@NotNull GenerationState state
) {
if (!generateCallableReferenceDeclarationContainerClass(iv, descriptor, state)) return;
if (isTopLevelCallableReference(descriptor)) {
if (isContainerPackage) {
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead,
// but there's no nice API to obtain that name here yet
// TODO: write the referenced declaration's module name and use it in reflection
@@ -466,12 +439,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
}
public static boolean isTopLevelCallableReference(@NotNull CallableDescriptor descriptor) {
return descriptor instanceof LocalVariableDescriptor
? DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class) == null
: descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor;
}
@NotNull
protected Method generateConstructor() {
List<FieldInfo> args = calculateConstructorParameters(typeMapper, state.getLanguageVersionSettings(), closure, asmType);
@@ -507,41 +474,24 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
iv.load(0, superClassAsmType);
List<Type> superCtorArgTypes = new ArrayList<>();
if (superClassAsmType.equals(LAMBDA) || functionReferenceTarget != null ||
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())
) {
String superClassConstructorDescriptor;
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())) {
int arity = calculateArity();
iv.iconst(arity);
superCtorArgTypes.add(Type.INT_TYPE);
if (shouldHaveBoundReferenceReceiver) {
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(
iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType
);
superCtorArgTypes.add(OBJECT_TYPE);
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType);
superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
}
if (isOptimizedFunctionReference || isAdaptedFunctionReference) {
assert functionReferenceTarget != null : "No function reference target: " + funDescriptor;
generateCallableReferenceDeclarationContainerClass(iv, functionReferenceTarget, state);
iv.aconst(functionReferenceTarget.getName().asString());
PropertyReferenceCodegen.generateCallableReferenceSignature(iv, functionReferenceTarget, state);
int flags =
(isTopLevelCallableReference(functionReferenceTarget) ? 1 : 0) +
(calculateFunctionReferenceFlags(functionReferenceCall, funDescriptor) << 1);
iv.aconst(flags);
superCtorArgTypes.add(JAVA_CLASS_TYPE);
superCtorArgTypes.add(JAVA_STRING_TYPE);
superCtorArgTypes.add(JAVA_STRING_TYPE);
superCtorArgTypes.add(Type.INT_TYPE);
else {
superClassConstructorDescriptor = "(I)V";
}
}
else {
assert !shouldHaveBoundReferenceReceiver : "Unexpected bound reference with supertype " + superClassAsmType;
superClassConstructorDescriptor = "()V";
}
iv.invokespecial(
superClassAsmType.getInternalName(), "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, superCtorArgTypes.toArray(new Type[0])), false
);
iv.invokespecial(superClassAsmType.getInternalName(), "<init>", superClassConstructorDescriptor, false);
iv.visitInsn(RETURN);
@@ -550,37 +500,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
return constructor;
}
private static int calculateFunctionReferenceFlags(
@NotNull ResolvedCall<?> call, @NotNull FunctionDescriptor anonymousAdaptedFunction
) {
boolean hasVarargMappedToElement = false;
CallableDescriptor target = call.getResultingDescriptor();
int shift =
(call.getDispatchReceiver() instanceof TransientReceiver ? 1 : 0) +
(call.getExtensionReceiver() instanceof TransientReceiver ? 1 : 0);
for (int i = shift;
i < anonymousAdaptedFunction.getValueParameters().size() && i - shift < target.getValueParameters().size();
i++) {
ValueParameterDescriptor targetParameter = target.getValueParameters().get(i - shift);
ValueParameterDescriptor adaptedParameter = anonymousAdaptedFunction.getValueParameters().get(i);
// Vararg to element conversion is happening if the target parameter is vararg (e.g. `vararg xs: Int`),
// but the adapted parameter's type is not equal to the target parameter's type (which is `IntArray`).
if (targetParameter.getVarargElementType() != null &&
!targetParameter.getType().equals(adaptedParameter.getType())) {
hasVarargMappedToElement = true;
break;
}
}
//noinspection ConstantConditions
boolean hasCoercionToUnit = KotlinBuiltIns.isUnit(anonymousAdaptedFunction.getReturnType()) &&
!KotlinBuiltIns.isUnit(target.getReturnType());
return (hasVarargMappedToElement ? 1 : 0) +
((hasCoercionToUnit ? 1 : 0) << 1);
}
protected int calculateArity() {
int arity = funDescriptor.getValueParameters().size();
if (funDescriptor.getExtensionReceiverParameter() != null) arity++;

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDispatchReceiverParameterForConstructorCall
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtParameter
@@ -133,13 +132,10 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
val remainingParametersDeclarations =
remainingParameters.map { DescriptorToSourceUtils.descriptorToDeclaration(it) as? KtParameter }
val generateAsFinal =
functionDescriptor.modality == Modality.FINAL ||
state.languageVersionSettings.supportsFeature(LanguageFeature.GenerateJvmOverloadsAsFinal)
val flags =
baseMethodFlags or
(if (isStatic) Opcodes.ACC_STATIC else 0) or
(if (generateAsFinal && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
val signature = typeMapper.mapSignatureWithCustomParameters(functionDescriptor, contextKind, remainingParameters, false)
val mv = classBuilder.newMethod(

View File

@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
@@ -99,11 +98,6 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
getDelegate().visitSource(name, debug);
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
getDelegate().visitSMAP(smap, backwardsCompatibleSyntax);
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getDelegate().visitOuterClass(owner, name, desc);
@@ -119,4 +113,9 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
public String getThisName() {
return getDelegate().getThisName();
}
@Override
public void addSMAP(FileMapping mapping) {
getDelegate().addSMAP(mapping);
}
}

View File

@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
@@ -50,17 +49,11 @@ public class DelegationFieldsInfo {
public final Type type;
public final String name;
public final boolean generateField;
public final String genericSignature;
private Field(Type type, String name, boolean generateField, String genericSignature) {
private Field(Type type, String name, boolean generateField) {
this.type = type;
this.name = name;
this.generateField = generateField;
this.genericSignature = genericSignature;
}
private Field(Type type, String name, boolean generateField) {
this(type, name, generateField, null);
}
@NotNull
@@ -82,8 +75,8 @@ public class DelegationFieldsInfo {
new DelegationFieldsInfo.Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
}
private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name, String genericSignature) {
fields.put(specifier, new DelegationFieldsInfo.Field(type, name, true, genericSignature));
private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name) {
fields.put(specifier, new DelegationFieldsInfo.Field(type, name, true));
}
@NotNull
@@ -104,15 +97,13 @@ public class DelegationFieldsInfo {
else {
KotlinType expressionType = bindingContext.getType(expression);
ClassDescriptor superClass = JvmCodegenUtil.getSuperClass(specifier, state, bindingContext);
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
Type asmType =
expressionType != null ? typeMapper.mapType(expressionType, sw) :
superClass != null ? typeMapper.mapType(superClass.getDefaultType(), sw) : null;
expressionType != null ? typeMapper.mapType(expressionType) :
superClass != null ? typeMapper.mapType(superClass) : null;
if (asmType == null) continue;
String genericSignature = sw.makeJavaGenericSignature();
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n, genericSignature);
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n);
}
n++;
}

View File

@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenForLambda;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.coroutines.ResolvedCallWithRealDescriptor;
import org.jetbrains.kotlin.codegen.coroutines.SuspensionPointKind;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.kotlin.codegen.inline.*;
import org.jetbrains.kotlin.codegen.intrinsics.*;
@@ -52,7 +51,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor;
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor;
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
import org.jetbrains.kotlin.name.Name;
@@ -61,7 +60,6 @@ import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
@@ -678,10 +676,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
generator.checkEmptyLoop(loopExit);
v.mark(loopEntry);
resetLastLineNumber();
markStartLineNumber(generator.getForExpression());
v.nop();
generator.checkPreCondition(loopExit);
// Some forms of for-loop can be optimized as post-condition loops.
@@ -748,9 +742,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel;
return StackValue.operation(
Type.VOID_TYPE,
getNothingType(),
adapter -> {
Type.VOID_TYPE, adapter -> {
PseudoInsnsKt.fixStackAndJump(v, label);
v.mark(afterBreakContinueLabel);
return Unit.INSTANCE;
@@ -1024,7 +1016,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull FunctionDescriptor descriptor,
@NotNull FunctionGenerationStrategy strategy,
@Nullable SamType samType,
@Nullable ResolvedCall<FunctionDescriptor> functionReferenceCall,
@Nullable FunctionDescriptor functionReferenceTarget,
@Nullable StackValue functionReferenceReceiver
) {
ClassBuilder cv = state.getFactory().newVisitor(
@@ -1034,19 +1026,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
ClosureCodegen coroutineCodegen = CoroutineCodegenForLambda.create(this, descriptor, declaration, cv);
ClosureContext closureContext =
descriptor.isSuspend()
? this.context.intoCoroutineClosure(
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state),
descriptor, this, state.getTypeMapper()
)
: this.context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen =
coroutineCodegen != null
? coroutineCodegen
: new ClosureCodegen(
state, declaration, samType, closureContext, functionReferenceCall, strategy, parentCodegen, cv
);
ClosureContext closureContext = descriptor.isSuspend() ? this.context.intoCoroutineClosure(
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state),
descriptor, this, state.getTypeMapper()
) : this.context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen = coroutineCodegen != null ? coroutineCodegen : new ClosureCodegen(
state, declaration, samType, closureContext,
functionReferenceTarget, strategy, parentCodegen, cv
);
closureCodegen.generate();
@@ -1507,9 +1494,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.visitLineNumber(lineNumber, label);
}
//we should generate additional linenumber info after inline call only if it used as argument
@Override
public void markLineNumberAfterInlineIfNeeded(boolean registerLineNumberAfterwards) {
if (!shouldMarkLineNumbers || registerLineNumberAfterwards) {
public void markLineNumberAfterInlineIfNeeded() {
if (!shouldMarkLineNumbers) {
//if it used as general argument
if (myLastLineNumber > -1) {
Label label = new Label();
@@ -1517,14 +1505,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.visitLineNumber(myLastLineNumber, label);
}
} else {
resetLastLineNumber();
//if it used as argument of infix call (in this case lineNumber for simple inlineCall also would be reset)
myLastLineNumber = -1;
}
}
private void resetLastLineNumber() {
myLastLineNumber = -1;
}
@Override
public int getLastLineNumber() {
return myLastLineNumber;
@@ -1628,13 +1613,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
private KotlinType getNothingType() {
return state.getModule().getBuiltIns().getNothingType();
}
@Override
public StackValue visitReturnExpression(@NotNull KtReturnExpression expression, StackValue receiver) {
return StackValue.operation(Type.VOID_TYPE, getNothingType(), adapter -> {
return StackValue.operation(Type.VOID_TYPE, adapter -> {
KtExpression returnedExpression = expression.getReturnedExpression();
CallableMemberDescriptor descriptor = getContext().getContextDescriptor();
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
@@ -1654,7 +1635,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
else {
returnType = this.returnType;
returnKotlinType = typeMapper.getReturnValueType(this.context.getFunctionDescriptor());
returnKotlinType = this.context.getFunctionDescriptor().getReturnType();
}
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
@@ -1662,7 +1643,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Label afterReturnLabel = new Label();
generateFinallyBlocksIfNeeded(returnType, returnKotlinType, afterReturnLabel);
markLineNumber(expression, false);
if (isNonLocalReturn) {
generateGlobalReturnFlag(v, nonLocalReturn.labelName);
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
@@ -1707,10 +1688,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
//FIRST_FUN_LABEL to prevent clashing with existing labels
return new NonLocalReturnInfo(
new JvmKotlinType(
typeMapper.mapReturnType(containingFunction),
typeMapper.getReturnValueType(containingFunction)
),
new JvmKotlinType(typeMapper.mapReturnType(containingFunction), containingFunction.getReturnType()),
FIRST_FUN_LABEL
);
} else {
@@ -1748,9 +1726,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
: returnType;
KotlinType kotlinTypeForExpression =
isBlockedNamedFunction || isVoidCoroutineLambda
? null
: typeMapper.getReturnValueType(context.getFunctionDescriptor());
isBlockedNamedFunction || isVoidCoroutineLambda ? null : context.getFunctionDescriptor().getReturnType();
gen(expr, typeForExpression, kotlinTypeForExpression);
@@ -1759,7 +1735,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!endsWithReturn(expr)) {
if (isLambdaVoidBody(expr, typeForExpression)) {
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
} else if (!isLambdaBody(expr)){
}
else {
markLineNumber(expr, true);
}
@@ -1781,14 +1758,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
private static boolean isLambdaVoidBody(@NotNull KtElement bodyExpression, @NotNull Type returnType) {
return isLambdaBody(bodyExpression) && Type.VOID_TYPE.equals(returnType);
}
private static boolean isLambdaBody(@NotNull KtElement bodyExpression) {
if (bodyExpression instanceof KtBlockExpression) {
PsiElement parent = bodyExpression.getParent();
return parent instanceof KtFunctionLiteral;
if (parent instanceof KtFunctionLiteral) {
return Type.VOID_TYPE.equals(returnType);
}
}
return false;
}
@@ -1875,9 +1851,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
if (descriptor instanceof TypeAliasDescriptor) {
ClassDescriptor classDescriptor = ((TypeAliasDescriptor) descriptor).getClassDescriptor();
assert classDescriptor != null :
"Type alias " + descriptor + " static member reference should be rejected by type checker, " +
"since there is no class corresponding to this type alias.";
if (classDescriptor == null) {
throw new IllegalStateException("Type alias " + descriptor + " static member reference should be rejected by type checker, " +
"since there is no class corresponding to this type alias.");
}
descriptor = classDescriptor;
}
@@ -1886,8 +1863,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (shouldGenerateSingletonAsThisOrOuterFromContext(classDescriptor)) {
return generateThisOrOuterFromContext(classDescriptor, false, false);
}
if (isCompanionObject(classDescriptor)) {
return generateCompanionObjectInstance(classDescriptor);
if (isCompanionObject(classDescriptor) && !couldUseDirectAccessToCompanionObject(classDescriptor, context)) {
return generateAccessorCallForCompanionObject(classDescriptor);
}
if (isObject(classDescriptor)) {
return StackValue.singleton(classDescriptor, typeMapper);
@@ -1897,7 +1874,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor();
if (companionObjectDescriptor != null) {
return generateCompanionObjectInstance(companionObjectDescriptor);
return StackValue.singleton(companionObjectDescriptor, typeMapper);
}
return StackValue.none();
}
@@ -1909,41 +1886,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
private StackValue generateCompanionObjectInstance(ClassDescriptor companionObjectDescriptor) {
assert isCompanionObject(companionObjectDescriptor) :
"Companion object expected: " + companionObjectDescriptor;
CodegenContext accessorContext = getContextForCompanionObjectAccessorIfRequiredOrNull(companionObjectDescriptor, context);
if (accessorContext == null) {
return StackValue.singleton(companionObjectDescriptor, typeMapper);
}
// Should use accessor
DeclarationDescriptor accessorContextDescriptor = accessorContext.getContextDescriptor();
assert accessorContextDescriptor instanceof ClassDescriptor :
"Expected to put accessor for companion object " + companionObjectDescriptor +
" into a class, but got " + accessorContextDescriptor;
accessorContext.getOrCreateAccessorForCompanionObject(companionObjectDescriptor);
Type hostClassType = typeMapper.mapClass((ClassDescriptor) accessorContextDescriptor);
Type companionObjectType = typeMapper.mapClass(companionObjectDescriptor);
// TODO we actually have corresponding accessor descriptor, it might be a better idea to use general method call generation.
return StackValue.operation(
companionObjectType,
companionObjectDescriptor.getDefaultType(),
v1 -> {
v1.invokestatic(
hostClassType.getInternalName(),
getCompanionObjectAccessorName(companionObjectDescriptor),
Type.getMethodDescriptor(companionObjectType),
/* itf */ false
);
return null;
});
}
private boolean shouldGenerateSingletonAsThisOrOuterFromContext(ClassDescriptor classDescriptor) {
if (!isPossiblyUninitializedSingleton(classDescriptor)) return false;
if (!isInsideSingleton(classDescriptor)) return false;
@@ -2537,23 +2479,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return null;
}
@Nullable
public static CodegenContext getCompanionObjectContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
for (CodegenContext current = context; current != null; current = current.getParentContext()) {
if (!(current instanceof ClassContext)) continue;
ClassContext classContext = (ClassContext) current;
ClassDescriptor companionObject = classContext.getContextDescriptor().getCompanionObjectDescriptor();
if (companionObject == null) continue;
if (DescriptorUtils.isSubclass(companionObject, descriptor)) {
return classContext.getCompanionObjectContext();
}
}
return null;
}
@NotNull
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) {
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd);
@@ -2593,12 +2518,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return;
}
SuspensionPointKind suspensionPointKind =
CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, this, state.getLanguageVersionSettings());
boolean maybeSuspensionPoint = suspensionPointKind != SuspensionPointKind.NEVER;
boolean isSuspendNoInlineCall =
CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this, state.getLanguageVersionSettings());
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor);
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendNoInlineCall, isConstructor);
}
callGenerator.processAndPutHiddenParameters(false);
@@ -2632,27 +2556,22 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
if (maybeSuspensionPoint) {
addSuspendMarker(v, true, suspensionPointKind == SuspensionPointKind.NOT_INLINE);
if (isSuspendNoInlineCall) {
addSuspendMarker(v, true);
}
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
if (maybeSuspensionPoint) {
if (isSuspendNoInlineCall) {
addReturnsUnitMarkerIfNecessary(v, resolvedCall);
addSuspendMarker(v, false, suspensionPointKind == SuspensionPointKind.NOT_INLINE);
addSuspendMarker(v, false);
addInlineMarker(v, false);
}
KotlinType returnType = resolvedCall.getResultingDescriptor().getReturnType();
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
if (state.getUseKotlinNothingValueException()) {
v.anew(Type.getObjectType("kotlin/KotlinNothingValueException"));
v.dup();
v.invokespecial("kotlin/KotlinNothingValueException", "<init>", "()V", false);
} else {
v.aconst(null);
}
v.aconst(null);
v.athrow();
}
}
@@ -2794,9 +2713,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Pair<TypeParameterMarker, ReificationArgument> typeParameterAndReificationArgument =
extractReificationArgument(typeSystem, type);
if (typeParameterAndReificationArgument == null) {
KotlinType approximatedType = approximateCapturedType(type);
KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper();
// type is not generic
JvmSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
Type asmType = typeMapper.mapTypeArgument(approximatedType, signatureWriter);
Type asmType = typeMapper.mapTypeParameter(approximatedType, signatureWriter);
mappings.addParameterMappingToType(
key.getName().getIdentifier(), approximatedType, asmType, signatureWriter.toString(), isReified
@@ -2812,22 +2732,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return getOrCreateCallGenerator(descriptor, resolvedCall.getCall().getCallElement(), mappings, false);
}
@NotNull
private KotlinType approximateCapturedType(@NotNull KotlinType type) {
if (state.getLanguageVersionSettings().supportsFeature(LanguageFeature.NewInference)) {
TypeApproximator approximator = new TypeApproximator(state.getModule().getBuiltIns());
KotlinType approximatedType =
CapturedTypeConstructorKt.isCaptured(type) ?
(KotlinType) approximator.approximateToSuperType(
type, TypeApproximatorConfiguration.InternalTypesApproximation.INSTANCE
) : null;
return approximatedType != null ? approximatedType : type;
} else {
return CapturedTypeApproximationKt.approximateCapturedTypes(type).getUpper();
}
}
@NotNull
private static Map<TypeParameterDescriptor, KotlinType> getTypeArgumentsForResolvedCall(
@NotNull ResolvedCall<?> resolvedCall,
@@ -2895,8 +2799,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
else if (isPossiblyUninitializedSingleton(receiverDescriptor) && isInsideSingleton(receiverDescriptor)) {
return generateThisOrOuterFromContext(receiverDescriptor, false, false);
}
else if (couldUseDirectAccessToCompanionObject(receiverDescriptor, context)) {
return StackValue.singleton(receiverDescriptor, typeMapper);
}
else {
return generateCompanionObjectInstance(receiverDescriptor);
return generateAccessorCallForCompanionObject(receiverDescriptor);
}
}
else if (receiverDescriptor instanceof ScriptDescriptor) {
@@ -2907,57 +2814,36 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
private CodegenContext getContextForCompanionObjectAccessorIfRequiredOrNull(
@NotNull ClassDescriptor companionObjectDescriptor,
@NotNull CodegenContext contextBeforeInline
) {
if (isDebuggerContext(contextBeforeInline)) {
return null;
}
@NotNull
private StackValue generateAccessorCallForCompanionObject(@NotNull ClassDescriptor companionObjectDescriptor) {
DeclarationDescriptor hostClassDescriptor = companionObjectDescriptor.getContainingDeclaration();
assert hostClassDescriptor instanceof ClassDescriptor :
"Containing declaration of the companion object " + companionObjectDescriptor +
": expected a class, actual: " + hostClassDescriptor;
if (!state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ProperVisibilityForCompanionObjectInstanceField)) {
return null;
}
CodegenContext hostClassContext = context.findParentContextWithDescriptor(hostClassDescriptor);
assert hostClassContext != null :
"Host class context for " + hostClassDescriptor + " not found in context hierarchy for " + context;
int accessFlag = AsmUtil.getVisibilityAccessFlag(companionObjectDescriptor);
hostClassContext.markCompanionObjectDescriptorWithAccessorRequired(companionObjectDescriptor);
CodegenContext context = contextBeforeInline.getFirstCrossInlineOrNonInlineContext();
boolean isInlineMethodContext = context.isInlineMethodContext();
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
Type hostClassType = typeMapper.mapClass((ClassifierDescriptor) hostClassDescriptor);
Type companionObjectType = typeMapper.mapClass(companionObjectDescriptor);
ClassDescriptor containingClassOfCompanionObject = DescriptorUtils.getContainingClass(companionObjectDescriptor);
if ((accessFlag & ACC_PRIVATE) != 0) {
// Private companion object
if (!isInlineMethodContext && contextDescriptor.getContainingDeclaration() == containingClassOfCompanionObject) {
return null;
}
return context.findParentContextWithDescriptor(containingClassOfCompanionObject);
} else if ((accessFlag & ACC_PROTECTED) != 0) {
// Protected companion object
if (!isInlineMethodContext && canAccessProtectedMembers(contextDescriptor, containingClassOfCompanionObject)) {
return null;
}
CodegenContext accessorContext = getParentContextSubclassOf(containingClassOfCompanionObject, context);
if (accessorContext == null) {
accessorContext = getCompanionObjectContextSubclassOf(containingClassOfCompanionObject, context);
}
assert accessorContext != null :
"Class context for accessor to a protected companion object " + companionObjectDescriptor + " not found:\n" +
JvmCodegenUtil.dumpContextHierarchy(context);
return accessorContext;
} else {
// Non-protected && non-private companion object
return null;
}
}
private static boolean canAccessProtectedMembers(DeclarationDescriptor contextDescriptor, ClassDescriptor classDescriptor) {
DeclarationDescriptor containingDeclaration = contextDescriptor.getContainingDeclaration();
return containingDeclaration == classDescriptor ||
JvmCodegenUtil.isInSamePackage(contextDescriptor, classDescriptor) ||
containingDeclaration instanceof ClassDescriptor &&
DescriptorUtils.isSubclass((ClassDescriptor) containingDeclaration, classDescriptor);
// TODO given that we actually have corresponding AccessorForCompanionObjectInstanceFieldDescriptor,
// it might be a better idea to use general method call generation
return StackValue.operation(
companionObjectType,
companionObjectDescriptor.getDefaultType(),
v -> {
v.invokestatic(
hostClassType.getInternalName(),
getCompanionObjectAccessorName(companionObjectDescriptor),
Type.getMethodDescriptor(companionObjectType),
/* itf */ false
);
return null;
});
}
@NotNull
@@ -3148,16 +3034,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
List<ValueArgument> arguments = valueArgument.getArguments();
int size = arguments.size();
// Named arguments in vararg are treated as having an implicit spread operator.
// There can be only single such argument for a given vararg parameter, but here it doesn't really matter:
// we'll just build a copy of array as if an array argument was passed as positional with an explicit spread operator.
boolean hasSpreadOperator =
state.getLanguageVersionSettings()
.supportsFeature(LanguageFeature.AllowAssigningArrayElementsToVarargsInNamedFormForFunctions)
? arguments.stream().anyMatch(argument -> argument.getSpreadElement() != null || argument.isNamed())
: arguments.stream().anyMatch(argument -> argument.getSpreadElement() != null);
boolean hasSpread = false;
for (int i = 0; i != size; ++i) {
if (arguments.get(i).getSpreadElement() != null) {
hasSpread = true;
break;
}
}
if (hasSpreadOperator) {
if (hasSpread) {
boolean arrayOfReferences = KotlinBuiltIns.isArray(outType);
if (size == 1) {
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
@@ -3274,7 +3159,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@Override
@SuppressWarnings("unchecked")
public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
@@ -3288,7 +3172,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
null, false
);
return genClosure(expression, functionDescriptor, strategy, null, (ResolvedCall<FunctionDescriptor>) resolvedCall, receiver);
return genClosure(
expression, functionDescriptor, strategy, null,
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiver
);
}
return generatePropertyReference(
@@ -3413,7 +3300,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue result;
if (!isPrimitive(expressionType(expression.getReceiverExpression()))) {
result = new StackValue.SafeFallback(type, kotlinType, ifnull, newReceiver);
result = new StackValue.SafeFallback(type, ifnull, newReceiver);
} else {
result = newReceiver;
}
@@ -3800,13 +3687,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Nullable
private static KotlinType getLeftOperandType(@Nullable PrimitiveNumericComparisonInfo numericComparisonInfo) {
if (numericComparisonInfo == null) return null;
return numericComparisonInfo.getLeftPrimitiveType();
return numericComparisonInfo.getLeftType();
}
@Nullable
private static KotlinType getRightOperandType(@Nullable PrimitiveNumericComparisonInfo numericComparisonInfo) {
if (numericComparisonInfo == null) return null;
return numericComparisonInfo.getRightPrimitiveType();
return numericComparisonInfo.getRightType();
}
/*tries to use IEEE 754 arithmetic*/
@@ -4088,8 +3975,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean properIeee754Comparisons = shouldUseProperIeee754Comparisons();
if (properIeee754Comparisons && left754Type != null && right754Type != null) {
type = comparisonOperandType(left754Type.type, right754Type.type);
//type = comparisonOperandType(leftType, rightType);
type = comparisonOperandType(leftType, rightType);
leftValue = gen(left);
rightValue = gen(right);
}
@@ -4272,7 +4158,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.operation(base.type, base.kotlinType, v -> {
base.put(base.type, base.kotlinType, v);
v.dup();
if (state.getUnifiedNullChecks()) {
if (state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_4) >= 0) {
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkNotNull", "(Ljava/lang/Object;)V", false);
} else {
Label ok = new Label();
@@ -4377,6 +4263,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.none();
}
@Override
public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) {
return initializeDestructuringDeclaration(multiDeclaration, false);
@@ -4608,16 +4495,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// We can use the $$delegatedProperties array as in non-inline functions and upon inlining, detect elements at what indices
// of that array are used in the inline function body, load the corresponding initializing bytecode from <clinit> of the
// container class (where the PropertyReferenceNImpl instance is created), copy and adapt it at the call site
StackValue value;
if (PropertyCodegen.isDelegatedPropertyWithOptimizedMetadata(variableDescriptor, bindingContext)) {
value = PropertyCodegen.getOptimizedDelegatedPropertyMetadataValue();
} else if (context.getFunctionDescriptor().isInline()) {
//noinspection ConstantConditions
value = generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null);
}
else {
value = PropertyCodegen.getDelegatedPropertyMetadata(variableDescriptor, bindingContext);
}
//noinspection ConstantConditions
StackValue value = context.getFunctionDescriptor().isInline()
? generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null)
: PropertyCodegen.getDelegatedPropertyMetadata(variableDescriptor, bindingContext);
value.put(K_PROPERTY_TYPE, null, v);
metadataVar.storeSelector(K_PROPERTY_TYPE, null, v);
}
@@ -4815,7 +4696,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
public StackValue visitThrowExpression(@NotNull KtThrowExpression expression, StackValue receiver) {
return StackValue.operation(Type.VOID_TYPE, getNothingType(), adapter -> {
return StackValue.operation(Type.VOID_TYPE, adapter -> {
gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
v.athrow();
return Unit.INSTANCE;

View File

@@ -31,21 +31,21 @@ open class FrameMapBase<T : Any> {
var currentSize = 0
private set
open fun enter(key: T, type: Type): Int {
open fun enter(descriptor: T, type: Type): Int {
val index = currentSize
myVarIndex.put(key, index)
myVarIndex.put(descriptor, index)
currentSize += type.size
myVarSizes.put(key, type.size)
myVarSizes.put(descriptor, type.size)
return index
}
open fun leave(key: T): Int {
val size = myVarSizes.get(key)
open fun leave(descriptor: T): Int {
val size = myVarSizes.get(descriptor)
currentSize -= size
myVarSizes.remove(key)
val oldIndex = myVarIndex.remove(key)
myVarSizes.remove(descriptor)
val oldIndex = myVarIndex.remove(descriptor)
if (oldIndex != currentSize) {
throw IllegalStateException("Descriptor can be left only if it is last: $key")
throw IllegalStateException("Descriptor can be left only if it is last: $descriptor")
}
return oldIndex
}

View File

@@ -19,12 +19,12 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
@@ -43,11 +43,9 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.constants.KClassValue;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.inline.InlineOnlyKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
@@ -68,7 +66,6 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.stream.Collectors;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
@@ -76,14 +73,14 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.generateBridgeForMainFu
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.isAccessor;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION;
import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
import static org.jetbrains.kotlin.load.java.JvmAbi.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -123,14 +120,27 @@ public class FunctionCodegen {
if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
FunctionGenerationStrategy strategy;
if (functionDescriptor.isSuspend()) {
strategy = new SuspendFunctionGenerationStrategy(
state,
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
function,
v.getThisName(),
state.getConstructorCallNormalizationMode(),
this
);
if (isEffectivelyInlineOnly(functionDescriptor)) {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, function);
} else if (!functionDescriptor.isInline()) {
strategy = new SuspendFunctionGenerationStrategy(
state,
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
function,
v.getThisName(),
state.getConstructorCallNormalizationMode(),
this
);
} else {
strategy = new SuspendInlineFunctionGenerationStrategy(
state,
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
function,
v.getThisName(),
state.getConstructorCallNormalizationMode(),
this
);
}
} else {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, function);
}
@@ -447,7 +457,7 @@ public class FunctionCodegen {
) {
OwnerKind contextKind = methodContext.getContextKind();
if (!state.getClassBuilderMode().generateBodies
|| isAbstractMethod(functionDescriptor, contextKind, state.getJvmDefaultMode())
|| isAbstractMethod(functionDescriptor, contextKind)
|| shouldSkipMethodBodyInAbiMode(state.getClassBuilderMode(), origin)
) {
generateLocalVariableTable(
@@ -624,19 +634,11 @@ public class FunctionCodegen {
frameMap.enter(continuationValueDescriptor, typeMapper.mapType(continuationValueDescriptor));
}
if (context.isInlineMethodContext()) {
functionFakeIndex = newFakeTempIndex(mv, frameMap, -1);
functionFakeIndex = newFakeTempIndex(mv, frameMap);
}
if (context instanceof InlineLambdaContext) {
int lineNumber = -1;
if (strategy instanceof ClosureGenerationStrategy) {
KtDeclarationWithBody declaration = ((ClosureGenerationStrategy) strategy).getDeclaration();
BindingContext bindingContext = typeMapper.getBindingContext();
if (declaration instanceof KtFunctionLiteral && isLambdaPassedToInlineOnly((KtFunction) declaration, bindingContext)) {
lineNumber = LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER;
}
}
lambdaFakeIndex = newFakeTempIndex(mv, frameMap, lineNumber);
lambdaFakeIndex = newFakeTempIndex(mv, frameMap);
}
methodEntry = new Label();
@@ -700,27 +702,8 @@ public class FunctionCodegen {
}
}
private static boolean isLambdaPassedToInlineOnly(KtFunction lambda, BindingContext bindingContext) {
ValueParameterDescriptor parameterDescriptor = InlineUtil.getInlineArgumentDescriptor(lambda, bindingContext);
if (parameterDescriptor == null) {
return false;
}
CallableDescriptor containingCallable = parameterDescriptor.getContainingDeclaration();
if (containingCallable instanceof FunctionDescriptor) {
return InlineOnlyKt.isInlineOnly((MemberDescriptor) containingCallable);
}
return false;
}
private static int newFakeTempIndex(@NotNull MethodVisitor mv, @NotNull FrameMap frameMap, int lineNumber) {
private static int newFakeTempIndex(@NotNull MethodVisitor mv, FrameMap frameMap) {
int fakeIndex = frameMap.enterTemp(Type.INT_TYPE);
if (lineNumber >= 0) {
Label label = new Label();
mv.visitLabel(label);
mv.visitLineNumber(lineNumber, label);
}
mv.visitLdcInsn(0);
mv.visitVarInsn(ISTORE, fakeIndex);
return fakeIndex;
@@ -732,9 +715,7 @@ public class FunctionCodegen {
@NotNull JvmDefaultMode jvmDefaultMode
) {
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
JvmAnnotationUtilKt
.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor),
jvmDefaultMode) &&
hasJvmDefaultAnnotation(functionDescriptor) &&
jvmDefaultMode.isCompatibility();
}
@@ -804,41 +785,30 @@ public class FunctionCodegen {
shift++;
}
boolean isEnumName = true;
KotlinTypeMapper typeMapper = state.getTypeMapper();
for (int i = 0; i < params.size(); i++) {
JvmMethodParameterSignature param = params.get(i);
JvmMethodParameterKind kind = param.getKind();
String parameterName;
switch (kind) {
case VALUE:
ValueParameterDescriptor parameter = valueParameterIterator.next();
String nameForDestructuredParameter = VariableAsmNameManglingUtils.getNameForDestructuredParameterOrNull(parameter);
if (kind == JvmMethodParameterKind.VALUE) {
ValueParameterDescriptor parameter = valueParameterIterator.next();
String nameForDestructuredParameter = VariableAsmNameManglingUtils.getNameForDestructuredParameterOrNull(parameter);
parameterName =
nameForDestructuredParameter == null
? computeParameterName(i, parameter)
: nameForDestructuredParameter;
break;
case RECEIVER:
parameterName = AsmUtil.getNameForReceiverParameter(
functionDescriptor, typeMapper.getBindingContext(), state.getLanguageVersionSettings());
break;
case OUTER:
parameterName = CAPTURED_THIS_FIELD; //should be 'this$X' depending on inner class nesting
break;
case ENUM_NAME_OR_ORDINAL:
parameterName = isEnumName ? "$enum$name" : "$enum$ordinal";
isEnumName = !isEnumName;
break;
default:
String lowercaseKind = kind.name().toLowerCase();
parameterName = needIndexForVar(kind)
? "$" + lowercaseKind + "$" + i
: "$" + lowercaseKind;
break;
parameterName =
nameForDestructuredParameter == null
? computeParameterName(i, parameter)
: nameForDestructuredParameter;
}
else if (kind == JvmMethodParameterKind.RECEIVER) {
parameterName = AsmUtil.getNameForReceiverParameter(
functionDescriptor, typeMapper.getBindingContext(), state.getLanguageVersionSettings());
}
else {
String lowercaseKind = kind.name().toLowerCase();
parameterName = needIndexForVar(kind)
? "$" + lowercaseKind + "$" + i
: "$" + lowercaseKind;
}
Type type = param.getAsmType();
@@ -1002,14 +972,14 @@ public class FunctionCodegen {
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
if (descriptor instanceof ConstructorDescriptor) return;
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
if (JvmBridgesImplKt.isAbstractOnJvmIgnoringActualModality(descriptor, state.getJvmDefaultMode())) return;
if (JvmBridgesImplKt.isAbstractOnJvmIgnoringActualModality(descriptor)) return;
// equals(Any?), hashCode(), toString() never need bridges
if (isMethodOfAny(descriptor)) return;
boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;
Set<Bridge<Method, DescriptorBasedFunctionHandleForJvm>> bridgesToGenerate;
Set<Bridge<Method>> bridgesToGenerate;
if (!isSpecial) {
bridgesToGenerate =
JvmBridgesImplKt.generateBridgesForFunctionDescriptorForJvm(descriptor, typeMapper::mapAsmMethod, state);
@@ -1018,27 +988,26 @@ public class FunctionCodegen {
boolean isSpecialBridge =
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) != null;
for (Bridge<Method, DescriptorBasedFunctionHandleForJvm> bridge : bridgesToGenerate) {
generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), getBridgeReturnType(bridge), isSpecialBridge, false);
for (Bridge<Method> bridge : bridgesToGenerate) {
generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false);
}
}
}
else {
Set<BridgeForBuiltinSpecial<Method>> specials =
BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(descriptor, typeMapper::mapAsmMethod, state);
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
descriptor, typeMapper::mapAsmMethod, state
);
if (!specials.isEmpty()) {
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
for (BridgeForBuiltinSpecial<Method> bridge : specials) {
generateBridge(
origin, descriptor, bridge.getFrom(), bridge.getTo(),
descriptor.getReturnType(), // TODO
bridge.isSpecial(), bridge.isDelegateToSuper()
);
bridge.isSpecial(), bridge.isDelegateToSuper());
}
}
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state.getJvmDefaultMode())) {
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
assert overridden != null;
@@ -1051,35 +1020,6 @@ public class FunctionCodegen {
}
}
private KotlinType getBridgeReturnType(Bridge<Method, DescriptorBasedFunctionHandleForJvm> bridge) {
// Return type for the bridge affects inline class values boxing/unboxing in bridge.
// Here we take 1st available return type for the bridge.
// In correct cases it doesn't matter what particular return type to use,
// since either all return types are inline class itself,
// 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;
}
}
if (state.getClassBuilderMode().mightBeIncorrectCode) {
// Don't care, 'Any?' would suffice.
return state.getModule().getBuiltIns().getNullableAnyType();
} else if (bridge.getOriginalFunctions().isEmpty()) {
throw new AssertionError("No overridden functions for the bridge method '" + bridge.getTo() + "'");
} else {
throw new AssertionError(
"No return type for the bridge method '" + bridge.getTo() + "' found in the following overridden functions:\n" +
bridge.getOriginalFunctions().stream()
.map(handle -> handle.getDescriptor().toString())
.collect(Collectors.joining("\n"))
);
}
}
public static boolean isThereOverriddenInKotlinClass(@NotNull CallableMemberDescriptor descriptor) {
return CollectionsKt.any(
getAllOverriddenDescriptors(descriptor),
@@ -1101,24 +1041,17 @@ public class FunctionCodegen {
}
@NotNull
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper typeMapper) {
return ArrayUtil.toStringArray(CollectionsKt.map(
getThrownExceptions(function, typeMapper.getLanguageVersionSettings()),
d -> typeMapper.mapClass(d).getInternalName()
));
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper mapper) {
return ArrayUtil.toStringArray(CollectionsKt.map(getThrownExceptions(function), d -> mapper.mapClass(d).getInternalName()));
}
@NotNull
public static List<ClassDescriptor> getThrownExceptions(
@NotNull FunctionDescriptor function,
@NotNull LanguageVersionSettings languageVersionSettings
) {
if (function.getKind() == DELEGATION &&
languageVersionSettings.supportsFeature(LanguageFeature.DoNotGenerateThrowsForDelegatedKotlinMembers)) {
return Collections.emptyList();
public static List<ClassDescriptor> getThrownExceptions(@NotNull FunctionDescriptor function) {
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
if (annotation == null) {
annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
}
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
if (annotation == null) return Collections.emptyList();
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
@@ -1225,10 +1158,6 @@ public class FunctionCodegen {
@NotNull MemberCodegen<?> parentCodegen,
@NotNull Method defaultMethod
) {
if (methodContext instanceof ConstructorContext) {
((ConstructorContext) methodContext).setThisInitialized(false);
}
GenerationState state = parentCodegen.state;
JvmMethodSignature signature = state.getTypeMapper().mapSignatureWithGeneric(functionDescriptor, methodContext.getContextKind());
@@ -1394,7 +1323,6 @@ public class FunctionCodegen {
@NotNull FunctionDescriptor descriptor,
@NotNull Method bridge,
@NotNull Method delegateTo,
@NotNull KotlinType bridgeReturnType,
boolean isSpecialBridge,
boolean isStubDeclarationWithDelegationToSuper
) {
@@ -1462,8 +1390,7 @@ public class FunctionCodegen {
iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
}
else {
if (isInterface(descriptor.getContainingDeclaration()) &&
JvmAnnotationUtilKt.isCompiledToJvmDefault(descriptor, state.getJvmDefaultMode())) {
if (hasJvmDefaultAnnotation(descriptor)) {
iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
}
else {
@@ -1472,7 +1399,7 @@ public class FunctionCodegen {
}
KotlinType returnType = descriptor.getReturnType();
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), bridgeReturnType, iv);
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), returnType, iv);
iv.areturn(bridge.getReturnType());
endVisit(mv, "bridge method", origin);
@@ -1588,34 +1515,19 @@ public class FunctionCodegen {
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
) {
Method delegateMethod = typeMapper.mapAsmMethod(delegateFunction);
Type[] argTypes = delegateMethod.getArgumentTypes();
List<KotlinType> argKotlinTypes = getKotlinTypesForJvmParameters(delegateFunction);
Method delegateToMethod = typeMapper.mapToCallableMethod(delegatedTo, /* superCall = */ false).getAsmMethod();
Method delegateMethod = typeMapper.mapAsmMethod(delegateFunction);
Type[] argTypes = delegateMethod.getArgumentTypes();
Type[] originalArgTypes = delegateToMethod.getArgumentTypes();
List<KotlinType> originalArgKotlinTypes = getKotlinTypesForJvmParameters(delegatedTo);
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, OBJECT_TYPE);
field.put(iv);
// When delegating to inline class, we invoke static implementation method
// that takes inline class underlying value as 1st argument.
int toArgsShift = toClass.isInline() ? 1 : 0;
int reg = 1;
for (int i = 0; i < argTypes.length; ++i) {
Type argType = argTypes[i];
KotlinType argKotlinType = argKotlinTypes.get(i);
Type toArgType = originalArgTypes[i + toArgsShift];
KotlinType toArgKotlinType = originalArgKotlinTypes.get(i);
StackValue.local(reg, argType, argKotlinType)
.put(toArgType, toArgKotlinType, iv);
reg += argType.getSize();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
//noinspection AssignmentToForLoopParameter
reg += argTypes[i].getSize();
}
String internalName = typeMapper.mapClass(toClass).getInternalName();
@@ -1629,7 +1541,6 @@ public class FunctionCodegen {
iv.invokevirtual(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false);
}
//noinspection ConstantConditions
StackValue stackValue = AsmUtil.genNotNullAssertions(
state,
StackValue.onStack(delegateToMethod.getReturnType(), delegatedTo.getReturnType()),
@@ -1654,28 +1565,6 @@ public class FunctionCodegen {
public boolean skipGenericSignature() {
return skipGenericSignature;
}
private List<KotlinType> getKotlinTypesForJvmParameters(@NotNull FunctionDescriptor functionDescriptor) {
List<KotlinType> kotlinTypes = new ArrayList<>();
ReceiverParameterDescriptor extensionReceiver = functionDescriptor.getExtensionReceiverParameter();
if (extensionReceiver != null) {
kotlinTypes.add(extensionReceiver.getType());
}
for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) {
kotlinTypes.add(parameter.getType());
}
if (functionDescriptor.isSuspend()) {
// Suspend functions take continuation type as last argument.
// It's not an inline class, so we don't really care about exact KotlinType here.
// Just make sure argument types are counted properly.
kotlinTypes.add(null);
}
return kotlinTypes;
}
}
);
}
@@ -1691,7 +1580,7 @@ public class FunctionCodegen {
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
containingDeclaration;
if (JvmAnnotationUtilKt.isCompiledToJvmDefault(memberDescriptor, mode)) {
if (hasJvmDefaultAnnotation(memberDescriptor)) {
return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) ||
(kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || mode.isCompatibility()));
} else {

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