Compare commits

...

194 Commits

Author SHA1 Message Date
Nikolay Krasko
3a2fc547f3 Fix compatibility after moving declaration from *.idea.caches.resolve
Compatibility check revealed problem in some plugins.

1. https://plugins.jetbrains.com/plugin/8249-truth-postfix-plugin

b06adbf4e6/plugin/src/main/kotlin/com/github/droibit/plugin/truth/postfix/utils/TemplateUtils.kt

2. https://plugins.jetbrains.com/plugin/10137-clean-architecture-templates

62c6e0fe37/src/main/kotlin/cat/helm/idea/extensions/FileUtils.kt
2018-05-10 13:58:52 +03:00
Yan Zhulanow
364c8af076 Update changelog for Kotlin 1.2.41 2018-04-28 04:08:27 +03:00
Mikhael Bogdanov
7b2b1f9f7d Skip @JvmDefault in UnimplementedKotlinInterfaceMemberAnnotator
#KT-23967 Fixed

(cherry picked from commit ec0b9aa)
2018-04-26 15:39:16 +02:00
Mikhael Bogdanov
3d3be3dc78 Revert "Get rid of 'BRIDGE' flag on $default functions"
Removed bridge flag triggers problem with Spring Boot: KT-23973
 This reverts commit cdcb651

 #KT-23973 Fixed

(cherry picked from commit 5efc9f2)
2018-04-26 15:39:10 +02:00
Alexey Tsvetkov
8209a50764 Fix incremental compilation with Java 9+
#KT-23901 fixed
2018-04-25 17:44:49 +03:00
Raluca Sauciuc
d4f25e1043 More fixes for Android Studio 3.2 compatibility
(cherry picked from commit 258cba2)
2018-04-24 16:59:53 +03:00
Mikaël Peltier
73b9685f38 KT-23931 Avoid infinite loop into RedundantGotoMethodTransformer
- Follow-up of 9fb0f59813 to avoid
infinite loop during redundant goto otpimization.

Fix of https://youtrack.jetbrains.com/issue/KT-23931

(cherry picked from commit b1ef670)
2018-04-23 20:27:56 +03:00
Mikhail Zarechenskiy
fdfe801c92 Render unwrapped suspend function in backend
Hierarchy of specially wrapped suspend function may have inconsistent
 overridden descriptors: some of them may be wrapped, some unwrapped.
 To mitigate this problem, currently it's proposed to render only
 unwrapped functions, which are always have stable overridden descriptors

 #KT-23809 Fixed
2018-04-23 18:04:40 +03:00
Dmitry Petrov
8b446a1649 Use correctElementType to determine array element type for withIndex
Rather unkind "gotcha" in ASM API.
2018-04-23 17:56:16 +03:00
Yan Zhulanow
6037b04f89 Minor: Fix typo in changelog 2018-04-19 17:38:22 +03:00
Pavel V. Talanov
80fd1ac8ab Do not throw when trying to resolve java outside project model
#KT-23444 Fixed
 #KT-22825 Fixed
2018-04-17 18:10:58 +02:00
Yan Zhulanow
c4ce4ac450 Update changelog for 1.2.40 2018-04-16 17:48:44 +03:00
Alexey Sedunov
5184edea5f Configuration: Put 'buildscript' block before 'plugins' in build.gradle
#KT-23588 Fixed

(cherry picked from commit 6c7959d)
2018-04-16 15:38:12 +03:00
Yan Zhulanow
66be4ccb5e Update changelog (1.2.40 Golden RC) 2018-04-13 21:11:49 +03:00
Raluca Sauciuc
1227ade91e Support androidx packages
... in the IDE plugin and the Android extensions compiler.

Change-Id: Iffd58351b0592e12ffc937c06d871d26958fe161

(cherry picked from commit 89d61ee)
2018-04-12 16:30:44 +03:00
Alexey Tsvetkov
8f30017405 Use KotlinCoreEnvironment for parsing Kotlin in IC
Creating and disposing CoreApplicationEnvironment on each call leads to
problems with parallel builds, while KotlinCoreEnvironment
avoids disposing application environment in case of parallel builds.

    #KT-23694 fixed
2018-04-11 21:47:48 +03:00
Alexey Tsvetkov
883a7fd2dc Move parseFileUtils to incremental-compilation-impl 2018-04-11 21:47:44 +03:00
Alexander Podkhalyuzin
f1e395c1d9 Do not show duplicated names in variables completion list
#KT-23546 Fixed

(cherry picked from commit e4dfa58)
2018-04-11 17:08:24 +03:00
Alexander Podkhalyuzin
b0d09109c4 Do not show autopopup variable name completion if it was closed
#KT-23546 Comment

(cherry picked from commit 0231a3a)
2018-04-11 17:07:53 +03:00
Natalia Selezneva
94532db659 Fix Repl stopping after first line. Do not exit after readLine in user code
Revert previous workaround from commit 8e88820
^KT-23622 Fixed
2018-04-11 08:46:37 +03:00
Anton Bannykh
4e0af21df4 Revert "Clean up test skips after KT-17137"
This reverts commit 715d5e9

(cherry picked from commit cc1c7dcb04c98bfb70a852e2a4d3456573015682)
2018-04-10 20:46:00 +03:00
Anton Bannykh
39809cedba Revert "JS: remove -XtypedArraysEnabled flag (always true now)"
This reverts commit 4a5e9bb

(cherry picked from commit 7863b7741ebf713e5388852b6ad49c72e63a2b7e)
2018-04-10 20:46:00 +03:00
Mikhael Bogdanov
625bfd8adb Restrict conditions for @JvmDefault super calls
Condition was too strict
  if @JvmDefault implicitly hidden by class in inheritance.
  Diagnostic is redundant cause there isn't breaking
  change depending on interface method generation strategy and
  delegating stub generation in inheriting class.

(cherry picked from commit 56d1184)
2018-04-10 16:43:28 +02:00
Mikhael Bogdanov
d3017a8071 Minor. Avoid recursion
(cherry picked from commit e23c406)
2018-04-10 16:43:26 +02:00
Mikhael Bogdanov
b45a5a8ca7 Restrict conditions for @JvmDefault super calls
Condition was too strict if we actually make super call
  through super class. Diagnostic is redundant cause there isn't breaking
  change depending on interface method generation strategy.

(cherry picked from commit 6d1af26)
2018-04-10 16:43:23 +02:00
Mikhael Bogdanov
fd97d56bc4 Update documentation for @JvmDefault
(cherry picked from commit 5f235a8)
2018-04-10 16:43:20 +02:00
Mikhael Bogdanov
3801410d1c Support custom options in quick fix test framework
(cherry picked from commit ea407ab)
2018-04-10 14:36:46 +02:00
Mikhael Bogdanov
916c5e2260 Add quick fix for adding @JvmDefault annotation
(cherry picked from commit c5d4f22)
2018-04-10 14:36:43 +02:00
Mikhael Bogdanov
23708991fe Fix misspelling in test data
(cherry picked from commit 31e459d)
2018-04-10 14:36:40 +02:00
Mikhael Bogdanov
26c8f32390 Add warning on overriding java default by non @JvmDefault method
(cherry picked from commit d788b3b)
2018-04-10 14:36:37 +02:00
Mikhael Bogdanov
e3d5021799 Support default method super calls within @JvmDefault ones
(cherry picked from commit cb9c1ae)
2018-04-10 14:36:34 +02:00
Mikhael Bogdanov
e5d903bc20 Properly calculate this for super call
(cherry picked from commit 942dd8a)
2018-04-10 14:36:31 +02:00
Ilya Chernikov
42950a9993 Use script compiler options on script dependencies in the IDE as well
further fixes #KT-19120
2018-04-09 15:29:45 +02:00
Nikolay Krasko
d69c627205 Add hard dependency to Java module in plugin.xml
Otherwise resulting plugin will be installable to PyCharm, WebStorm and
other Intellij IDE without Java.

It can be resolved with `xi:include`, but it should be done with care,
because some declarations in `jvm.xml` should be placed after some
declarations in `plugin.xml` (action groups suffer from this issue for
sure).
2018-04-09 12:32:35 +03:00
Yan Zhulanow
54f03aeaf9 Update the changelog for 1.2.40 2018-04-06 15:18:41 +03:00
Yan Zhulanow
8e8882065c REPL: Fix REPL stopping after the first line (#KT-23622) 2018-04-05 18:17:06 +03:00
Alexander Udalov
fbb2ae4ef1 Disable packing module-info to libraries until Android issue is fixed
https://issuetracker.google.com/issues/77587908

 #KT-21266 Open
2018-04-04 21:53:50 +02:00
Yan Zhulanow
2283366076 Revert "Debugger: Fix breakpoints and stepping for inline-only function lambda arguments (#KT-23064)"
This reverts commit aa75d88
2018-04-04 19:23:00 +03:00
Mikhael Bogdanov
7f8efc6dab Add @RequireKotlin(1.2.40) on interface with @JvmDefaults and its subinterfaces
(cherry picked from commit 4aec949)
2018-04-04 16:18:41 +02:00
Mikhael Bogdanov
da097a312b Update test data
(cherry picked from commit be33a9b)
2018-04-04 14:58:09 +02:00
Mikhael Bogdanov
b3399a6529 Update @JvmDefault documentation
(cherry picked from commit a27d1b7)
2018-04-04 14:58:06 +02:00
Natalia Selezneva
da4d4153de Rearrange script definition contributors to avoid old EP appear before new EP
Fix highlighting of build.gradle.kts files with LivePlugin enabled
^KT-23571 Fixed

(cherry picked from commit a6019cc)
2018-04-04 13:56:22 +03:00
Vyacheslav Gerasimov
73676d7a9e Upgrade shadow plugin to 2.0.2
Fixes warning 'Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.'

(cherry picked from commit f55d137790)
2018-04-04 10:35:06 +02:00
Alexander Udalov
ff3da15cde Check that kotlin.stdlib is explicitly required in module-info
Writing a Jigsaw-modular Kotlin program which doesn't require
kotlin.stdlib doesn't make sense because it most likely will fail at
runtime, on access to anything from the standard library. Previously, we
checked that kotlin.stdlib was in the module graph, but that's not
enough, we should also check that the source module requires it.
'-Xallow-kotlin-package' can be used to disable the error.

Add a test checking that an indirect (transitive) dependency is also OK

(cherry picked from commit 0439abba46)
2018-04-03 22:04:24 +02:00
Ilya Gorbunov
696bff31f4 Make JDK 9 required to build the project
(cherry picked from commit 7501d2ad69)
2018-04-03 22:04:22 +02:00
Ilya Gorbunov
a8b561be15 Use default compileJava9Java task to build java9 source set
(cherry picked from commit 299d6fa772)
2018-04-03 22:04:19 +02:00
Ilya Gorbunov
3e8dab05f7 Improve JDK discovery for JDK9+ on Windows
(cherry picked from commit bd4abaa8bf)
2018-04-03 22:04:17 +02:00
Alexander Udalov
d67201aae2 Add module-info.java for kotlin-reflect
The standard way of loading resources with built-ins metadata from the
current class loader no longer works in the modular mode on Java 9
because the current class loader is for module 'kotlin.reflect', but the
metadata is located in the module 'kotlin.stdlib'. On Java 9, we now use
the class loader of 'kotlin.stdlib' to load these resources.

 #KT-21266 Fixed

(cherry picked from commit 828cc6dbf3)
2018-04-03 22:04:15 +02:00
Alexander Udalov
01fc60fab3 Add module-info.java for standard Kotlin libraries
Using the new multi-release jar feature, store compiled
module-info.class files into META-INF/versions/9 instead of the artifact
root. Hopefully, this will break fewer tools which do not support
module-info.class files because any sane tool should not do anything
with files in META-INF because before Java 9 that directory only
contained resources.

Upgrade some Maven plugins to newer versions which do not fail on
module-info.class files

 #KT-21266 In Progress

(cherry picked from commit 2d41c7d462)
2018-04-03 22:04:13 +02:00
Alexander Udalov
48140586b9 Fix warning about kotlin-reflect-api bundling Kotlin Runtime
This fixes the "Some JAR files in the classpath have the Kotlin Runtime
library bundled into them" warning when compiling all modules that
depend on kotlin-reflect-api. This warning is reported on jars in the
classpath which look like standard library artifacts, but in fact are
not because their manifest does not say so. With this change, we're now
writing the manifest of standard library artifacts to the resulting jar
of kotlin-reflect-api, with the standard library component name
"internal" (in fact, it doesn't affect anything here, any name would be
OK) to make the compiler believe that this is actually a standard
library jar

(cherry picked from commit 964bf503a6)
2018-04-03 22:04:09 +02:00
Alexey Tsvetkov
8e66f6af9b Temporarily turn off source map generation in JS IC tests
Until IncrementalJsCompilerRunnerTestGenerated$ClassHierarchyAffected.testEnumEntryRemoved 
is fixed
2018-04-03 21:14:18 +03:00
Alexey Tsvetkov
686e8bc06a Use daemon if available for parsing files in JPS 2018-04-03 21:14:13 +03:00
Alexey Tsvetkov
3cab8b4f41 Invalidate usages of removed classes before round
#KT-23165 fixed
2018-04-03 21:14:08 +03:00
Alexey Tsvetkov
18310d9b4c Convert KotlinSourceFileCollector: simplify after conversion 2018-04-03 21:14:03 +03:00
Alexey Tsvetkov
b393d78520 Convert KotlinSourceFileCollector: actual conversion 2018-04-03 21:14:00 +03:00
Alexey Tsvetkov
720bba5bba Convert KotlinSourceFileCollector: rename file 2018-04-03 21:13:55 +03:00
Alexey Tsvetkov
3d72966469 Remove usages of deprecated API 2018-04-03 21:13:50 +03:00
Alexey Tsvetkov
458bd709c9 Replace reflection with direct call 2018-04-03 21:13:46 +03:00
Alexey Tsvetkov
5cd044691b Convert CompilerRunnerUtil: actual conversion 2018-04-03 21:13:41 +03:00
Alexey Tsvetkov
1776dc6de2 Convert CompilerRunnerUtil: rename file 2018-04-03 21:13:37 +03:00
Alexey Tsvetkov
b538e01889 Reformat jps-plugin module 2018-04-03 21:13:33 +03:00
Mikhael Bogdanov
2cd5bd4d83 Update test data
(cherry picked from commit 08ff1de)
2018-04-03 19:47:12 +02:00
Mikhael Bogdanov
db722b468f Require 'jvmDefaultFlag' for default super calls
(cherry picked from commit 2c56f0b)
2018-04-03 19:47:08 +02:00
Mikhael Bogdanov
ba4858dde9 Inline utility method
(cherry picked from commit db59e91)
2018-04-03 19:47:05 +02:00
Mikhael Bogdanov
8037619a51 Write 'RequireKotlin' annotation on @JvmDefault members
(cherry picked from commit 3f5fea0)
2018-04-03 19:47:02 +02:00
Mikhael Bogdanov
522be915c5 Add custom diagnostic checker for @JvmDefault annotation
(cherry picked from commit 23e8adb)
2018-04-03 19:46:59 +02:00
Mikhael Bogdanov
e7b8279dcd Relocate @JvmDefault to stdlib module
(cherry picked from commit 89f22e6)
2018-04-03 19:46:55 +02:00
Mikhael Bogdanov
7a1aa8ac81 Update test data. Use simple ''@JvmDefault' instead full qualifier
(cherry picked from commit 38f8924)
2018-04-03 19:46:50 +02:00
Mikhael Bogdanov
9e88b3d691 Check method abstractness during bridge generation per method not interface
(cherry picked from commit 2a8041e)
2018-04-03 19:46:45 +02:00
Mikhael Bogdanov
6e903333a6 Remove @JvmDefault members from delegation
(cherry picked from commit f290b32)
2018-04-03 19:46:40 +02:00
Mikhael Bogdanov
a51181b009 Support inline for private @JvmDefault members
(cherry picked from commit d84a15c)
2018-04-03 19:46:36 +02:00
Mikhael Bogdanov
69c635e7c3 Minor.Reformat
(cherry picked from commit affe445)
2018-04-03 19:46:33 +02:00
Mikhael Bogdanov
5ba37fdff7 Support synthetic accessors for @JvmDefault members
(cherry picked from commit 308283e)
2018-04-03 19:46:29 +02:00
Mikhael Bogdanov
4a0037850b Minor.Reformat
(cherry picked from commit 1acd564)
2018-04-03 19:46:26 +02:00
Mikhael Bogdanov
3bbffa38ab Add @JvmDefault diagnostics
(cherry picked from commit 1d3e57a)
2018-04-03 19:46:23 +02:00
Mikhael Bogdanov
75b3a662f3 Remove unused parameters, compiler keys and obsolete code
(cherry picked from commit 63afd37)
2018-04-03 19:46:19 +02:00
Mikhael Bogdanov
a28a0beaea Initial support of @JvmDefault
(cherry picked from commit fe45eb2)
2018-04-03 19:46:16 +02:00
Mikhael Bogdanov
33577b4078 Add @JvmDefault annotation
(cherry picked from commit e885195)
2018-04-03 19:46:12 +02:00
Mikhael Bogdanov
4664f7c55d Remove unused test data
(cherry picked from commit 5830f99)
2018-04-03 19:46:08 +02:00
Mikhael Bogdanov
995156b801 Remove wrong directive
Similar test exists under 'defaults' foldes

(cherry picked from commit c143480)
2018-04-03 19:46:05 +02:00
Mikhael Bogdanov
38a8959356 Specify idea.home.path for java 8 tests
Default discovery mechanism points to wrong location

(cherry picked from commit b337b9e)
2018-04-03 19:46:00 +02:00
Mikhail Glukhikh
b0da004779 Fix handling of characters in "convert to string template"
So #KT-23045 Fixed
So #KT-23046 Fixed

(cherry picked from commit 6d94578)
2018-04-03 18:27:12 +03:00
Dmitry Savvinov
df6ed491f5 Don't throw exception on recursion for class header scope
The root issue here is that when we have some cycle in scopes, the place
where we detect a loop depends on where we've entered that cycle.

Previously, we didn't know about cases where we enter scopes loop
through `ClassResolutionScopesSupport.scopeForClassHeaderResolution` =>
there were no need to handle recursion on `scopeForClassHeaderResolution`
carefully.

It seems that in some very narrow cases (launch of specific
inspection on specficic code with specific caches state), we do manage
to enter loop exactly through `scopeForClassHeaderResolution` (see
KT-23033), which causes exception.

^KT-23033 Fixed

(cherry-picked from 5b216a0270)
2018-04-03 18:24:12 +03:00
Alexander Udalov
02f4a02fbe Fix NPE from JarURLConnection.getUseCaches when loading compiler plugins
#KT-22513 Fixed

(cherry picked from commit d0e99e9a3f)
2018-04-03 16:57:07 +02:00
Mikhail Glukhikh
6c0afb25fb Fix several false positives and make safer "redundant companion ref"
Don't report it on an import directive #KT-23520 Fixed
Don't report it if companion nested class is referenced #KT-23519 Fixed
Check companion reference both by descriptor and by name

(cherry picked from commit ab973b2)
2018-04-03 17:48:33 +03:00
Mikhail Glukhikh
075533595e Optimization: RedundantCompanionReferenceInspection
(cherry picked from commit 23488fa)
2018-04-03 17:48:22 +03:00
Alexey Sedunov
65365ac88b JS: Use the same output paths for JPS and Maven-based builds
#KT-22586 Fixed

(cherry picked from commit ae37cc3)
2018-04-03 12:35:57 +03:00
Yan Zhulanow
be9614793b Kapt: Find the right annotation descriptor in case of repeatable annotations (#KT-23427)
(cherry picked from commit dc3cd01fad)
2018-04-03 03:22:47 +03:00
Yan Zhulanow
6ea5b79223 Pill: Add marker option for JUnit3RunnerWithInners test runner
(cherry picked from commit 4cab250f72)
2018-04-03 03:22:43 +03:00
Yan Zhulanow
584bf7d70d Kapt: Do not escape cyrillic letters in stubs (#KT-23286)
(cherry picked from commit 46973bf1fe)
2018-04-03 03:22:39 +03:00
Yan Zhulanow
e69f45b895 Pill: Support Android tests
(cherry picked from commit ae3d574473)
2018-04-03 03:22:36 +03:00
Yan Zhulanow
91882262fc Minor: Fix Parcelable test data
(cherry picked from commit ead7653f84)
2018-04-03 03:22:32 +03:00
Yan Zhulanow
b422471683 Pill: Add idea-android-output-parser module to JPS model
(cherry picked from commit 78f2fe1eab)
2018-04-03 03:22:28 +03:00
Yan Zhulanow
46eb8854c2 Tests: Disable inspections after test as Platform test framework requires
(cherry picked from commit 5d9bdbec10)
2018-04-03 03:22:25 +03:00
Yan Zhulanow
b4f90a90d9 Android: Extract dependencies to Android plugin to extensions
(cherry picked from commit 8f02d338a6)
2018-04-03 03:22:22 +03:00
Yan Zhulanow
a92bd947af Kapt: Support 'kapt.kotlin.generated' option in Maven
(cherry picked from commit 39e9d28c63)
2018-04-03 03:22:16 +03:00
Yan Zhulanow
76365e01eb Kapt: Annotation processors should not be discovered when the processor fqNames are set by user (#KT-22939)
(cherry picked from commit b1d7935)
2018-04-03 03:22:09 +03:00
Yan Zhulanow
eee3dcc9e1 Kapt, minor: make Gradle API a bit cleaner
(cherry picked from commit dc8eb7446f)
2018-04-03 03:21:03 +03:00
Yan Zhulanow
a573b748a3 Fix EA-117939: Add a read action
(cherry picked from commit b3fbec9ec3)
2018-04-03 03:21:00 +03:00
Yan Zhulanow
59ec96e02b Evaluate: Fix annotation value evaluation (#KT-23058)
(cherry picked from commit 81f3346329)
2018-04-03 03:20:54 +03:00
Yan Zhulanow
5d236f7f85 Show warning alert when the installed Kotlin plugin version is incompatible with the IDE platform version
(cherry picked from commit 4d13e38948)
2018-04-03 03:20:50 +03:00
Yan Zhulanow
1e30cd822c EA-100549: Throw an exception with an additional data instead of Java assertion
(cherry picked from commit b664177bd5)
2018-04-03 03:20:47 +03:00
Yan Zhulanow
ceadec3c1b Fix EA-79206: Process only valid layout .xml files in Android Extensions
(cherry picked from commit ec0abb0854)
2018-04-03 03:20:43 +03:00
Yan Zhulanow
39d89fba95 Fix EA-113820: Accept also nullable elements in 'getRelevantElement()'
(cherry picked from commit c8a1517190)
2018-04-03 03:20:40 +03:00
Yan Zhulanow
5a72c8272e Fix compatibility for compiler API in DeclarationAttributeAltererExtension (EA-114961)
(cherry picked from commit 2b0489529d)
2018-04-03 03:20:37 +03:00
Yan Zhulanow
30beab4376 Remove "New Kotlin Activity" action as Android plugin can generate it by itself (#KT-22845, EA-114706)
(cherry picked from commit ff4cdfb43e)
2018-04-03 03:20:33 +03:00
Yan Zhulanow
4394fe26ce Debugger: A dirty fix for setting breakpoints inside finally {} in case if exception is thrown from try {} (#KT-22654)
(cherry picked from commit 966480a155)
2018-04-03 03:20:29 +03:00
Yan Zhulanow
aa75d887dc Debugger: Fix breakpoints and stepping for inline-only function lambda arguments (#KT-23064)
(cherry picked from commit eec9c6b)
2018-04-03 03:20:15 +03:00
Elifarley C
642611c43c toBigDecimal: Avoid creating new BigDecimal instance for some values
Avoid creating new `BigDecimal` instance by calling `BigDecimal.valueOf(this)`, which doesn't create a new instance if the argument falls in the range [0..10].
(there's a `private static final BigDecimal[] zeroThroughTen` cache in BigDecimal.java with 11 BigDecimal instances)

(cherry picked from commit 1b3d539)
2018-04-02 15:32:09 +03:00
Ilya Gorbunov
431504234d Minor code improvements, add more test cases #KT-11208
Compare new readLine with the reference implementation in BufferedReader.

(cherry picked from commit d2a235b)
2018-04-02 15:31:22 +03:00
meztihn
cfd92593c6 KT-11208 Remove readLine's new charset parameter
It can't be introduced in a patch release.

(cherry picked from commit 12e427b)
2018-04-02 15:31:12 +03:00
meztihn
2835f497b8 KT-11208 Improve readLine's tests readability
(cherry picked from commit cca7a59)
2018-04-02 15:31:00 +03:00
meztihn
129f6bebd9 KT-11208 Remove readLine's lineSeparator parameter
(cherry picked from commit 68cb66f)
2018-04-02 15:30:49 +03:00
meztihn
d5aa7f227f KT-11208 Remove stream buffering
(cherry picked from commit f6c1886)
2018-04-02 15:30:38 +03:00
Ilya Gorbunov
5692c1b086 kotlin-stdlib-js: do not import experimental sourceset in IDEA
Temporary workaround to prevent multiple IDEA modules sharing the same content root error.

(cherry picked from commit f45e3ac)
2018-04-02 15:30:29 +03:00
Alexey Sedunov
ffe7a58bf9 Move Out Of Object Intention: Fix assertion error
#KT-22983 Fixed

(cherry picked from commit b0a99c7)
2018-04-02 14:40:12 +03:00
Alexey Sedunov
82d8a3610a Extract Function: Drop extra space in modifier list
#KT-23274 Fixed

(cherry picked from commit 2104a0f)
2018-04-02 14:39:58 +03:00
Alexey Sedunov
4ec406fa6f Convert Function to Property: Forbid for properties with both initializer and getter
#KT-23293 Fixed

(cherry picked from commit 0a0043a)
2018-04-02 14:39:44 +03:00
Alexey Sedunov
80086c46e4 Rename: Increase precedence of RenameSyntheticDeclarationByReferenceHandler
Otherwise it's not applicable references to Java declarations

 #KT-20241 Fixed

(cherry picked from commit 43b4a49)
2018-04-02 14:39:29 +03:00
Alexey Sedunov
1e07f9aafa JS: Fix NodeJS run configuration support
#KT-16710 Fixed

(cherry picked from commit f4936d3)
2018-04-02 14:38:25 +03:00
Alexey Sedunov
7bcb11c94a Move: Support "Search references" option in dialogs
(cherry picked from commit e604707)
2018-04-02 14:38:15 +03:00
Vyacheslav Gerasimov
279befb46b Build: Fix dependency on markdown in :prepare:idea-plugin
org.jetbrains:markdown brings kotlin-stdlib dependency transitively, which resolves to default configuration of :kotlin-stdlib project. But we need to pack jar from distJar configuration. Also sourceSets.builtins.output is copied to plugin because :kotlin-stdlib has compile dependency on it. Probably we should also refactor :kotlin-stdlib to avoid such confusions in future.
2018-03-30 20:22:26 +03:00
Natalia Selezneva
545430ce98 Do not reload dependencies for scripts that wasn't recently touched
(cherry picked from commit 27f1eb1)
2018-03-30 14:45:51 +03:00
Natalia Selezneva
6d59778970 Do not show "Gradle Project needs to be imported" notification for gradle script if only spaces are added 2018-03-30 14:45:27 +03:00
Alexander Udalov
c52d6ad98f Sanitize compiler version for version requirement checks
Strip everything after (and including) the first '-' character.

The previous approach of skipping the checks if "SNAPSHOT" is in the
version, is subsumed by the new one because "1.2-SNAPSHOT" now becomes
"1.2" with regards to the version requirement checks, which allows the
compiler to use the 1.2-only API

(cherry picked from commit 5d9348eea1)
2018-03-29 17:12:46 +02:00
Alexander Podkhalyuzin
6000827eca Fixed aliased imports cache #KT-23430 Fixed
(cherry picked from commit b78869e)
2018-03-29 16:06:25 +02:00
Zalim Bashorov
675c1df26c [JS BE] Fix the crash on compound operations with a qualified call on left side
#KT-22001 Fixed

(cherry picked from commit 9349b9b)
2018-03-28 22:51:57 +03:00
Ilmir Usmanov
2a859144d1 Do not generate beforeInlineMarker on tailrec jump
Before this change, the codegen used to generate beforeInlineMarker
in order to spill variables later. However, since the tailrec call
is replaced with jump, no afterInlineMarker is generated, leading to
inconsistency of these markers. Thus, the spilling fails.
This change disables generating of beforeInlineMarker.

 #KT-21521: Fixed
2018-03-28 16:29:32 +03:00
Ilmir Usmanov
420b313920 Fix transforming of coroutine's create when it is suspend lambda with receiver
Unlike ordinary lambdas suspend lambdas has create method which invokes
the constructor of the lambda object (continuation).
The inliner could not cope with this.
The previous change fixed the case of suspend lambda without receiver.
This change adds support of suspend lambdas with receiver.

 #KT-21605: Fixed
2018-03-28 16:29:26 +03:00
Toshiaki Kameyama
e889c69226 Fix false positive in redundant companion reference #KT-23435 Fixed
(cherry picked from commit e96b5f3)
2018-03-28 13:30:02 +02:00
Mikhail Glukhikh
a14b079c8f Fix more broken QF tests
(cherry picked from commit 804d340)
2018-03-27 09:33:22 +02:00
Mikhail Glukhikh
e671879954 Fix broken QF tests
(cherry picked from commit e937a35)
2018-03-27 09:33:10 +02:00
Toshiaki Kameyama
8e04ecfd74 Add intentions for specifying use-site targets for an annotation
So #KT-19871 Fixed

(cherry picked from commit e06c137)
2018-03-27 09:32:59 +02:00
Toshiaki Kameyama
903c3a7b57 Fix two exceptions in "Convert concatenation to template
So #KT-23045 Fixed
So #KT-23045 Fixed

(cherry picked from commit 26dc584)
2018-03-27 09:32:44 +02:00
Toshiaki Kameyama
686b8e85ee Don't suggest 'Redundant semicolon' before lambda extension call
So #KT-23152 Fixed

(cherry picked from commit 7328f75)
2018-03-27 09:32:32 +02:00
Toshiaki Kameyama
86c27ef944 Suggest "Add annotation target" quick fix also for field use-site
So #KT-23227 Fixed

(cherry picked from commit a67068d)
2018-03-27 09:32:02 +02:00
Toshiaki Kameyama
cedeb86303 Suggest "Remove braces" in nested if correctly #KT-14270 Fixed
(cherry picked from commit e328d2d)
2018-03-27 09:31:49 +02:00
Toshiaki Kameyama
2afdb5a773 Fix "Add braces to if" when semicolon is used instead of a new line
So #KT-23123 Fixed

(cherry picked from commit 8082a5d)
2018-03-27 09:31:37 +02:00
Mikhail Glukhikh
01161b2dcb Fix parameter handling in "Move suspicious reference into parentheses"
Related to KT-21743

(cherry picked from commit b739db3)
2018-03-27 09:31:10 +02:00
Toshiaki Kameyama
09ac5ac1bb Fix "move suspicious reference into parentheses" for functional types
So #KT-21743 Fixed

(cherry picked from commit fbd06dc)
2018-03-27 09:30:58 +02:00
Toshiaki Kameyama
b542cc680b Add inspection to highlight unnecessary explicit companion references
So #KT-22971 Fixed

(cherry picked from commit 3fbf85d)
2018-03-27 09:30:45 +02:00
Alexander Udalov
e76ae20190 Report warnings on usages of kotlin-stdlib-jre7/kotlin-stdlib-jre8
#KT-21347 Fixed

(cherry picked from commit 46a1109910)
2018-03-26 19:08:14 +02:00
Nikolay Krasko
c8ab37e8ea Minor: another message fix (KT-23309)
#KT-23309 Fixed
2018-03-26 16:23:06 +03:00
Nikolay Krasko
c8b68d6ad1 Minor: typo fix (KT-23309)
#KT-23309 Fixed
2018-03-26 16:23:06 +03:00
Nikolay Krasko
06c3d7888f Fix generating cls stubs when is metadata using type tables (KT-23345)
Affected cases:
 - return type for suspend lambda
 - aliased type in type alias declaration
 - using type alias instead of aliased type in declarations

 #KT-23345 Fixed
2018-03-26 16:23:06 +03:00
Nikolay Krasko
21f26de894 Add -Xuse-type-table to jvm compiler options 2018-03-26 16:23:05 +03:00
Nikolay Krasko
1c5f1e152a Use stringValue for getting version of *jre usage in Maven (KT-23271)
#KT-23271 Fixed
2018-03-26 16:23:05 +03:00
Toshiaki Kameyama
e8a5f068fa KT-20282 'Move statement up' works incorrectly for statement after 'finally' block if 'try' block contains closure 2018-03-26 16:23:05 +03:00
Roman Artemev
71bc8633c8 Fixed handling of default params in declaration (KT-23239) 2018-03-26 15:44:21 +03:00
Roman Artemev
7d0087c55e Added test to check default params in declaration (issue KT-23239) 2018-03-26 15:44:13 +03:00
Denis Zharkov
6d29519dc3 Add a cache for PsiBasedClassResolver instances
The PsiBasedClassResolver constructor isn't very cheap to call
because it runs computation of conflicting names each time

Again, this is helpful for Spring-interop because PsiBasedClassResolver
is used very frequently there

 #KT-23380 Fixed
2018-03-26 08:00:48 +03:00
Denis Zharkov
5fffc1b268 Add a cache for KtImportDirective::importedFqName
It's very useful for Spring users because KotlinAnnotatedElementsSearcher
calls PsiBasedClassResolver::canBeTargetReference rather frequently
on a file and the latter function retreives importedFqName for each
import in the file that becomes a problem because computing fq-name
from PSI is a heavy computation

 #KT-23380 In Progress
2018-03-26 08:00:35 +03:00
Denis Zharkov
a0838fde35 Fix a memory leak of old resolve session from light classes
The problem is that diagnostics might indirectly retain a reference to an
obsolete ResolverForProject (it becomes outdated after out of block
modification).

At the same time light class instances may survive afer OOM when they
are leaked somewhere (e.g. to Java resolve)

The idea is to store the Diagnostics instance inside a
ResolverForProject component which will be collected once
ResolverForProject is collected itself.

 #KT-23380 In Progress
2018-03-26 08:00:22 +03:00
Mikhail Zarechenskiy
957f9c2a21 Prohibit incorrect annotations with use-site targets more precisely
#KT-21696 Fixed

The problem is coming from the fact that `AnnotationTarget.VALUE_PARAMETER` is mapped to receiver parameter and to value parameter, but annotation with use-site target `receiver` can be used only on type reference of receiver parameter
2018-03-25 18:25:19 +03:00
Mikhail Zarechenskiy
84cbada35b Minor, remove unused method, add TODO 2018-03-25 18:25:09 +03:00
Mikhail Zarechenskiy
fed1c0e476 Prohibit non-const expressions through varargs in annotations
Fixes #KT-23153 for Kotlin 1.3

 The problem was in the type check of expression type against expected type. When feature `AssigningArraysToVarargsInNamedFormInAnnotations` (KT-20171) appeared, expected type could be wrong, which led to failed type check
2018-03-25 18:24:58 +03:00
Mikhail Zarechenskiy
bbf5e08990 Refactoring: rename parameter to argument for annotation diagnostics 2018-03-25 18:24:48 +03:00
Mikhail Zarechenskiy
6054645508 Refactor and prettify checkCompileTimeConstant method 2018-03-25 18:24:37 +03:00
Alexey Tsvetkov
ba33de6665 IC: add destination dir to start of classpath instead of end
Otherwise IC fails when a project declares a class with the same name
as in one of its dependencies.
The issue is relevant only for non-JPS IC (Gradle, Maven, etc.),
but I added the test for JPS too.

  #KT-20516 fixed
2018-03-24 23:10:11 +03:00
Alexey Tsvetkov
1264c4c048 Do not exclude :ultimate:generateTests in "Generate All Tests"
:ultimate is excluded by default now,
so `-x :ultimate:generateTests` fails
2018-03-24 23:10:07 +03:00
Ilmir Usmanov
aaf56ddbbc Do not ignore copy operations while finding source instructions
in redundant locals elimination.

Since IgnoringCopySourceInterpreter ignores ALOADs and ASTOREs,
the source instruction of ALOAD K in {ALOAD N, ASTORE K, ALOAD K}
sequence is not ASTORE K. In this case we cannot simply replace K
with N, since there can be multiple {ALOAD N, ASTORE K} sequences
in separate branches. After replacement we get different stack
frames.
This change resolves this.

However, in ReturnUnitMethodTransformer we want to ignore copies
of the same GETSTATIC kotlin/Unit.INSTANCE, since we do not mess
with local variables and just replace ASTORE with ARETURN to help
tail-call optimization.
 #KT-23373: Fixed
2018-03-23 22:02:21 +03:00
Ilmir Usmanov
6a2b9c33fc Raise deprecation level to ERROR of coroutineContext
inside kotlin.coroutines.experimental.intrinsics package
 #KT-22400
2018-03-23 22:02:11 +03:00
Yan Zhulanow
6fd4b0d4ab Update changelog for Kotlin 1.2.40 2018-03-23 21:13:25 +03:00
Natalia Selezneva
44ab7c49af Fix compatibility with LivePlugin
^KT-23371 Fixed

(cherry picked from commit c7513b5)
2018-03-22 17:23:09 +03:00
Yan Zhulanow
f0433b7ec1 Android modules should not be imported as common modules (#KT-23367) 2018-03-22 04:54:09 +03:00
Yan Zhulanow
a96e61c96c Minor: Add Android Studio platform prefix in Android patchset branches to fix 'runIde' task for them 2018-03-22 04:54:02 +03:00
Yan Zhulanow
73e255c97c Minor: Fix bundled Kotlin plugin removal in Android Studio bundle for macOS 2018-03-22 04:53:56 +03:00
Natalia Selezneva
3559ed669d Set FATAL severity for errors from GradleScriptTemplateProvider
(cherry picked from commit 3b11b89)
2018-03-21 19:38:13 +03:00
Alexander Podkhalyuzin
089a7eed11 Fixed broken exception reporter
(cherry picked from commit 7d72fe0)
2018-03-21 17:40:37 +03:00
Denis Zharkov
fdb7995a3f Avoid retaining whole KotlinClassHeader in IDEKotlinBinaryClassCache
Before this change there was a retention chain
VirtualFile -> KotlinBinaryData -> KotlinBinaryHeaderData -> KotlinClassHeader

The latter one contains all binary metadata (a lot of String[])
while only a small part of it is used.

The used parts are moved straight to KotlinBinaryClassHeaderData
in this change.

 #KT-19484 Fixed
2018-03-20 10:46:44 +03:00
Alexey Tsvetkov
fb8759dc8c Set up idea.home.path in :incremental-compilation-impl
To avoid warnings in stderr
2018-03-19 19:01:13 +03:00
Alexey Tsvetkov
dad2274ff1 Report correct source to output mapping for kjsm files
Now IC can correctly remove kjsm files when source files are changed
2018-03-19 19:01:08 +03:00
Alexey Tsvetkov
e1e139fb02 Remove all kjsm files before writing new ones 2018-03-19 19:01:03 +03:00
Alexey Tsvetkov
1b699c5039 Compare diverged .meta.js files in a human readable way 2018-03-19 19:00:59 +03:00
Alexey Tsvetkov
fda9d5d5bb Fix comparing directories after IC test
A directory-after-rebuild should correspond to expectedDir parameter,
a directory-after-IC should correspond to actualDir parameter.
Also we should not forgive extra directories.
2018-03-19 19:00:55 +03:00
Alexey Tsvetkov
bf5e67cad3 Generate meta info in JS IC tests 2018-03-19 19:00:50 +03:00
Alexey Tsvetkov
4def41144b Avoid serializing JS metadata twice per compilation 2018-03-19 19:00:45 +03:00
Alexey Tsvetkov
d9191a0ace Sort package fragments by fq-name for JS serialization 2018-03-19 19:00:41 +03:00
Alexey Tsvetkov
4092608ff6 Optimize serializing JS metadata
This makes JS IC tests twice as fast
2018-03-19 19:00:37 +03:00
Alexey Tsvetkov
f711fc8406 Avoid reading JS libraries twice per compilation 2018-03-19 19:00:33 +03:00
Alexey Tsvetkov
355a0f8859 Improve JS inliner performance 2018-03-19 19:00:29 +03:00
Alexey Tsvetkov
eb01d9aaaf Ensure all output directories are cleared on IC rebuild
In some cases IC needs to perform a rebuild.
Before this change IC was not clearing output directories
besides destination dir for classes, so for example
kapt stubs were not cleared.

Stalled stubs might lead to compile errors.
For example:
1. foo/XGen.java is generated from annotated class foo/X (XGen also
references X).
2. foo/X is moved to bar/X and some other change forces IC to rebuild.
3. kapt generates bar/X stub, but foo/X stub
was not removed because stubs dir is not cleared.
4. kapt runs annotation processors, foo/XGen.java is generated from
foo/X stub, bar/XGen.java is generated from bar/X stub.
5. kotlinc rebuilds. Since destination dir is cleared properly,
only bar/X.class exists.
6. javac tries to compile foo/XGen and fails, because it
compiles against actual Kotlin classes, not stubs.

This commit fixes the issue by passing all output directories
of a task from Gradle to Kotlin IC.

   #KT-21735 fixed
2018-03-19 17:43:53 +03:00
Alexey Tsvetkov
3cbd842b8b Fix unresolved references in kotlin-gradle-plugin in Idea 2018-03-19 17:43:48 +03:00
Ilya Chernikov
f960ca38eb Implement support for additional compiler arguments for scripts in IDE
fixes #KT-19120
2018-03-19 11:51:14 +01:00
Ilya Chernikov
dff4cfd1fc Refactor language feature settings processing for exposing it outside of the CLI compiler 2018-03-19 11:50:50 +01:00
Natalia Selezneva
1a2f4223c3 Add test for fatal severity in scripts
(cherry picked from commit 58edab3)
2018-03-19 12:55:04 +03:00
Natalia Selezneva
7c8dcdee62 Add FATAL severity to ScriptExternalHighlightingPass
(cherry picked from commit f957b30)
2018-03-19 12:54:42 +03:00
Natalia Selezneva
b3af085cfd Add FATAL severity to script dependencies resolve result
(cherry picked from commit dcea9d0)
2018-03-19 12:54:14 +03:00
Natalia Selezneva
4844176f49 Restore old package for ScriptTemplatesProvider.
Note that this is EP used in another plugins (ex. LivePlugin https://plugins.jetbrains.com/plugin/7282-liveplugin)

(cherry picked from commit 82481b4)
2018-03-19 12:53:53 +03:00
Natalia Selezneva
0bcb6851e9 Don't highlight gradle scripts during gradle import.
Show warning on the top panel for these files

(cherry picked from commit 1f75eae)
2018-03-19 12:52:05 +03:00
Natalia Selezneva
4645884785 Don't highlight scripts if resolver returns Failure.
Note that we don't highlight script when ScriptDependenciesFileAttribute is not set.

(cherry picked from commit 5f1118e)
2018-03-19 12:49:59 +03:00
Natalia Selezneva
576974f7ad Scripts: display errors from external resolver in panel if text range is empty
(cherry picked from commit 4b4acfe)
2018-03-19 12:49:33 +03:00
Natalia Selezneva
923716e38f Introduce default ScriptTemplate for Gradle scripts
^KT-23228 Fixed

(cherry picked from commit 26a4b67)
2018-03-19 12:49:09 +03:00
Natalia Selezneva
41dc8b6263 Minor: reformat
(cherry picked from commit 9f02664)
2018-03-19 12:47:04 +03:00
840 changed files with 15058 additions and 3114 deletions

View File

@@ -4,7 +4,7 @@
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-x :ultimate:generateTests" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>

View File

@@ -1,5 +1,243 @@
# CHANGELOG
## 1.2.41
### Compiler Fixes
- [`KT-23901`](https://youtrack.jetbrains.com/issue/KT-23901) Incremental compilation fails on Java 9
- [`KT-23931`](https://youtrack.jetbrains.com/issue/KT-23931) Exception on optimizing eternal loops
- [`KT-23900`](https://youtrack.jetbrains.com/issue/KT-23900) Exception on some cases with nested arrays
- [`KT-23809`](https://youtrack.jetbrains.com/issue/KT-23809) Exception on processing complex hierarchies with `suspend` functions when `-Xdump-declarations-to` is active
### Other
- [`KT-23973`](https://youtrack.jetbrains.com/issue/KT-23973) New compiler behavior lead to ambiguous mappings in Spring Boot temporarily reverted
## 1.2.40
### Compiler
#### New Features
- [`KT-22703`](https://youtrack.jetbrains.com/issue/KT-22703) Allow expect/actual annotation constructors to have default values
- [`KT-19159`](https://youtrack.jetbrains.com/issue/KT-19159) Support `crossinline` lambda parameters of `suspend` function type
- [`KT-21913`](https://youtrack.jetbrains.com/issue/KT-21913) Support default arguments for expected declarations
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Provide extra compiler arguments in `ScriptTemplateDefinition`
- [`KT-19415`](https://youtrack.jetbrains.com/issue/KT-19415) Introduce `@JvmDefault` annotation
- [`KT-21515`](https://youtrack.jetbrains.com/issue/KT-21515) Restrict visibility of classifiers inside `companion object`s
#### Performance Improvements
- [`KT-10057`](https://youtrack.jetbrains.com/issue/KT-10057) Use `lcmp` instruction instead of `kotlin/jvm/internal/Intrinsics.compare`
- [`KT-14258`](https://youtrack.jetbrains.com/issue/KT-14258) Suboptimal codegen for private fieldaccess to private field in companion object
- [`KT-18731`](https://youtrack.jetbrains.com/issue/KT-18731) `==` between enums should use reference equality, not `Intrinsics.areEqual()`.
- [`KT-22714`](https://youtrack.jetbrains.com/issue/KT-22714) Unnecessary checkcast to array of object from an array of specific type
- [`KT-5177`](https://youtrack.jetbrains.com/issue/KT-5177) Optimize code generation for `for` loop with `withIndex()`
- [`KT-19477`](https://youtrack.jetbrains.com/issue/KT-19477) Allow to implement several common modules with a single platform module
- [`KT-21347`](https://youtrack.jetbrains.com/issue/KT-21347) Add compiler warning about using kotlin-stdlib-jre7 or kotlin-stdlib-jre8 artifacts
#### Fixes
- [`KT-16424`](https://youtrack.jetbrains.com/issue/KT-16424) Broken bytecode for nullable generic methods
- [`KT-17171`](https://youtrack.jetbrains.com/issue/KT-17171) `ClassCastException` in case of SAM conversion with `out` variance
- [`KT-19399`](https://youtrack.jetbrains.com/issue/KT-19399) Incorrect bytecode generated for inline functions in some complex cases
- [`KT-21696`](https://youtrack.jetbrains.com/issue/KT-21696) Incorrect warning for use-site target on extension function
- [`KT-22031`](https://youtrack.jetbrains.com/issue/KT-22031) Non-`abstract` expect classes should not have `abstract` members
- [`KT-22260`](https://youtrack.jetbrains.com/issue/KT-22260) Never flag `inline suspend fun` with `NOTHING_TO_INLINE`
- [`KT-22352`](https://youtrack.jetbrains.com/issue/KT-22352) Expect/actual checker can't handle properties and functions with the same name
- [`KT-22652`](https://youtrack.jetbrains.com/issue/KT-22652) Interface with default overrides is not perceived as a SAM
- [`KT-22904`](https://youtrack.jetbrains.com/issue/KT-22904) Incorrect bytecode generated for withIndex iteration on `Array<Int>`
- [`KT-22906`](https://youtrack.jetbrains.com/issue/KT-22906) Invalid class name generated for lambda created from method reference in anonymous object
- [`KT-23044`](https://youtrack.jetbrains.com/issue/KT-23044) Overriden public property with internal setter cannot be found in runtime
- [`KT-23104`](https://youtrack.jetbrains.com/issue/KT-23104) Incorrect code generated for LHS of an intrinsified `in` operator in case of generic type substituted with `Character`
- [`KT-23309`](https://youtrack.jetbrains.com/issue/KT-23309) Minor spelling errors in JVM internal error messages
- [`KT-22001`](https://youtrack.jetbrains.com/issue/KT-22001) JS: compiler crashes on += with "complex" receiver
- [`KT-23239`](https://youtrack.jetbrains.com/issue/KT-23239) JS: Default arguments for non-final member function support is missing for MPP
- [`KT-17091`](https://youtrack.jetbrains.com/issue/KT-17091) Converting to SAM Java type appends non-deterministic hash to class name
- [`KT-21521`](https://youtrack.jetbrains.com/issue/KT-21521) Compilation exception when trying to compile a `suspend` function with `tailrec` keyword
- [`KT-21605`](https://youtrack.jetbrains.com/issue/KT-21605) Cross-inlined coroutine with captured outer receiver creates unverifiable code
- [`KT-21864`](https://youtrack.jetbrains.com/issue/KT-21864) Expect-actual matcher doesn't consider generic upper bounds
- [`KT-21906`](https://youtrack.jetbrains.com/issue/KT-21906) `ACTUAL_MISSING` is reported for actual constructor of non-actual class
- [`KT-21939`](https://youtrack.jetbrains.com/issue/KT-21939) Improve `ACTUAL_MISSING` diagnostics message
- [`KT-22513`](https://youtrack.jetbrains.com/issue/KT-22513) Flaky "JarURLConnection.getUseCaches" NPE during compilation when using compiler plugins
### Libraries
- [`KT-11208`](https://youtrack.jetbrains.com/issue/KT-11208) `readLine()` shouldn't use buffered reader
### IDE
#### New Features
- [`KT-10368`](https://youtrack.jetbrains.com/issue/KT-10368) Run Action for Kotlin Scratch Files
- [`KT-16892`](https://youtrack.jetbrains.com/issue/KT-16892) Shortcut to navigate between header and impl
- [`KT-23005`](https://youtrack.jetbrains.com/issue/KT-23005) Support `prefix`/`suffix` attributes for language injection in Kotlin with annotations and comments
#### Performance Improvements
- [`KT-19484`](https://youtrack.jetbrains.com/issue/KT-19484) KotlinBinaryClassCache retains a lot of memory
- [`KT-23183`](https://youtrack.jetbrains.com/issue/KT-23183) `ConfigureKotlinNotification.getNotificationString()` scans modules with Kotlin files twice
- [`KT-23380`](https://youtrack.jetbrains.com/issue/KT-23380) Improve IDE performance when working with Spring projects
#### Fixes
- [`KT-15482`](https://youtrack.jetbrains.com/issue/KT-15482) `KotlinNullPointerException` in IDE from expected class with nested class
- [`KT-15739`](https://youtrack.jetbrains.com/issue/KT-15739) Internal visibility across common and platform-dependent modules
- [`KT-19025`](https://youtrack.jetbrains.com/issue/KT-19025) Not imported `build.gradle.kts` is all red
- [`KT-19165`](https://youtrack.jetbrains.com/issue/KT-19165) IntelliJ should suggest to reload Gradle projects when `build.gradle.kts` changes
- [`KT-20282`](https://youtrack.jetbrains.com/issue/KT-20282) 'Move statement up' works incorrectly for statement after `finally` block if `try` block contains closure
- [`KT-20521`](https://youtrack.jetbrains.com/issue/KT-20521) Kotlin Gradle script: valid `build.gradle.kts` is red and becomes normal only after reopening the project
- [`KT-20592`](https://youtrack.jetbrains.com/issue/KT-20592) `KotlinNullPointerException`: nested class inside expect / actual interface
- [`KT-21013`](https://youtrack.jetbrains.com/issue/KT-21013) "Move statement up/down" fails for multiline declarations
- [`KT-21420`](https://youtrack.jetbrains.com/issue/KT-21420) `.gradle.kts` editor should do no semantic highlighting until the first successful dependency resolver response
- [`KT-21683`](https://youtrack.jetbrains.com/issue/KT-21683) Language injection: JPAQL. Injection should be present for "query" parameter of `@NamedNativeQueries`
- [`KT-21745`](https://youtrack.jetbrains.com/issue/KT-21745) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Maven
- [`KT-21746`](https://youtrack.jetbrains.com/issue/KT-21746) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Gradle
- [`KT-21753`](https://youtrack.jetbrains.com/issue/KT-21753) Language injection: SpEL. Not injected for key in `@Caching`
- [`KT-21771`](https://youtrack.jetbrains.com/issue/KT-21771) All annotations in `Annotations.kt` from kotlin-test-js module wrongly have ACTUAL_MISSING
- [`KT-21831`](https://youtrack.jetbrains.com/issue/KT-21831) Opening class from `kotlin-stdlib-jdk8.jar` fails with EE: "Stub list in ... length differs from PSI"
- [`KT-22229`](https://youtrack.jetbrains.com/issue/KT-22229) Kotlin local delegated property Import auto-removed with "Java: Optimize imports on the fly"
- [`KT-22724`](https://youtrack.jetbrains.com/issue/KT-22724) ISE: "psiFile must not be null" at `KotlinNodeJsRunConfigurationProducer.setupConfigurationFromContext()`
- [`KT-22817`](https://youtrack.jetbrains.com/issue/KT-22817) Hitting 'Propagate Parameters' in Change Signature throws `UnsupportedOperationException`
- [`KT-22851`](https://youtrack.jetbrains.com/issue/KT-22851) Apply button is always active on Kotlin compiler settings tab
- [`KT-22858`](https://youtrack.jetbrains.com/issue/KT-22858) Multiplatform: String constructor parameter is reported in Java file of jvm module on creation of a new instance of a class from common module
- [`KT-22865`](https://youtrack.jetbrains.com/issue/KT-22865) Support multiple expectedBy dependencies when importing project from Gradle or Maven
- [`KT-22873`](https://youtrack.jetbrains.com/issue/KT-22873) Common module-based light classes do not see JDK
- [`KT-22874`](https://youtrack.jetbrains.com/issue/KT-22874) Exception on surround with "if else" when resulting if should be wrapped with `()`
- [`KT-22925`](https://youtrack.jetbrains.com/issue/KT-22925) Unable to view Type Hierarchy from constructor call in expression
- [`KT-22926`](https://youtrack.jetbrains.com/issue/KT-22926) Confusing behavior of Type Hierarchy depending on the caret position at superclass constructor
- [`KT-23097`](https://youtrack.jetbrains.com/issue/KT-23097) Enhance multiplatform project wizard
- [`KT-23271`](https://youtrack.jetbrains.com/issue/KT-23271) Warn about using kotlin-stdlib-jre* libs in `dependencyManagement` section in Maven with `eap` and `dev` Kotlin versions
- [`KT-20672`](https://youtrack.jetbrains.com/issue/KT-20672) IDE can't resolve references to elements from files with `@JvmPackageName`
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Variable name auto-completion popup gets in the way
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Do not show duplicated names in variables completion list
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Use script compiler options on script dependencies in the IDE as well
### IDE. Gradle. Script
- [`KT-23228`](https://youtrack.jetbrains.com/issue/KT-23228) Do not highlight `.gradle.kts` files in non-Gradle projects
### IDE. Inspections and Intentions
#### New Features
- [`KT-16382`](https://youtrack.jetbrains.com/issue/KT-16382) Intention to convert `expr.unsafeCast<Type>()` to `expr as Type` and vice versa
- [`KT-20439`](https://youtrack.jetbrains.com/issue/KT-20439) Intentions to add/remove labeled return to last expression in a lambda
- [`KT-22011`](https://youtrack.jetbrains.com/issue/KT-22011) Inspection to report the usage of Java Collections methods on immutable Kotlin Collections
- [`KT-22933`](https://youtrack.jetbrains.com/issue/KT-22933) Intention/inspection to convert Pair constructor to `to` function
- [`KT-19871`](https://youtrack.jetbrains.com/issue/KT-19871) Intentions for specifying use-site targets for an annotation
- [`KT-22971`](https://youtrack.jetbrains.com/issue/KT-22971) Inspection to highlight and remove unnecessary explicit companion object references
#### Fixes
- [`KT-12226`](https://youtrack.jetbrains.com/issue/KT-12226) "Convert concatenation to template" does not process `$` sign as a Char
- [`KT-15858`](https://youtrack.jetbrains.com/issue/KT-15858) "Replace with a `foreach` function call" intention breaks code
- [`KT-16332`](https://youtrack.jetbrains.com/issue/KT-16332) Add braces to 'if' statement intention does not put end-of-line comment properly into braces
- [`KT-17058`](https://youtrack.jetbrains.com/issue/KT-17058) "Create implementations from headers": each implementation gets own file
- [`KT-17306`](https://youtrack.jetbrains.com/issue/KT-17306) Don't report package name mismatch if there's no Java code in the module
- [`KT-19730`](https://youtrack.jetbrains.com/issue/KT-19730) Quickfix for delegated properties boilerplate generation doesn't work on locals
- [`KT-21005`](https://youtrack.jetbrains.com/issue/KT-21005) "Missing KDoc inspection" is broken
- [`KT-21082`](https://youtrack.jetbrains.com/issue/KT-21082) "Create actual declaration" of top-level subclass of expected `sealed class` in the same file as actual declaration of sealed class present
- [`KT-22110`](https://youtrack.jetbrains.com/issue/KT-22110) "Can be joined with assignment" inspection underlining extends into comment
- [`KT-22329`](https://youtrack.jetbrains.com/issue/KT-22329) "Create class" quickfix is not suggested in `when` branch
- [`KT-22428`](https://youtrack.jetbrains.com/issue/KT-22428) Create member function from usage shouldn't present type parameters as options
- [`KT-22492`](https://youtrack.jetbrains.com/issue/KT-22492) "Specify explicit lambda signature" intention is available only on lambda braces
- [`KT-22719`](https://youtrack.jetbrains.com/issue/KT-22719) Incorrect warning 'Redundant semicolon' when having method call before lambda expression
- [`KT-22861`](https://youtrack.jetbrains.com/issue/KT-22861) "Add annotation target" quickfix is not available on annotation with use site target
- [`KT-22862`](https://youtrack.jetbrains.com/issue/KT-22862) "Add annotation target" quickfix does not process existent annotations with use site target
- [`KT-22917`](https://youtrack.jetbrains.com/issue/KT-22917) Update order of containers for `create class` quickfix
- [`KT-22949`](https://youtrack.jetbrains.com/issue/KT-22949) NPE on conversion of `run`/`apply` with explicit lambda signature to `let`/`also`
- [`KT-22950`](https://youtrack.jetbrains.com/issue/KT-22950) Convert stdlib extension function to scoping function works incorrectly in case of explicit lambda signature
- [`KT-22954`](https://youtrack.jetbrains.com/issue/KT-22954) "Sort modifiers" quickfix works incorrectly when method is annotated
- [`KT-22970`](https://youtrack.jetbrains.com/issue/KT-22970) Add explicit this intention/inspection missing for lambda invocation
- [`KT-23109`](https://youtrack.jetbrains.com/issue/KT-23109) "Remove redundant 'if' statement" inspection breaks code with labeled return
- [`KT-23215`](https://youtrack.jetbrains.com/issue/KT-23215) "Add function to supertype" quickfix works incorrectly
- [`KT-14270`](https://youtrack.jetbrains.com/issue/KT-14270) Intentions "Add/Remove braces" should be applied to the statement where caret is if there several nested statements one into another
- [`KT-21743`](https://youtrack.jetbrains.com/issue/KT-21743) Method reference not correctly moved into parentheses
- [`KT-23045`](https://youtrack.jetbrains.com/issue/KT-23045) AE “Failed to create expression from text” on concatenating string with broken quote mark char literal
- [`KT-23046`](https://youtrack.jetbrains.com/issue/KT-23046) CCE ”KtBinaryExpression cannot be cast to KtStringTemplateExpression” on concatenating broken quote mark char literal with string
- [`KT-23227`](https://youtrack.jetbrains.com/issue/KT-23227) "Add annotation target" quickfix is not suggested for `field:` use-site target
### IDE. Refactorings
#### Fixes
- [`KT-13255`](https://youtrack.jetbrains.com/issue/KT-13255) Refactor / Rename: renaming local variable or class to existing name gives no warning
- [`KT-13284`](https://youtrack.jetbrains.com/issue/KT-13284) Refactor / Rename: superfluous imports and FQNs in Java using `@JvmOverloads` functions
- [`KT-13907`](https://youtrack.jetbrains.com/issue/KT-13907) Rename refactoring warns about name conflict if there is function with different signature but the same name
- [`KT-13986`](https://youtrack.jetbrains.com/issue/KT-13986) Full qualified names of classes in comments should be changed after class Move, if comment contains backquotes
- [`KT-14671`](https://youtrack.jetbrains.com/issue/KT-14671) `typealias`: refactor/rename should propose to rename occurrences in comments
- [`KT-15039`](https://youtrack.jetbrains.com/issue/KT-15039) Extra usage is found for a parameter in data class in destructuring construction
- [`KT-15228`](https://youtrack.jetbrains.com/issue/KT-15228) Extract function from inline function should create public function
- [`KT-15302`](https://youtrack.jetbrains.com/issue/KT-15302) Reference to typealias in SAM conversion is not found
- [`KT-16510`](https://youtrack.jetbrains.com/issue/KT-16510) Can't rename quoted identifier `is`
- [`KT-17827`](https://youtrack.jetbrains.com/issue/KT-17827) Refactor / Move corrupts bound references when containing class of member element is changed
- [`KT-19561`](https://youtrack.jetbrains.com/issue/KT-19561) Name conflict warning when renaming method to a name matching an extension method with the same name exists
- [`KT-20178`](https://youtrack.jetbrains.com/issue/KT-20178) Refactor → Rename can't make companion object name empty
- [`KT-22282`](https://youtrack.jetbrains.com/issue/KT-22282) Moving a Kotlin file to another package does not change imports in itself
- [`KT-22482`](https://youtrack.jetbrains.com/issue/KT-22482) Rename refactoring insert qualifier for non related property call
- [`KT-22661`](https://youtrack.jetbrains.com/issue/KT-22661) Refactor/Move: top level field reference is not imported automatically after move to the source root
- [`KT-22678`](https://youtrack.jetbrains.com/issue/KT-22678) Refactor / Copy: "Class uses constructor which will be inaccessible after move" when derived class has a protected constructor
- [`KT-22692`](https://youtrack.jetbrains.com/issue/KT-22692) Refactor/Move: unnecessary curly braces added on moving to a separate file a top level function with a top level field usage
- [`KT-22745`](https://youtrack.jetbrains.com/issue/KT-22745) Refactor/Move inserts FQ function name at the call site if there is a field same named as the function
- [`KT-22747`](https://youtrack.jetbrains.com/issue/KT-22747) Moving top-level function to a different (existing) file doesn't update references from Java
- [`KT-22751`](https://youtrack.jetbrains.com/issue/KT-22751) Refactor/Rename: type alias name clash is not reported
- [`KT-22769`](https://youtrack.jetbrains.com/issue/KT-22769) Refactor/Move: there is no warning on moving sealed class or its inheritors to another file
- [`KT-22771`](https://youtrack.jetbrains.com/issue/KT-22771) Refactor/Move: there is no warning on moving nested class to another class with stricter visibility
- [`KT-22812`](https://youtrack.jetbrains.com/issue/KT-22812) Refactor/Rename extension functions incorrectly conflicts with other extension functions
- [`KT-23065`](https://youtrack.jetbrains.com/issue/KT-23065) Refactor/Move: Specify the warning message on moving sealed class inheritors without moving the sealed class itself
### IDE. Script
- [`KT-22647`](https://youtrack.jetbrains.com/issue/KT-22647) Run script Action in IDE should use Kotlin compiler from the IDE plugin
- [`KT-18930`](https://youtrack.jetbrains.com/issue/KT-18930) IDEA is unstable With Gradle Kotlin DSL
- [`KT-21042`](https://youtrack.jetbrains.com/issue/KT-21042) Gradle Script Kotlin project is full-red
- [`KT-11618`](https://youtrack.jetbrains.com/issue/KT-11618) Running .kts file from IntelliJ IDEA doesn't allow to import classes in other files which are also part of the project
### IDE. Debugger
- [`KT-22205`](https://youtrack.jetbrains.com/issue/KT-22205) Breakpoints won't work for Kotlin testing with JUnit
### JavaScript
- [`KT-22019`](https://youtrack.jetbrains.com/issue/KT-22019) Fix wrong list sorting order
### Tools. CLI
- [`KT-22777`](https://youtrack.jetbrains.com/issue/KT-22777) Unstable language version setting has no effect when attached runtime has lower version
### Tools. Gradle
- [`KT-22824`](https://youtrack.jetbrains.com/issue/KT-22824) `expectedBy` dependency should be expressed as `compile` dependency in POM
- [`KT-15371`](https://youtrack.jetbrains.com/issue/KT-15371) Multiplatform: setting free compiler args can break build
- [`KT-22864`](https://youtrack.jetbrains.com/issue/KT-22864) Allow multiple expectedBy configuration dependencies in Gradle
- [`KT-22895`](https://youtrack.jetbrains.com/issue/KT-22895) 'kotlin-runtime' library is missing in the compiler classpath sometimes
- [`KT-23085`](https://youtrack.jetbrains.com/issue/KT-23085) Use proper names for the Gradle task inputs/outputs added at runtime
- [`KT-23694`](https://youtrack.jetbrains.com/issue/KT-23694) Fix parallel build in Kotlin IC invalid KotlinCoreEnvironment disposal
### Tools. Android
- Android Extensions: Support fragments from kotlinx package;
### Tools. Incremental Compile
- [`KT-20516`](https://youtrack.jetbrains.com/issue/KT-20516) "Unresolved reference" when project declares same class as its dependency
- [`KT-22542`](https://youtrack.jetbrains.com/issue/KT-22542) "Source file or directory not found" for incremental compilation with Kobalt
- [`KT-23165`](https://youtrack.jetbrains.com/issue/KT-23165) Incremental compilation is sometimes broken after moving one class
### Tools. JPS
- [`KT-16091`](https://youtrack.jetbrains.com/issue/KT-16091) Incremental compilation ignores changes in Java static field
- [`KT-22995`](https://youtrack.jetbrains.com/issue/KT-22995) EA-91869 - NA: `LookupStorage.<init>`
### Tools. kapt
- [`KT-21735`](https://youtrack.jetbrains.com/issue/KT-21735) Kapt cache was not cleared sometimes
### Tools. REPL
- [`KT-21611`](https://youtrack.jetbrains.com/issue/KT-21611) REPL: Empty lines should be ignored
## 1.2.30
### Android

View File

@@ -29,15 +29,16 @@ Welcome to [Kotlin](https://kotlinlang.org/)! Some handy links:
In order to build Kotlin distribution you need to have:
- JDK 1.6, 1.7 and 1.8
- JDK 1.6, 1.7, 1.8 and 9
- Setup environment variables as following:
JAVA_HOME="path to JDK 1.8"
JDK_16="path to JDK 1.6"
JDK_17="path to JDK 1.7"
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 8 installed, and to point all of the environment variables mentioned above to your JDK 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_properties_and_system_properties) to setup JDK_* variables.

View File

@@ -54,13 +54,16 @@ abstract class IncrementalCacheCommon<ClassName>(workingDir: File) : BasicMapsOw
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
fun getSubtypesOf(className: FqName): Sequence<FqName> =
subtypesMap[className].asSequence()
fun getSourceFileIfClass(fqName: FqName): File? =
classFqNameToSourceMap[fqName]
open fun markDirty(removedAndCompiledSources: List<File>) {
open fun markDirty(removedAndCompiledSources: Collection<File>) {
for (sourceFile in removedAndCompiledSources) {
val classes = sourceToClassesMap[sourceFile]
classes.forEach {

View File

@@ -60,7 +60,7 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon<FqName>(
headerFile.writeBytes(value)
}
override fun markDirty(removedAndCompiledSources: List<File>) {
override fun markDirty(removedAndCompiledSources: Collection<File>) {
super.markDirty(removedAndCompiledSources)
dirtySources.addAll(removedAndCompiledSources)
}

View File

@@ -82,6 +82,9 @@ open class IncrementalJvmCache(
fun classesBySources(sources: Iterable<File>): Iterable<JvmClassName> =
sources.flatMap { sourceToClassesMap[it] }
fun sourceInCache(file: File): Boolean =
sourceToClassesMap.contains(file)
fun sourcesByInternalName(internalName: String): Collection<File> =
internalNameToSource[internalName]

View File

@@ -22,20 +22,27 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
internal interface NameTransformer<Name> {
fun asString(name: Name): String
fun asName(string: String): Name
fun asFqName(string: String): FqName
}
internal object FqNameTransformer : NameTransformer<FqName> {
override fun asString(name: FqName): String =
name.asString()
name.asString()
override fun asName(string: String): FqName =
FqName(string)
FqName(string)
override fun asFqName(string: String): FqName =
asName(string)
}
internal object JvmClassNameTransformer : NameTransformer<JvmClassName> {
override fun asString(name: JvmClassName): String =
name.internalName
name.internalName
override fun asName(string: String): JvmClassName =
JvmClassName.byInternalName(string)
JvmClassName.byInternalName(string)
override fun asFqName(string: String): FqName =
asName(string).fqNameForClassNameWithoutDollars
}

View File

@@ -42,6 +42,9 @@ internal abstract class AbstractSourceToOutputMap<Name>(
operator fun get(sourceFile: File): Collection<Name> =
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asName)
fun getFqNames(sourceFile: File): Collection<FqName> =
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asFqName)
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()

View File

@@ -20,9 +20,13 @@ import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.DebugProtoBuf
import org.jetbrains.kotlin.metadata.js.DebugJsProtoBuf
import org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
import org.jetbrains.kotlin.protobuf.ExtensionRegistry
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor
@@ -34,6 +38,8 @@ import java.io.PrintWriter
import java.io.StringWriter
import java.util.*
import java.util.zip.CRC32
import java.util.zip.GZIPInputStream
import kotlin.comparisons.compareBy
// Set this to true if you want to dump all bytecode (test will fail in this case)
private val DUMP_ALL = System.getProperty("comparison.dump.all") == "true"
@@ -162,6 +168,24 @@ private fun classFileToString(classFile: File): String {
return out.toString()
}
private fun metaJsToString(metaJsFile: File): String {
val out = StringWriter()
val metadataList = arrayListOf<KotlinJavascriptMetadata>()
KotlinJavascriptMetadataUtils.parseMetadata(metaJsFile.readText(), metadataList)
for (metadata in metadataList) {
val (header, content) = GZIPInputStream(ByteArrayInputStream(metadata.body)).use { stream ->
DebugJsProtoBuf.Header.parseDelimitedFrom(stream, JsSerializerProtocol.extensionRegistry) to
DebugJsProtoBuf.Library.parseFrom(stream, JsSerializerProtocol.extensionRegistry)
}
out.write("\n------ header -----\n$header")
out.write("\n------ library -----\n$content")
}
return out.toString()
}
private fun getExtensionRegistry(): ExtensionRegistry {
val registry = ExtensionRegistry.newInstance()!!
DebugJvmProtoBuf.registerAllExtensions(registry)
@@ -173,6 +197,9 @@ private fun fileToStringRepresentation(file: File): String {
file.name.endsWith(".class") -> {
classFileToString(file)
}
file.name.endsWith(KotlinJavascriptMetadataUtils.META_JS_SUFFIX) -> {
metaJsToString(file)
}
else -> {
file.readText()
}

View File

@@ -116,7 +116,7 @@ Properties().apply {
extra["JDK_16"] = jdkPath("1.6")
extra["JDK_17"] = jdkPath("1.7")
extra["JDK_18"] = jdkPath("1.8")
extra["JDK_9"] = jdkPathIfFound("9")
extra["JDK_9"] = jdkPath("9")
extra["JDK_10"] = jdkPathIfFound("10")
rootProject.apply {
@@ -595,10 +595,12 @@ fun jdkPath(version: String): String = jdkPathIfFound(version)
fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
tasks.withType<JavaCompile> {
options.isFork = true
options.forkOptions.javaHome = file(javaHome)
options.compilerArgs.add("-proc:none")
options.encoding = "UTF-8"
if (name != "compileJava9Java") {
options.isFork = true
options.forkOptions.javaHome = file(javaHome)
options.compilerArgs.add("-proc:none")
options.encoding = "UTF-8"
}
}
tasks.withType<KotlinCompile> {

View File

@@ -2,7 +2,7 @@
buildscript {
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
extra["versions.shadow"] = "2.0.1"
extra["versions.shadow"] = "2.0.2"
extra["versions.intellij-plugin"] = "0.3.0-SNAPSHOT"
extra["versions.native-platform"] = "0.14"

View File

@@ -123,6 +123,9 @@ fun removePathPrefix(path: String): String {
val unzipIntellijSdk by tasks.creating {
configureExtractFromConfigurationTask(intellij, pathRemap = { removePathPrefix(it) }) {
zipTree(it.singleFile).matching {
if (OperatingSystem.current().isMacOsX && androidStudioRelease != null) {
exclude("Android Studio*.app/Contents/plugins/Kotlin/**")
}
exclude("plugins/Kotlin/**")
}
}

View File

@@ -141,6 +141,10 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
"-Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar"
)
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
jvmArgs("-Didea.platform.prefix=AndroidStudio")
}
if (project.hasProperty("noPCE")) {
jvmArgs("-Didea.ProcessCanceledException=disabled")
}

View File

@@ -149,7 +149,9 @@ fun MutableCollection<JdkId>.discoverJdksOnUnix(project: Project) {
private val windowsConventionalJdkRegistryPaths = listOf(
"SOFTWARE\\JavaSoft\\Java Development Kit",
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit")
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit",
"SOFTWARE\\JavaSoft\\JDK",
"SOFTWARE\\Wow6432Node\\JavaSoft\\JDK")
fun MutableCollection<JdkId>.discoverJdksOnWindows(project: Project) {
val registry = Native.get(WindowsRegistry::class.java)

View File

@@ -70,6 +70,8 @@ class JpsCompatiblePlugin : Plugin<Project> {
if (project == project.rootProject) {
project.tasks.create("pill") {
doLast { pill(project) }
TaskUtils.useAndroidSdk(this)
TaskUtils.useAndroidJar(this)
}
project.tasks.create("unpill") {
@@ -188,17 +190,32 @@ class JpsCompatiblePlugin : Plugin<Project> {
junitConfiguration.apply {
getOrCreateChild("option", "name" to "WORKING_DIRECTORY").setAttribute("value", "file://\$PROJECT_DIR\$")
getOrCreateChild("option", "name" to "VM_PARAMETERS").also { vmParams ->
val ideaHomePathOptionKey = "-Didea.home.path="
val ideaHomePathOption = ideaHomePathOptionKey + platformDirProjectRelative
val existingOptions = vmParams.getAttributeValue("value", "")
var options = vmParams.getAttributeValue("value", "")
.split(' ')
.map { it.trim() }
.filter { it.isNotEmpty() && !it.startsWith(ideaHomePathOptionKey) }
.filter { it.isNotEmpty() }
val newOptions = existingOptions.joinToString(" ") + " " + ideaHomePathOption
fun addOrReplaceOptionValue(name: String, value: Any) {
options = options.filter { !it.startsWith("-D$name=") } + listOf("-D$name=$value")
}
vmParams.setAttribute("value", newOptions)
val robolectricClasspath = project.rootProject
.project(":plugins:android-extensions-compiler")
.configurations.getByName("robolectricClasspath")
.files.joinToString(File.pathSeparator)
val androidJarPath = project.configurations.getByName("androidJar").singleFile
val androidSdkPath = project.configurations.getByName("androidSdk").singleFile
addOrReplaceOptionValue("idea.home.path", platformDirProjectRelative)
addOrReplaceOptionValue("ideaSdk.androidPlugin.path", platformDirProjectRelative + "/plugins/android/lib")
addOrReplaceOptionValue("robolectric.classpath", robolectricClasspath)
addOrReplaceOptionValue("use.pill", "true")
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
vmParams.setAttribute("value", options.joinToString(" "))
}
}

View File

@@ -83,7 +83,17 @@ private inline fun String.isFirstChar(f: (Char) -> Boolean) = isNotEmpty() && f(
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, body: T.() -> Unit): T =
(tasks.findByName(taskName)?.let { it as T } ?: task<T>(taskName)).apply { body() }
private fun Test.useAndroidConfiguration(systemPropertyName: String, configName: String) {
object TaskUtils {
fun useAndroidSdk(task: Task) {
task.useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidSdk")
}
fun useAndroidJar(task: Task) {
task.useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
}
}
private fun Task.useAndroidConfiguration(systemPropertyName: String, configName: String) {
val configuration = with(project) {
configurations.getOrCreate(configName)
.also {
@@ -95,15 +105,18 @@ private fun Test.useAndroidConfiguration(systemPropertyName: String, configName:
}
dependsOn(configuration)
doFirst {
systemProperty(systemPropertyName, configuration.singleFile.canonicalPath)
if (this is Test) {
doFirst {
systemProperty(systemPropertyName, configuration.singleFile.canonicalPath)
}
}
}
fun Test.useAndroidSdk() {
useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidSdk")
fun Task.useAndroidSdk() {
TaskUtils.useAndroidSdk(this)
}
fun Test.useAndroidJar() {
useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
fun Task.useAndroidJar() {
TaskUtils.useAndroidJar(this)
}

View File

@@ -17,20 +17,18 @@
package org.jetbrains.kotlin.backend.common.bridges
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor,
signature: (FunctionDescriptor) -> Signature,
isBodyOwner: (DeclarationDescriptor) -> Boolean
descriptor: FunctionDescriptor,
signature: (FunctionDescriptor) -> Signature,
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
): Set<Bridge<Signature>> {
return generateBridges(DescriptorBasedFunctionHandle(descriptor, isBodyOwner), { signature(it.descriptor) })
return generateBridges(DescriptorBasedFunctionHandle(descriptor, areDeclarationAndDefinitionSame), { signature(it.descriptor) })
}
/**
@@ -51,26 +49,28 @@ fun <Signature> generateBridgesForFunctionDescriptor(
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
*/
class DescriptorBasedFunctionHandle(
val descriptor: FunctionDescriptor,
/*
To generate proper bridges for non-abstract function
we should know if the function declaration and its definition in the target platform are the same or not.
For JS and JVM8 they are placed in interface classes and we need generate bridge for such function ('isAbstract' will return false).
For JVM6 target function body generated in separate place (DefaultImpl) and method in interface is abstract
For JVM6 target function body is generated in a separate place (DefaultImpls) and
the method in the interface is abstract so we must not generate bridges for such cases.
*/
isBodyOwner: (DeclarationDescriptor) -> Boolean
val descriptor: FunctionDescriptor,
/*
To generate proper bridges for non-abstract function
we should know if the function declaration and its definition in the target platform are the same or not.
For JS and @JvmDefault JVM members they are placed in interface classes and
we need generate bridge for such function ('isAbstract' will return false).
For non-@JvmDefault function, its body is generated in a separate place (DefaultImpls) and
the method in the interface is abstract so we must not generate bridges for such cases.
*/
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
) : FunctionHandle {
private val overridden = descriptor.overriddenDescriptors.map { DescriptorBasedFunctionHandle(it.original, isBodyOwner) }
private val overridden = descriptor.overriddenDescriptors.map {
DescriptorBasedFunctionHandle(
it.original,
areDeclarationAndDefinitionSame
)
}
override val isDeclaration: Boolean =
descriptor.kind.isReal ||
findInterfaceImplementation(descriptor) != null
override val isDeclaration: Boolean = descriptor.kind.isReal || findInterfaceImplementation(descriptor) != null
override val isAbstract: Boolean =
descriptor.modality == Modality.ABSTRACT ||
isBodyOwner(descriptor.containingDeclaration)
descriptor.modality == Modality.ABSTRACT || !areDeclarationAndDefinitionSame(descriptor)
override val isInterfaceDeclaration: Boolean
get() = DescriptorUtils.isInterface(descriptor.containingDeclaration)

View File

@@ -58,6 +58,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAn
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -180,9 +181,9 @@ public class AsmUtil {
return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes));
}
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind, GenerationState state) {
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
return (functionDescriptor.getModality() == Modality.ABSTRACT ||
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !state.isJvm8TargetWithDefaults()))
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor)))
&& !isStaticMethod(kind, functionDescriptor);
}
@@ -226,7 +227,7 @@ public class AsmUtil {
flags |= ACC_STATIC;
}
if (isAbstractMethod(functionDescriptor, kind, state)) {
if (isAbstractMethod(functionDescriptor, kind)) {
flags |= ACC_ABSTRACT;
}

View File

@@ -19,27 +19,28 @@ import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.util.Printer
class CallableMethod(
override val owner: Type,
private val defaultImplOwner: Type?,
private val defaultMethodDesc: String,
private val signature: JvmMethodSignature,
private val invokeOpcode: Int,
override val dispatchReceiverType: Type?,
override val dispatchReceiverKotlinType: KotlinType?,
override val extensionReceiverType: Type?,
override val extensionReceiverKotlinType: KotlinType?,
override val generateCalleeType: Type?,
override val returnKotlinType: KotlinType?,
private val isInterfaceMethod: Boolean = Opcodes.INVOKEINTERFACE == invokeOpcode
override val owner: Type,
private val defaultImplOwner: Type?,
private val defaultMethodDesc: String,
private val signature: JvmMethodSignature,
private val invokeOpcode: Int,
override val dispatchReceiverType: Type?,
override val dispatchReceiverKotlinType: KotlinType?,
override val extensionReceiverType: Type?,
override val extensionReceiverKotlinType: KotlinType?,
override val generateCalleeType: Type?,
override val returnKotlinType: KotlinType?,
private val isInterfaceMethod: Boolean = Opcodes.INVOKEINTERFACE == invokeOpcode,
private val isDefaultMethodInInterface: Boolean = false
) : Callable {
fun getValueParameters(): List<JvmMethodParameterSignature> =
signature.valueParameters
signature.valueParameters
override val valueParameterTypes: List<Type>
get() = signature.valueParameters.filter { it.kind == JvmMethodParameterKind.VALUE }.map { it.asmType }
fun getAsmMethod(): Method =
signature.asmMethod
signature.asmMethod
override val parameterTypes: Array<Type>
get() = getAsmMethod().argumentTypes
@@ -47,11 +48,11 @@ class CallableMethod(
override fun genInvokeInstruction(v: InstructionAdapter) {
v.visitMethodInsn(
invokeOpcode,
owner.internalName,
getAsmMethod().name,
getAsmMethod().descriptor,
isInterfaceMethod
invokeOpcode,
owner.internalName,
getAsmMethod().name,
getAsmMethod().descriptor,
isInterfaceMethod
)
}
@@ -64,10 +65,11 @@ class CallableMethod(
if ("<init>" == method.name) {
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.internalName, "<init>", defaultMethodDesc, false)
}
else {
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.internalName,
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
} else {
v.visitMethodInsn(
INVOKESTATIC, defaultImplOwner.internalName,
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, isDefaultMethodInInterface
)
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
}
@@ -77,8 +79,8 @@ class CallableMethod(
get() = signature.returnType
override fun isStaticCall(): Boolean =
invokeOpcode == INVOKESTATIC
invokeOpcode == INVOKESTATIC
override fun toString(): String =
"${Printer.OPCODES[invokeOpcode]} $owner.$signature"
"${Printer.OPCODES[invokeOpcode]} $owner.$signature"
}

View File

@@ -1488,6 +1488,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
if (tryCatchBlockEnd != null) {
if (finallyBlockStackElement != null) {
markLineNumber(finallyBlockStackElement.expression, true);
}
v.goTo(tryCatchBlockEnd);
}
@@ -2416,7 +2420,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
) {
boolean isSafeCallOrOnStack = receiver instanceof StackValue.SafeCall || receiver instanceof StackValue.OnStack;
if (isSuspendCall && !isSafeCallOrOnStack) {
if (isSuspendCall && !isSafeCallOrOnStack && !tailRecursionCodegen.isTailRecursion(resolvedCall)) {
// Inline markers are used to spill the stack before coroutine suspension
addInlineMarker(v, true);
}

View File

@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
@@ -66,7 +67,6 @@ import java.util.*;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
@@ -74,6 +74,7 @@ import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarg
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -86,10 +87,12 @@ public class FunctionCodegen {
private final ClassBuilder v;
private final MemberCodegen<?> memberCodegen;
private final Function1<DeclarationDescriptor, Boolean> IS_PURE_INTERFACE_CHECKER = new Function1<DeclarationDescriptor, Boolean>() {
private final Function1<CallableMemberDescriptor, Boolean> DECLARATION_AND_DEFINITION_CHECKER = new Function1<CallableMemberDescriptor, Boolean>() {
@Override
public Boolean invoke(DeclarationDescriptor descriptor) {
return JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state);
public Boolean invoke(CallableMemberDescriptor descriptor) {
return !isInterface(descriptor.getContainingDeclaration()) ||
(state.getTarget() != JvmTarget.JVM_1_6 &&
hasJvmDefaultAnnotation(descriptor));
}
};
@@ -173,11 +176,7 @@ public class FunctionCodegen {
) {
OwnerKind contextKind = methodContext.getContextKind();
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration) &&
functionDescriptor.getVisibility() == Visibilities.PRIVATE &&
!processInterfaceMember(functionDescriptor, contextKind, state)) {
return;
}
if (isInterface(containingDeclaration) && !processInterfaceMethod(functionDescriptor, contextKind, false)) return;
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
@@ -220,10 +219,6 @@ public class FunctionCodegen {
generateBridges(functionDescriptor);
}
if (isJvm8InterfaceWithDefaultsMember(functionDescriptor, state) && contextKind != OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()) {
generateDelegateForDefaultImpl(functionDescriptor, origin.getElement());
}
boolean staticInCompanionObject = CodegenUtilKt.isJvmStaticInCompanionObject(functionDescriptor);
if (staticInCompanionObject) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
@@ -376,7 +371,7 @@ public class FunctionCodegen {
boolean staticInCompanionObject
) {
OwnerKind contextKind = methodContext.getContextKind();
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind)) {
generateLocalVariableTable(
mv,
jvmSignature,
@@ -597,18 +592,6 @@ public class FunctionCodegen {
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
methodEnd = new Label();
}
else if (OwnerKind.DEFAULT_IMPLS == context.getContextKind() && isJvm8InterfaceWithDefaultsMember(functionDescriptor, parentCodegen.state)) {
int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
Type type = typeMapper.mapOwner(functionDescriptor);
Method asmMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
generateDelegateToStaticMethodBody(
true, mv,
new Method(asmMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, asmMethod.getDescriptor()),
type.getInternalName()
);
methodEnd = new Label();
}
else {
FrameMap frameMap = createFrameMap(
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
@@ -959,14 +942,14 @@ public class FunctionCodegen {
private boolean hasSpecialBridgeMethod(@NotNull FunctionDescriptor descriptor) {
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) == null) return false;
return !BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
).isEmpty();
}
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
if (descriptor instanceof ConstructorDescriptor) return;
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
if (IS_PURE_INTERFACE_CHECKER.invoke(descriptor.getContainingDeclaration())) return;
if (!DECLARATION_AND_DEFINITION_CHECKER.invoke(descriptor)) return;
// equals(Any?), hashCode(), toString() never need bridges
if (isMethodOfAny(descriptor)) return;
@@ -976,7 +959,7 @@ public class FunctionCodegen {
Set<Bridge<Method>> bridgesToGenerate;
if (!isSpecial) {
bridgesToGenerate =
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER);
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER);
if (!bridgesToGenerate.isEmpty()) {
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
boolean isSpecialBridge =
@@ -989,7 +972,7 @@ public class FunctionCodegen {
}
else {
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
);
if (!specials.isEmpty()) {
@@ -1001,7 +984,7 @@ public class FunctionCodegen {
}
}
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state)) {
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
assert overridden != null;
@@ -1073,7 +1056,8 @@ public class FunctionCodegen {
) {
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
if (isInterface(contextClass) && !processInterface(contextClass, kind, state)) {
if (isInterface(contextClass) &&
!processInterfaceMethod(functionDescriptor, kind, true)) {
return;
}
@@ -1088,7 +1072,7 @@ public class FunctionCodegen {
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
if (!(functionDescriptor instanceof ConstructorDescriptor)) {
flags |= ACC_STATIC;
flags |= ACC_STATIC | ACC_BRIDGE;
}
Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);
@@ -1330,7 +1314,7 @@ public class FunctionCodegen {
iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
}
else {
if (isJvm8InterfaceWithDefaultsMember(descriptor, state)) {
if (hasJvmDefaultAnnotation(descriptor)) {
iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
}
else {
@@ -1489,20 +1473,23 @@ public class FunctionCodegen {
);
}
public static boolean processInterfaceMember(
@NotNull CallableMemberDescriptor function,
public static boolean processInterfaceMethod(
@NotNull CallableMemberDescriptor memberDescriptor,
@NotNull OwnerKind kind,
@NotNull GenerationState state
boolean isDefaultOrSynthetic
) {
return processInterface(function.getContainingDeclaration(), kind, state);
}
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
containingDeclaration;
public static boolean processInterface(
@NotNull DeclarationDescriptor contextClass,
@NotNull OwnerKind kind,
@NotNull GenerationState state
) {
assert isInterface(contextClass) : "'processInterface' method should be called only for interfaces, but: " + contextClass;
return JvmCodegenUtil.isJvm8InterfaceWithDefaults(contextClass, state) ? kind != OwnerKind.DEFAULT_IMPLS : kind == OwnerKind.DEFAULT_IMPLS;
if (hasJvmDefaultAnnotation(memberDescriptor)) {
return kind != OwnerKind.DEFAULT_IMPLS;
} else {
switch (kind) {
case DEFAULT_IMPLS: return true;
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefaultOrSynthetic;
default: return false;
}
}
}
}

View File

@@ -71,6 +71,7 @@ import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationCons
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -216,7 +217,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDefaultImplsIfNeeded() {
if (isInterface(descriptor) && !isLocal && (!JvmCodegenUtil.isJvm8InterfaceWithDefaults(descriptor, state) || state.getGenerateDefaultImplsForJvm8())) {
if (isInterface(descriptor) && !isLocal) {
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
ClassBuilder defaultImplsBuilder =
state.getFactory().newVisitor(JvmDeclarationOriginKt.DefaultImpls(myClass.getPsiOrParent(), descriptor), defaultImplsType, myClass.getContainingKtFile());
@@ -400,9 +401,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateDelegates(delegationFieldsInfo);
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
generateSyntheticAccessors();
}
generateSyntheticAccessors();
generateEnumMethods();
@@ -1405,23 +1404,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateTraitMethods() {
if (isInterfaceWithoutDefaults(descriptor, state)) return;
if (isInterface(descriptor)) return;
List<FunctionDescriptor> restrictedInheritance = new ArrayList<>();
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
FunctionDescriptor interfaceFun = entry.getKey();
//skip java 8 default methods
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !isJvm8InterfaceWithDefaultsMember(interfaceFun, state)) {
if (state.isJvm8TargetWithDefaults() && !JvmCodegenUtil.isJvm8InterfaceWithDefaults(interfaceFun.getContainingDeclaration(), state)) {
restrictedInheritance.add(interfaceFun);
}
else {
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
}
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !hasJvmDefaultAnnotation(interfaceFun)) {
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
}
}
CodegenUtilKt.reportTarget6InheritanceErrorIfNeeded(descriptor, myClass.getPsiOrParent(), restrictedInheritance, state);
}
private void generateDelegationToDefaultImpl(@NotNull FunctionDescriptor interfaceFun, @NotNull FunctionDescriptor inheritedFun) {

View File

@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.FacadePartWithSourceFile;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.RootContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
@@ -36,9 +35,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Opcodes;
import java.io.File;
@@ -48,6 +45,7 @@ import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
public class JvmCodegenUtil {
@@ -55,40 +53,7 @@ public class JvmCodegenUtil {
private JvmCodegenUtil() {
}
public static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
return isInterfaceWithoutDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
}
private static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
if (!DescriptorUtils.isInterface(descriptor)) return false;
if (descriptor instanceof DeserializedClassDescriptor) {
SourceElement source = ((DeserializedClassDescriptor) descriptor).getSource();
if (source instanceof KotlinJvmBinarySourceElement) {
KotlinJvmBinaryClass binaryClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
assert binaryClass instanceof FileBasedKotlinClass :
"KotlinJvmBinaryClass should be subclass of FileBasedKotlinClass, but " + binaryClass;
/*TODO need add some flags to compiled code*/
return true || ((FileBasedKotlinClass) binaryClass).getClassVersion() == Opcodes.V1_6;
}
}
return !isJvm8TargetWithDefaults;
}
public static boolean isJvm8InterfaceWithDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
return isJvm8InterfaceWithDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
}
public static boolean isJvm8InterfaceWithDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
return DescriptorUtils.isInterface(descriptor) && !isInterfaceWithoutDefaults(descriptor, isJvm8Target, isJvm8TargetWithDefaults);
}
public static boolean isJvm8InterfaceWithDefaultsMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
return isJvm8InterfaceWithDefaults(declaration, state);
}
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor) {
if (!isJvmInterface(descriptor.getContainingDeclaration())) {
return false;
}
@@ -96,7 +61,7 @@ public class JvmCodegenUtil {
return descriptor.getModality() == Modality.ABSTRACT;
}
return !isJvm8InterfaceWithDefaultsMember(descriptor, state);
return !hasJvmDefaultAnnotation(descriptor);
}
public static boolean isJvmInterface(DeclarationDescriptor descriptor) {
@@ -202,7 +167,15 @@ public class JvmCodegenUtil {
}
if (!isCallInsideSameClassAsFieldRepresentingProperty(property, context)) {
if (!isDebuggerContext(context)) {
DeclarationDescriptor propertyOwner = property.getContainingDeclaration();
boolean isAnnotationValue;
if (propertyOwner instanceof ClassDescriptor) {
isAnnotationValue = ((ClassDescriptor) propertyOwner).getKind() == ANNOTATION_CLASS;
} else {
isAnnotationValue = false;
}
if (isAnnotationValue || !isDebuggerContext(context)) {
// Unless we are evaluating expression in debugger context, only properties of the same class can be directly accessed
return false;
}

View File

@@ -63,12 +63,12 @@ import java.util.LinkedHashSet;
import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getInlineName;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
@@ -407,7 +407,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
ClassDescriptor classDescriptor = ((ClassContext) outermost).getContextDescriptor();
if (context instanceof MethodContext) {
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
if (isInterface(functionDescriptor.getContainingDeclaration()) && !isJvm8InterfaceWithDefaultsMember(functionDescriptor, state)) {
if (isInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor)) {
return typeMapper.mapDefaultImpls(classDescriptor);
}
}
@@ -695,9 +695,16 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
}
protected void generateSyntheticAccessors() {
protected final void generateSyntheticAccessors() {
for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
generateSyntheticAccessor(accessor);
boolean hasJvmDefaultAnnotation = hasJvmDefaultAnnotation(accessor.getCalleeDescriptor());
OwnerKind kind = context.getContextKind();
if (!isInterface(context.getContextDescriptor()) ||
(hasJvmDefaultAnnotation && kind == OwnerKind.IMPLEMENTATION) ||
(!hasJvmDefaultAnnotation && kind == OwnerKind.DEFAULT_IMPLS)) {
generateSyntheticAccessor(accessor);
}
}
}
@@ -813,7 +820,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) &&
!isNonDefaultInterfaceMember(functionDescriptor, state) &&
!isNonDefaultInterfaceMember(functionDescriptor) &&
!isJvmStaticInObjectOrClass;
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;

View File

@@ -350,9 +350,7 @@ public class PropertyCodegen {
if (annotations.getAllAnnotations().isEmpty()) return;
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
if (!isInterface(contextDescriptor) ||
(FunctionCodegen.processInterface(contextDescriptor, kind, state) ||
(kind == OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()))) {
if (!isInterface(contextDescriptor) || FunctionCodegen.processInterfaceMethod(descriptor, kind, true)) {
memberCodegen.generateSyntheticAnnotationsMethod(
descriptor, getSyntheticMethodSignature(descriptor), annotations, AnnotationUseSiteTarget.PROPERTY
);

View File

@@ -2061,7 +2061,7 @@ public abstract class StackValue {
@NotNull CallableDescriptor descriptor
) {
throw new RuntimeException(
"Augment assignment and increment are not supported for local delegated properties ans inline properties: " +
"Augmented assignment and increment are not supported for local delegated properties and inline properties: " +
descriptor);
}
}

View File

@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
@@ -45,16 +44,16 @@ class BridgeForBuiltinSpecial<out Signature : Any>(
object BuiltinSpecialBridgesUtil {
@JvmStatic fun <Signature : Any> generateBridgesForBuiltinSpecial(
function: FunctionDescriptor,
signatureByDescriptor: (FunctionDescriptor) -> Signature,
isBodyOwner: (DeclarationDescriptor) -> Boolean
function: FunctionDescriptor,
signatureByDescriptor: (FunctionDescriptor) -> Signature,
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
): Set<BridgeForBuiltinSpecial<Signature>> {
val functionHandle = DescriptorBasedFunctionHandle(function, isBodyOwner)
val functionHandle = DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)
val fake = !functionHandle.isDeclaration
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
val reachableDeclarations = findAllReachableDeclarations(function, isBodyOwner)
val reachableDeclarations = findAllReachableDeclarations(function, areDeclarationAndDefinitionSame)
// e.g. `getSize()I`
val methodItself = signatureByDescriptor(function)
@@ -78,8 +77,10 @@ object BuiltinSpecialBridgesUtil {
if (fake) {
for (overridden in function.overriddenDescriptors.map { it.original }) {
if (!DescriptorBasedFunctionHandle(overridden, isBodyOwner).isAbstract) {
commonBridges.removeAll(findAllReachableDeclarations(overridden, isBodyOwner).map(signatureByDescriptor))
if (!DescriptorBasedFunctionHandle(overridden, areDeclarationAndDefinitionSame).isAbstract) {
commonBridges.removeAll(findAllReachableDeclarations(overridden,
areDeclarationAndDefinitionSame
).map(signatureByDescriptor))
}
}
}
@@ -88,7 +89,7 @@ object BuiltinSpecialBridgesUtil {
val superImplementationDescriptor =
if (specialBridge != null && fake && !functionHandle.isAbstract)
findSuperImplementationForStubDelegation(function, isBodyOwner, signatureByDescriptor)
findSuperImplementationForStubDelegation(function, areDeclarationAndDefinitionSame, signatureByDescriptor)
else
null
@@ -137,11 +138,11 @@ object BuiltinSpecialBridgesUtil {
* Also note that there is no special bridges for final declarations, thus no stubs either
*/
private fun <Signature> findSuperImplementationForStubDelegation(
function: FunctionDescriptor,
isBodyOwner: (DeclarationDescriptor) -> Boolean,
signatureByDescriptor: (FunctionDescriptor) -> Signature
function: FunctionDescriptor,
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean,
signatureByDescriptor: (FunctionDescriptor) -> Signature
): FunctionDescriptor? {
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, isBodyOwner)).descriptor
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)).descriptor
// Implementation from interface will be generated by common mechanism
if (DescriptorUtils.isInterface(implementation.containingDeclaration)) return null
@@ -157,10 +158,15 @@ private fun <Signature> findSuperImplementationForStubDelegation(
}
private fun findAllReachableDeclarations(
functionDescriptor: FunctionDescriptor,
isBodyOwner: (DeclarationDescriptor) -> Boolean
functionDescriptor: FunctionDescriptor,
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
): MutableSet<FunctionDescriptor> =
findAllReachableDeclarations(DescriptorBasedFunctionHandle(functionDescriptor, isBodyOwner)).map { it.descriptor }.toMutableSet()
findAllReachableDeclarations(
DescriptorBasedFunctionHandle(
functionDescriptor,
areDeclarationAndDefinitionSame
)
).map { it.descriptor }.toMutableSet()
private fun <Signature> CallableMemberDescriptor.getSpecialBridgeSignatureIfExists(
signatureByDescriptor: (FunctionDescriptor) -> Signature

View File

@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
@@ -39,7 +37,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.types.ErrorUtils
@@ -233,26 +230,6 @@ fun ClassBuilder.generateMethod(
}
}
fun reportTarget6InheritanceErrorIfNeeded(
classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List<FunctionDescriptor>, state: GenerationState
) {
if (!restrictedInheritance.isEmpty()) {
val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor }
for ((key, value) in groupBy) {
state.diagnostics.report(
ErrorsJvm.TARGET6_INTERFACE_INHERITANCE.on(
classElement, classDescriptor, key,
value.joinToString(separator = "\n", prefix = "\n") {
Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty)
}
)
)
}
}
}
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
isJvmStaticIn {
DescriptorUtils.isNonCompanionObject(it) ||
@@ -439,4 +416,4 @@ fun MethodNode.textifyMethodNode(): String {
val sw = StringWriter()
text.print(PrintWriter(sw))
return "$sw"
}
}

View File

@@ -27,6 +27,8 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.isCallableMemberWithJvmDefaultAnnotation;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
@@ -414,7 +416,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull D descriptor,
@Nullable ClassDescriptor superCallTarget,
@NotNull GenerationState state) {
if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor, state)) {
if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor)) {
CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext();
CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget);
assert c != null : "Couldn't find a context for a super-call: " + descriptor;
@@ -569,10 +571,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
CodegenContext properContext = getFirstCrossInlineOrNonInlineContext();
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
boolean isInliningContext = properContext.isInlineMethodContext();
boolean sameJvmDefault = hasJvmDefaultAnnotation(descriptor) ==
isCallableMemberWithJvmDefaultAnnotation(properContext.contextDescriptor) ||
properContext.contextDescriptor instanceof AccessorForCallableDescriptor;
if (!isInliningContext && (
!properContext.hasThisDescriptor() ||
enclosing == properContext.getThisDescriptor() ||
enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) {
((enclosing == properContext.getThisDescriptor()) && sameJvmDefault) ||
((enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor()) && sameJvmDefault))) {
return descriptor;
}
return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
@@ -623,6 +628,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
if (descriptorContext == null) {
return descriptor;
}
if (hasJvmDefaultAnnotation(descriptor) && descriptorContext instanceof DefaultImplsClassContext) {
descriptorContext = ((DefaultImplsClassContext) descriptorContext).getInterfaceContext();
}
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
int propertyAccessFlag = getVisibilityAccessFlag(descriptor);

View File

@@ -23,20 +23,21 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
class DefaultImplsClassContext(
typeMapper: KotlinTypeMapper,
contextDescriptor: ClassDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>?,
localLookup: ((DeclarationDescriptor) -> Boolean)?,
private val interfaceContext: ClassContext
typeMapper: KotlinTypeMapper,
contextDescriptor: ClassDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>?,
localLookup: ((DeclarationDescriptor) -> Boolean)?,
val interfaceContext: ClassContext
) : ClassContext(typeMapper, contextDescriptor, contextKind, parentContext, localLookup) {
override fun getCompanionObjectContext(): CodegenContext<*>? = interfaceContext.companionObjectContext
override fun getAccessors(): Collection<AccessorForCallableDescriptor<*>> {
val accessors = super.getAccessors()
val alreadyExistKeys = accessors.map ({ Pair(it.calleeDescriptor, it.superCallTarget) })
val filtered = interfaceContext.accessors.associateByTo(linkedMapOf()) { Pair(it.calleeDescriptor, it.superCallTarget) }.apply { keys -= alreadyExistKeys }
val alreadyExistKeys = accessors.map({ Pair(it.calleeDescriptor, it.superCallTarget) })
val filtered = interfaceContext.accessors.associateByTo(linkedMapOf()) { Pair(it.calleeDescriptor, it.superCallTarget) }
.apply { keys -= alreadyExistKeys }
return accessors + filtered.values
}
}

View File

@@ -122,7 +122,7 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
if (succ.opcode != Opcodes.POP) continue
if (insn.opcode == Opcodes.ALOAD && methodNode.localVariables.firstOrNull { it.index == insn.localIndex() } != null) continue
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
if (sources.size != 1) continue
res[insn] = succ
}
@@ -182,7 +182,7 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
it.opcode == Opcodes.ASTORE && it.localIndex() == succ.localIndex()
} != 1) continue
if (!ignoreLocalVariableTable && methodNode.localVariables.firstOrNull { it.index == succ.localIndex() } != null) continue
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
if (sources.size > 1) continue
res[insn] = succ
}

View File

@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.utils.keysToMap
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
/*
* Replace POP with ARETURN iff
@@ -47,7 +48,7 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }.toList()
val popSuccessors = findSuccessors(methodNode, pops)
val sourceInsns = findSourceInstructions(internalClassName, methodNode, pops)
val sourceInsns = findSourceInstructions(internalClassName, methodNode, pops, ignoreCopy = true)
val safePops = filterOutUnsafes(popSuccessors, units, sourceInsns)
// Replace POP with ARETURN for tail call optimization
@@ -122,9 +123,14 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
internal fun findSourceInstructions(
internalClassName: String,
methodNode: MethodNode,
insns: Collection<AbstractInsnNode>
insns: Collection<AbstractInsnNode>,
ignoreCopy: Boolean
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
val frames = MethodTransformer.analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
val frames = MethodTransformer.analyze(
internalClassName,
methodNode,
if (ignoreCopy) IgnoringCopyOperationSourceInterpreter() else SourceInterpreter()
)
return insns.keysToMap {
val index = methodNode.instructions.indexOf(it)
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -291,7 +291,7 @@ class MethodInliner(
}
val isContinuationCreate = isContinuation && oldInfo != null && resultNode.name == "create" &&
resultNode.desc.startsWith("(" + CONTINUATION_ASM_TYPE.descriptor)
resultNode.desc.endsWith(")" + CONTINUATION_ASM_TYPE.descriptor)
for (capturedParamDesc in info.allRecapturedParameters) {
if (capturedParamDesc.fieldName == THIS && isContinuationCreate) {

View File

@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberWithJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.org.objectweb.asm.Label
@@ -58,21 +59,23 @@ interface SourceCompilerForInline {
val lazySourceMapper: DefaultSourceMapper
fun generateLambdaBody(adapter: MethodVisitor,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: ExpressionLambda): SMAP
fun generateLambdaBody(
adapter: MethodVisitor,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: ExpressionLambda
): SMAP
fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode
fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
)
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean
@@ -89,7 +92,7 @@ interface SourceCompilerForInline {
}
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement): SourceCompilerForInline {
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement) : SourceCompilerForInline {
override val state = codegen.state
@@ -126,51 +129,53 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
return InlineCallSiteInfo(
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
)
}
override val lazySourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper
override fun generateLambdaBody(adapter: MethodVisitor,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: ExpressionLambda): SMAP {
override fun generateLambdaBody(
adapter: MethodVisitor,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: ExpressionLambda
): SMAP {
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
val closureContext =
if (lambdaInfo.isPropertyReference)
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
else
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
if (lambdaInfo.isPropertyReference)
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
else
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
return generateMethodBody(
adapter, invokeMethodDescriptor, context,
lambdaInfo.functionWithBodyOrCallableReference,
jvmMethodSignature, lambdaInfo
adapter, invokeMethodDescriptor, context,
lambdaInfo.functionWithBodyOrCallableReference,
jvmMethodSignature, lambdaInfo
)
}
private fun generateMethodBody(
adapter: MethodVisitor,
descriptor: FunctionDescriptor,
context: MethodContext,
expression: KtExpression,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: PsiExpressionLambda?
adapter: MethodVisitor,
descriptor: FunctionDescriptor,
context: MethodContext,
expression: KtExpression,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: PsiExpressionLambda?
): SMAP {
val isLambda = lambdaInfo != null
// Wrapping for preventing marking actual parent codegen as containing reified markers
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
if (isLambda)
codegen.parentCodegen.className
else
state.typeMapper.mapImplementationOwner(descriptor).internalName,
if (isLambda) emptyList() else additionalInnerClasses,
isLambda
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
if (isLambda)
codegen.parentCodegen.className
else
state.typeMapper.mapImplementationOwner(descriptor).internalName,
if (isLambda) emptyList() else additionalInnerClasses,
isLambda
)
val strategy = when (expression) {
@@ -182,11 +187,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
val info = lambdaInfo.propertyReferenceInfo
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
true, info!!.getFunction, info.target, asmType, receiverType,
lambdaInfo.functionWithBodyOrCallableReference, state, true
true, info!!.getFunction, info.target, asmType, receiverType,
lambdaInfo.functionWithBodyOrCallableReference, state, true
)
}
else {
} else {
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, receiverType, null, true)
}
}
@@ -205,8 +209,8 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
private fun createSMAPWithDefaultMapping(
declaration: KtExpression,
mappings: List<FileMapping>
declaration: KtExpression,
mappings: List<FileMapping>
): SMAP {
val containingFile = declaration.containingFile
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in " + containingFile)
@@ -216,12 +220,12 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
@Suppress("UNCHECKED_CAST")
private class FakeMemberCodegen(
internal val delegate: MemberCodegen<*>,
declaration: KtElement,
codegenContext: FieldOwnerContext<*>,
private val className: String,
private val parentAsInnerClasses: List<ClassDescriptor>,
private val isInlineLambdaCodegen: Boolean
internal val delegate: MemberCodegen<*>,
declaration: KtElement,
codegenContext: FieldOwnerContext<*>,
private val className: String,
private val parentAsInnerClasses: List<ClassDescriptor>,
private val isInlineLambdaCodegen: Boolean
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
override fun generateDeclaration() {
@@ -248,18 +252,17 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
if (isInlineLambdaCodegen) {
super.addParentsToInnerClassesIfNeeded(innerClasses)
}
else {
} else {
innerClasses.addAll(parentAsInnerClasses)
}
}
}
override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode {
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
@@ -269,10 +272,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val inliningFunction = element as KtDeclarationWithBody?
val node = MethodNode(
API,
AsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
asmMethod.name,
asmMethod.descriptor, null, null
API,
AsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
asmMethod.name,
asmMethod.descriptor, null, null
)
//for maxLocals calculation
@@ -283,10 +286,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val smap = if (callDefault) {
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
implementationOwner.internalName,
additionalInnerClasses,
false
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
implementationOwner.internalName,
additionalInnerClasses,
false
)
if (element !is KtNamedFunction) {
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
@@ -296,8 +299,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
)
createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
}
else {
} else {
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
}
maxCalcAdapter.visitMaxs(-1, -1)
@@ -307,9 +309,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
}
override fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
) {
if (!codegen.hasFinallyBlocks()) return
@@ -336,8 +338,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val finallyNode = createEmptyMethodNode()
finallyNode.visitLabel(start)
val finallyCodegen = ExpressionCodegen(finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen)
val finallyCodegen = ExpressionCodegen(
finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen
)
finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
val frameMap = finallyCodegen.frameMap
@@ -390,19 +394,28 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val parentContext = context.parentContext
val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
parentContext.originalSuspendLambdaDescriptor!!
}
else context.contextDescriptor
} else context.contextDescriptor
return InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
}
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
context = getContext(functionDescriptor, functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile, additionalInnerClasses)
context = getContext(
functionDescriptor,
functionDescriptor,
state,
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile,
additionalInnerClasses
)
}
companion object {
fun getContext(
descriptor: DeclarationDescriptor, innerDescriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?, additionalInners: MutableList<ClassDescriptor>
descriptor: DeclarationDescriptor,
innerDescriptor: DeclarationDescriptor,
state: GenerationState,
sourceFile: KtFile?,
additionalInners: MutableList<ClassDescriptor>
): CodegenContext<*> {
if (descriptor is PackageFragmentDescriptor) {
//no inners
@@ -411,30 +424,32 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
val parent = getContext(
container,
descriptor,
state,
sourceFile,
additionalInners
container,
descriptor,
state,
sourceFile,
additionalInners
)
return when (descriptor) {
is ScriptDescriptor -> {
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
parent.intoScript(
descriptor,
earlierScripts ?: emptyList(),
descriptor as ClassDescriptor, state.typeMapper
descriptor,
earlierScripts ?: emptyList(),
descriptor as ClassDescriptor, state.typeMapper
)
}
is ClassDescriptor -> {
val kind =
if (DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor)
OwnerKind.DEFAULT_IMPLS
else OwnerKind.IMPLEMENTATION
if (DescriptorUtils.isInterface(descriptor) &&
innerDescriptor !is ClassDescriptor && !innerDescriptor.isCallableMemberWithJvmDefaultAnnotation()
)
OwnerKind.DEFAULT_IMPLS
else OwnerKind.IMPLEMENTATION
additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
)
parent.intoClass(descriptor, kind, state)
}

View File

@@ -82,17 +82,28 @@ class RedundantGotoMethodTransformer : MethodTransformer() {
private fun rewriteLabelIfNeeded(
jumpInsn: JumpInsnNode,
labelsToReplace: HashMap<LabelNode, JumpInsnNode>
labelsToReplace: Map<LabelNode, JumpInsnNode>
) {
val lastTargetLabel = getLastTargetJumpInsn(jumpInsn, labelsToReplace).label
if (lastTargetLabel != jumpInsn.label) {
val lastJumpInsn = getLastTargetJumpInsn(jumpInsn, labelsToReplace, mutableListOf())
if (lastJumpInsn != null && lastJumpInsn != jumpInsn) {
// Do not remove the old label because it can be used to define a local variable range.
jumpInsn.label = lastTargetLabel
jumpInsn.label = lastJumpInsn.label
}
}
private fun getLastTargetJumpInsn(jumpInsn: JumpInsnNode, labelsToReplace: HashMap<LabelNode, JumpInsnNode>): JumpInsnNode {
labelsToReplace[jumpInsn.label]?.let { return getLastTargetJumpInsn(it, labelsToReplace) }
private fun getLastTargetJumpInsn(
jumpInsn: JumpInsnNode,
labelsToReplace: Map<LabelNode, JumpInsnNode>,
alreadyVisited: MutableList<JumpInsnNode>
): JumpInsnNode? {
labelsToReplace[jumpInsn.label]?.let {
if (alreadyVisited.contains(it)) {
// Cycle detected, do no apply goto optimization
return null
}
alreadyVisited.add(it)
return getLastTargetJumpInsn(it, labelsToReplace, alreadyVisited)
}
return jumpInsn
}
}

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
@@ -24,7 +25,7 @@ class ArrayWithIndexForLoopGenerator(
) : AbstractWithIndexForLoopGenerator(codegen, forExpression, loopParameter, rangeCall) {
private val arrayType = codegen.asmType(ExpressionCodegen.getExpectedReceiverType(rangeCall))
private val arrayElementType = arrayType.elementType
private val arrayElementType = AsmUtil.correctElementType(arrayType)
private var arrayVar = -1
private var arrayLengthVar = -1

View File

@@ -26,8 +26,9 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper
class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
// We use empty BindingContext, because it is only used by KotlinTypeMapper for purposes irrelevant to the needs of this class
private val typeMapper = KotlinTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, false)
private val typeMapper = KotlinTypeMapper(
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapAsmMethod(function)
}

View File

@@ -62,7 +62,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
// Avoid errors when some classes are not loaded for some reason
private val typeMapper = KotlinTypeMapper(
bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false, false
bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false
)
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()

View File

@@ -177,8 +177,6 @@ class GenerationState private constructor(
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val isJvm8Target: Boolean = target == JvmTarget.JVM_1_8
val isJvm8TargetWithDefaults: Boolean = isJvm8Target && configuration.getBoolean(JVMConfigurationKeys.JVM8_TARGET_WITH_DEFAULTS)
val generateDefaultImplsForJvm8: Boolean = configuration.getBoolean(JVMConfigurationKeys.INTERFACE_COMPATIBILITY)
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
@@ -189,7 +187,7 @@ class GenerationState private constructor(
val bindingContext: BindingContext = bindingTrace.bindingContext
val typeMapper: KotlinTypeMapper = KotlinTypeMapper(
this.bindingContext, classBuilderMode, IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
this.moduleName, isJvm8Target, isJvm8TargetWithDefaults
this.moduleName, isJvm8Target
)
val intrinsics: IntrinsicMethods = run {
val shouldUseConsistentEquals = languageVersionSettings.supportsFeature(LanguageFeature.ThrowNpeOnExplicitEqualsForBoxedNull) &&

View File

@@ -72,6 +72,7 @@ import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
@@ -83,7 +84,6 @@ public class KotlinTypeMapper {
private final IncompatibleClassTracker incompatibleClassTracker;
private final String moduleName;
private final boolean isJvm8Target;
private final boolean isJvm8TargetWithDefaults;
private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
@NotNull
@@ -143,15 +143,13 @@ public class KotlinTypeMapper {
@NotNull ClassBuilderMode classBuilderMode,
@NotNull IncompatibleClassTracker incompatibleClassTracker,
@NotNull String moduleName,
boolean isJvm8Target,
boolean isJvm8TargetWithDefaults
boolean isJvm8Target
) {
this.bindingContext = bindingContext;
this.classBuilderMode = classBuilderMode;
this.incompatibleClassTracker = incompatibleClassTracker;
this.moduleName = moduleName;
this.isJvm8Target = isJvm8Target;
this.isJvm8TargetWithDefaults = isJvm8TargetWithDefaults;
}
@NotNull
@@ -730,8 +728,8 @@ public class KotlinTypeMapper {
descriptor = classCallable;
continue;
}
else if (isSuperCall && !isJvm8TargetWithDefaults && !isInterface(descriptor.getContainingDeclaration())) {
//Don't unwrap fake overrides from class to interface cause substituted override would be implicitly generated for target 1.6
else if (isSuperCall && !hasJvmDefaultAnnotation(descriptor) && !isInterface(descriptor.getContainingDeclaration())) {
//Don't unwrap fake overrides from class to interface cause substituted override would be implicitly generated
return descriptor;
}
@@ -749,7 +747,7 @@ public class KotlinTypeMapper {
String defaultImplDesc = mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
return new CallableMethod(
owner, owner, defaultImplDesc, method, INVOKESPECIAL,
null, null, null, null, null, originalDescriptor.getReturnType(), false
null, null, null, null, null, originalDescriptor.getReturnType(), false, false
);
}
@@ -773,6 +771,7 @@ public class KotlinTypeMapper {
Type thisClass;
KotlinType dispatchReceiverKotlinType;
boolean isInterfaceMember = false;
boolean isDefaultMethodInInterface = false;
if (functionParent instanceof ClassDescriptor) {
FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
@@ -787,14 +786,15 @@ public class KotlinTypeMapper {
baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
isDefaultMethodInInterface = isJvmInterface(ownerForDefault) && hasJvmDefaultAnnotation(baseMethodDescriptor);
ownerForDefaultImpl =
isJvmInterface(ownerForDefault) && !isJvm8InterfaceWithDefaults(ownerForDefault) ?
isJvmInterface(ownerForDefault) && !hasJvmDefaultAnnotation(baseMethodDescriptor) ?
mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
thisClass = mapClass(currentOwner);
dispatchReceiverKotlinType = currentOwner.getDefaultType();
if (declarationOwner instanceof JavaClassDescriptor || isJvm8InterfaceWithDefaults(declarationOwner)) {
if (declarationOwner instanceof JavaClassDescriptor || hasJvmDefaultAnnotation(declarationFunctionDescriptor)) {
invokeOpcode = INVOKESPECIAL;
signature = mapSignatureSkipGeneric(functionDescriptor);
returnKotlinType = functionDescriptor.getReturnType();
@@ -806,7 +806,14 @@ public class KotlinTypeMapper {
FunctionDescriptor originalDescriptor = descriptor.getOriginal();
signature = mapSignatureSkipGeneric(originalDescriptor, OwnerKind.DEFAULT_IMPLS);
returnKotlinType = originalDescriptor.getReturnType();
owner = mapDefaultImpls(currentOwner);
if (descriptor instanceof AccessorForCallableDescriptor &&
hasJvmDefaultAnnotation(((AccessorForCallableDescriptor) descriptor).getCalleeDescriptor())) {
owner = mapClass(currentOwner);
isInterfaceMember = true;
}
else {
owner = mapDefaultImpls(currentOwner);
}
}
}
else {
@@ -896,15 +903,10 @@ public class KotlinTypeMapper {
return new CallableMethod(
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, calleeType, returnKotlinType,
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE, isDefaultMethodInInterface
);
}
private boolean isJvm8InterfaceWithDefaults(@NotNull ClassDescriptor ownerForDefault) {
return isJvmInterface(ownerForDefault) &&
JvmCodegenUtil.isJvm8InterfaceWithDefaults(ownerForDefault, isJvm8Target, isJvm8TargetWithDefaults);
}
public static boolean isAccessor(@Nullable CallableMemberDescriptor descriptor) {
return descriptor instanceof AccessorForCallableDescriptor<?>;
}

View File

@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
import org.jetbrains.org.objectweb.asm.FieldVisitor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import java.io.BufferedWriter
import java.io.File
@@ -82,7 +84,9 @@ class SignatureDumpingBuilderFactory(
}
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor {
signatures += RawSignature(name, desc, MemberKind.METHOD) to origin.descriptor
signatures += RawSignature(name, desc, MemberKind.METHOD) to origin.descriptor?.let {
if (it is CallableDescriptor) it.unwrapInitialDescriptorForSuspendFunction() else it
}
return super.newMethod(origin, access, name, desc, signature, exceptions)
}

View File

@@ -17,8 +17,9 @@
package org.jetbrains.kotlin.cli.common.arguments
import com.intellij.util.xmlb.annotations.Transient
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.*
import java.util.*
@SuppressWarnings("WeakerAccess")
@@ -164,9 +165,89 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
put(AnalysisFlag.allowKotlinPackage, allowKotlinPackage)
put(AnalysisFlag.experimental, experimental?.toList().orEmpty())
put(AnalysisFlag.useExperimental, useExperimental?.toList().orEmpty())
put(AnalysisFlag.explicitApiVersion, apiVersion != null)
}
}
open fun configureLanguageFeatures(collector: MessageCollector): MutableMap<LanguageFeature, LanguageFeature.State> =
HashMap<LanguageFeature, LanguageFeature.State>().apply {
if (multiPlatform) {
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
}
when (coroutinesState) {
CommonCompilerArguments.ERROR -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED_WITH_ERROR)
CommonCompilerArguments.ENABLE -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED)
CommonCompilerArguments.WARN -> {}
else -> {
val message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + coroutinesState
collector.report(CompilerMessageSeverity.ERROR, message, null)
}
}
if (newInference) {
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
}
if (legacySmartCastAfterTry) {
put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED)
}
if (effectSystem) {
put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED)
put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED)
}
if (readDeserializedContracts) {
put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED)
}
if (properIeee754Comparisons) {
put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED)
}
}
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
// If only "-api-version" is specified, language version is assumed to be the latest stable
val languageVersion = parseVersion(collector, languageVersion, "language") ?: LanguageVersion.LATEST_STABLE
// If only "-language-version" is specified, API version is assumed to be equal to the language version
// (API version cannot be greater than the language version)
val apiVersion = parseVersion(collector, apiVersion, "API") ?: languageVersion
if (apiVersion > languageVersion) {
collector.report(
CompilerMessageSeverity.ERROR,
"-api-version (${apiVersion.versionString}) cannot be greater than -language-version (${languageVersion.versionString})"
)
}
if (!languageVersion.isStable) {
collector.report(
CompilerMessageSeverity.STRONG_WARNING,
"Language version ${languageVersion.versionString} is experimental, there are no backwards compatibility guarantees for new language and library features"
)
}
return LanguageVersionSettingsImpl(
languageVersion,
ApiVersion.createByLanguageVersion(apiVersion),
configureAnalysisFlags(collector),
configureLanguageFeatures(collector)
)
}
private fun parseVersion(collector: MessageCollector, value: String?, versionOf: String): LanguageVersion? =
if (value == null) null
else LanguageVersion.fromVersionString(value)
?: run {
val versionStrings = LanguageVersion.values().map(LanguageVersion::description)
val message = "Unknown $versionOf version: $value\nSupported $versionOf versions: ${versionStrings.joinToString(", ")}"
collector.report(CompilerMessageSeverity.ERROR, message, null)
null
}
// Used only for serialize and deserialize settings. Don't use in other places!
class DummyImpl : CommonCompilerArguments()
}

View File

@@ -99,6 +99,10 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
// Advanced options
@GradleOption(DefaultValues.BooleanTrueDefault::class)
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
var typedArrays: Boolean by FreezableVar(true)
@GradleOption(DefaultValues.BooleanFalseDefault::class)
@Argument(value = "-Xfriend-modules-disabled", description = "Disable internal declaration export")
var friendModulesDisabled: Boolean by FreezableVar(false)

View File

@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
class K2JVMCompilerArguments : CommonCompilerArguments() {
companion object {
@@ -137,6 +138,9 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xmultifile-parts-inherit", description = "Compile multifile classes as a hierarchy of parts and facade")
var inheritMultifileParts: Boolean by FreezableVar(false)
@Argument(value = "-Xuse-type-table", description = "Use type table in metadata serialization")
var useTypeTable: Boolean by FreezableVar(false)
@Argument(
value = "-Xskip-runtime-version-check",
description = "Allow Kotlin runtime libraries of incompatible versions in the classpath"
@@ -224,6 +228,9 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var noExceptionOnExplicitEqualsForBoxedNull by FreezableVar(false)
@Argument(value = "-Xenable-jvm-default", description = "Allow to use '@JvmDefault' for JVM default method support")
var enableJvmDefault: Boolean by FreezableVar(false)
// Paths to output directories for friend modules.
var friendPaths: Array<String>? by FreezableVar(null)
@@ -233,6 +240,15 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
jsr305,
supportCompatqualCheckerFrameworkAnnotations
)
result[AnalysisFlag.enableJvmDefault] = enableJvmDefault
return result
}
override fun configureLanguageFeatures(collector: MessageCollector): MutableMap<LanguageFeature, LanguageFeature.State> {
val result = super.configureLanguageFeatures(collector)
if (strictJavaNullabilityAssertions) {
result[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED
}
return result
}
}

View File

@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.utils.StringsKt;
import java.io.File;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -162,89 +161,10 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
}
private void setupLanguageVersionSettings(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
LanguageVersion languageVersion = parseVersion(configuration, arguments.getLanguageVersion(), "language");
LanguageVersion apiVersion = parseVersion(configuration, arguments.getApiVersion(), "API");
if (languageVersion != null || apiVersion != null) {
configuration.put(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT, true);
}
if (languageVersion == null) {
// If no "-language-version" is specified, language version is assumed to be the latest stable
languageVersion = LanguageVersion.LATEST_STABLE;
}
if (apiVersion == null) {
// If no "-api-version" is specified, API version is assumed to be equal to the language version
// (API version cannot be greater than the language version)
apiVersion = languageVersion;
}
MessageCollector collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
if (apiVersion.compareTo(languageVersion) > 0) {
collector.report(
ERROR,
"-api-version (" + apiVersion.getVersionString() + ") cannot be greater than " +
"-language-version (" + languageVersion.getVersionString() + ")",
null
);
}
if (!languageVersion.isStable()) {
collector.report(
STRONG_WARNING,
"Language version " + languageVersion.getVersionString() + " is experimental, there are " +
"no backwards compatibility guarantees for new language and library features",
null
);
}
Map<LanguageFeature, LanguageFeature.State> extraLanguageFeatures = new HashMap<>(0);
if (arguments.getMultiPlatform()) {
extraLanguageFeatures.put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED);
}
LanguageFeature.State coroutinesState = chooseCoroutinesApplicabilityLevel(configuration, arguments);
if (coroutinesState != null) {
extraLanguageFeatures.put(LanguageFeature.Coroutines, coroutinesState);
}
if (arguments.getNewInference()) {
extraLanguageFeatures.put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED);
}
if (arguments.getLegacySmartCastAfterTry()) {
extraLanguageFeatures.put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED);
}
if (arguments.getEffectSystem()) {
extraLanguageFeatures.put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED);
extraLanguageFeatures.put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED);
}
if (arguments.getReadDeserializedContracts()) {
extraLanguageFeatures.put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED);
}
if (arguments.getProperIeee754Comparisons()) {
extraLanguageFeatures.put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED);
}
setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, arguments);
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl(
languageVersion,
ApiVersion.createByLanguageVersion(apiVersion),
arguments.configureAnalysisFlags(collector),
extraLanguageFeatures
));
}
protected void setupPlatformSpecificLanguageFeatureSettings(
@NotNull Map<LanguageFeature, LanguageFeature.State> extraLanguageFeatures,
@NotNull A commandLineArguments
) {
// do nothing
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, arguments.configureLanguageVersionSettings(collector));
}
private static final String kotlinHomeEnvVar = System.getenv(KOTLIN_HOME_ENV_VAR);
@@ -299,43 +219,6 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
return null;
}
@Nullable
private static LanguageFeature.State chooseCoroutinesApplicabilityLevel(
@NotNull CompilerConfiguration configuration,
@NotNull CommonCompilerArguments arguments
) {
switch (arguments.getCoroutinesState()) {
case CommonCompilerArguments.ERROR:
return LanguageFeature.State.ENABLED_WITH_ERROR;
case CommonCompilerArguments.ENABLE:
return LanguageFeature.State.ENABLED;
case CommonCompilerArguments.WARN:
return null;
default:
String message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + arguments.getCoroutinesState();
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null);
return null;
}
}
@Nullable
private static LanguageVersion parseVersion(
@NotNull CompilerConfiguration configuration, @Nullable String value, @NotNull String versionOf
) {
if (value == null) return null;
LanguageVersion version = LanguageVersion.fromVersionString(value);
if (version != null) {
return version;
}
List<String> versionStrings = ArraysKt.map(LanguageVersion.values(), LanguageVersion::getDescription);
String message = "Unknown " + versionOf + " version: " + value + "\n" +
"Supported " + versionOf + " versions: " + StringsKt.join(versionStrings, ", ");
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null);
return null;
}
protected abstract void setupPlatformSpecificArgumentsAndServices(
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
);

View File

@@ -29,8 +29,6 @@ public class CLIConfigurationKeys {
CompilerConfigurationKey.create("allow kotlin package");
public static final CompilerConfigurationKey<Boolean> REPORT_PERF =
CompilerConfigurationKey.create("report performance information");
public static final CompilerConfigurationKey<Boolean> IS_API_VERSION_EXPLICIT =
CompilerConfigurationKey.create("is API version explicit");
// Used in Eclipse plugin (see KotlinCLICompiler)
public static final CompilerConfigurationKey<String> INTELLIJ_PLUGIN_ROOT =

View File

@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.Services
import java.io.PrintStream
import java.net.URL
import java.net.URLConnection
import java.util.function.Predicate
abstract class CLITool<A : CommonToolArguments> {
@@ -79,6 +81,8 @@ abstract class CLITool<A : CommonToolArguments> {
}
fun exec(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
disableURLConnectionCaches()
printVersionIfNeeded(messageCollector, arguments)
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
@@ -92,6 +96,16 @@ abstract class CLITool<A : CommonToolArguments> {
return execImpl(fixedMessageCollector, services, arguments)
}
private fun disableURLConnectionCaches() {
// We disable caches to avoid problems with compiler under daemon, see https://youtrack.jetbrains.com/issue/KT-22513
// For some inexplicable reason, URLConnection.setDefaultUseCaches is an instance method modifying a static field,
// so we have to create a dummy instance to call that method
object : URLConnection(URL("file:.")) {
override fun connect() = throw UnsupportedOperationException()
}.defaultUseCaches = false
}
// Used in kotlin-maven-plugin (KotlinCompileMojoBase)
protected abstract fun execImpl(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode

View File

@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.script.ScriptContentLoader
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
import org.jetbrains.kotlin.script.adjustByDefinition
import java.io.File
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
@@ -48,7 +49,9 @@ class CliScriptDependenciesProvider(
else {
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
if (scriptDef != null) {
val deps = scriptContentLoader.loadContentsAndResolveDependencies(scriptDef, file)
val deps = scriptContentLoader
.loadContentsAndResolveDependencies(scriptDef, file)
.dependencies?.adjustByDefinition(scriptDef)
if (deps != null) {
log.info("[kts] new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")

View File

@@ -37,6 +37,7 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
}
private fun ScriptReport.Severity.convertSeverity(): CompilerMessageSeverity = when(this) {
ScriptReport.Severity.FATAL -> CompilerMessageSeverity.ERROR
ScriptReport.Severity.ERROR -> CompilerMessageSeverity.ERROR
ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING
ScriptReport.Severity.INFO -> CompilerMessageSeverity.INFO

View File

@@ -65,10 +65,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.kotlin.utils.KotlinPaths;
import org.jetbrains.kotlin.utils.PathUtil;
import org.jetbrains.kotlin.utils.StringsKt;
import org.jetbrains.kotlin.utils.*;
import java.io.File;
import java.io.IOException;
@@ -388,6 +385,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
configuration.put(JSConfigurationKeys.META_INFO, true);
}
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, arguments.getTypedArrays());
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.getFriendModulesDisabled());
if (!arguments.getFriendModulesDisabled() && arguments.getFriendModules() != null) {

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.cli.jvm
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
@@ -47,6 +46,8 @@ object JvmRuntimeVersionsConsistencyChecker {
private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN = "manifest.impl.value.kotlin.runtime.component.main"
private const val KOTLIN_STDLIB_MODULE = "$META_INF/kotlin-stdlib.kotlin_module"
private const val KOTLIN_STDLIB_JRE_7_MODULE = "$META_INF/kotlin-stdlib-jre7.kotlin_module"
private const val KOTLIN_STDLIB_JRE_8_MODULE = "$META_INF/kotlin-stdlib-jre8.kotlin_module"
private const val KOTLIN_REFLECT_MODULE = "$META_INF/kotlin-reflection.kotlin_module"
private val RUNTIME_IMPLEMENTATION_TITLES = setOf(
@@ -90,7 +91,9 @@ object JvmRuntimeVersionsConsistencyChecker {
// Runtime jars with components "Core" only (a subset of [jars])
val coreJars: List<KotlinLibraryFile>,
// Library jars which have some Kotlin Runtime library bundled into them
val otherLibrariesWithBundledRuntime: List<VirtualFile>
val otherLibrariesWithBundledRuntime: List<VirtualFile>,
val stdlibJre7: List<KotlinLibraryFile>,
val stdlibJre8: List<KotlinLibraryFile>
)
fun checkCompilerClasspathConsistency(
@@ -129,7 +132,7 @@ object JvmRuntimeVersionsConsistencyChecker {
val actualApi = ApiVersion.parse(actualRuntimeVersion.toString())
if (actualApi == null) {
messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion")
} else if (!configuration.getBoolean(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT) && actualApi < currentApi) {
} else if (!languageVersionSettings.getFlag(AnalysisFlag.explicitApiVersion) && actualApi < currentApi) {
// If there's no explicit "-api-version" AND there's an old stdlib in the classpath (older than the default value of API),
// we infer API = the version of that stdlib.
// Note that "no explicit -api-version" requirement is necessary because for example, in
@@ -152,6 +155,15 @@ object JvmRuntimeVersionsConsistencyChecker {
)
}
if (configuration.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_2) {
for (stdlibJre7 in runtimeJarsInfo.stdlibJre7) {
messageCollector.issue(stdlibJre7.file, "kotlin-stdlib-jre7 is deprecated. Please use kotlin-stdlib-jdk7 instead")
}
for (stdlibJre8 in runtimeJarsInfo.stdlibJre8) {
messageCollector.issue(stdlibJre8.file, "kotlin-stdlib-jre8 is deprecated. Please use kotlin-stdlib-jdk8 instead")
}
}
val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime
if (librariesWithBundled.isNotEmpty()) {
messageCollector.issue(
@@ -264,6 +276,8 @@ object JvmRuntimeVersionsConsistencyChecker {
val jars = ArrayList<KotlinLibraryFile>(2)
val coreJars = ArrayList<KotlinLibraryFile>(2)
val otherLibrariesWithBundledRuntime = ArrayList<VirtualFile>(0)
val stdlibJre7 = ArrayList<KotlinLibraryFile>(0)
val stdlibJre8 = ArrayList<KotlinLibraryFile>(0)
val visitedPaths = hashSetOf<String>()
@@ -281,17 +295,28 @@ object JvmRuntimeVersionsConsistencyChecker {
if (fileKind.isCoreComponent) {
coreJars.add(file)
}
if (fileKind.isStdlibJre7) {
stdlibJre7.add(file)
}
if (fileKind.isStdlibJre8) {
stdlibJre8.add(file)
}
}
FileKind.OldRuntime -> jars.add(KotlinLibraryFile(jarFile, ApiVersion.KOTLIN_1_0.version))
FileKind.LibraryWithBundledRuntime -> otherLibrariesWithBundledRuntime.add(jarFile)
}
}
return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime)
return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime, stdlibJre7, stdlibJre8)
}
private sealed class FileKind {
class Runtime(val version: MavenComparableVersion, val isCoreComponent: Boolean) : FileKind()
class Runtime(
val version: MavenComparableVersion,
val isStdlibJre7: Boolean,
val isStdlibJre8: Boolean,
val isCoreComponent: Boolean
) : FileKind()
// Runtime library of Kotlin 1.0
object OldRuntime : FileKind()
@@ -311,11 +336,13 @@ object JvmRuntimeVersionsConsistencyChecker {
}
val runtimeComponent = manifest?.mainAttributes?.getValue(KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE)
val isStdlibJre7 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_7_MODULE) != null
val isStdlibJre8 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_8_MODULE) != null
return when (runtimeComponent) {
KOTLIN_RUNTIME_COMPONENT_MAIN ->
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = false)
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = false)
KOTLIN_RUNTIME_COMPONENT_CORE ->
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = true)
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = true)
null -> when {
jarRoot.findFileByRelativePath(KOTLIN_STDLIB_MODULE) == null &&
jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant

View File

@@ -227,17 +227,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
}
override fun setupPlatformSpecificLanguageFeatureSettings(
extraLanguageFeatures: MutableMap<LanguageFeature, LanguageFeature.State>,
commandLineArguments: K2JVMCompilerArguments
) {
if (commandLineArguments.strictJavaNullabilityAssertions) {
extraLanguageFeatures[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED
}
super.setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, commandLineArguments)
}
private fun registerJavacIfNeeded(
environment: KotlinCoreEnvironment,
arguments: K2JVMCompilerArguments
@@ -388,6 +377,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
)
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, arguments.inheritMultifileParts)
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable)
configuration.put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
configuration.put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, !arguments.useOldClassFilesReading)

View File

@@ -265,7 +265,7 @@ class ClasspathRootsResolver(
}
}
if (requireStdlibModule && sourceModule != null && KOTLIN_STDLIB_MODULE_NAME !in allDependencies) {
if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
report(
ERROR,
"The Kotlin standard library is not found in the module graph. " +

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.cli.jvm.repl.reader
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
import org.jetbrains.kotlin.cli.jvm.repl.writer.END_LINE
import org.jetbrains.kotlin.cli.jvm.repl.writer.ReplWriter
import org.w3c.dom.Element
import org.xml.sax.InputSource
@@ -78,12 +77,10 @@ class ReplSystemInWrapper(
val xmlInput = byteBuilder.toString()
val unescapedXml = parseXml(xmlInput)
val resultLine = if (isReplScriptExecuting)
return if (isReplScriptExecuting)
unescapeLineBreaks(unescapedXml)
else
unescapedXml
return "$resultLine$END_LINE"
}
private fun resetBufferIfNeeded() {

View File

@@ -62,7 +62,11 @@ class IncrementalCompilationOptions(
requestedCompilationResults: Array<Int>,
val resultDifferenceFile: File? = null,
val friendDifferenceFile: File? = null,
val usePreciseJavaTracking: Boolean
val usePreciseJavaTracking: Boolean,
/**
* Directories that should be cleared when IC decides to rebuild
*/
val localStateDirs: List<File>
) : CompilationOptions(compilerMode, targetPlatform, reportCategories, reportSeverity, requestedCompilationResults) {
companion object {
const val serialVersionUID: Long = 0
@@ -80,6 +84,7 @@ class IncrementalCompilationOptions(
"resultDifferenceFile=$resultDifferenceFile, " +
"friendDifferenceFile=$friendDifferenceFile, " +
"usePreciseJavaTracking=$usePreciseJavaTracking" +
"localStateDirs=$localStateDirs" +
")"
}
}

View File

@@ -140,6 +140,12 @@ interface CompileService : Remote {
compilationResults: CompilationResults?
): CallResult<Int>
@Throws(RemoteException::class)
fun classesFqNamesByFiles(
sessionId: Int,
sourceFiles: Set<File>
): CallResult<Set<String>>
@Throws(RemoteException::class)
fun clearJarCache()

View File

@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapte
import org.jetbrains.kotlin.daemon.report.RemoteICReporter
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
@@ -352,6 +353,15 @@ class CompileServiceImpl(
}
}
override fun classesFqNamesByFiles(
sessionId: Int, sourceFiles: Set<File>
): CompileService.CallResult<Set<String>> =
ifAlive {
withValidClientOrSessionProxy(sessionId) {
CompileService.CallResult.Good(classesFqNames(sourceFiles))
}
}
override fun compile(
sessionId: Int,
compilerArguments: Array<out String>,
@@ -522,7 +532,8 @@ class CompileServiceImpl(
artifactChanges, changesRegistry,
buildHistoryFile = incrementalCompilationOptions.resultDifferenceFile,
friendBuildHistoryFile = incrementalCompilationOptions.friendDifferenceFile,
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
localStateDirs = incrementalCompilationOptions.localStateDirs
)
return compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles)
}

View File

@@ -97,12 +97,6 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> PARAMETERS_METADATA =
CompilerConfigurationKey.create("Parameters metadata for java 1.8 reflection");
public static final CompilerConfigurationKey<Boolean> INTERFACE_COMPATIBILITY =
CompilerConfigurationKey.create("Generate additional 'DefaultImpls' class files for jvm 8 target for compatibility with 6 target interfaces");
public static final CompilerConfigurationKey<Boolean> JVM8_TARGET_WITH_DEFAULTS =
CompilerConfigurationKey.create("Generate default methods in interfaces");
public static final CompilerConfigurationKey<IncrementalCompilationComponents> INCREMENTAL_COMPILATION_COMPONENTS =
CompilerConfigurationKey.create("incremental cache provider");
@@ -135,4 +129,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<List<String>> ADDITIONAL_JAVA_MODULES =
CompilerConfigurationKey.create("additional Java modules");
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_DEFAULT =
CompilerConfigurationKey.create("Allow to use '@JvmDefault'");
}

View File

@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
object JvmDelegationFilter : DelegationFilter {
@@ -33,7 +34,9 @@ object JvmDelegationFilter : DelegationFilter {
//We always have only one implementation otherwise it's an error in kotlin and java
val realMember = DescriptorUtils.unwrapFakeOverride(interfaceMember)
return !isJavaDefaultMethod(realMember) && !isBuiltInMemberMappedToJavaDefault(realMember)
return !isJavaDefaultMethod(realMember) &&
!realMember.hasJvmDefaultAnnotation() &&
!isBuiltInMemberMappedToJavaDefault(realMember)
}
private fun isJavaDefaultMethod(interfaceMember: CallableMemberDescriptor): Boolean {

View File

@@ -16,9 +16,11 @@
package org.jetbrains.kotlin.resolve.jvm.annotations
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
fun DeclarationDescriptor.findJvmOverloadsAnnotation() = annotations.findAnnotation(FqName("kotlin.jvm.JvmOverloads"))
@@ -26,4 +28,7 @@ fun DeclarationDescriptor.findJvmFieldAnnotation() = DescriptorUtils.getAnnotati
fun DeclarationDescriptor.hasJvmFieldAnnotation(): Boolean {
return findJvmFieldAnnotation() != null
}
}
fun DeclarationDescriptor.isCallableMemberWithJvmDefaultAnnotation() =
(this as? CallableMemberDescriptor)?.hasJvmDefaultAnnotation() ?: false

View File

@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
@@ -36,7 +38,8 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val supportDefaults = jvmTarget == JvmTarget.JVM_1_8
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
val descriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
if (descriptor is JavaPropertyDescriptor) return
if (!supportDefaults &&
isStaticDeclaration(descriptor) &&
@@ -46,26 +49,64 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker
context.trace.report(diagnostic.on(reportOn))
}
if (getSuperCallExpression(resolvedCall.call) == null) return
val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return
if (!isInterface(descriptor.original.containingDeclaration)) return
val realDescriptor = unwrapFakeOverride(descriptor)
val realDescriptorOwner = realDescriptor.containingDeclaration as? ClassDescriptor ?: return
if (isInterface(realDescriptorOwner) && realDescriptor is JavaCallableMemberDescriptor) {
val classifier = DescriptorUtils.getParentOfType(context.scope.ownerDescriptor, ClassifierDescriptor::class.java)
//is java interface default method called from trait
if (classifier != null && DescriptorUtils.isInterface(classifier)) {
context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor || realDescriptor.hasJvmDefaultAnnotation())) {
val bindingContext = context.trace.bindingContext
val thisForSuperCall = getSuperCallLabelTarget(bindingContext, superCallExpression)
if (thisForSuperCall != null && DescriptorUtils.isInterface(thisForSuperCall)) {
val declarationWithCall = findInterfaceMember(thisForSuperCall, superCallExpression, bindingContext)
if (declarationWithCall?.hasJvmDefaultAnnotation() == false) {
context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
return
}
}
else if (!supportDefaults) {
val diagnostic = if (isDefaultCallsProhibited(context)) DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET_ERROR else DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET
if (!supportDefaults) {
val diagnostic =
if (isDefaultCallsProhibited(context)) DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET_ERROR else DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET
context.trace.report(diagnostic.on(reportOn))
}
}
}
private fun findInterfaceMember(
descriptorToSearch: ClassDescriptor,
startExpression: KtSuperExpression,
bindingContext: BindingContext
): CallableMemberDescriptor? {
val parents = generateSequence({ startExpression.parent }) { it.parent }
parents.fold<PsiElement, PsiElement>(startExpression) { child, parent ->
if (parent is KtClassBody &&
descriptorToSearch == bindingContext.get(BindingContext.CLASS, parent.parent)
) {
return when (child) {
is KtNamedFunction -> bindingContext.get(BindingContext.FUNCTION, child)
is KtProperty -> bindingContext.get(BindingContext.VARIABLE, child) as? PropertyDescriptor
else -> null
}
} else parent
}
return null
}
private fun isDefaultCallsProhibited(context: CallCheckerContext) =
context.languageVersionSettings.supportsFeature(LanguageFeature.DefaultMethodsCallFromJava6TargetError)
context.languageVersionSettings.supportsFeature(LanguageFeature.DefaultMethodsCallFromJava6TargetError)
private fun getSuperCallLabelTarget(
bindingContext: BindingContext,
expression: KtSuperExpression
): ClassDescriptor? {
val thisTypeForSuperCall = bindingContext.get(BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression) ?: return null
val descriptor = thisTypeForSuperCall.constructor.declarationDescriptor
return descriptor as? ClassDescriptor
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve.jvm.checkers
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.annotations.JVM_DEFAULT_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val enableJvmDefault = context.languageVersionSettings.getFlag(AnalysisFlag.enableJvmDefault)
descriptor.annotations.findAnnotation(JVM_DEFAULT_FQ_NAME)?.let { annotationDescriptor ->
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotationDescriptor) ?: declaration
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) {
context.trace.report(ErrorsJvm.JVM_DEFAULT_NOT_IN_INTERFACE.on(reportOn))
} else if (jvmTarget == JvmTarget.JVM_1_6) {
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_JVM6_TARGET.on(reportOn))
} else if (!enableJvmDefault) {
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(declaration))
}
return@check
}
if (descriptor is ClassDescriptor) {
val hasDeclaredJvmDefaults =
descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>().any {
it.kind.isReal && it.hasJvmDefaultAnnotation()
}
if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, enableJvmDefault)) {
context.trace.report(ErrorsJvm.JVM_DEFAULT_THROUGH_INHERITANCE.on(declaration))
}
}
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) return
val memberDescriptor = descriptor as? CallableMemberDescriptor ?: return
if (descriptor is PropertyAccessorDescriptor) return
if (memberDescriptor.overriddenDescriptors.any { it.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) }) {
context.trace.report(ErrorsJvm.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE.on(declaration))
} else if (enableJvmDefault) {
descriptor.overriddenDescriptors.flatMap { OverridingUtil.getOverriddenDeclarations(it) }.toSet().let {
for (realDescriptor in OverridingUtil.filterOutOverridden(it)) {
if (realDescriptor is JavaMethodDescriptor && realDescriptor.modality != Modality.ABSTRACT) {
return context.trace.report(ErrorsJvm.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT.on(declaration))
}
}
}
}
}
private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, enableJvmDefault: Boolean): Boolean {
if (enableJvmDefault) return true
if (descriptor !is ClassDescriptor) return true
return descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>()
.all { memberDescriptor ->
memberDescriptor.kind.isReal || OverridingUtil.filterOutOverridden(memberDescriptor.overriddenDescriptors.toSet()).all {
!isInterface(it.containingDeclaration) || !it.hasJvmDefaultAnnotation() || it.modality == Modality.ABSTRACT
}
}
}
}

View File

@@ -84,7 +84,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(NO_REFLECTION_IN_CLASS_PATH, "Call uses reflection API which is not found in compilation classpath. " +
"Make sure you have kotlin-reflect.jar in the classpath");
MAP.put(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can't call Java default methods via super");
MAP.put(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can call default methods via super only within @JvmDefault members. Please annotate the containing interface member with @JvmDefault");
MAP.put(SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC, "Using non-JVM static members protected in the superclass companion is unsupported yet");
MAP.put(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS,
@@ -133,6 +133,14 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE, "Assignment to a for-in-array loop range variable. Behavior may change in Kotlin 1.3. " +
"See https://youtrack.jetbrains.com/issue/KT-21354 for more details");
MAP.put(JVM_DEFAULT_NOT_IN_INTERFACE,"'@JvmDefault' is only supported on interface members");
MAP.put(JVM_DEFAULT_IN_JVM6_TARGET,"'@JvmDefault' is only supported since JVM target 1.8. Recompile with '-jvm-target 1.8'");
MAP.put(JVM_DEFAULT_REQUIRED_FOR_OVERRIDE, "'@JvmDefault' is required for an override of a '@JvmDefault' member");
MAP.put(JVM_DEFAULT_IN_DECLARATION, "Usage of '@JvmDefault' is only allowed if the flag -Xenable-jvm-default is enabled");
MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed if the flag -Xenable-jvm-default is enabled");
MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed if the flag -Xenable-jvm-default is enabled");
MAP.put(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault");
}
@NotNull

View File

@@ -114,6 +114,15 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtExpression> ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> JVM_DEFAULT_NOT_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> JVM_DEFAULT_IN_JVM6_TARGET = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_REQUIRED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_IN_DECLARATION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_THROUGH_INHERITANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<PsiElement> USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
enum NullabilityInformationSource {
KOTLIN {
@NotNull

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.resolve.jvm.platform
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmDefaultSuperCallChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val enableJvmDefault = context.languageVersionSettings.getFlag(AnalysisFlag.enableJvmDefault)
if (enableJvmDefault) return
val superExpression = getSuperCallExpression(resolvedCall.call) ?: return
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
if (!resultingDescriptor.hasJvmDefaultAnnotation()) return
if (DescriptorUtils.isInterface(resultingDescriptor.containingDeclaration)) {
context.trace.report(ErrorsJvm.USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL.on(reportOn))
}
}
}

View File

@@ -91,9 +91,11 @@ object JvmPlatformConfigurator : PlatformConfigurator(
container.useImpl<JavaSyntheticScopes>()
container.useImpl<SamConversionResolverImpl>()
container.useImpl<InterfaceDefaultMethodCallChecker>()
container.useImpl<JvmDefaultChecker>()
container.useImpl<InlinePlatformCompatibilityChecker>()
container.useImpl<JvmModuleAccessibilityChecker>()
container.useImpl<JvmModuleAccessibilityChecker.ClassifierUsage>()
container.useInstance(JvmTypeSpecificityComparator)
container.useImpl<JvmDefaultSuperCallChecker>()
}
}

View File

@@ -28,21 +28,22 @@ import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KParameter
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.full.primaryConstructor
import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.templates.AcceptedAnnotations
import kotlin.script.templates.*
open class KotlinScriptDefinitionFromAnnotatedTemplate(
template: KClass<out Any>,
val environment: Map<String, Any?>? = null,
val templateClasspath: List<File> = emptyList()
) : KotlinScriptDefinition(template) {
val scriptFilePattern by lazy {
val pattern =
takeUnlessError {
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()?.scriptFilePattern
val ann = template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()
ann?.scriptFilePattern
}
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()?.scriptFilePattern }
?: DEFAULT_SCRIPT_FILE_PATTERN
@@ -144,6 +145,15 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
override val annotationsForSamWithReceivers: List<String>
get() = samWithReceiverAnnotations ?: super.annotationsForSamWithReceivers
override val additionalCompilerArguments: Iterable<String>? by lazy {
takeUnlessError {
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateAdditionalCompilerArguments>()?.let {
val res = it.provider.primaryConstructor?.call(it.arguments.asIterable())
res
}
}?.getAdditionalCompilerArguments(environment)
}
private inline fun<T> takeUnlessError(reportError: Boolean = true, body: () -> T?): T? =
try {
body()

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.script
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
@@ -25,8 +26,9 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
import kotlin.reflect.KClass
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure
import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.dependencies.ScriptReport
@@ -37,13 +39,15 @@ class ScriptContentLoader(private val project: Project) {
private fun loadAnnotations(scriptDefinition: KotlinScriptDefinition, file: VirtualFile): List<Annotation> {
val classLoader = scriptDefinition.template.java.classLoader
// TODO_R: report error on failure to load annotation class
return getAnnotationEntries(file, project)
return ApplicationManager.getApplication().runReadAction<List<Annotation>> {
getAnnotationEntries(file, project)
.mapNotNull { psiAnn ->
// TODO: consider advanced matching using semantic similar to actual resolving
scriptDefinition.acceptedAnnotations.find { ann ->
psiAnn.typeName.let { it == ann.simpleName || it == ann.qualifiedName }
}?.let { constructAnnotation(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
}
}
}
private fun getAnnotationEntries(file: VirtualFile, project: Project): Iterable<KtAnnotationEntry> {
@@ -62,7 +66,7 @@ class ScriptContentLoader(private val project: Project) {
fun loadContentsAndResolveDependencies(
scriptDef: KotlinScriptDefinition,
file: VirtualFile
): ScriptDependencies? {
): DependenciesResolver.ResolveResult {
val scriptContents = getScriptContents(scriptDef, file)
val environment = getEnvironment(scriptDef)
val result = try {
@@ -75,7 +79,7 @@ class ScriptContentLoader(private val project: Project) {
e.asResolveFailure(scriptDef)
}
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
return result.dependencies?.adjustByDefinition(scriptDef)
return result
}
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
@@ -92,5 +96,5 @@ fun ScriptDependencies.adjustByDefinition(
fun Throwable.asResolveFailure(scriptDef: KotlinScriptDefinition): Failure {
val prefix = "${scriptDef.dependencyResolver::class.simpleName} threw exception ${this::class.simpleName}:\n "
return Failure(ScriptReport(prefix + (message ?: "<no message>")))
return Failure(ScriptReport(prefix + (message ?: "<no message>"), ScriptReport.Severity.FATAL))
}

View File

@@ -218,12 +218,13 @@ public interface Errors {
DiagnosticFactory0<PsiElement> ANNOTATION_CLASS_MEMBER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> INVALID_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> NULLABLE_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_CONST = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_CONST = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotatedExpression> ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> ANNOTATION_USED_AS_ANNOTATION_ARGUMENT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_IS_NON_CONST = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> ILLEGAL_KOTLIN_VERSION_STRING_VALUE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);

View File

@@ -818,9 +818,9 @@ public class DefaultErrorMessages {
MAP.put(ANNOTATION_CLASS_MEMBER, "Members are not allowed in annotation class");
MAP.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member");
MAP.put(NULLABLE_TYPE_OF_ANNOTATION_MEMBER, "An annotation parameter cannot be nullable");
MAP.put(ANNOTATION_PARAMETER_MUST_BE_CONST, "An annotation parameter must be a compile-time constant");
MAP.put(ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST, "An enum annotation parameter must be a enum constant");
MAP.put(ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL, "An annotation parameter must be a class literal (T::class)");
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_CONST, "An annotation argument must be a compile-time constant");
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST, "An enum annotation argument must be a enum constant");
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL, "An annotation argument must be a class literal (T::class)");
MAP.put(ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT, "Default value of annotation parameter must be a compile-time constant");
MAP.put(ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE,
@@ -828,6 +828,7 @@ public class DefaultErrorMessages {
"Use new line if whole block-level expression must be annotated or wrap annotated expression in parentheses");
MAP.put(ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, "An annotation can't be used as the annotations argument");
MAP.put(ANNOTATION_ARGUMENT_IS_NON_CONST, "An annotation argument must be a compile-time constant");
MAP.put(CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, "Const 'val' are only allowed on top level or in objects");
MAP.put(CONST_VAL_WITH_DELEGATE, "Const 'val' should not have a delegate");

View File

@@ -40,5 +40,19 @@ interface DeclarationAttributeAltererExtension {
isImplicitModality: Boolean
): Modality? = null
@Deprecated(
"Use refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, isImplicitModality)",
ReplaceWith("refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, false)")
)
fun refineDeclarationModality(
modifierListOwner: KtModifierListOwner,
declaration: DeclarationDescriptor?,
containingDeclaration: DeclarationDescriptor?,
currentModality: Modality,
bindingContext: BindingContext
): Modality? {
return refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, false)
}
fun shouldConvertFirstSAMParameterToReceiver(function: FunctionDescriptor): Boolean = false
}

View File

@@ -1,23 +1,11 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -154,15 +142,11 @@ class AnnotationChecker(
}
}
fun checkWithUseSiteTargets(additionalTarget: KotlinTarget? = null, useDeprecatedTargets: Boolean = false): Boolean {
fun checkWithUseSiteTargets(): Boolean {
if (useSiteTarget == null) return false
val useSiteMapping = KotlinTarget.USE_SITE_MAPPING[useSiteTarget].let {
if (useDeprecatedTargets && it == RECEIVER) KotlinTarget.VALUE_PARAMETER else it
}
val allTargets = actualTargets.onlyWithUseSiteTarget + listOfNotNull(additionalTarget)
return allTargets.any { it in applicableTargets && it == useSiteMapping }
val useSiteMapping = KotlinTarget.USE_SITE_MAPPING[useSiteTarget]
return actualTargets.onlyWithUseSiteTarget.any { it in applicableTargets && it == useSiteMapping }
}
if (check(actualTargets.defaultTargets) || check(actualTargets.canBeSubstituted) || checkWithUseSiteTargets()) {
@@ -170,14 +154,6 @@ class AnnotationChecker(
return
}
if (!languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes)) {
val isAnnotationOnType = TargetLists.T_TYPE_REFERENCE == actualTargets
if (isAnnotationOnType && checkWithUseSiteTargets(KotlinTarget.VALUE_PARAMETER, true)) {
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE.on(entry, useSiteTarget!!.renderName))
return
}
}
if (useSiteTarget != null) {
trace.report(
Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
@@ -350,7 +326,7 @@ class AnnotationChecker(
val T_OBJECT_LITERAL = targetList(OBJECT_LITERAL, CLASS, EXPRESSION)
val T_TYPE_REFERENCE = targetList(TYPE) {
onlyWithUseSiteTarget(RECEIVER)
onlyWithUseSiteTarget(VALUE_PARAMETER)
}
val T_TYPE_PARAMETER = targetList(TYPE_PARAMETER)

View File

@@ -1,21 +1,12 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -26,14 +17,60 @@ import org.jetbrains.kotlin.psi.*
object AnnotationUseSiteTargetChecker {
fun check(annotated: KtAnnotated, descriptor: DeclarationDescriptor, trace: BindingTrace) {
fun check(
annotated: KtAnnotated,
descriptor: DeclarationDescriptor,
trace: BindingTrace,
languageVersionSettings: LanguageVersionSettings
) {
trace.checkDeclaration(annotated, descriptor)
if (annotated is KtCallableDeclaration) {
annotated.receiverTypeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = true) }
annotated.typeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = false) }
}
if (annotated is KtFunction) {
for (parameter in annotated.valueParameters) {
if (parameter.hasValOrVar()) continue
val parameterDescriptor = trace.bindingContext[BindingContext.VALUE_PARAMETER, parameter] ?: continue
trace.checkDeclaration(parameter, parameterDescriptor)
parameter.typeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = false) }
}
}
}
private fun BindingTrace.checkTypeReference(
topLevelTypeReference: KtTypeReference,
languageVersionSettings: LanguageVersionSettings,
isReceiver: Boolean
) {
checkAsTopLevelTypeReference(topLevelTypeReference, languageVersionSettings, isReceiver)
topLevelTypeReference.acceptChildren(
typeReferenceRecursiveVisitor { typeReference ->
checkAsTopLevelTypeReference(typeReference, languageVersionSettings, isReceiver = false)
}
)
}
private fun BindingTrace.checkAsTopLevelTypeReference(
topLevelTypeReference: KtTypeReference,
languageVersionSettings: LanguageVersionSettings,
isReceiver: Boolean
) {
for (annotationEntry in topLevelTypeReference.annotationEntries) {
val target = annotationEntry.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue
if (target != AnnotationUseSiteTarget.RECEIVER || !isReceiver) {
val diagnostic =
if (languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes))
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(annotationEntry, "undefined target", target.renderName)
else
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE.on(annotationEntry, target.renderName)
reportDiagnosticOnce(diagnostic)
}
}
}
@@ -64,8 +101,9 @@ object AnnotationUseSiteTargetChecker {
}
AnnotationUseSiteTarget.SETTER_PARAMETER -> checkIfMutableProperty(annotated, annotation)
AnnotationUseSiteTarget.FILE -> reportDiagnosticOnce(INAPPLICABLE_FILE_TARGET.on(useSiteTarget))
AnnotationUseSiteTarget.RECEIVER -> {
}
AnnotationUseSiteTarget.RECEIVER ->
// annotation with use-site target `receiver` can be only on type reference, but not on declaration
reportDiagnosticOnce(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(annotation, "declaration", target.renderName))
}
}
}

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.annotations
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
@@ -28,6 +29,12 @@ val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
val JVM_FIELD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmField")
val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault")
fun CallableMemberDescriptor.hasJvmDefaultAnnotation() =
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)
fun DeclarationDescriptor.hasJvmStaticAnnotation(): Boolean {
return annotations.findAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) != null
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve;
@@ -222,7 +211,7 @@ public class ModifiersChecker {
}
private void checkModifierListCommon(@NotNull KtDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
AnnotationUseSiteTargetChecker.INSTANCE.check(modifierListOwner, descriptor, trace);
AnnotationUseSiteTargetChecker.INSTANCE.check(modifierListOwner, descriptor, trace, languageVersionSettings);
runDeclarationCheckers(modifierListOwner, descriptor);
annotationChecker.check(modifierListOwner, trace, descriptor);
ModifierCheckerCore.INSTANCE.check(modifierListOwner, trace, descriptor, languageVersionSettings);

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve.calls.callResolverUtil
@@ -22,20 +11,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
@@ -186,41 +174,65 @@ fun getSuperCallExpression(call: Call): KtSuperExpression? {
fun getEffectiveExpectedType(
parameterDescriptor: ValueParameterDescriptor,
argument: ValueArgument,
context: ResolutionContext<*>
resolvedArgument: ResolvedValueArgument,
languageVersionSettings: LanguageVersionSettings,
trace: BindingTrace
): KotlinType {
if (argument.getSpreadElement() != null || shouldCheckAsArray(parameterDescriptor, argument, context)) {
if (parameterDescriptor.varargElementType == null) {
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
return DONT_CARE
}
return parameterDescriptor.type
}
val varargElementType = parameterDescriptor.varargElementType
if (varargElementType != null) {
return varargElementType
}
return parameterDescriptor.type
val argument = resolvedArgument.arguments.singleOrNull()
return if (argument != null)
getEffectiveExpectedTypeForSingleArgument(parameterDescriptor, argument, languageVersionSettings, trace)
else
getExpectedType(parameterDescriptor)
}
private fun shouldCheckAsArray(
fun getEffectiveExpectedType(
parameterDescriptor: ValueParameterDescriptor,
argument: ValueArgument,
context: ResolutionContext<*>
): KotlinType {
return getEffectiveExpectedTypeForSingleArgument(parameterDescriptor, argument, context.languageVersionSettings, context.trace)
}
fun getEffectiveExpectedTypeForSingleArgument(
parameterDescriptor: ValueParameterDescriptor,
argument: ValueArgument,
languageVersionSettings: LanguageVersionSettings,
trace: BindingTrace
): KotlinType {
if (argument.getSpreadElement() != null) {
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
return if (parameterDescriptor.varargElementType == null) DONT_CARE else parameterDescriptor.type
}
if (arrayAssignmentToVarargInNamedFormInAnnotation(parameterDescriptor, argument, languageVersionSettings, trace)) {
return parameterDescriptor.type
}
return getExpectedType(parameterDescriptor)
}
private fun getExpectedType(parameterDescriptor: ValueParameterDescriptor): KotlinType {
return parameterDescriptor.varargElementType ?: parameterDescriptor.type
}
private fun arrayAssignmentToVarargInNamedFormInAnnotation(
parameterDescriptor: ValueParameterDescriptor,
argument: ValueArgument,
languageVersionSettings: LanguageVersionSettings,
trace: BindingTrace
): Boolean {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
if (!languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
if (!isParameterOfAnnotation(parameterDescriptor)) return false
return argument.isNamed() && parameterDescriptor.isVararg && isArrayOrArrayLiteral(argument, context)
return argument.isNamed() && parameterDescriptor.isVararg && isArrayOrArrayLiteral(argument, trace)
}
fun isArrayOrArrayLiteral(argument: ValueArgument, context: ResolutionContext<*>): Boolean {
fun isArrayOrArrayLiteral(argument: ValueArgument, trace: BindingTrace): Boolean {
val argumentExpression = argument.getArgumentExpression() ?: return false
if (argumentExpression is KtCollectionLiteralExpression) return true
val type = context.trace.getType(argumentExpression) ?: return false
val type = trace.getType(argumentExpression) ?: return false
return KotlinBuiltIns.isArrayOrPrimitiveArray(type)
}
@@ -276,15 +288,3 @@ fun createResolutionCandidatesForConstructors(
ResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor)
}
}
fun KtLambdaExpression.getCorrespondingParameterForFunctionArgument(
bindingContext: BindingContext
): ValueParameterDescriptor? {
val resolvedCall = KtPsiUtil.getParentCallIfPresent(this)?.getResolvedCall(bindingContext) ?: return null
val valueArgument =
resolvedCall.call.getValueArgumentForExpression(this)
?: return null
val mapping = resolvedCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return null
return mapping.valueParameter
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve.calls.checkers
@@ -61,7 +50,7 @@ class AssigningNamedArgumentToVarargChecker : CallChecker {
argumentExpression: KtExpression,
context: ResolutionContext<*>
) {
if (isArrayOrArrayLiteral(argument, context)) {
if (isArrayOrArrayLiteral(argument, context.trace)) {
if (argument.hasSpread()) {
context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression))
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.resolve.constants.evaluate
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext.COLLECTION_LITERAL_CALL
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
@@ -97,8 +87,9 @@ class ConstantExpressionEvaluator(
val varargElementType = parameterDescriptor.varargElementType
val argumentsAsVararg = varargElementType != null && !hasSpread(resolvedArgument)
val constantType = if (argumentsAsVararg) varargElementType else parameterDescriptor.type
val compileTimeConstants = resolveAnnotationValueArguments(resolvedArgument, constantType!!, trace)
val constants = compileTimeConstants.map { it.toConstantValue(constantType) }
val expectedType = getEffectiveExpectedType(parameterDescriptor, resolvedArgument, languageVersionSettings, trace)
val compileTimeConstants = resolveAnnotationValueArguments(resolvedArgument, constantType!!, expectedType, trace)
val constants = compileTimeConstants.map { it.toConstantValue(expectedType) }
if (argumentsAsVararg) {
if (isArrayPassedInNamedForm(constants, resolvedArgument)) return constants.single()
@@ -120,72 +111,82 @@ class ConstantExpressionEvaluator(
private fun checkCompileTimeConstant(
argumentExpression: KtExpression,
expectedType: KotlinType,
trace: BindingTrace
expressionType: KotlinType,
trace: BindingTrace,
useDeprecationWarning: Boolean
) {
val expressionType = trace.getType(argumentExpression)
if (expressionType == null || !KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
// TYPE_MISMATCH should be reported otherwise
return
}
// array(1, <!>null<!>, 3) - error should be reported on inner expression
if (argumentExpression is KtCallExpression) {
getArgumentExpressionsForArrayCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
}
if (argumentExpression is KtCollectionLiteralExpression) {
getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)?.let {
checkArgumentsAreCompileTimeConstants(
it,
trace
)
}
}
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
if (constant != null && constant.canBeUsedInAnnotations) {
if (constant.usesNonConstValAsConstant) {
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
}
if (argumentExpression is KtClassLiteralExpression) {
val lhsExpression = argumentExpression.receiverExpression
if (lhsExpression != null) {
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
}
}
}
checkInnerPartsOfCompileTimeConstant(constant, trace, argumentExpression, useDeprecationWarning)
return
}
val descriptor = expressionType.constructor.declarationDescriptor
if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression))
} else if (descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor)) {
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
} else {
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression))
val diagnosticFactory = when {
DescriptorUtils.isEnumClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
else -> Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST
}
if (useDeprecationWarning)
reportDeprecationWarningOnNonConst(argumentExpression, trace)
else
trace.report(diagnosticFactory.on(argumentExpression))
}
private fun checkInnerPartsOfCompileTimeConstant(
constant: CompileTimeConstant<*>,
trace: BindingTrace,
argumentExpression: KtExpression,
useDeprecationWarning: Boolean
) {
// array(1, <!>null<!>, 3) - error should be reported on inner expression
val callArguments = when (argumentExpression) {
is KtCallExpression -> getArgumentExpressionsForArrayCall(argumentExpression, trace)
is KtCollectionLiteralExpression -> getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)
else -> null
}
if (callArguments != null) {
for (argument in callArguments) {
val type = trace.getType(argument) ?: continue
checkCompileTimeConstant(argument, type, trace, useDeprecationWarning)
}
}
// TODO: Consider removing this check, because we already checked inner expression
if (constant.usesNonConstValAsConstant) {
if (useDeprecationWarning) {
reportDeprecationWarningOnNonConst(argumentExpression, trace)
} else {
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
}
}
if (argumentExpression is KtClassLiteralExpression) {
val lhsExpression = argumentExpression.receiverExpression
if (lhsExpression != null) {
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
if (useDeprecationWarning) {
reportDeprecationWarningOnNonConst(argumentExpression, trace)
} else {
trace.report(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
}
}
}
}
}
private fun checkArgumentsAreCompileTimeConstants(
argumentsWithComponentType: Pair<List<KtExpression>, KotlinType?>,
trace: BindingTrace
) {
val (arguments, componentType) = argumentsWithComponentType
for (expression in arguments) {
checkCompileTimeConstant(expression, componentType!!, trace)
}
private fun reportDeprecationWarningOnNonConst(expression: KtExpression, trace: BindingTrace) {
trace.report(Errors.ANNOTATION_ARGUMENT_IS_NON_CONST.on(expression))
}
private fun getArgumentExpressionsForArrayCall(
expression: KtCallExpression,
trace: BindingTrace
): Pair<List<KtExpression>, KotlinType?>? {
): List<KtExpression>? {
val resolvedCall = expression.getResolvedCall(trace.bindingContext) ?: return null
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
}
@@ -193,19 +194,16 @@ class ConstantExpressionEvaluator(
private fun getArgumentExpressionsForCollectionLiteralCall(
expression: KtCollectionLiteralExpression,
trace: BindingTrace
): Pair<List<KtExpression>, KotlinType?>? {
): List<KtExpression>? {
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
}
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): Pair<List<KtExpression>, KotlinType>? {
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): List<KtExpression>? {
if (!CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
return null
}
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
val componentType = module.builtIns.getArrayElementType(returnType)
val result = arrayListOf<KtExpression>()
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
for (valueArgument in resolvedValueArgument.arguments) {
@@ -216,7 +214,7 @@ class ConstantExpressionEvaluator(
}
}
return Pair<List<KtExpression>, KotlinType>(result, componentType)
return result
}
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
@@ -226,6 +224,7 @@ class ConstantExpressionEvaluator(
private fun resolveAnnotationValueArguments(
resolvedValueArgument: ResolvedValueArgument,
deprecatedExpectedType: KotlinType,
expectedType: KotlinType,
trace: BindingTrace
): List<CompileTimeConstant<*>> {
@@ -240,7 +239,21 @@ class ConstantExpressionEvaluator(
if (constant != null) {
constants.add(constant)
}
checkCompileTimeConstant(argumentExpression, expectedType, trace)
val expressionType = trace.getType(argumentExpression) ?: continue
// this type check should not used as it can introduce subtle bugs when type checking rules against expected type are changing
if (!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonConstValuesAsVarargsInAnnotations) &&
!KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, deprecatedExpectedType)
) {
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
checkCompileTimeConstant(argumentExpression, expressionType, trace, useDeprecationWarning = true)
}
continue // TYPE_MISMATCH should be reported otherwise
}
checkCompileTimeConstant(argumentExpression, expressionType, trace, useDeprecationWarning = false)
}
return constants
}

View File

@@ -345,7 +345,7 @@ class DeprecationResolver(
ProtoBuf.VersionRequirement.VersionKind.API_VERSION ->
languageVersionSettings.apiVersion.version
ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION ->
KotlinCompilerVersion.getVersion()?.takeIf { "SNAPSHOT" !in it }?.let(::createVersion)
KotlinCompilerVersion.getVersion()?.substringBefore('-')?.let(::createVersion)
else -> null
}
if (currentVersion != null && currentVersion < requiredVersion) {

View File

@@ -40,7 +40,7 @@ class ClassResolutionScopesSupport(
}
}
val scopeForClassHeaderResolution: () -> LexicalScope = storageManager.createLazyValue {
val scopeForClassHeaderResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) {
scopeWithGenerics(getOuterScope())
}

View File

@@ -32,6 +32,9 @@ sourceSets {
projectTest {
workingDir = rootDir
doFirst {
systemProperty("idea.home.path", intellijRootDir().canonicalPath)
}
}
testsJar()

View File

@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.File
@@ -43,7 +44,8 @@ abstract class IncrementalCompilerRunner<
protected val cacheVersions: List<CacheVersion>,
protected val reporter: ICReporter,
protected val artifactChangesProvider: ArtifactChangesProvider?,
protected val changesRegistry: ChangesRegistry?
protected val changesRegistry: ChangesRegistry?,
private val localStateDirs: Collection<File> = emptyList()
) {
protected val cacheDirectory = File(workingDir, cacheDirName)
@@ -70,7 +72,15 @@ abstract class IncrementalCompilerRunner<
caches.clean()
dirtySourcesSinceLastTimeFile.delete()
destinationDir(args).deleteRecursively()
reporter.report { "Deleting output directories on rebuild:" }
for (dir in sequenceOf(destinationDir(args)) + localStateDirs.asSequence()) {
if (!dir.isDirectory) continue
dir.deleteRecursively()
dir.mkdirs()
reporter.report { "deleted $dir" }
}
caches = createCacheManager(args)
if (providedChangedFiles == null) {
@@ -271,6 +281,30 @@ abstract class IncrementalCompilerRunner<
return exitCode
}
protected fun getRemovedClassesChanges(
caches: IncrementalCachesManager<*>,
changedFiles: ChangedFiles.Known
): DirtyData {
val removedClasses = HashSet<String>()
val dirtyFiles = changedFiles.modified.filterTo(HashSet()) { it.isKotlinFile() }
val removedFiles = changedFiles.removed.filterTo(HashSet()) { it.isKotlinFile() }
val existingClasses = classesFqNames(dirtyFiles)
val previousClasses = caches.platformCache
.classesFqNamesBySources(dirtyFiles + removedFiles)
.map { it.asString() }
for (fqName in previousClasses) {
if (fqName !in existingClasses) {
removedClasses.add(fqName)
}
}
val changesCollector = ChangesCollector()
removedClasses.forEach { changesCollector.collectSignature(FqName(it), areSubclassesAffected = true) }
return changesCollector.getDirtyData(listOf(caches.platformCache), reporter)
}
open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false
protected open fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.*
import org.jetbrains.kotlin.name.FqName
import java.io.File
fun makeJsIncrementally(
@@ -92,7 +93,29 @@ class IncrementalJsCompilerRunner(
if (changedLib != null) return CompilationMode.Rebuild { "Library has been changed: $changedLib" }
return CompilationMode.Incremental(getDirtyFiles(changedFiles))
val dirtyFiles = getDirtyFiles(changedFiles)
// todo: unify with JVM calculateSourcesToCompile
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
if (lookupSymbols.isEmpty()) return
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
dirtyFiles.addAll(dirtyFilesFromLookups)
}
fun markDirtyBy(dirtyClassesFqNames: Collection<FqName>) {
if (dirtyClassesFqNames.isEmpty()) return
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
dirtyFiles.addAll(dirtyFilesFromFqNames)
}
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
return CompilationMode.Incremental(dirtyFiles)
}
override fun makeServices(

View File

@@ -71,7 +71,8 @@ fun makeIncrementally(
sourceRoots.map { JvmSourceRoot(it, null) }.toSet(),
versions, reporter,
// Use precise setting in case of non-Gradle build
usePreciseJavaTracking = true
usePreciseJavaTracking = true,
localStateDirs = emptyList()
)
compiler.compile(sourceFiles, args, messageCollector, providedChangedFiles = null)
}
@@ -104,14 +105,16 @@ class IncrementalJvmCompilerRunner(
changesRegistry: ChangesRegistry? = null,
private val buildHistoryFile: File? = null,
private val friendBuildHistoryFile: File? = null,
private val usePreciseJavaTracking: Boolean
private val usePreciseJavaTracking: Boolean,
localStateDirs: Collection<File>
) : IncrementalCompilerRunner<K2JVMCompilerArguments, IncrementalJvmCachesManager>(
workingDir,
"caches-jvm",
cacheVersions,
reporter,
artifactChangesProvider,
changesRegistry
changesRegistry,
localStateDirs = localStateDirs
) {
override fun isICEnabled(): Boolean =
IncrementalCompilation.isEnabled()
@@ -138,7 +141,11 @@ class IncrementalJvmCompilerRunner(
else
null
override fun calculateSourcesToCompile(caches: IncrementalJvmCachesManager, changedFiles: ChangedFiles.Known, args: K2JVMCompilerArguments): CompilationMode {
override fun calculateSourcesToCompile(
caches: IncrementalJvmCachesManager,
changedFiles: ChangedFiles.Known,
args: K2JVMCompilerArguments
): CompilationMode {
val dirtyFiles = getDirtyFiles(changedFiles)
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
@@ -211,10 +218,13 @@ class IncrementalJvmCompilerRunner(
}
val androidLayoutChanges = processLookupSymbolsForAndroidLayouts(changedFiles)
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
markDirtyBy(androidLayoutChanges)
markDirtyBy(classpathChanges.lookupSymbols)
markDirtyBy(classpathChanges.fqNames)
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
return CompilationMode.Incremental(dirtyFiles)
}
@@ -311,7 +321,9 @@ class IncrementalJvmCompilerRunner(
override fun preBuildHook(args: K2JVMCompilerArguments, compilationMode: CompilationMode) {
when (compilationMode) {
is CompilationMode.Incremental -> {
args.classpathAsList += args.destinationAsFile.apply { mkdirs() }
val destinationDir = args.destinationAsFile
destinationDir.mkdirs()
args.classpathAsList = listOf(destinationDir) + args.classpathAsList
}
is CompilationMode.Rebuild -> {
// there is no point in updating annotation file since all files will be compiled anyway

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental.parsing
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.local.CoreLocalFileSystem
import com.intellij.psi.PsiManager
import com.intellij.psi.SingleRootFileViewProvider
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
import java.util.*
fun classesFqNames(files: Set<File>): Set<String> {
val existingKotlinFiles = files.filter { it.name.endsWith(".kt", ignoreCase = true) && it.isFile }
if (existingKotlinFiles.isEmpty()) return emptySet()
val disposable = Disposer.newDisposable()
return try {
classesFqNames(existingKotlinFiles, disposable)
} finally {
Disposer.dispose(disposable)
}
}
private fun classesFqNames(kotlinFiles: Collection<File>, disposable: Disposable): Set<String> {
val config = CompilerConfiguration()
config.put(JVMConfigurationKeys.NO_JDK, true)
config.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
val environment = KotlinCoreEnvironment.createForProduction(disposable, config, configFiles)
val psiManager = PsiManager.getInstance(environment.project)
val fileManager = VirtualFileManager.getInstance()
val localFS = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem
val result = HashSet<String>()
for (file in kotlinFiles) {
val virtualFile = localFS.findFileByIoFile(file)!!
for (psiFile in SingleRootFileViewProvider(psiManager, virtualFile).allFiles) {
if (psiFile !is KtFile) continue
val classes = ArrayDeque<KtClassOrObject>()
psiFile.declarations.filterClassesTo(classes)
while (classes.isNotEmpty()) {
val klass = classes.pollFirst()
klass.fqName?.let {
result.add(it.asString())
}
klass.declarations.filterClassesTo(classes)
}
}
}
return result
}
private fun Collection<KtDeclaration>.filterClassesTo(classes: Deque<KtClassOrObject>) {
filterIsInstanceTo<KtClassOrObject, Deque<KtClassOrObject>>(classes)
}

View File

@@ -101,7 +101,7 @@ abstract class AbstractIncrementalCompilerRunnerTestBase<Args : CommonCompilerAr
Assert.assertEquals("Rebuild exit code differs from incremental exit code", rebuildExpectedToSucceed, rebuildSucceeded)
if (rebuildSucceeded) {
assertEqualDirectories(outDir, rebuildOutDir, forgiveExtraFiles = rebuildSucceeded)
assertEqualDirectories(rebuildOutDir, outDir, forgiveExtraFiles = false)
}
}
}

View File

@@ -37,6 +37,7 @@ abstract class AbstractIncrementalJsCompilerRunnerTest : AbstractIncrementalComp
override fun createCompilerArguments(destinationDir: File, testDir: File): K2JSCompilerArguments =
K2JSCompilerArguments().apply {
outputFile = File(destinationDir, "${testDir.name}.js").path
sourceMap = true
sourceMap = false
metaInfo = true
}
}

View File

@@ -756,6 +756,12 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa
doTest(fileName);
}
@TestMetadata("classMovedIntoOtherClass")
public void testClassMovedIntoOtherClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classMovedIntoOtherClass/");
doTest(fileName);
}
@TestMetadata("classRemoved")
public void testClassRemoved() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classRemoved/");

View File

@@ -756,6 +756,12 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
doTest(fileName);
}
@TestMetadata("classMovedIntoOtherClass")
public void testClassMovedIntoOtherClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classMovedIntoOtherClass/");
doTest(fileName);
}
@TestMetadata("classRemoved")
public void testClassRemoved() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classRemoved/");

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental.parsing
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.UsefulTestCase
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.File
class ClassesFqNamesTest {
private lateinit var workingDir: File
@Before
fun setUp() {
workingDir = FileUtil.createTempDirectory("ClassesFqNamesTest", null)
}
@After
fun tearDown() {
workingDir.deleteRecursively()
}
@Test
fun testSingleClass() {
doTest(
setOf("test.Foo"),
"""
package test
class Foo""".trimIndent()
)
}
@Test
fun testMultipleClasses() {
doTest(
setOf("test.Fizz", "test.Buzz"),
"""
package test
class Fizz
class Buzz""".trimIndent()
)
}
@Test
fun testInnerClasses() {
doTest(
setOf("test.Foo", "test.Foo.Fizz", "test.Foo.Buzz"),
"""
package test
class Foo {
class Fizz
class Buzz
}""".trimIndent()
)
}
@Test
fun testObject() {
doTest(
setOf("test.Foo", "test.Foo.Fizz", "test.Bar", "test.Bar.Buzz"),
"""
package test
object Foo {
class Fizz
}
class Bar {
object Buzz
}""".trimIndent()
)
}
private fun doTest(expectedClasses: Set<String>, code: String) {
val testKt = File(workingDir, "test.kt")
testKt.writeText(code)
val expected = expectedClasses.sorted().joinToString("\n")
val actual = classesFqNames(setOf(testKt)).sorted().joinToString("\n")
UsefulTestCase.assertEquals(expected, actual)
}
}

View File

@@ -34,11 +34,11 @@ import org.jetbrains.kotlin.codegen.AsmUtil.isAbstractMethod
import org.jetbrains.kotlin.codegen.BuiltinSpecialBridgesUtil
import org.jetbrains.kotlin.codegen.FunctionCodegen.isMethodOfAny
import org.jetbrains.kotlin.codegen.FunctionCodegen.isThereOverriddenInKotlinClass
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -60,6 +60,8 @@ import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescripto
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -73,12 +75,12 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
private val typeMapper = state.typeMapper
private val IS_PURE_INTERFACE_CHECKER = fun(descriptor: DeclarationDescriptor): Boolean =
JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state)
private val DECLARATION_AND_DEFINITION_CHECKER = fun(descriptor: CallableMemberDescriptor): Boolean =
!isInterface(descriptor.containingDeclaration) || state.target !== JvmTarget.JVM_1_6 && descriptor.hasJvmDefaultAnnotation()
override fun lower(irClass: IrClass) {
val classDescriptor = irClass.descriptor
if (IS_PURE_INTERFACE_CHECKER(classDescriptor) || classDescriptor is FileClassDescriptor) return
if (classDescriptor is FileClassDescriptor) return
if (classDescriptor is DefaultImplsClassDescriptor) {
return /*TODO?*/
@@ -133,7 +135,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
bridgesToGenerate = generateBridgesForFunctionDescriptor(
descriptor,
getSignatureMapper(typeMapper),
IS_PURE_INTERFACE_CHECKER
DECLARATION_AND_DEFINITION_CHECKER
)
if (!bridgesToGenerate.isEmpty()) {
val origin = if (descriptor.kind == DECLARATION) getSourceFromDescriptor(descriptor) else null
@@ -148,7 +150,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
val specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
descriptor,
getSignatureMapper(typeMapper),
IS_PURE_INTERFACE_CHECKER
DECLARATION_AND_DEFINITION_CHECKER
)
if (!specials.isEmpty()) {
@@ -160,7 +162,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
}
}
if (!descriptor.kind.isReal && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state)) {
if (!descriptor.kind.isReal && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
descriptor.getOverriddenBuiltinReflectingJvmDescriptor<CallableMemberDescriptor>() ?:
error("Expect to find overridden descriptors for $descriptor")

View File

@@ -31,6 +31,12 @@ interface CommandLineProcessor {
put(option, paths)
}
fun <T> CompilerConfiguration.appendList(option: CompilerConfigurationKey<List<T>>, values: List<T>) {
val paths = getList(option).toMutableList()
paths.addAll(values)
put(option, paths)
}
fun CompilerConfiguration.applyOptionsFrom(map: Map<String, List<String>>, pluginOptions: Collection<CliOption>) {
for ((key, values) in map) {
val option = pluginOptions.firstOrNull { it.name == key } ?: continue

View File

@@ -37,6 +37,8 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
super(stub, KtStubElementTypes.IMPORT_DIRECTIVE);
}
private volatile FqName importedFqName;
@Override
public <R, D> R accept(@NotNull KtVisitor<R, D> visitor, D data) {
return visitor.visitImportDirective(this, data);
@@ -78,7 +80,16 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
if (stub != null) {
return stub.getImportedFqName();
}
return fqNameFromExpression(getImportedReference());
FqName importedFqName = this.importedFqName;
if (importedFqName != null) return importedFqName;
KtExpression importedReference = getImportedReference();
// in case it's not parsed
if (importedReference == null) return null;
importedFqName = fqNameFromExpression(importedReference);
this.importedFqName = importedFqName;
return importedFqName;
}
@Nullable
@@ -106,6 +117,12 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
return !PsiTreeUtil.hasErrorElements(this);
}
@Override
public void subtreeChanged() {
super.subtreeChanged();
importedFqName = null;
}
@Nullable
private static FqName fqNameFromExpression(@Nullable KtExpression expression) {
if (expression == null) {

View File

@@ -170,6 +170,14 @@ fun prefixExpressionRecursiveVisitor(block: (KtPrefixExpression) -> Unit) =
}
}
fun typeReferenceRecursiveVisitor(block: (KtTypeReference) -> Unit) =
object : KtTreeVisitorVoid() {
override fun visitTypeReference(typeReference: KtTypeReference) {
super.visitTypeReference(typeReference)
block(typeReference)
}
}
fun namedFunctionVisitor(block: (KtNamedFunction) -> Unit) =
object : KtVisitorVoid() {
override fun visitNamedFunction(namedFunction: KtNamedFunction) {

View File

@@ -28,7 +28,7 @@ object KotlinStubVersions {
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
private const val BINARY_STUB_VERSION = 64
private const val BINARY_STUB_VERSION = 66
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
// Increasing this version will lead to reindexing of all classfiles.

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.script
import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.openapi.util.UserDataHolderBase
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
@@ -26,7 +27,7 @@ import kotlin.reflect.KClass
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.templates.standard.ScriptTemplateWithArgs
open class KotlinScriptDefinition(val template: KClass<out Any>) {
open class KotlinScriptDefinition(val template: KClass<out Any>) : UserDataHolderBase() {
open val name: String = "Kotlin Script"
@@ -45,6 +46,9 @@ open class KotlinScriptDefinition(val template: KClass<out Any>) {
open val dependencyResolver: DependenciesResolver get() = DependenciesResolver.NoDependencies
open val acceptedAnnotations: List<KClass<out Annotation>> get() = emptyList()
@Deprecated("temporary workaround for missing functionality, will be replaced by the new API soon")
open val additionalCompilerArguments: Iterable<String>? = null
}
object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class)

View File

@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
@@ -70,20 +69,44 @@ fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
return DFS.ifAny(
listOf(this),
{ current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
{ it.declaresDefaultValue() || it.isActualParameterWithExpectedDefault }
{ it.declaresDefaultValue() || it.isActualParameterWithAnyExpectedDefault }
)
}
val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean
get() {
val function = containingDeclaration
if (function is FunctionDescriptor && function.isActual) {
with(ExpectedActualResolver) {
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
return expected is FunctionDescriptor && expected.valueParameters[index].hasDefaultValue()
}
fun ValueParameterDescriptor.checkExpectedParameter(checker: (ValueParameterDescriptor) -> Boolean) : Boolean {
val function = containingDeclaration
if (function is FunctionDescriptor && function.isActual) {
with(ExpectedActualResolver) {
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
return expected is FunctionDescriptor && checker(expected.valueParameters[index])
}
return false
}
return false
}
/**
* The following two properties describe two different situations:
*
* Consider hierarchy:
* expect open class A { foo(p = 1) }
* expect open class B : A { foo(p) }
*
* actual open class A { foo(p) }
* actual open class B : A { foo(p) }
*
* For parameter `p` of method `foo`:
* `Any` property returns `true` for both actual A and B
* `Corresponding` property returns `true` only for `actual A` because `expect B` declaration doesn't have an default value
*/
val ValueParameterDescriptor.isActualParameterWithAnyExpectedDefault: Boolean
get() {
return checkExpectedParameter { it.hasDefaultValue() }
}
val ValueParameterDescriptor.isActualParameterWithCorrespondingExpectedDefault: Boolean
get() {
return checkExpectedParameter { it.declaresDefaultValue() }
}
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(

View File

@@ -22,9 +22,11 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.resolve.RequireKotlinNames
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithExpectedDefault
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithAnyExpectedDefault
import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.IntValue
@@ -141,6 +143,8 @@ class DescriptorSerializer private constructor(
val requirement = serializeVersionRequirement(classDescriptor)
if (requirement != null) {
builder.versionRequirement = requirement
} else {
writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor, builder)
}
val versionRequirementTableProto = versionRequirementTable.serialize()
@@ -306,8 +310,7 @@ class DescriptorSerializer private constructor(
val requirement = serializeVersionRequirement(descriptor)
if (requirement != null) {
builder.versionRequirement = requirement
}
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
} else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
}
@@ -408,7 +411,7 @@ class DescriptorSerializer private constructor(
private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder {
val builder = ProtoBuf.ValueParameter.newBuilder()
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithExpectedDefault
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithAnyExpectedDefault
val flags = Flags.getValueParameterFlags(
hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline
@@ -615,13 +618,36 @@ class DescriptorSerializer private constructor(
return builder
}
// Interfaces which have @JvmDefault members somewhere in the hierarchy need the compiler 1.2.40+
// so that the generated bridges in subclasses would call the super members correctly
private fun writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor: ClassDescriptor, builder: ProtoBuf.Class.Builder) {
if (
isInterface(classDescriptor) &&
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any {
it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation()
}
) {
builder.versionRequirement = writeVersionRequirement(1, 2, 40, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION)
}
}
private fun writeVersionRequirement(languageFeature: LanguageFeature): Int {
val languageVersion = languageFeature.sinceVersion!!
return writeVersionRequirement(
languageVersion.major, languageVersion.minor, 0,
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION
)
}
private fun writeVersionRequirement(major: Int, minor: Int, patch: Int, versionKind: ProtoBuf.VersionRequirement.VersionKind): Int {
val requirement = ProtoBuf.VersionRequirement.newBuilder().apply {
VersionRequirement.Version(languageVersion.major, languageVersion.minor).encode(
writeVersion = { version = it },
writeVersionFull = { versionFull = it }
VersionRequirement.Version(major, minor, patch).encode(
writeVersion = { version = it },
writeVersionFull = { versionFull = it }
)
if (versionKind != defaultInstanceForType.versionKind) {
this.versionKind = versionKind
}
}
return versionRequirementTable[requirement]
}

View File

@@ -2,6 +2,7 @@ Usage: kotlinc-js <options> <source files>
where advanced options include:
-Xfriend-modules=<path> Paths to friend modules
-Xfriend-modules-disabled Disable internal declaration export
-Xtyped-arrays Translate primitive arrays to JS typed arrays
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier

View File

@@ -8,6 +8,7 @@ where advanced options include:
-Xnormalize-constructor-calls={disable|enable}
Normalize constructor calls (disable: don't normalize; enable: normalize), default is disable
-Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings
-Xenable-jvm-default Allow to use '@JvmDefault' for JVM default method support
-Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade
-Xmodule-path=<path> Paths where to find Java 9+ modules
-Xjavac-arguments=<option[,]> Java compiler arguments
@@ -40,6 +41,7 @@ where advanced options include:
Default value is 'enable'
-Xuse-javac Use javac for Java source and class files analysis
-Xuse-old-class-files-reading Use old class files reading implementation (may slow down the build and should be used in case of problems with the new implementation)
-Xuse-type-table Use type table in metadata serialization
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier

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