Compare commits

...

316 Commits

Author SHA1 Message Date
Igor Chevdar
3a35ba7e58 Fixed WrappedClassDescriptor 2019-01-23 11:16:19 +03:00
Pavel Punegov
d0fb059d58 Update K/N to 1.1.1-release-6082 2019-01-23 11:15:38 +03:00
Roman Artemev
27d3a1e534 Update 1.3.20 ChangeLog 2019-01-21 19:17:24 +03:00
Yan Zhulanow
2027d58ef3 Remove Android Extensions from the default JPS classpath 2019-01-21 18:50:51 +03:00
Pavel Punegov
8f5ca82b26 Update to 1.1.0-release-5988 for 1.3.20 2019-01-21 17:43:35 +03:00
Mikhail Glukhikh
0d9c30a311 Use correct project for settings.gradle manipulations #KT-29333 Fixed
Otherwise we get an error "Element from alien project".
See details in added comment.
2019-01-21 13:57:44 +03:00
Ilya Chernikov
76b8319fbe Change default jvmTarget for scripts compilation via jvmhost to 1.8
#KT-29319 fixed
2019-01-18 18:10:32 +01:00
Ilya Chernikov
069857c12c Implement test for #KT-29301, #KT-29296 and #KT-29293 2019-01-18 18:10:31 +01:00
Ilya Chernikov
5ab6472a4d Keep ivy resolvers in the main-kts.jar
#KT-29301 fixed
2019-01-18 18:10:31 +01:00
Ilya Chernikov
5306e3f88a Implement and use helpers for economical classpath update in script configs 2019-01-18 18:10:30 +01:00
Ilya Chernikov
97a8739182 Allow explicit nulls for props with default, allow null as base classloader for evaluation
and use proper default evaluation configuration if not supplied explicitly;
also add reset method to the properties builder and containsKey method to
the properties collection
#KT-29296 fixed
2019-01-18 18:10:29 +01:00
Ilya Chernikov
1623ed027d Add stdlib, etc. to the script dependencies on compilation
#KT-29293 fixed
2019-01-18 18:10:29 +01:00
Alexander Podkhalyuzin
e0226ce5dd Removed usages to deprecated API, which is going to be removed in 2019.1
(cherry picked from commit 36b2640ab7)
2019-01-18 18:33:24 +03:00
Ilya Gorbunov
e1734fbbda Document that sorting is stable in each platform
#KT-12473 Fixed

(cherry picked from commit 0ac85ad715)
2019-01-18 17:47:53 +03:00
Ilya Gorbunov
d2a0a2a0de Ensure stable sorting in MutableList.sort/sortWith
MutableList.sortWith now works correctly in JS_IR backend too

#KT-12473

(cherry picked from commit 56672c2564)
2019-01-18 17:47:53 +03:00
Ilmir Usmanov
59c5ab7d8e Do not mark fake inliner variables as alive
This prevents them from spilling.
 #KT-29317 Fixed

(cherry picked from commit e8c52e0a8f)
2019-01-18 17:05:47 +03:00
Ilmir Usmanov
8ed766e628 Add regression test
#KT-29327

(cherry picked from commit 7e4e1b9a4d)
2019-01-18 16:44:46 +03:00
Ilmir Usmanov
ad12184e14 Revert "Simplify tail-call optimisation check"
This reverts commit a5bcd3495e.

 #KT-27190: Open
 #KT-29327: Fixed

(cherry picked from commit dc6bb4cd08)
2019-01-18 16:44:12 +03:00
Ilmir Usmanov
4f6971339d Fix test data 2019-01-17 14:23:54 +03:00
Ilmir Usmanov
9ee4cab849 Put default value to vars iff they are not boxed
#KT-24672 Fixed
2019-01-17 14:23:47 +03:00
Alexander Udalov
e2de2fc059 Make CommonToolArguments.nullable
#KT-28974 Fixed

(cherry picked from commit 05c25342ad)
2019-01-16 14:58:32 +01:00
Pavel Punegov
eae3cf9f32 Update to 1.1.0-rc2-5686 2019-01-14 22:49:44 +03:00
Yan Zhulanow
825dd7abe9 Fix testJavacIsLoadedOnce() kapt integration test 2019-01-14 17:38:15 +03:00
Ilya Matveev
ffc235b730 Allow setting test binary linker options using a test compilation
#KT-29254 Fixed
2019-01-14 20:45:08 +07:00
Dmitry Savvinov
9ff115514e Get rid of FUNCTOR slice, use lazy value in ContractDecription instead
Functor is an imperative representation of function's contract (contrary
to ContractDescription, which is a declarative one). ContractDescription
is convenient when we deal with sources of contracts declarations
(binaries, source), while Functors are convenient for analyzing code
with contracts.

It means that we have to convert ContractDescription into Functor when
we start working with contracts. This computation isn't trivial, and
Functor and ContractDescription are in 1-1 correspondence, so we would
like to cache Functor for each ContractDescription somewhere.

We used to do this in binding trace, in slice FUNCTOR.

Now, it turns out that this approach causes "Rewrite at slice"
exception, see KT-28847. We won't go into details of why that happens
here, you can see the issue comments for details (but be prepared for the
very long and nitty-gritty story)

This commit removes the problematic slice and introduces another
approach, where Functor is attached to the ContractDescription, computed
lazily and cached here.

^KT-28847 Fixed
2019-01-14 12:04:08 +03:00
Dmitry Savvinov
dc1e44813c Add test on rewrite at slice FUNCTOR 2019-01-14 12:04:07 +03:00
Alexander Podkhalyuzin
016e103755 Implemented KotlinResolveScopeEnlarger for modules
Before that we had dependency to iml file, which is incorrect

(cherry picked from commit 893479bd5e)
2019-01-14 10:55:05 +03:00
Ting-Yuan Huang
12e03c34c6 Allow specifying isolation mode for KAPT workers
There are a few isolation modes for Gradle workers. KAPT uses 2 of them.

IsolationMode.NONE is the default. It runs workers in Gradle daemon and
is more memory efficient.

IsolationMode.PROCESS forks workers into individual processes. This
keeps some resource leaking annotation processors from affecting the
rest of compilation.

Users can specify kapt.workers.isolation=process, if they need to use
some annotation processor that are known to be resource leaking.
2019-01-11 23:51:20 +03:00
Ilya Gorbunov
65c6dd9e1a Clarify how elements of arrays are compared by contentEquals function
Add clarification only for the particular group of overloads including
 arrays of object and floating point numbers.

#KT-22942 Fixed

(cherry picked from commit 23950042f6)
2019-01-11 21:37:57 +03:00
Ilya Gorbunov
6c7cbfc09c Improve Any.equals/hashCode docs
- add code formatting
- remove 'reference' adjective, as Kotlin doesn't distinguish primitives from reference types
- add the requirement of inequality to null
- replace inaccurate note with a link to the reference (relates to KT-26604)

#KT-14866

(cherry picked from commit ef278ea030)
2019-01-11 21:37:55 +03:00
Ilya Gorbunov
74d06c63e6 Provide stable sorting when JS engine sorting doesn't look stable
#KT-12473

(cherry picked from commit 51eb21d44b)
2019-01-11 21:37:54 +03:00
Ilya Gorbunov
01a3accd53 Remove specialization of toTypedArray for LongArray and BooleanArray in JS
The default implementation for primitive arrays returns an array of correct type.

#KT-29187 Fixed

(cherry picked from commit 7c3c454654)
2019-01-11 21:37:52 +03:00
Ilya Gorbunov
da23ed15af Update copyright in generated stdlib sources
(cherry picked from commit fcef876c7e)
2019-01-11 21:37:51 +03:00
Sergey Igushkin
5cd7d6414d Fixes for review KOTLIN-CR-2599
* Move source artifacts to KotlinVariant classes (since joint Android
 variants may have multiple source artifacts, make it a set)

* Change lowerSpinalCaseName to dashSeparatedName (doesn't transform
 the strings to lower case inside)

* Don't transform the project name to lower case (in the future, it may
 be reasonable to stop transforming the target and component names, too)
 Still transform the target names and the component names.
 Currently, this is the way we don't break existing publications and may
 still reconsider this in the future.

* Add a workaround for a list of GString's assigned to
 publishLibraryVariants

* Check for Android library variants existence in a more strict way,
 report existing variants that are not library variants.

(cherry picked from commit 8bc7ac32f3)
2019-01-11 20:44:57 +03:00
Sergey Igushkin
0544745a5c Properly setup localToProject attribute in jvmWithJava (KT-29035)
A dependency on a multiplatform module with a jvmWithJava target failed
to resolve because the 'apiElements' and 'runtimeElements'
configurations didn't have the attribute 'localToProject' set to
'public'.

Those configurations need to have have the attribute set as per the
fix of KT-28795, but it doesn't happen.

Issue #KT-29035 Fixed

(cherry picked from commit 7e6527ca65)
2019-01-11 20:44:41 +03:00
Sergey Igushkin
1651e94bb8 Expose 'allKotlinSourceSets' in KotlinCompilation (KT-28749)
As KotlinCompilation only contains the directly added source sets in its
`kotlinSourceSets` property, we need to provide a convenient way to
collect the whole source sets hierarchy for a compilation.

We added internal `allKotlinSourceSets` some time ago, and it seems
reasonable to expose it as public API.

Issue #KT-28749 Fixed

(cherry picked from commit 0abd044800)
2019-01-11 20:44:14 +03:00
Sergey Igushkin
2c359a61ff Link the 'api' configuration to 'apiElements' (KT-28355)
As we introduced the 'api' configurations for Kotlin source sets, the
Java plugin did not link these configurations to its 'apiElements', and
those dependencies would only get published with the 'runtime' scope
through the 'implementation' configuration.

To fix this, manually specify that 'apiElements' extendsFrom 'api'.

Issue #KT-28355 Fixed

(cherry picked from commit 0cf95f84cb)
2019-01-11 20:43:59 +03:00
Sergey Igushkin
a5ef558355 Fix transitive dependencies overriding default Kotlin version (KT-28820)
In Gradle 5.0, the 'prefer' function semantics has changed, and now a
transitive dependency version wins over the 'preferred' one. Instead,
'require' has been introduced in 5.0 with the old semantics.

Our users expect that the default Kotlin dependency version will be
at least as new as the plugin version, so we now need to use 'require'
with Gradle 5.0+

Issue KT-28820 Fixed

(cherry picked from commit 82f13b90e6)
2019-01-11 20:43:40 +03:00
Sergey Igushkin
e9bfd0b3c2 Always rewrite dependencies in POMs when publishing an MPP (KT-28482)
As non-Gradle consumers and Gradle consumers with metadata disabled
cannot read Gradle metadata, in POMs (the only source of dependencies
for the consumers mentioned above), we should publish the dependencies
on modules with metadata as the target artifact IDs rather than the root
MPP module ID (e.g. 'foo-jvm' rather than 'foo').

To do that, we rewrite the POMs of the publications even when Gradle
metadata is enabled. Note: in the POMs, a project dependency is already
written in the form of the artifact ID of the root Kotlin software
component, so it complicates the dependencies rewriting a little.

To rewrite third-party dependencies, we detect dependencies that
resolved to no artifact and have a single child in the Gradle
dependencies graph of the resolved configuration – this is what a
dependency looks like which was redirected to another module via
'available-at'.

Issue #KT-28482 Fixed

(cherry picked from commit f9c45c30a2)
2019-01-11 20:43:13 +03:00
Sergey Igushkin
669d7ae9c3 Fix failure when creating a compilation in afterEvaluate (KT-28896)
To configure a compilation's sources, we run an action in
`whenEvaluated { ... }`, expecting that the compilation's task already
exists. This was not true with compilations created from a user build
script or a 3rd-party plugin in `afterEvaluate { ... }`.

Fix this by expecting that a task may possibly not exist at that point,
and also using `whenEvaluated { ... }` instead of
`afterEvaluate { ... }` in several places that are executed for each new
compilation as a workaround for
https://github.com/gradle/gradle/issues/1135.

Issue #KT-28896 Fixed

(cherry picked from commit 2fd524f1c0)
2019-01-11 20:42:54 +03:00
Sergey Igushkin
60d8f6eabd Publish Android variants from multiplatform projects
Also update the code for rewriting the dependencies, as Android variants
have their dependencies configurations formed a bit differently, and
also introduce the logic for choosing the right component by the
configuration name the dependency resolves to.

Issue #KT-27535 Fixed

(cherry picked from commit de5e86ae9f)
2019-01-11 20:42:32 +03:00
Sergey Igushkin
8791ce1685 Restructure source JARs logic, move it to components management
Move the logic of attaching a source JAR to a publication to the
components management part, as building a source JAR will be done
differently for Android.

(cherry picked from commit 9a2dce7ea5)
2019-01-11 20:42:19 +03:00
Sergey Igushkin
f42336950f Allow a target to have multiple publications, restructure the code
Instead of exposing a single `component` in a target, allow it to have a
set of `components`, then create a Maven publication for each of the
components.

Move `createUsageContexts` to private API since a target that has
multiple publications may need to create the usage contexts for those
publications differently.

Move some of the components technical stuff to interfaces
`DelegatedToPublication` and
`ComponentWithCoordinatesDelegatedToPublication` in order to reuse it
later for Android's components.

(cherry picked from commit d211bd53c9)
2019-01-11 20:41:54 +03:00
Sergey Igushkin
726901291e refactor: Support creating AndroidProjectHandler from outside the plugin
(cherry picked from commit a6b55cc5d7)
2019-01-11 20:41:32 +03:00
Ilya Gorbunov
f7712fc351 Avoid hitting max argument limit in String(chars)
Rewrite CharArray to String conversions to appending chars one by one.

Refine parameter checking in String(chars, offset, length) to adhere to
the common exception contract and document it.

#KT-29003

(cherry picked from commit 30c769c19a)
2019-01-11 19:33:57 +03:00
Pavel Punegov
4fa215eb47 Replace class instantiation with object in JS tests
(cherry picked from commit dc8cb103c5)
2019-01-11 17:45:00 +03:00
Pavel Punegov
84f173e75a DefaultAsserter object. Add function to replace constructor invoke.
(cherry picked from commit 1c4ecd287d)
2019-01-11 17:44:41 +03:00
Pavel Punegov
1a885cf1f4 Make kotlin.test asserter be ThreadLocal
(cherry picked from commit ac0f612781)
2019-01-11 17:44:24 +03:00
Pavel Punegov
898cbf974a Exclude native annotations in JS IR tests
(cherry picked from commit 4b3693bf37)
2019-01-11 17:42:53 +03:00
Pavel Punegov
386a3ee83e Add ThreadLocal and SharedImmutable native annotations as OptionalExpectation
to kotlin.native.concurrent

(cherry picked from commit 122ec85bf0)
2019-01-11 17:42:22 +03:00
Mikhael Bogdanov
392ab05f5f Delete dead code on last optimization step, otherwise ASM will split exception table on it.
ASM has logic that splits exception tables in MethodWriter.computeAllFrames:
     // Loop over all the basic blocks and visit the stack map frames that must be stored in the
     // StackMapTable attribute. Also replace unreachable code with NOP* ATHROW, and remove it from
     // exception handler ranges.
     ...
     firstHandler = Handler.removeRange(firstHandler, basicBlock, nextBasicBlock);
     ...
  https://gitlab.ow2.org/asm/asm/issues/317867

  #KT-28546 Fixed

(cherry picked from commit 2bdf68ad67)
2019-01-11 15:29:57 +01:00
Mikhael Bogdanov
547c6ab897 Temporary disable line numbers generation for default values from expect declarations
Proper SMAP support for default values from expect declarations is required.
 Default value in expect declaration could has line number that
 exceed line count in actual file that causes an error

  #KT-23739 Fixed
  #KT-29174 Open

(cherry picked from commit 306a982722)
2019-01-11 15:29:50 +01:00
Andrey Uskov
231e5679b1 Create Kotlin SDK on load or import project with JS/Common modules
#KT-22590 Fixed
2019-01-11 17:05:24 +03:00
Andrey Uskov
03389cd249 Fix scope detection for MPP projects
#KT-27718 Fixed
#KT-28626 Fixed
2019-01-11 17:04:52 +03:00
Andrey Uskov
42c53b5d76 Change task creation with task registration in Kotlin plugin
#KT-27657 Fixed

(cherry picked from commit b6aed5b98a)
2019-01-11 17:03:56 +03:00
Mikhail Zarechenskiy
d303ae5c28 Fix dependency for Gradle integration tests module
After d5ebe2e6
2019-01-11 14:48:04 +03:00
Mikhail Glukhikh
b47636ba9d IDEA plugin: remove "Show FIR action" and fir-view without fir.enabled
#KT-28813 Fixed
(it's planned to include FIR in artifacts after 1.3.30)

(cherry picked from commit 4fd773a38b)
2019-01-11 13:50:15 +03:00
Sergey Rostov
911748fde2 JPS: exclude source roots from other targets
Previously `findJavaRootDescriptor` was return source root for random
module. This cause build errors for mpp (same file may appear in
multiple source roots of common and platform modules)

#KT-28988 Fixed

(cherry picked from commit 75e59fdc46)
2019-01-11 13:18:01 +03:00
Dmitry Savvinov
682f15f248 Introduce specific version of NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY for KT-28061
In 1.3.0 there was introduced KT-28061 bug, which caused some of the
NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY diagnostics to be lost (turning
"red" code into "green")

500dc11514 fixes the bug and returns
lost diagnostics back. This commit adds additional information for some
of the cases where diagnostics were list and then brought back (for the
user sanity).

The heuristic used for detecting cases which need additional information
is simple: if function has return in in-place called lambda, and
NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY should be reported, then we
enhance it with additional information.

^KT-28061 Fixed
2019-01-11 11:46:30 +03:00
Ilya Matveev
91b08d374b Fix linkTaskName getters of K/N compilations 2019-01-11 13:23:05 +07:00
Ilya Matveev
0cc417c97b Support getting the default K/N test binary from a compilation
Fix for https://github.com/JetBrains/kotlin-native/issues/2487
2019-01-11 13:22:58 +07:00
Mikhail Zarechenskiy
169155d854 Reorganize dependencies around kotlin-compiler.jar
#KT-26807 Fixed
2019-01-11 00:19:44 +03:00
Ilya Gorbunov
3f8f53cb8c Remove redundant clause from 'until' function docs
(cherry picked from commit 9289a2c573)
2019-01-10 22:56:00 +03:00
Bernhard Posselt
6fc756c4c0 Add documentation on how merging works for toMap() for Iterables, Arrays and Sequences
(cherry picked from commits 300f68e0d8, 19906f13ea)
2019-01-10 22:54:39 +03:00
Denis Zharkov
6a8ef4ac1a Fix exception in ultra-light classes in case of complex mpp hierarchy
Without the introduced override, default implementation of isEquivalentTo
runs delegate computation of `another` that is illegal
for KtUltraLightClass

^KT-28912 Fixed
2019-01-10 14:12:10 +03:00
Ilya Matveev
4aaf36131f One more fix for MinGW path in K/N runner 2019-01-10 18:02:47 +07:00
Ilya Chernikov
f2e1b0bc22 Add import support to main-kts, with test 2019-01-10 10:56:37 +01:00
Ilya Chernikov
ec6b1dc1e5 Add shared script instances support, fix and refactor evaluation accordingly
also fix arguments order in the evaluator
2019-01-10 10:56:37 +01:00
Ilya Chernikov
aa2315f378 Add mapping function for transformations with ResultsWithDiagnostics
also improve chaining helpers
2019-01-10 10:56:37 +01:00
Ilya Chernikov
28b91ce848 [minor] add comment to the "Fix locking in script definition provider" commit 2019-01-10 10:56:36 +01:00
Ilya Chernikov
3c7e57d9c4 [minor] fix scripting test on windows 2019-01-10 10:56:36 +01:00
Yan Zhulanow
dfd163af34 Fix 'CommandLineProcessor' extension point calling, switch it to using ServiceLoaderLite 2019-01-09 22:05:53 +03:00
Yan Zhulanow
8b24dd98f6 Remove JPS support for Android Extensions 2019-01-09 22:05:49 +03:00
Ilya Matveev
4b4a709e86 Fix MinGW path in Kotlin/Native runner 2019-01-09 20:48:21 +07:00
Mikhael Bogdanov
0c4c6860be Add tests for Obsolete issues
#KT-18977 Obsolete

(cherry picked from commit f7ce8c18c6)
2019-01-09 10:22:08 +01:00
Mikhael Bogdanov
d6fcc35f17 Add test for Obsolete issues
#KT-15956 Obsolete
 #KT-15751 Obsolete
 #KT-16417 Obsolete
 #KT-21787 Obsolete

(cherry picked from commit 9a059809bf)
2019-01-08 14:05:05 +01:00
Mikhael Bogdanov
0602baa38e Avoid ConcurrentModificationException
#KT-26384 Fixed

(cherry picked from commit 6a19e45e27)
2019-01-08 13:58:30 +01:00
Mikhael Bogdanov
c9ac71dd8d Proper resort variables on inlining lowered ir closures
Original problem is that lowered ir closures doesn't meet inliner expectations
 about captured variable position in inlining method.
 E.g.: Call 'foo(valueParam) { capturedParam }' to
  inline function 'foo' with declaration

      inline fun foo(valueParam: Foo, inlineParamWithCaptured: Bar.() ->) ....

 is reorganized through inlining to equivalent call foo(valueParam, capturedParam1, cp2 ...).
 But lowered closure for lambda parameter has totally different parameters order:

     fun loweredLambda$x(extensionReceiver, captured1, cp2..., valueParam1, vp2...)

 So before inlining lowered closure should be transformed to

     fun loweredLambda$x(extensionReceiver, valueParam1, vp2..., captured1, cp2..)

 #KT-28547 Fixed

(cherry picked from commit 02d9c526e2)
2019-01-03 08:42:52 +01:00
Mikhael Bogdanov
e04959a939 Update copyright in generated FIR related stuff
(cherry picked from commit fcf8ea44b2)
2019-01-03 08:30:53 +01:00
Mikhael Bogdanov
a399539094 Regenerate builtins
(cherry picked from commit dfee1787e5)
2019-01-03 08:30:46 +01:00
Mikhael Bogdanov
d71e0fc7c3 Update copyright in generated non-compiler tests
(cherry picked from commit e963c52c80)
2019-01-03 08:30:38 +01:00
Mikhael Bogdanov
ac870129df Add test for obsolete KT-17431 issue
#KT-17431 Obsolete

(cherry picked from commit e0bcba5c0e)
2019-01-03 08:30:28 +01:00
Mikhael Bogdanov
7f485172a8 Update copyright in generated compiler tests
(cherry picked from commit cf47bc0130)
2019-01-03 08:29:53 +01:00
Mikhael Bogdanov
df4cbd50d6 Properly find invoke method on default lambda inlining
In general case parameter type could differ from actual default lambda type.
  E.g.: fun inlineFun(s: (Child) -> Base = { a: Base -> a as Child}),
  where type of default lambda is '(Base) -> Child'.
  In such case we should find somehow actual invoke method in bytecode knowing
  only name, number of parameters and that's actual invoke is non-synthetic
  regardless of bridge one.

  #KT-21946 Fixed

(cherry picked from commit 6bf70a5dd2)
2019-01-03 08:29:09 +01:00
Ilmir Usmanov
066ecd5308 Fix test data 2018-12-28 20:02:27 +03:00
Ilmir Usmanov
30c7b3cc1d Support val initialization in non-inline function with EXACTLY_ONCE effect
by generating a box for the value.
 #KT-26126 Fixed
2018-12-28 15:22:24 +03:00
Ilmir Usmanov
38bc99d792 Put default value (null or zero) to slot for uninitialized values
This way range of the variable is correct in LVT.
 #KT-24672 Fixed
2018-12-28 15:22:20 +03:00
Alexander Udalov
88ed2e268f Fix loading default Java annotation values in actual typealias from binary classes
#KT-22704 Fixed

(cherry picked from commit 8ab9226805)
2018-12-28 13:03:34 +01:00
Alexander Udalov
720a35bc26 Use fast .class file reading implementation in boxAgainstJava tests
Since these tests compile Kotlin code against compiled Java code, it's
only reasonable to use the same .class file reading implementation as is
used in production for the same purpose

(cherry picked from commit 3fee84b966)
2018-12-28 13:03:32 +01:00
Ilmir Usmanov
e141441bf5 Update test data
#KT-28309
2018-12-28 14:42:05 +03:00
Ilmir Usmanov
f50f9d069f Do not spill fake variables
#KT-28309
2018-12-28 14:42:04 +03:00
Ilmir Usmanov
c4f99b850b Add continuation parameter of suspend lambda's invoke to frame map
thus it will not overlap with $i$a and $i$f fake variables.
 #KT-28309
2018-12-28 14:42:03 +03:00
Ilmir Usmanov
8e3eb04271 Set type of inliner's fake variable slots to int by storing 0
Otherwise, D8 drops the whole LVT.
 #KT-28309 Fixed
2018-12-28 14:42:02 +03:00
Nicolay Mitropolsky
75987697db Light-annotations: fix for reading class-literal varargs (KT-29027, IDEA-204252)
(cherry picked from commit ebd6caaa71)
2018-12-28 11:50:38 +03:00
Nikolay Krasko
1c93018db4 Remove assertion with selection in 1.3.20 2018-12-27 21:32:54 +03:00
Mikhail Glukhikh
6fa26c5356 Improve expect / actual markers on one line
Before this commit, only one-line enums and annotation classes were
considered. Now we can have enum header on one line and
some entries on another lines, and it still works.
Same with primary constructor parameters.

#KT-22637 Fixed

(cherry picked from commit 8de2ff2163)
2018-12-27 20:24:01 +03:00
Mikhail Glukhikh
e97009bd49 Do not report "redundant arrow" with parameters without expected type
#KT-29049 Fixed
Part of KT-29005

(cherry picked from commit cdef811c55)
2018-12-27 20:23:43 +03:00
Nikolay Krasko
6ae156c8a4 Add UI options for comments generation (KT-5590)
#KT-5590 Fixed
2018-12-27 19:56:22 +03:00
Dmitry Petrov
595d55707c Support inline classes in javaObjectType/javaPrimitiveType
#KT-28290
2018-12-27 15:27:21 +03:00
Natalia Selezneva
9fbc71475b Scratch: move 'Make module' checkbox closer to modules combobox
(cherry picked from commit 022b21efa0)

^KT-28910
2018-12-27 09:01:29 +03:00
Natalia Selezneva
a13c744533 Set scratch file extension using API for IDEA 182 or higher
(cherry picked from commit 404c3ea57b)
2018-12-27 09:01:09 +03:00
Natalia Selezneva
f2f1e923ee Script tests: check that script is highlighted
(cherry picked from commit 6eff314b9d)
2018-12-27 09:00:53 +03:00
Natalia Selezneva
0905c6ba27 Refactoring: move scratch options to ScratchFile from ScratchPanel
(cherry picked from commit d389c9fd85)
2018-12-27 09:00:40 +03:00
Natalia Selezneva
0ebe31af73 Scratch: do not show error message when scratch execution is cancelled by user
(cherry picked from commit a408711f37)
2018-12-27 09:00:29 +03:00
Natalia Selezneva
846fb60c91 Refactoring: unify methods to report errors in scratches
(cherry picked from commit 2fbbf2400d)
2018-12-27 09:00:17 +03:00
Natalia Selezneva
ce36fc594f Refactoring: move test output handler to separate class
(cherry picked from commit 2f32c6e164)
2018-12-27 09:00:03 +03:00
Natalia Selezneva
9e6db690d5 Refactoring: add composite output handler to avoid multiple forEach calls
(cherry picked from commit 392e69c690)
2018-12-27 08:59:50 +03:00
Natalia Selezneva
1702c8df25 Scratch: implement stop action
(cherry picked from commit 2511f70bd9)

^KT-28643 Fixed
2018-12-27 08:59:38 +03:00
Natalia Selezneva
88fcbdd079 Scratch: get scratch panel from selected editor
CommonDataKeys.EDITOR key isn't present for some events (for example when user click on isRepl checkbox on scratch panel or there isn't any file open in the editor)

(cherry picked from commit d403514cee)

^KT-28045 Fixed
2018-12-27 08:59:13 +03:00
Natalia Selezneva
8015483db6 Refactoring: use output handlers to make action enabled or disabled
(cherry picked from commit 59a32ff94d)
2018-12-27 08:58:48 +03:00
Leonid Startsev
e644c05b31 Make serialization plugin for Maven consistent with all other plugins:
Use correct import handler because old one was not working in IDE
Change maven artifact id to match pattern from other plugins

(cherry picked from commit 662c1b6d4a)
2018-12-26 18:54:39 +03:00
Mikhail Glukhikh
1220ef51b5 Support '.toType()' and literal fixes related to unsigned type mismatch
#KT-26836 Fixed

(cherry picked from commit 8420fceb8c)
2018-12-26 18:43:54 +03:00
Mikhail Glukhikh
624a4802b4 Do not suggest cast for SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED
Related to KT-27590

(cherry picked from commit 73b6148407)
2018-12-26 18:43:39 +03:00
Mikhail Glukhikh
7aef1a9073 Suggest quick-fixes for SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED
#KT-27590 Fixed

(cherry picked from commit d7ce79cc76)
2018-12-26 18:43:24 +03:00
Mikhail Glukhikh
774b5408b6 More tests for KT-28997, fix isLocal for anonymous object in script
(cherry picked from commit a9147ff446)
2018-12-26 18:43:10 +03:00
Mikhail Glukhikh
ac867bb063 Fix light class generation for local classes in scripts
Before this commit, we used script context for all classes
defined in script. However, for local classes in scripts it's mistake,
and now we generate them as usual, despite of the fact we are in script.

#KT-28997 Fixed

(cherry picked from commit 661ac711c0)
2018-12-26 18:42:56 +03:00
Mikhail Glukhikh
9583b05160 Extract 'PsiElement.hasJavaResolutionFacade()' (related to KT-28199)
(cherry picked from commit 7d51be17c8)
2018-12-26 18:42:40 +03:00
Mikhail Glukhikh
a0e3340a03 Launch constructor delegation search only for elements from a file
This should fix EA-133791

(cherry picked from commit d599bb160f)
2018-12-26 18:42:22 +03:00
Mikhail Glukhikh
7b68e5b74e Launch convention method reference search only for elements from a file
#KT-28199 Fixed

(cherry picked from commit 399ec5c961)
2018-12-26 18:42:06 +03:00
Nikolay Krasko
debc248a78 Check file is valid before executing toPsiFile (EA-133882) 2018-12-26 15:47:07 +03:00
Nikolay Krasko
297f5eefb2 Consider qualified name is null if some part is null (EA-126499) 2018-12-26 15:46:59 +03:00
Natalia Selezneva
1751e7ca78 Kotlin code fragments in markdown should have script definition because they are parsed as scripts
(cherry picked from commit 9dc57567e4)
2018-12-26 08:59:40 +03:00
Natalia Selezneva
30b5535dc1 Create one instance of StandardIdeScriptDefinition per project
ScriptModuleInfo for scripts outside source roots in compared by virtualFile and script definition.
So when we use ScriptDefinitionsManaged.getDefaultScriptDefinition we shouldn't create a new one on each call

EA-132810 - assert: DiagnoseUnknownModuleInfoReporter.report

(cherry picked from commit 4e6fb84bae)
2018-12-26 08:59:05 +03:00
Natalia Selezneva
973622bc60 Remove ScriptModificationListener from 183 branch
Since 183 changes in .gradle.kts files are tracked correctly by platform and notification 'Gradle project needs to be imported' is shown when those files are modified

(cherry picked from commit ba2f211384)
2018-12-26 08:58:45 +03:00
Natalia Selezneva
cfa3422644 Scripts: fix NPE during accessing ScriptDependenciesCache
Getting value from SLRUMap needs write lock, because it can move value from one queue to another
EA-105195 Fixed

(cherry picked from commit 6042a3a0f7)
2018-12-26 08:58:28 +03:00
Natalia Selezneva
00a4365752 Fix 'Invalid file' exception during script dependencies update
Fix EA-125840 - assert: FileManagerImpl.findFile

(cherry picked from commit 8ceae8bd6d)
2018-12-26 08:58:11 +03:00
Natalia Selezneva
cfd030ac8d Fix order of initialization of project language version in ConfigureKotlinTest
Project.getLanguageVersion with contextModule == null returns latest stable version.
But Module.getLanguageVersion save it's version to project setting if useProjectSettings checkbox is selected.
So Project.getLanguageVersion can return different versions before and after invocation Module.getLanguageVersion

(cherry picked from commit 816a8d74a2)
2018-12-26 08:57:53 +03:00
Andrey Uskov
6230af0f3b Fix reimport of Kotlin projects created via wizard
#KT-27941 Fixed
2018-12-24 17:11:29 +03:00
Ilmir Usmanov
0fa22c3327 Obtain correct captured suspend local function
if we call the function inside, for example, lambda.
 #KT-28844 Fixed
2018-12-24 15:58:38 +03:00
Mikhail Zarechenskiy
9ba0202d59 Prohibit JvmOverloads on constructors of annotation classes
In LV >= 1.4 & -progressive

 #KT-25702 Fixed
2018-12-24 12:51:40 +03:00
Mikhail Zarechenskiy
a967c47d1c Prohibit type parameters for local variables in LV >= 1.4 & -progressive
#KT-8341 Fixed
2018-12-24 12:51:38 +03:00
Mikhail Zarechenskiy
e8fea9d4ef Fix mapping of platform inline class types
For the inline class:
 ```
 inline class IC(val x: Int)
 ```

 Type (IC..IC?) should be mapped to the wrapper `IC`
 because it can hold object and also because it does so for primitives

 #KT-28983 Fixed
2018-12-24 12:51:36 +03:00
Ilya Chernikov
cc5cf643a8 Implement script filename extensions discovery via artifact transforms
to avoid using never-up-to-date task and make discovery cacheable and
checkable for up-to-dateness
#KT-28469 fixed
2018-12-21 15:48:38 +01:00
Ilya Chernikov
20a631a838 Fix script filename extension discovery from asm-readed class
and improve diagnostics on definition loading failure
2018-12-21 15:48:37 +01:00
Shagen Ogandzhanian
c6e5a5d72a Support named constructors in idl-backed code generation
this resolves https://youtrack.jetbrains.com/issue/KT-27361
2018-12-21 15:31:12 +01:00
Ilya Gorbunov
a6bad98241 Fix current Kotlin version to avoid changing it in local builds
(cherry picked from commit 7c7c11e916)
2018-12-21 17:24:34 +03:00
Ilya Gorbunov
7cf16d9af6 Fix link to sealed classes doc page
#KT-28829 Fixed

(cherry picked from commit 68f898153c)
2018-12-21 17:24:33 +03:00
Ilya Gorbunov
59eeb287c9 Minor: fix Random companion reference in docs
Random's companion is named 'Default' rather than 'Companion'

(cherry picked from commit 614139755c)
2018-12-21 17:24:31 +03:00
Ilya Matveev
2e14313bc8 Fix K/N test for windows: rename target usage 2018-12-21 13:04:41 +03:00
Ilya Matveev
1872b3dd1d Fix native binary tests for Windows 2018-12-21 13:04:41 +03:00
Ilya Chernikov
4c3ac350c9 [minor] use psi original file if virtual file is not available...
for script dependencies, fixes completion tests
2018-12-20 22:06:56 +01:00
Ilya Chernikov
44f8e92c6f Introduce script names and location ids, use them in diagnostics and...
for virtual file names. Also fix compiled script serialization.
2018-12-20 22:06:55 +01:00
Ilya Chernikov
f279ae5576 [minor] add missing dependency 2018-12-20 22:06:55 +01:00
Ilya Chernikov
e4f4619f37 Implement script dependencies collection tests 2018-12-20 22:06:54 +01:00
Ilya Chernikov
bff63fe902 [minor] refactor scripting tests: extract cli testdata into separate dir, remove annotation 2018-12-20 22:06:53 +01:00
Ilya Chernikov
7b6cd7305a Refactor core env: extract script compilation dependencies collection 2018-12-20 22:06:53 +01:00
Ilya Chernikov
7640718805 [minor] fix compilation - avoid proguarding of addToStdLib.kt 2018-12-20 22:06:52 +01:00
Ilya Chernikov
8830387118 Implement import test, fix import support in compiler and evaluator 2018-12-20 22:06:51 +01:00
Ilya Chernikov
908b8a4b4e Implement imported scripts evaluation and construction 2018-12-20 22:06:51 +01:00
Ilya Chernikov
3430aa24ec Implement script import support in the compiler 2018-12-20 22:06:50 +01:00
Ilya Chernikov
f3b206227a Implement simple "add to compilation" functionality for scripts
(incomplete import - scripts added to the compilation but not yet
imported into scope)
Base functionality needed for #KT-27960
2018-12-20 22:06:49 +01:00
Toshiaki Kameyama
a1d2a5ac82 Add "Convert to also" intention
#KT-28699 Fixed

(cherry picked from commit 6a4c6eacd7)
2018-12-20 15:04:49 +03:00
Mikhail Glukhikh
fc33aa9552 OverrideMemberChooserObject refactoring: introduce MemberGenerateMode
(cherry picked from commit 93882736ed)
2018-12-20 15:04:21 +03:00
Mikhail Glukhikh
2c0ecedb5a Create expect/actual class: fix inline class generation
#KT-28744 Fixed
#KT-28745 Fixed

(cherry picked from commit ca3d758fba)
2018-12-20 15:04:07 +03:00
Mikhail Glukhikh
3ba7339a46 MPP JVM/JS wizard: fix classpath of 'run' task #KT-28869 Fixed
(cherry picked from commit d3a5b0dcd6)
2018-12-20 15:03:27 +03:00
Mikhail Glukhikh
e449f18fc0 MPP wizard tests: use 1.3.20-eap-25
(cherry picked from commit 55666f3f03)
2018-12-20 15:03:08 +03:00
Vasily Levchenko
7def3c19dc Update Kotlin/Native: RC2 1.1.0.5323 2018-12-19 12:33:59 +03:00
Vasily Levchenko
fc46a7704c Update Kotlin/Native: RC2 1.1.0.5323 2018-12-19 00:12:46 +03:00
Shagen Ogandzhanian
4d06db6852 Support ClipboardEvent in definitions generated from idl 2018-12-18 15:11:06 +01:00
Shagen Ogandzhanian
883dbfe138 Introduce TrackEvent, MediaStreamTrackEvent-related IDL definitions 2018-12-18 15:10:58 +01:00
Alexey Tsvetkov
d6f388845d Refactor: move logging code to org.jetbrains.kotlin.gradle.logging 2018-12-18 15:29:55 +03:00
Alexey Tsvetkov
2e9a596b53 Report compiler messages from daemon in Gradle thread
#KT-28836 fixed

RMI messages are reported from RMI threads.
When Gradle logger is used from non-Gradle thread,
messages are not grouped in command-line
and they are not shown in build scans.
To fix this, we store all messages from Kotlin daemon
in a buffer, then report them from a Gradle thread.
2018-12-18 15:29:55 +03:00
Alexey Tsvetkov
da86804719 Use task's logger where appropriate
KT-28836

Using project's logger prevents messages
from showing in task's output (in command-line and build scans)
2018-12-18 15:29:55 +03:00
Ilya Matveev
2bbbf9677f Add a klib export method consuming a configure action 2018-12-18 18:08:20 +07:00
Ilya Matveev
543671227d Don't create run tasks for non-host targets 2018-12-18 18:08:20 +07:00
Ilya Matveev
5b5262eedf Change executable of a run task when binary's baseName is changed 2018-12-18 18:08:20 +07:00
Ilya Matveev
42ad282dee Add tests for new binaries DSL 2018-12-18 18:08:20 +07:00
Ilya Matveev
23b0143688 Fix existing MPP tests 2018-12-18 18:08:20 +07:00
Ilya Matveev
1e782311e5 Don't hardcode a toolchain path for K/N on Windows 2018-12-18 18:08:20 +07:00
Ilya Matveev
7eae8ccc09 Fix error message about incorrect kotlin.native.home property 2018-12-18 18:08:20 +07:00
Ilya Matveev
375e46b91f Support aggregate tasks to build binaries per compilation 2018-12-18 18:08:20 +07:00
Ilya Matveev
cfdfdcb954 Support free compiler args for binaries 2018-12-18 18:08:20 +07:00
Ilya Matveev
819c6e5a51 Allow changing base name for a Kotlin/Native binary 2018-12-18 18:08:20 +07:00
Ilya Matveev
2b1d2ea2fe Support bitcode embedding for frameworks 2018-12-18 18:08:20 +07:00
Ilya Matveev
e20444e441 Support -Xexport-library for K/N in the MPP plugin 2018-12-18 18:08:20 +07:00
Ilya Matveev
c71c2fba05 Provide aggregate link tasks 2018-12-18 18:08:20 +07:00
Ilya Matveev
fb5095f94e Provide an extended DSL for final native binaries
In 1.3.0 only basic settings for final native binaries (e.g.
executables or frameworks) are available. They allow a user to
specify what kinds of binaries should be produced from one or another
compilation but they don't allow specifying different options for
different binaries or creating more than 2 (debug and release)
binaries of the same kind (e.g. executable) from the same
compilation. Also link tasks for these binaries are created after
project evaluation thus they are inaccessible for a user outside
of an afterEvaluate block.

This patch adds an extended binary DSL allowing a user to declare
binaries independently from compilations and to specify different
options (e.g. linker arguments) for different binaries. Also
link tasks for binaries declared in this DSL are created at a
configuration time so user can access them outside of an
afterEvaluate block.

Also this patch adds creating run tasks for all executables
declared in the buildscript (KT-28106)

Initial DSL methods for binaries declaration are still supported.

Kotlin DSL example is the following:

kotlin {
    macosX64 {
        binaries {
            // Create debug and release executable with
            // a name prefix 'Foo'.
            // Two domain objects will be created:
            // fooDebugExecutable and fooReleaseExecutable
            executable("Foo", listOf(RELEASE, DEBUG)) {
                compilation = compilations["foo"]
                entryPoint = "foo.main"
                linkerOpts.add("-Llib/path")
                println(runTask.name)
            }

            // Name prefix and build types are optional.
            // debugFramework and releaseFramework are created here.
            framework()
        }
    }
}
2018-12-18 18:08:20 +07:00
Mikhail Zarechenskiy
ac77446657 Fix unbound class literals for inline classes
#KT-28361 Fixed
2018-12-18 11:37:54 +03:00
Denis Zharkov
7c66d0e3a6 Minor. Add a comment to KtLightElement::givenAnnotations 2018-12-18 09:32:27 +03:00
Denis Zharkov
c7634fb41a Create annotation arguments in ultra-light classes via PsiElementFactory 2018-12-18 09:32:27 +03:00
Denis Zharkov
d634db2d82 Restrict search scope for KtUltraLightParameter
^KT-28365 Fixed
2018-12-18 09:32:27 +03:00
Denis Zharkov
43482f60ae Fix throws-list for case of kotlin.Throwable in ultra-light classes 2018-12-18 09:32:27 +03:00
Denis Zharkov
b940b64d06 Do not generate no-arg constructor for sealed ultra-light class 2018-12-18 09:32:27 +03:00
Denis Zharkov
72e42ba2cb Support annotation based on descriptor in ultra-light classes
It helps to generate properly the annotations for delegates
Also note in test, that annotations in Base class have really weird
text of arguments and also don't have names
2018-12-18 09:32:27 +03:00
Denis Zharkov
20766dce65 Minor. Introduce typeMapper val into UltraLightSupport
To avoid multiple creation
2018-12-18 09:32:27 +03:00
Sergey Igushkin
34199c5d92 Fix Gradle 5.0 deprecation warnings:
* DefaultSourceDirectorySet constructor is deprecated -> objects()
* IvyRepository.layout('pattern') { } is deprecated -> patternLayout { }

Issue #KT-26808 Fixed

(cherry picked from commit 67e82a54e5)
2018-12-17 20:07:46 +03:00
Sergey Igushkin
816976035b Fix the localToProject attribute schema for Gradle 4.10.2+
In Gradle 4.10.2, a change was made in the attributes disambiguation
process: if some of the candidates have a single attribute value and
others don't have that attribute (i.e. have a null value), the
disambiguation rule for that attribute doesn't get called.
Effectively, null values are excluded from disambiguation, but still may
cause ambiguity (sic!)

See: https://github.com/gradle/gradle/issues/6747#issuecomment-445921139

This change affected our attribute `localToProject` that we use to
disambiguate the deprecated but still consumable configurations like
`compile`, `runtime`, `testCompile`, `testRuntime` from those
configurations which should have priority during project dependency
resolution: the `*Element` ones. Our scheme marked the former
configurations with the attribute and the latter were not marked, with
a disambiguation rule that preferred null values.

To fix this logic with Gradle 4.10.2, we instead mark both kinds of
configurations with the attribute, which now has a value 'public'
that is preferred by the rule over the other values. We also make sure
that the attribute doesn't leak into the published Gradle metadata, as
it is only needed for project-to-project dependencies resolution.

Issue #KT-28795 Fixed

(cherry picked from commit 557fb07f44)
2018-12-17 20:07:46 +03:00
Sergey Igushkin
8df408122f Workaround for ConcurrentModificationException in KotlinModelBuilder
In Gradle 5.0, iterating over the `.withType<...>()` result below
caused a ConcurrentModificationException. Workaround that by first
collecting the items into a list.

(cherry picked from commit 2349aaf488)
2018-12-17 20:07:45 +03:00
Sergey Igushkin
f349b92896 Fix some tests for Gradle 5.0 and update some dependency versions
* Introduce GradleVersionRequired.InRange and thus prevent older
tests (e.g. Android 2.3.0) from running with newer Gradle versions

* Add a task outputs pattern suitable for Gradle 5.0

* Run some of the Android tests with AGP 3.1.0 (and Gradle 4.4) instead
of 3.0.0 to ensure compatibility with Gradle 5.0

* Update test projects according to Gradle 5.0 dropped deprecated
features: classesDir, left-shift operator, default org.gradle.util.*
imports

* Fix a Gradle test after Gradle 5.0 changed `publishing` behavior to
run the closure eagerly rather than after evaluation

(cherry picked from commit d7522e2283)
2018-12-17 20:07:45 +03:00
Sergey Igushkin
f221a6794b Advance test Gradle version to 5.0
(cherry picked from commit 5f21ced26b)
2018-12-17 20:07:45 +03:00
Shagen Ogandzhanian
037b7a5f5e Introduce idl definition for SVGMaskElement 2018-12-17 16:25:15 +01:00
Alexey Tsvetkov
39af8f3994 Enable JS IC by default
#KT-28842 Fixed
2018-12-17 15:46:42 +03:00
Alexey Tsvetkov
fd192f811e Add project property to disable AP discovery in compile classpath
AP discovery in compile classpath can be disabled in all subprojects
by adding "kapt.include.compile.classpath = false" to 'gradle.properties' file.

KT-24530

The setting can be overrided per project by using KAPT DSL
in a 'build.gradle' file:
```
kapt {
    includeCompileClasspath = false
}
```
2018-12-17 15:42:22 +03:00
Mikhael Bogdanov
d83e2afcdf Use last ASM version to read binaries
#KT-28798 Fixed

(cherry picked from commit 1a0c3dfaa6)
2018-12-17 12:20:23 +01:00
Yan Zhulanow
45e5013097 Fix a compilation error after rebase 2018-12-17 18:47:13 +09:00
Alexey Tsvetkov
24aa636283 Test that javac is loaded once when worker is reused 2018-12-16 04:29:38 +03:00
Ting-Yuan Huang
2884cfc9e4 Cache classloaders for tools.jar and kapt in Gradle workers
#KT-28852 fixed

The loaders and hence some classes were repeatedly loaded and
jit-compiled everytime when KaptExecution were dispatched. Those
classes, like JavaCompiler, can be very large and therefore created a
significant overhead. In some projects, the overhead accounted for more
than 40% of total CPU time of annotation processing.

This change tries to cache the classloaders so that they won't be
reloaded and re-jitted.
2018-12-16 04:29:34 +03:00
Alexey Tsvetkov
2cc7bab0ff Run in-process compiler in separate thread
The compiler uses thread local values,
so when the compiler runs Gradle's thread,
it leaks classes preventing
a compiler's classloader from being collected.

    #KT-28037 fixed
2018-12-16 03:32:42 +03:00
Alexey Tsvetkov
f3bef7e48b Minor: remove unused util 2018-12-16 03:32:39 +03:00
Alexey Tsvetkov
7717921574 Print stacktrace to Gradle logger instead of writing directly to stderr 2018-12-16 03:32:36 +03:00
Shagen Ogandzhanian
08180d95e9 Introduce better typing for on[event-name] attributes from idl
see https://upsource.jetbrains.com/kotlin/review/KOTLIN-CR-2548
2018-12-14 16:22:39 +01:00
Denis Zharkov
318f8e2891 Transform KotlinClassFinder::findKotlinClass to extension 2018-12-14 11:51:24 +03:00
Denis Zharkov
724fa51fb4 Avoid multiple subsequent reading of the same class-file in front-end
^KT-23466 Fixed
2018-12-14 11:51:24 +03:00
Denis Zharkov
68aa525877 Minor. Reformat BinaryJavaClass 2018-12-14 11:51:24 +03:00
Denis Zharkov
51c4a10276 Convert JavaClassFinder.java to kotlin 2018-12-14 11:51:24 +03:00
Denis Zharkov
75572882a3 Convert JavaClassFinder.java to kotlin: rename file 2018-12-14 11:51:24 +03:00
Denis Zharkov
b731b02eda Minor. Reformat LazyJavaPackageScope.kt 2018-12-14 11:51:24 +03:00
Shagen Ogandzhanian
f5d28808c8 Introduce PointerEvent-related definitions
* Resolves https://youtrack.jetbrains.com/issue/KT-23932
 * Backed by review https://upsource.jetbrains.com/kotlin/branch/KT-23932-POINTER-EVENT-FROM-REMOTE-IDL
2018-12-13 21:46:59 +01:00
Shagen Ogandzhanian
5b206eeee6 Support float initializers in fun params generated from idl definitions 2018-12-13 21:46:40 +01:00
Shagen Ogandzhanian
f29926006b Add mininal test suite to idl2k, remove deprecated ANTLRFileStream 2018-12-13 21:42:42 +01:00
Alexey Tsvetkov
9dc11b2dd7 Make AbstractJvmAbiContentTest system independent 2018-12-13 21:23:20 +03:00
Alexey Tsvetkov
4422fd220a Register classpath as inputs of SmartJavaExec tasks 2018-12-13 21:23:17 +03:00
Ilya Chernikov
0731ad4bf0 [minor] get rid of obsolete "environment" wording 2018-12-13 18:04:43 +01:00
Ilya Chernikov
7dc3797e85 Refactor scripting - rename env vars to provided properties everywhere 2018-12-13 18:04:42 +01:00
Ilya Chernikov
4c81b4d4a7 Add generic interfaces to dependency resolvers 2018-12-13 18:04:42 +01:00
Ilya Chernikov
2c907e800a Add script config refinement before compilation into API 2018-12-13 18:04:41 +01:00
Ilya Chernikov
fe16ac8628 Add UrlScriptSource 2018-12-13 18:04:40 +01:00
Ilya Chernikov
a11dd0a7b5 [minor] copy utility fun to reduce dependencies 2018-12-13 18:04:39 +01:00
Ilya Chernikov
3bd19503b0 Fix vararg argument mapping for generic args convertor 2018-12-13 18:04:39 +01:00
Roman Artemev
c52204359b Update changelog 1.3.20 EAP1 2018-12-13 19:41:51 +03:00
Ivan Gavrilovic
51fc596aa9 Complete Java usage tracker if analysis extension finishes (KT-27487)
In cases when kapt compiler plugin runs in stubs generation mode,
Java usage tracker was not completed. This caused issues with
the incremental compilation if Java files changed.

E.g. if a constant defined in Java source file changed, stubs
would not be recompiled because the Java usage tracker would
not report changed type. This commit fixes that issue.
2018-12-13 17:13:41 +03:00
Alexander Udalov
0cfbd1a27f Fix isInitialized for companion lateinit properties
Instead of trying to access a missing field `Foo.foo`, call the
synthetic accessor `Foo.access$getFoo$cp` which, as per previous commit,
no longer contains the lateinit assertion

 #KT-21862 Fixed

(cherry picked from commit 8c74312cf6)
2018-12-13 14:13:02 +01:00
Alexander Udalov
5da0d8f060 Move lateinit assertion for companion property to companion object
Previously, for a property named `x` in the companion object of a class
named `Foo`, we generated:
- `Foo.access$getX$cp`, consisting of `GETFIELD Foo.x` and lateinit
  assertion
- `Foo.Companion.getX`, consisting of `INVOKEVIRTUAL Foo.access$getX$cp`

Now, we generate:
- `Foo.access$getX$cp`, consisting of `GETFIELD Foo.x`
- `Foo.Companion.getX`, consisting of `INVOKEVIRTUAL Foo.access$getX$cp`
  and lateinit assertion

The reason is that this way we can avoid generating another accessor and
reuse `Foo.access$getX$cp` in case `isInitialized` is called on a
lateinit property from companion.

For private properties, getX is not generated, but instead the assertion
is generated on each access to the field (which can be improved, see
KT-28331). The same happens for access to non-private properties from
inside the same context where they're declared.

 #KT-21862 In Progress

(cherry picked from commit 43413fcc44)
2018-12-13 14:13:00 +01:00
Alexander Udalov
d0969e77dd Minor, reformat & fix warnings in intermediateValueForProperty
(cherry picked from commit 8617365983)
2018-12-13 14:12:59 +01:00
Mikhail Glukhikh
b4101ef2ae Add "Ambiguous context due to scope receiver in suspend fun" inspection
#KT-28696 Fixed

(cherry picked from commit a15b47c93c)
2018-12-12 18:22:53 +03:00
Mikhail Glukhikh
edd4f283c6 Refactor "change type to mutable" in suspicious collection reassignment
Related to KT-20626

(cherry picked from commit 42fa6ce6f0)
2018-12-12 18:22:40 +03:00
Mikhail Glukhikh
7d07329292 Change description of boolean argument/augmented assignment inspections
(cherry picked from commit b17ee60c6f)
2018-12-12 18:22:26 +03:00
Mikhail Glukhikh
1eadec5432 Boolean literal arguments: check previous arg, fix all args in a row
(cherry picked from commit 13b09f532c)
2018-12-12 18:22:11 +03:00
Mikhail Glukhikh
0a33859eb2 Boolean literal arguments: do not highlight with single boolean argument
(cherry picked from commit 235b50d86e)
2018-12-12 18:21:59 +03:00
Mikhail Glukhikh
9a0f3f9e57 Boolean literal arguments: don't report on a call, just on an element
(cherry picked from commit d31e0b9632)
2018-12-12 18:21:44 +03:00
Toshiaki Kameyama
2a7bb8d13e Introduce "Boolean literal arguments" inspection #KT-2029 Fixed
(cherry picked from commit 0d7116aa5d)
2018-12-12 18:21:25 +03:00
Mikhail Glukhikh
fc9b41a05c Augmented list assignment inspection: add "replace with ordinary" fix
Relates to KT-20626

(cherry picked from commit aa9e48b9b6)
2018-12-12 18:21:11 +03:00
Mikhail Glukhikh
ac16907f1c Don't highlight "replace with +=" for read-only collections
Related to KT-20626

(cherry picked from commit ed8305995e)
2018-12-12 18:20:58 +03:00
Mikhail Glukhikh
c24bbff948 Add "Suspicious collection reassignment" inspection #KT-20626 Fixed
(cherry picked from commit c560aada3d)
2018-12-12 18:20:44 +03:00
Mikhail Glukhikh
410123d0f7 Introduce KtReferenceSearch to use LocalSearchScope, when possible
This fixes a set of problems in J2K tests in 183
#KT-28368 Fixed

(cherry picked from commit 3e936f64bf)
2018-12-12 18:20:28 +03:00
Leonid Startsev
04cb2265d8 Declare real external symbols for overriden by synthetic function
instead of unbound

Unbound symbols were throwing an exception on attempt to analyze them
in the other parts of compiler and are generally incorrect

(cherry picked from commit fdf4f02dde)
2018-12-12 17:31:54 +03:00
Yan Zhulanow
d5e1fc24e0 Evaluator: Render inline class values using its toString() implementation (KT-27414) 2018-12-12 21:42:21 +09:00
Yan Zhulanow
7725f0d1d7 Kapt: Switch to more appropriate way of converting URIs to Files 2018-12-12 21:42:20 +09:00
Yan Zhulanow
6e3494d83c Fix Android Lint tests (182 bunch only) 2018-12-12 21:42:19 +09:00
Yan Zhulanow
3cfee99ac6 Remove Lint tests for annotation argument API check.
Looks like newer Lint API checker ignores type usage in annotations, so these tests are no more needed.
2018-12-12 21:42:18 +09:00
Yan Zhulanow
68cd113d83 Fix testSimple() for "Remove Parcelable" action 2018-12-12 21:42:17 +09:00
Yan Zhulanow
8de34046a8 AllOpen: Update test data (enum constructors are now private) 2018-12-12 21:42:16 +09:00
Yan Zhulanow
a2be50a223 Update debugger test data, fix the current behavior 2018-12-12 21:42:15 +09:00
Yan Zhulanow
700a7c68eb Remove a magic constant from 'KotlinLambdaMethodFilter' 2018-12-12 21:42:14 +09:00
Yan Zhulanow
d7d066d081 Revert "Remove unneeded usage of the blocking invokeInManagerThread() (KT-24282)"
This reverts commit 6c868701
2018-12-12 21:42:13 +09:00
Yan Zhulanow
a30b4af7a4 Uast: Update test data (enum constructors are now private) 2018-12-12 21:42:12 +09:00
Yan Zhulanow
55097c09a0 NoArg: Update test data (enum constructors are now private) 2018-12-12 21:42:11 +09:00
Yan Zhulanow
09c97d7a18 Kapt: Update test data (stub converter tests) 2018-12-12 21:42:10 +09:00
Yan Zhulanow
9ac928aa1b Add missing 'disallowRootAccess()' to debugger and stub tests 2018-12-12 21:42:09 +09:00
Yan Zhulanow
5322dbe3fe Fix backend tests after changing format of synthetic variables for inline functions 2018-12-12 21:42:09 +09:00
Yan Zhulanow
3927e7615a Fix quick evaluation for array expressions (KT-13268) 2018-12-12 21:42:08 +09:00
Yan Zhulanow
3a3bd4826f Fix breakpoints for the same inline function nested calls (KT-22366)
This commit changes the format of the synthetic local variables for inline functions.
2018-12-12 21:42:07 +09:00
Yan Zhulanow
148ac0471d Remove unneeded usage of the blocking invokeInManagerThread() (KT-24282) 2018-12-12 21:42:06 +09:00
Yan Zhulanow
2eba1714bc Fix evaluation for captured inline classes (KT-28487) 2018-12-12 21:42:05 +09:00
Yan Zhulanow
758db84e53 Fix evaluation for static interface methods declared in Java (KT-23585) 2018-12-12 21:42:04 +09:00
Yan Zhulanow
75f8025d6a Fix source mapping for stepping into package facades from libraries (KT-28028) 2018-12-12 21:42:03 +09:00
Yan Zhulanow
e41d8ca122 Add a LookupLocation to 'getSyntheticExtensionProperties()', use it in 'DebuggerFieldSyntheticScopeProvider' 2018-12-12 21:42:02 +09:00
Yan Zhulanow
d0b71643b7 Evaluate: Enable 'foo_field' convention only for Jvm/Common code 2018-12-12 21:42:01 +09:00
Yan Zhulanow
80d1c9a7de Refactoring: Replace 'ParametersDescriptor' with a simple 'List' 2018-12-12 21:42:00 +09:00
Yan Zhulanow
4b060b68fe Evaluate: Support synthetic 'field' variable evaluation (KT-28342) 2018-12-12 21:41:59 +09:00
Yan Zhulanow
2d10730233 Minor: Move changeSuperToMagicAccessor() function to its single use site, J2K it 2018-12-12 21:41:58 +09:00
Yan Zhulanow
53a2fb7302 Kapt: Preserve 'getJarPathForClass()' (used in kapt-cli) 2018-12-12 21:41:57 +09:00
Yan Zhulanow
09d0cba192 Evaluate: Use '<name>_field' syntax for field value evaluation (KT-14075) 2018-12-12 21:41:56 +09:00
Yan Zhulanow
a5b19826e7 Provide a default implementation for 'SyntheticScope' 2018-12-12 21:41:55 +09:00
Denis Zharkov
863be9369a Add diagnostic for calling ConcurrentHashMap::contains by convention
^KT-18053 Fixed
2018-12-12 15:38:42 +03:00
Mikhail Glukhikh
92e125413d Do not modify highlighting settings for non-Kotlin files #KT-28716 Fixed
(cherry picked from commit 3889bb05d6)
2018-12-12 14:24:07 +03:00
Alexey Tsvetkov
6aebc695ec Minor: replace UsefulTestCase with KtUsefulTestCase
For some reason assertSameLinesWithFile from UsefulTestCase
fails with exception on TeamCity, whereas the one KtUsefulTestCase
does not
2018-12-12 12:01:45 +03:00
Alexey Tsvetkov
1bb75ac2ec Exclude InsnList from proguard
It is used by jvm-abi-gen plugin
2018-12-12 12:01:43 +03:00
Roman
1e2115ba83 Merge pull request #2024 from JetBrains/rr/gradle/native-update-1.1.0-rc1-5227
Update Kotlin/Native: RC1 1.1.0.5227
2018-12-12 08:04:57 +03:00
Alexey Tsvetkov
34dd6062fd Exclude local variables and try catch blocks of non-inline functions from ABI 2018-12-11 22:51:51 +03:00
Alexey Tsvetkov
e7cea0239a Check descriptor visibility before excluding method from ABI class 2018-12-11 22:51:48 +03:00
Alexey Tsvetkov
962a52ef0d Minor: rename const according to style guide 2018-12-11 22:51:44 +03:00
Alexey Tsvetkov
6a50cd8a11 Attempt to fix ABI tests on TC
Locally they work fine
2018-12-11 22:51:40 +03:00
Alexey Tsvetkov
b96d77db63 Disable removing private/synthetic/local classes temporarily 2018-12-11 22:51:36 +03:00
Alexey Tsvetkov
fe9287a20e Report output classes 2018-12-11 22:51:33 +03:00
Alexey Tsvetkov
d30eb186fd Reuse BytecodeListingTextCollectingVisitor in tests 2018-12-11 22:51:29 +03:00
Alexey Tsvetkov
b8c0d0f589 Reuse TransformationMethodVisitor in ABI gen plugin 2018-12-11 22:51:25 +03:00
Alexey Tsvetkov
e6b1e1df3a Convert TransformationMethodVisitor: step 2 2018-12-11 22:51:22 +03:00
Alexey Tsvetkov
f7d4aae815 Convert TransformationMethodVisitor: step 1 2018-12-11 22:51:18 +03:00
Alexey Tsvetkov
da5bfd6bea Minor fixes after review 2018-12-11 22:51:12 +03:00
Alexey Tsvetkov
d0c59dc73f Exclude nested classes of private classes from ABI classes 2018-12-11 22:51:07 +03:00
Alexey Tsvetkov
79b9f2fdf2 Report locations of errors in ABI classes tests 2018-12-11 22:51:03 +03:00
Alexey Tsvetkov
1207568c60 Add tests for compilation against abi classes 2018-12-11 22:51:00 +03:00
Alexey Tsvetkov
0bcec43b9a Add tests for non-compatible ABI changes 2018-12-11 22:50:56 +03:00
Alexey Tsvetkov
0c5ccbe6eb Exclude clinit from ABI classes 2018-12-11 22:50:52 +03:00
Alexey Tsvetkov
d3d027bc2d Exclude synthetic classes from ABI classes 2018-12-11 22:50:48 +03:00
Alexey Tsvetkov
278afe0691 Minor: extract function 2018-12-11 22:50:44 +03:00
Alexey Tsvetkov
6854ed319b Delay I/O when transforming ABI classes 2018-12-11 22:50:41 +03:00
Alexey Tsvetkov
07d3842de8 Remove unused cosntant pool entries from ABI classes 2018-12-11 22:50:37 +03:00
Alexey Tsvetkov
c66ce278e2 Exclude private typealiases from ABI classes 2018-12-11 22:50:33 +03:00
Alexey Tsvetkov
9a76ea227d Exclude local and private classes from ABI classes 2018-12-11 22:50:29 +03:00
Alexey Tsvetkov
ecbe37085b Exclude non-inline method bodies from ABI classes 2018-12-11 22:50:25 +03:00
Alexey Tsvetkov
5dc88796d9 Exclude private members from ABI classes 2018-12-11 22:50:22 +03:00
Alexey Tsvetkov
bf3debdfb2 Add plugin for JVM ABI classes generation
#KT-25128 Fixed

ABI class generation is implemented as a compiler plugin.
Command-line usage:
1. Add a path to 'jvm-abi-gen.jar' to the plguin classpath argument
(`-Xplugin`). By default the jar is located at
'kotlinc/lib/jvm-abi-gen.jar' in the kotlinc distribution archive.
2. Specify an output directory for ABI classes via
`-Pplugin:org.jetbrains.kotlin.jvm.abi:outputDir=<DIR>`.
2018-12-11 22:50:18 +03:00
Toshiaki Kameyama
9bb9bdd0a5 Assign backing field: don't add empty line
#KT-28694 Fixed

(cherry picked from commit 07ffac72cf)
2018-12-11 22:20:58 +03:00
Mikhail Glukhikh
5bf88069db For each parameter not used: handle char sequences correctly
An enhancement for KT-27209

(cherry picked from commit b143a1c8f7)
2018-12-11 22:20:25 +03:00
Mikhail Glukhikh
f874b8aebd Disable extract actions on non-JVM classes #KT-28476 Fixed
(cherry picked from commit 833f564f0e)
2018-12-11 22:20:08 +03:00
Mikhail Glukhikh
2873aaf4e2 For each parameter not used: introduce "replace with repeat"
An enhancement for KT-27209

(cherry picked from commit 11909a86a8)
2018-12-11 22:19:52 +03:00
Mikhail Glukhikh
daab8d4e14 For each parameter not used: cleanup
(cherry picked from commit e06c995516)
2018-12-11 22:19:34 +03:00
Mikhail Glukhikh
df648dbb06 Redundant arrow: don't report on forEach call with underscore
#KT-27209 Fixed

(cherry picked from commit 9aa1d1495b)
2018-12-11 22:19:17 +03:00
Mikhail Glukhikh
c4d52e0a80 Redundant arrow: support removing of 'it ->' #KT-28631 Fixed
(cherry picked from commit c8c485d27e)
2018-12-11 22:18:31 +03:00
Ilya Chernikov
6988ab0a4f Fix locking in script definition provider
fixes possible parallel modifications on definitions loading, e.g.
as in https://github.com/shyiko/ktlint/issues/287
2018-12-11 15:24:22 +01:00
Denis Zharkov
630502e17d Unwrap InvocationTargetException in dependency injection
^KT-28348 Fixed
2018-12-11 16:14:17 +03:00
Denis Zharkov
0cc6ece8dc Optimize searching constructor delegation calls
^KT-28755 Fixed
2018-12-11 16:14:17 +03:00
Denis Zharkov
b6dcebb08e Minor. Reformat usagesSearch/utils.kt 2018-12-11 16:14:17 +03:00
Alexey Tsvetkov
196193c238 Deprecate AP discovery in compile configurations in Gradle
#KT-24368 Fixed
2018-12-11 16:10:54 +03:00
Alexey Tsvetkov
e04c080e89 Add option to disable AP discovery in compile classpath
#KT-24530 Fixed

To disable discovery and enable avoidance for kapt tasks,
use "kapt.includeCompileClasspath = false"
2018-12-11 16:10:51 +03:00
Vasily Levchenko
b8f92714ac Update Kotlin/Native: RC1 1.1.0.5227 2018-12-11 15:33:42 +03:00
Simon Ogorodnik
ac052ce52a Support overriding module/library/sdk for particular light PsiClass
To support light R classes
2018-12-11 15:01:54 +03:00
Denis Zharkov
83934bfd14 Temporary remove some tests after a fix for KT-24937
Otherwise, our project is failed to be indexed
2018-12-11 12:03:52 +03:00
Denis Zharkov
7214d36a49 Relax assertion in parser for a recovery case with annotations
^KT-24937 Fixed
2018-12-11 12:03:44 +03:00
Yan Zhulanow
43eb3e4042 ServiceLoaderLite: Support paths with spaces (KT-28527) 2018-12-11 17:46:51 +09:00
Dmitry Petrov
6b6c3e7ff3 KT-28585 Fix boxing for values of captured vars of inline class type 2018-12-10 15:08:55 +03:00
Dmitry Petrov
3ab2da1226 KT-28405 Fix toString for inline classes with underlying arrays 2018-12-10 15:08:48 +03:00
Dmitry Savvinov
d51be4cd77 Fix missed returned expression if the last expression was condition jump
See ticket comments for the detailed description

^KT-28061 Fixed
2018-12-10 13:45:20 +03:00
Dmitry Savvinov
68889d839d Add test on in-place lambda with return + safecall
Currently, diagnostics behavior is undesired. The next commit fixes it

^KT-28061 In Progress
2018-12-10 13:45:15 +03:00
1435 changed files with 22997 additions and 11545 deletions

View File

@@ -115,6 +115,7 @@
<Problem reference="com.intellij.util.AstLoadingFilter" reason="Absent in 181. Almost all methods were renamed in 183. Use org.jetbrains.kotlin.util.AstLoadingFilter instead." />
<Problem reference="com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture" reason="Absent in &lt;= 181. Use org.jetbrains.kotlin.test.HierarchyViewTestFixture instead." />
<Problem reference="org.jetbrains.kotlin.test.HierarchyViewTestFixtureCompat" reason="Do not use the wrapper for 181 directly. Use org.jetbrains.kotlin.test.HierarchyViewTestFixture instead." />
<Problem reference="com.intellij.psi.codeStyle.CodeStyleSettingsProvider" reason="Additional method is introduced in 183 instead of deprecated one. Use CodeStyleSettingsProviderCompat instead." />
</list>
</option>
</inspection_tool>

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ sourceSets {
runtimeJar {
from("$projectDir/src") { include("**/*.xml") }
manifest.attributes.put("Class-Path", "kotlin-stdlib.jar kotlin-reflect.jar kotlin-script-runtime.jar kotlin-preloader.jar")
manifest.attributes.put("Class-Path", "$compilerManifestClassPath kotlin-preloader.jar")
}
dist()

View File

@@ -169,6 +169,7 @@ extra["versions.robolectric"] = "3.1"
extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0"
extra["versions.markdown"] = "0.1.25"
extra["versions.trove4j"] = "1.0.20181211"
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled = project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild
@@ -479,6 +480,7 @@ tasks {
":compiler:container:test",
":compiler:tests-java8:test",
":compiler:tests-spec:remoteRunTests")
dependsOn(":plugins:jvm-abi-gen:test")
}
create("jsCompilerTest") {

View File

@@ -15,6 +15,7 @@ fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = task<JavaExec> javaE
val classpath = classpath
val main = main
dependsOn(classpath)
inputs.files(classpath)
inputs.property("main", main)
doFirst {
val classPathString = classpath.joinToString(" ") { project.file(it).toURI().toString() }

View File

@@ -104,6 +104,9 @@ fun Project.firstFromJavaHomeThatExists(vararg paths: String, jdkHome: File = Fi
fun Project.toolsJar(jdkHome: File = File(this.property("JDK_18") as String)): File? =
firstFromJavaHomeThatExists("lib/tools.jar", jdkHome = jdkHome)
val compilerManifestClassPath
get() = "kotlin-stdlib.jar kotlin-reflect.jar kotlin-script-runtime.jar trove4j.jar"
object EmbeddedComponents {
val CONFIGURATION_NAME = "embeddedComponents"
}

View File

@@ -18,7 +18,6 @@ val packagesToRelocate =
"org.jdom",
"org.picocontainer",
"org.jline",
"gnu",
"org.fusesource",
"kotlinx.coroutines")

View File

@@ -1217,8 +1217,16 @@ public class AsmUtil {
return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName();
}
public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) {
if (isPrimitive(type)) {
public static void putJavaLangClassInstance(
@NotNull InstructionAdapter v,
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull GenerationState state
) {
if (kotlinType != null && InlineClassesUtilsKt.isInlineClassType(kotlinType)) {
v.aconst(boxType(type, kotlinType, state));
}
else if (isPrimitive(type)) {
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
}
else {

View File

@@ -40,7 +40,16 @@ public class ClassBuilderMode {
* Full function bodies
*/
public final static ClassBuilderMode FULL = new ClassBuilderMode(
/* bodies = */ true,
/* bodies = */ true,
/* metadata = */ true,
/* sourceRetention = */ false,
/* generateMultiFileFacadePartClasses = */ true);
/**
* ABI for compilation (non-private signatures + inline function bodies)
*/
public final static ClassBuilderMode ABI = new ClassBuilderMode(
/* bodies = */ true,
/* metadata = */ true,
/* sourceRetention = */ false,
/* generateMultiFileFacadePartClasses = */ true);

View File

@@ -245,7 +245,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
DescriptorSerializer serializer =
DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
ProtoBuf.Function.Builder builder = serializer.functionProto(freeLambdaDescriptor);
if (builder == null) return;
ProtoBuf.Function functionProto = builder.build();
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, av -> {
writeAnnotationData(av, serializer, functionProto);
@@ -400,7 +402,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
if (container instanceof ClassDescriptor) {
// TODO: would it work for arrays?
putJavaLangClassInstance(iv, state.getTypeMapper().mapClass((ClassDescriptor) container));
SimpleType containerKotlinType = ((ClassDescriptor) container).getDefaultType();
Type containerType = state.getTypeMapper().mapClass((ClassDescriptor) container);
putJavaLangClassInstance(iv, containerType, containerKotlinType, state);
}
else if (container instanceof PackageFragmentDescriptor) {
iv.aconst(state.getTypeMapper().mapOwner(descriptor));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.
*/
@@ -89,6 +89,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.*;
import java.util.function.Supplier;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
@@ -97,8 +98,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
@@ -454,6 +454,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return typeMapper.mapType(type);
}
@NotNull
public Type mapTypeAsDeclaration(@NotNull KotlinType type) {
return typeMapper.mapTypeAsDeclaration(type);
}
@NotNull
public Type expressionType(@Nullable KtExpression expression) {
return CodegenUtilKt.asmType(expression, typeMapper, bindingContext);
@@ -1430,12 +1435,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
});
}
public boolean isShouldMarkLineNumbers() {
return shouldMarkLineNumbers;
}
public void setShouldMarkLineNumbers(boolean shouldMarkLineNumbers) {
this.shouldMarkLineNumbers = shouldMarkLineNumbers;
public <T> T runWithShouldMarkLineNumbers(boolean enable, Supplier<T> operation) {
boolean originalStatus = shouldMarkLineNumbers;
this.shouldMarkLineNumbers = enable;
try {
return operation.get();
} finally {
this.shouldMarkLineNumbers = originalStatus;
}
}
public void markStartLineNumber(@NotNull KtElement element) {
@@ -1881,7 +1888,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@Nullable
private ClassDescriptor getSuperCallTarget(@NotNull Call call) {
public ClassDescriptor getSuperCallTarget(@NotNull Call call) {
KtSuperExpression superExpression = CallResolverUtilKt.getSuperCallExpression(call);
return superExpression == null ? null : getSuperCallLabelTarget(context, superExpression);
}
@@ -2051,7 +2058,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
isDefaultAccessor(propertyDescriptor.getGetter()) && isDefaultAccessor(propertyDescriptor.getSetter())))) {
fieldAccessorKind = JvmCodegenUtil.isDebuggerContext(context) ? AccessorKind.NORMAL : AccessorKind.IN_CLASS_COMPANION;
}
else if ((syntheticBackingField &&
else //noinspection ConstantConditions
if ((syntheticBackingField &&
context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration)) {
fieldAccessorKind = AccessorKind.FIELD_FROM_LOCAL;
}
@@ -2077,17 +2085,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean skipPropertyAccessors;
PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
boolean directAccessToGetter = couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context,
state.getShouldInlineConstVals());
boolean directAccessToSetter = couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context,
state.getShouldInlineConstVals());
boolean directAccessToGetter =
couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context, state.getShouldInlineConstVals());
boolean directAccessToSetter =
couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context, state.getShouldInlineConstVals());
if (fieldAccessorKind == AccessorKind.LATEINIT_INTRINSIC) {
skipPropertyAccessors = !isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext;
skipPropertyAccessors =
(!isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext) &&
!isBackingFieldMovedFromCompanion;
if (!skipPropertyAccessors) {
propertyDescriptor = (AccessorForPropertyBackingField)
backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
if (isBackingFieldMovedFromCompanion && context.getContextDescriptor() instanceof AccessorForPropertyBackingField) {
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getParentContext()
.getAccessor(propertyDescriptor, AccessorKind.IN_CLASS_COMPANION, delegateType, superCallTarget);
}
else {
propertyDescriptor =
backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
}
}
ownerDescriptor = propertyDescriptor;
}
@@ -2097,10 +2113,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
(directAccessToGetter && (!propertyDescriptor.isVar() || directAccessToSetter));
if (!skipPropertyAccessors) {
//noinspection ConstantConditions
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(
propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget
);
propertyDescriptor = backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
assert propertyDescriptor instanceof AccessorForPropertyBackingField :
"Unexpected accessor descriptor: " + propertyDescriptor;
ownerDescriptor = propertyDescriptor;
@@ -3021,7 +3034,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public int indexOfLocalNotDelegated(KtReferenceExpression lhs) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs);
if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) {
if (isBoxedLocalCapturedInClosure(bindingContext, declarationDescriptor)) {
return -1;
}
if (declarationDescriptor instanceof LocalVariableDescriptor && ((LocalVariableDescriptor) declarationDescriptor).isDelegated()) {
@@ -3117,7 +3130,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS);
}
putJavaLangClassInstance(v, typeMapper.mapType(type));
putJavaLangClassInstance(v, typeMapper.mapType(type), type, state);
}
if (wrapIntoKClass) {
@@ -4030,6 +4043,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
else if (property.hasModifier(KtTokens.LATEINIT_KEYWORD)) {
initializeLocalVariable(property, null);
}
else {
initializeLocalVariableWithFakeDefaultValue(property);
}
return StackValue.none();
}
@@ -4173,6 +4189,50 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
storeTo.storeSelector(resultType, resultKotlinType, v);
}
// This is a workaround to avoid bugs with incorrect range of uninitialized variable:
// 1) JDI error 305
// 2) Expected R, got . in code with contracts
// 3) D8 dropping the whole LVT
private void initializeLocalVariableWithFakeDefaultValue(@NotNull KtProperty variableDeclaration) {
LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) getVariableDescriptorNotNull(variableDeclaration);
// Boxed variables already have a value
if (isBoxedLocalCapturedInClosure(bindingContext, variableDescriptor)) return;
assert !variableDeclaration.hasDelegateExpressionOrInitializer() &&
!variableDescriptor.isLateInit() : variableDeclaration.getText() + " in not variable declaration without initializer";
KotlinType kotlinType = variableDescriptor.getType();
Type type = typeMapper.mapType(kotlinType);
if (type == Type.VOID_TYPE) return;
int index = lookupLocalIndex(variableDescriptor);
assert index >= 0: variableDescriptor + " is not in frame map";
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
v.iconst(0);
break;
case Type.FLOAT:
v.fconst(0.0f);
break;
case Type.LONG:
v.lconst(0L);
break;
case Type.DOUBLE:
v.dconst(0.0);
break;
default:
v.aconst(null);
}
v.store(index, type);
}
@NotNull
private StackValue generateProvideDelegateCallForLocalVariable(
@NotNull StackValue initializer,

View File

@@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
@@ -619,6 +620,7 @@ public class FunctionCodegen {
isReleaseCoroutines);
}
Label methodEntry = null;
Label methodEnd;
int functionFakeIndex = -1;
@@ -647,15 +649,21 @@ public class FunctionCodegen {
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
functionDescriptor.getValueParameters(), isStaticMethod(context.getContextKind(), functionDescriptor)
);
// Manually add `continuation` parameter to frame map, thus it will not overlap with fake indices
if (functionDescriptor.isSuspend() && CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(functionDescriptor)) {
FunctionDescriptor view = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(functionDescriptor, parentCodegen.state);
ValueParameterDescriptor continuationValueDescriptor = view.getValueParameters().get(view.getValueParameters().size() - 1);
frameMap.enter(continuationValueDescriptor, typeMapper.mapType(continuationValueDescriptor));
}
if (context.isInlineMethodContext()) {
functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
functionFakeIndex = newFakeTempIndex(mv, frameMap);
}
if (context instanceof InlineLambdaContext) {
lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
lambdaFakeIndex = newFakeTempIndex(mv, frameMap);
}
Label methodEntry = new Label();
methodEntry = new Label();
mv.visitLabel(methodEntry);
context.setMethodStartLabel(methodEntry);
@@ -707,37 +715,43 @@ public class FunctionCodegen {
//TODO: it's best to move all below logic to 'generateLocalVariableTable' method
if (context.isInlineMethodContext() && functionFakeIndex != -1) {
assert methodEntry != null : "methodEntry is not initialized";
mv.visitLocalVariable(
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + typeMapper.mapAsmMethod(functionDescriptor).getName(),
Type.INT_TYPE.getDescriptor(), null,
methodBegin, methodEnd,
methodEntry, methodEnd,
functionFakeIndex);
}
if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
String name = thisType.getClassName();
int indexOfLambdaOrdinal = name.lastIndexOf("$");
if (indexOfLambdaOrdinal > 0) {
int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
String internalName = thisType.getInternalName();
String lambdaLocalName = StringsKt.substringAfterLast(internalName, '/', internalName);
KtPureElement functionArgument = parentCodegen.element;
String functionName = "unknown";
if (functionArgument instanceof KtFunction) {
ValueParameterDescriptor inlineArgumentDescriptor =
InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
if (inlineArgumentDescriptor != null) {
functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
}
KtPureElement functionArgument = parentCodegen.element;
String functionName = "unknown";
if (functionArgument instanceof KtFunction) {
ValueParameterDescriptor inlineArgumentDescriptor =
InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
if (inlineArgumentDescriptor != null) {
functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
}
mv.visitLocalVariable(
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal + "$" + functionName,
Type.INT_TYPE.getDescriptor(), null,
methodBegin, methodEnd,
lambdaFakeIndex);
}
assert methodEntry != null : "methodEntry is not initialized";
mv.visitLocalVariable(
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + "-" + functionName + "-" + lambdaLocalName,
Type.INT_TYPE.getDescriptor(), null,
methodEntry, methodEnd,
lambdaFakeIndex);
}
}
private static int newFakeTempIndex(@NotNull MethodVisitor mv, FrameMap frameMap) {
int fakeIndex = frameMap.enterTemp(Type.INT_TYPE);
mv.visitLdcInsn(0);
mv.visitVarInsn(ISTORE, fakeIndex);
return fakeIndex;
}
private static boolean isCompatibilityStubInDefaultImpls(
@NotNull FunctionDescriptor functionDescriptor,
@NotNull MethodContext context,
@@ -1299,8 +1313,14 @@ public class FunctionCodegen {
Label loadArg = new Label();
iv.ifeq(loadArg);
StackValue.local(parameterIndex, type, parameterDescriptor.getType())
.store(loadStrategy.genValue(parameterDescriptor, codegen), iv);
CallableDescriptor containingDeclaration = parameterDescriptor.getContainingDeclaration();
codegen.runWithShouldMarkLineNumbers(
!(containingDeclaration instanceof MemberDescriptor) || !((MemberDescriptor) containingDeclaration).isExpect(),
() -> {
StackValue.local(parameterIndex, type, parameterDescriptor.getType())
.store(loadStrategy.genValue(parameterDescriptor, codegen), iv);
return null;
});
iv.mark(loadArg);
}

View File

@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.types.KotlinType;
@@ -107,21 +108,22 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
JvmKotlinType type = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
Type asmType = type.getType();
KotlinType kotlinType = type.getKotlinType();
if (asmType.getSort() == Type.ARRAY) {
Type elementType = correctElementType(asmType);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
asmType = JAVA_STRING_TYPE;
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
}
else {
if (elementType.getSort() != Type.CHAR) {
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
asmType = JAVA_STRING_TYPE;
}
else if (elementType.getSort() != Type.CHAR) {
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
asmType = JAVA_STRING_TYPE;
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
}
}
genInvokeAppendMethod(iv, asmType, type.getKotlinType(), typeMapper);
genInvokeAppendMethod(iv, asmType, kotlinType, typeMapper);
}
iv.aconst(")");

View File

@@ -170,10 +170,10 @@ class ScriptCodegen private constructor(
genFieldFromParam(typeMapper.mapClass(receiver), receiversParamIndex, name)
}
scriptDescriptor.scriptEnvironmentProperties.forEachIndexed { envVarIndex, envVar ->
scriptDescriptor.scriptProvidedProperties.forEachIndexed { envVarIndex, envVar ->
val fieldClassType = typeMapper.mapType(envVar)
val envVarParamIndex = frameMap.enterTemp(fieldClassType)
val name = scriptContext.getEnvironmentVarName(envVarIndex)
val name = scriptContext.getProvidedPropertyName(envVarIndex)
genFieldFromParam(fieldClassType, envVarParamIndex, name)
}
@@ -209,12 +209,12 @@ class ScriptCodegen private constructor(
null
)
}
for (envVarIndex in scriptDescriptor.scriptEnvironmentProperties.indices) {
for (envVarIndex in scriptDescriptor.scriptProvidedProperties.indices) {
classBuilder.newField(
NO_ORIGIN,
ACC_PUBLIC or ACC_FINAL,
scriptContext.getEnvironmentVarName(envVarIndex),
scriptContext.getEnvironmentVarType(envVarIndex).descriptor,
scriptContext.getProvidedPropertyName(envVarIndex),
scriptContext.getProvidedPropertyType(envVarIndex).descriptor,
null,
null
)

View File

@@ -728,15 +728,20 @@ public abstract class StackValue {
@NotNull Field refWrapper,
@NotNull VariableDescriptor variableDescriptor
) {
return new FieldForSharedVar(localType, classType, fieldName, refWrapper,
variableDescriptor.isLateInit(), variableDescriptor.getName());
return new FieldForSharedVar(
localType, variableDescriptor.getType(), classType, fieldName, refWrapper,
variableDescriptor.isLateInit(), variableDescriptor.getName()
);
}
@NotNull
public static FieldForSharedVar fieldForSharedVar(@NotNull FieldForSharedVar field, @NotNull StackValue newReceiver) {
Field oldReceiver = (Field) field.receiver;
Field newSharedVarReceiver = field(oldReceiver, newReceiver);
return new FieldForSharedVar(field.type, field.owner, field.name, newSharedVarReceiver, field.isLateinit, field.variableName);
return new FieldForSharedVar(
field.type, field.kotlinType,
field.owner, field.name, newSharedVarReceiver, field.isLateinit, field.variableName
);
}
public static StackValue coercion(@NotNull StackValue value, @NotNull Type castType, @Nullable KotlinType castKotlinType) {
@@ -880,6 +885,7 @@ public abstract class StackValue {
// 2) call using callable reference: in this case it is not local, but rather captured value
// 3) recursive call: we are in the middle of defining it, but, thankfully, we can simply call `this.invoke` to
// create new coroutine
// 4) Normal call, but the value is captured
// First, check whether this is a normal call
int index = codegen.lookupLocalIndex(callee);
@@ -893,24 +899,27 @@ public abstract class StackValue {
Type calleeType = CodegenBinding.asmTypeForAnonymousClass(bindingContext, callee);
if (codegen.context.hasThisDescriptor()) {
ClassDescriptor thisDescriptor = codegen.context.getThisDescriptor();
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, callee);
if (thisDescriptor instanceof SyntheticClassDescriptorForLambda &&
((SyntheticClassDescriptorForLambda) thisDescriptor).isCallableReference()) {
// Call is inside a callable reference
// if it is call to recursive local, just return this$0
Boolean isRecursive = bindingContext.get(RECURSIVE_SUSPEND_CALLABLE_REFERENCE, thisDescriptor);
if (isRecursive != null && isRecursive) {
ClassDescriptor classDescriptor =
bindingContext.get(CLASS_FOR_CALLABLE, callee);
assert classDescriptor != null : "No CLASS_FOR_CALLABLE" + callee;
return thisOrOuter(codegen, classDescriptor, false, false);
}
// Otherwise, just call constructor of the closure
return codegen.findCapturedValue(callee);
}
if (classDescriptor == thisDescriptor) {
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
codegen.v.visitVarInsn(ALOAD, 0);
return onStack(calleeType);
}
}
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
codegen.v.visitVarInsn(ALOAD, 0);
return onStack(calleeType);
// Otherwise, this is captured value
return codegen.findCapturedValue(callee);
}
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
@@ -1655,8 +1664,14 @@ public abstract class StackValue {
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
if (!skipLateinitAssertion) {
genNotNullAssertionForLateInitIfNeeded(v);
if (!skipLateinitAssertion && descriptor.isLateInit()) {
CallableMemberDescriptor contextDescriptor = codegen.context.getContextDescriptor();
boolean isCompanionAccessor =
contextDescriptor instanceof AccessorForPropertyBackingField &&
((AccessorForPropertyBackingField) contextDescriptor).getAccessorKind() == AccessorKind.IN_CLASS_COMPANION;
if (!isCompanionAccessor) {
genNonNullAssertForLateinit(v, this.descriptor.getName().asString());
}
}
coerceTo(type, kotlinType, v);
}
@@ -1689,6 +1704,19 @@ public abstract class StackValue {
coerce(typeOfValueOnStack, kotlinTypeOfValueOnStack, type, kotlinType, v);
// For non-private lateinit properties in companion object, the assertion is generated in the public getFoo method
// in the companion and _not_ in the synthetic accessor access$getFoo$cp in the outer class. The reason is that this way,
// the synthetic accessor can be reused for isInitialized checks, which require there to be no assertion.
// For lateinit properties that are accessed via the backing field directly (or via the synthetic accessor, if the access
// is from a different context), the assertion will be generated on each access, see KT-28331.
if (descriptor instanceof AccessorForPropertyBackingField) {
PropertyDescriptor property = ((AccessorForPropertyBackingField) descriptor).getCalleeDescriptor();
if (!skipLateinitAssertion && property.isLateInit() && JvmAbi.isPropertyWithBackingFieldInOuterClass(property) &&
!JvmCodegenUtil.couldUseDirectAccessToProperty(property, true, false, codegen.context, false)) {
genNonNullAssertForLateinit(v, property.getName().asString());
}
}
KotlinType returnType = descriptor.getReturnType();
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
v.aconst(null);
@@ -1727,12 +1755,6 @@ public abstract class StackValue {
return true;
}
private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) {
if (!descriptor.isLateInit()) return;
StackValue.genNonNullAssertForLateinit(v, descriptor.getName().asString());
}
@Override
public void store(@NotNull StackValue rightSide, @NotNull InstructionAdapter v, boolean skipReceiver) {
PropertySetterDescriptor setterDescriptor = descriptor.getSetter();
@@ -1900,10 +1922,11 @@ public abstract class StackValue {
final Name variableName;
public FieldForSharedVar(
Type type, Type owner, String name, StackValue.Field receiver,
Type type, KotlinType kotlinType,
Type owner, String name, StackValue.Field receiver,
boolean isLateinit, Name variableName
) {
super(type, null, false, false, receiver, receiver.canHaveSideEffects());
super(type, kotlinType, false, false, receiver, receiver.canHaveSideEffects());
if (isLateinit && variableName == null) {
throw new IllegalArgumentException("variableName should be non-null for captured lateinit variable " + name);

View File

@@ -1,124 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import org.jetbrains.org.objectweb.asm.util.Textifier;
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getNodeText;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.wrapWithMaxLocalCalc;
public abstract class TransformationMethodVisitor extends MethodVisitor {
private final MethodNode methodNode;
private final MethodVisitor delegate;
public TransformationMethodVisitor(
@NotNull MethodVisitor delegate,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
) {
super(Opcodes.ASM5);
this.delegate = delegate;
this.methodNode = new MethodNode(access, name, desc, signature, exceptions);
this.methodNode.localVariables = new ArrayList<>(5);
this.mv = wrapWithMaxLocalCalc(methodNode);
}
@Override
public void visitEnd() {
// force mv to calculate maxStack/maxLocals in case it didn't yet done
if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) {
mv.visitMaxs(-1, -1);
}
super.visitEnd();
try {
if (shouldBeTransformed(methodNode)) {
performTransformations(methodNode);
}
methodNode.accept(new EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate));
// In case of empty instructions list MethodNode.accept doesn't call visitLocalVariables of delegate
// So we just do it here
if (methodNode.instructions.size() == 0
// MethodNode does not create a list of variables for abstract methods, so we would get NPE in accept() instead
&& (!(delegate instanceof MethodNode) || methodNode.localVariables != null)
) {
List<LocalVariableNode> localVariables = methodNode.localVariables;
// visits local variables
int n = localVariables == null ? 0 : localVariables.size();
for (int i = 0; i < n; ++i) {
localVariables.get(i).accept(delegate);
}
}
delegate.visitEnd();
}
catch (Throwable t) {
throw new CompilationException("Couldn't transform method node:\n" + getNodeText(methodNode), t, null);
}
}
protected abstract void performTransformations(@NotNull MethodNode methodNode);
/**
* You can use it when you need to ignore visit end
*/
private static class EndIgnoringMethodVisitorDecorator extends MethodVisitor {
public EndIgnoringMethodVisitorDecorator(int api, @NotNull MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitEnd() {
}
}
@Nullable
public TraceMethodVisitor getTraceMethodVisitorIfPossible() {
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(new Textifier());
try {
methodNode.accept(traceMethodVisitor);
}
catch (Throwable e) {
return null;
}
return traceMethodVisitor;
}
private static boolean shouldBeTransformed(@NotNull MethodNode node) {
return node.instructions.size() > 0;
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.util.Textifier
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
import java.util.ArrayList
import org.jetbrains.kotlin.codegen.inline.nodeText
import org.jetbrains.kotlin.codegen.inline.wrapWithMaxLocalCalc
abstract class TransformationMethodVisitor(
private val delegate: MethodVisitor,
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?,
api: Int = Opcodes.ASM5
) : MethodVisitor(api) {
private val methodNode = MethodNode(access, name, desc, signature, exceptions).apply {
localVariables = ArrayList(5)
}
val traceMethodVisitorIfPossible: TraceMethodVisitor?
get() {
val traceMethodVisitor = TraceMethodVisitor(Textifier())
try {
methodNode.accept(traceMethodVisitor)
} catch (e: Throwable) {
return null
}
return traceMethodVisitor
}
init {
mv = wrapWithMaxLocalCalc(methodNode)
}
override fun visitEnd() {
// force mv to calculate maxStack/maxLocals in case it didn't yet done
if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) {
mv.visitMaxs(-1, -1)
}
super.visitEnd()
try {
if (shouldBeTransformed(methodNode)) {
performTransformations(methodNode)
}
methodNode.accept(EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate))
// In case of empty instructions list MethodNode.accept doesn't call visitLocalVariables of delegate
// So we just do it here
if (methodNode.instructions.size() == 0
// MethodNode does not create a list of variables for abstract methods, so we would get NPE in accept() instead
&& (delegate !is MethodNode || methodNode.localVariables != null)
) {
val localVariables = methodNode.localVariables
// visits local variables
val n = localVariables?.size ?: 0
for (i in 0 until n) {
localVariables!![i].accept(delegate)
}
}
delegate.visitEnd()
} catch (t: Throwable) {
throw CompilationException("Couldn't transform method node:\n" + methodNode.nodeText, t, null)
}
}
protected abstract fun performTransformations(methodNode: MethodNode)
/**
* You can use it when you need to ignore visit end
*/
private class EndIgnoringMethodVisitorDecorator(api: Int, mv: MethodVisitor) : MethodVisitor(api, mv) {
override fun visitEnd() {
}
}
private fun shouldBeTransformed(node: MethodNode): Boolean {
return node.instructions.size() > 0
}
}

View File

@@ -323,30 +323,27 @@ fun FqName.topLevelClassInternalName() = JvmClassName.byClassId(ClassId(parent()
fun FqName.topLevelClassAsmType(): Type = Type.getObjectType(topLevelClassInternalName())
fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodegen, valueParameters: List<ValueParameterDescriptor>) {
val savedIsShouldMarkLineNumbers = codegen.isShouldMarkLineNumbers
// Do not write line numbers until destructuring happens
// (otherwise destructuring variables will be uninitialized in the beginning of lambda)
codegen.isShouldMarkLineNumbers = false
codegen.runWithShouldMarkLineNumbers(false) {
for (parameterDescriptor in valueParameters) {
if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue
for (parameterDescriptor in valueParameters) {
if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue
for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) {
codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type))
}
for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) {
codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type))
val destructuringDeclaration =
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
codegen.initializeDestructuringDeclarationVariables(
destructuringDeclaration,
TransientReceiver(parameterDescriptor.type),
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
)
}
val destructuringDeclaration =
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
codegen.initializeDestructuringDeclarationVariables(
destructuringDeclaration,
TransientReceiver(parameterDescriptor.type),
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
)
}
codegen.isShouldMarkLineNumbers = savedIsShouldMarkLineNumbers
}
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.codegen.context
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.FieldInfo
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.StackValue
@@ -33,9 +32,8 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptProvidedPropertiesDescriptor
import org.jetbrains.org.objectweb.asm.Type
import kotlin.reflect.KClass
class ScriptContext(
val typeMapper: KotlinTypeMapper,
@@ -76,25 +74,24 @@ class ScriptContext(
private val ctorImplicitReceiversParametersStart =
ctorValueParametersStart + (scriptDescriptor.getSuperClassNotAny()?.unsubstitutedPrimaryConstructor?.valueParameters?.size ?: 0)
private val ctorEnvironmentVarsParametersStart =
private val ctorProvidedPropertiesParametersStart =
ctorImplicitReceiversParametersStart + scriptDescriptor.implicitReceivers.size
fun getImplicitReceiverName(index: Int): String =
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorImplicitReceiversParametersStart + index].name.identifier
fun getImplicitReceiverType(index: Int): Type? {
val receivers = script.kotlinScriptDefinition.implicitReceivers
val kClass = receivers.getOrNull(index)?.classifier as? KClass<*>
return kClass?.java?.classId?.let(AsmUtil::asmTypeByClassId)
val receiverParam = scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorImplicitReceiversParametersStart + index]
return state.typeMapper.mapType(receiverParam.type)
}
fun getEnvironmentVarName(index: Int): String =
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorEnvironmentVarsParametersStart + index].name.identifier
fun getProvidedPropertyName(index: Int): String =
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorProvidedPropertiesParametersStart + index].name.identifier
fun getEnvironmentVarType(index: Int): Type = typeMapper.mapType(scriptDescriptor.scriptEnvironmentProperties[index].type)
fun getProvidedPropertyType(index: Int): Type = typeMapper.mapType(scriptDescriptor.scriptProvidedProperties[index].type)
fun getOuterReceiverExpression(prefix: StackValue?, thisOrOuterClass: ClassDescriptor): StackValue {
if (thisOrOuterClass is ScriptEnvironmentDescriptor) {
if (thisOrOuterClass is ScriptProvidedPropertiesDescriptor) {
return prefix ?: StackValue.LOCAL_0
}
receiverDescriptors.forEachIndexed { index, outerReceiver ->
@@ -113,10 +110,8 @@ class ScriptContext(
fun getScriptFieldName(scriptDescriptor: ScriptDescriptor): String {
val index = earlierScripts.indexOf(scriptDescriptor)
if (index < 0) {
throw IllegalStateException("Unregistered script: $scriptDescriptor")
}
return "script$" + (index + 1)
return if (index >= 0) "script$" + (index + 1)
else "\$\$importedScript${scriptDescriptor.name.identifier}"
}
override fun toString(): String {

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.
*/
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
@@ -538,7 +539,7 @@ class CoroutineTransformerMethodVisitor(
// k + 2 - exception
val variablesToSpill =
(0 until localsCount)
.filter { it !in setOf(continuationIndex, dataIndex, exceptionIndex) }
.filterNot { it in setOf(continuationIndex, dataIndex, exceptionIndex) }
.map { Pair(it, frame.getLocal(it)) }
.filter { (index, value) ->
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
@@ -944,7 +945,13 @@ private fun allSuspensionPointsAreTailCalls(
}
if (insideTryBlock) return@all false
safelyReachableReturns[endIndex + 1] != null
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
sourceFrames[returnIndex].top().sure {
"There must be some value on stack to return"
}.insns.all { sourceInsn ->
sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex
}
} ?: false
}
}

View File

@@ -20,6 +20,8 @@ import com.google.common.collect.LinkedListMultimap
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.org.objectweb.asm.tree.*
import java.util.*
import kotlin.collections.HashSet
import kotlin.collections.LinkedHashSet
abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
val tryBlocksMetaInfo: IntervalMetaInfo<TryCatchBlockNodeInfo> = IntervalMetaInfo(this)
@@ -114,7 +116,7 @@ class IntervalMetaInfo<T : SplittableInterval<T>>(private val processor: Coverin
}
fun splitAndRemoveCurrentIntervals(by: Interval, keepStart: Boolean) {
currentIntervals.map { splitAndRemoveInterval(it, by, keepStart) }
currentIntervals.toList().forEach { splitAndRemoveIntervalFromCurrents(it, by, keepStart) }
}
fun processCurrent(curIns: LabelNode, directOrder: Boolean) {
@@ -141,7 +143,7 @@ class IntervalMetaInfo<T : SplittableInterval<T>>(private val processor: Coverin
return split
}
fun splitAndRemoveInterval(interval: T, by: Interval, keepStart: Boolean): SplitPair<T> {
fun splitAndRemoveIntervalFromCurrents(interval: T, by: Interval, keepStart: Boolean): SplitPair<T> {
val splitPair = split(interval, by, keepStart)
val removed = currentIntervals.remove(splitPair.patchedPart)
assert(removed) { "Wrong interval structure: $splitPair" }

View File

@@ -381,7 +381,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
// so we should split original interval by inserted finally one
for (TryCatchBlockNodeInfo block : updatingClusterBlocks) {
//update exception mapping
SplitPair<TryCatchBlockNodeInfo> split = tryBlocksMetaInfo.splitAndRemoveInterval(block, splitBy, false);
SplitPair<TryCatchBlockNodeInfo> split = tryBlocksMetaInfo.splitAndRemoveIntervalFromCurrents(block, splitBy, false);
checkFinally(split.getNewPart());
checkFinally(split.getPatchedPart());
//block patched in split method

View File

@@ -156,17 +156,18 @@ class DefaultLambda(
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
invokeMethod = Method(
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
)
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
val signature = sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
node = getMethodNode(
classReader.b,
invokeMethod.name,
invokeMethod.descriptor,
lambdaClassType
) ?: error("Can't find method '${invokeMethod.name}${invokeMethod.descriptor}' in '${classReader.className}'")
methodName,
signature,
lambdaClassType,
signatureAmbiguity = true
) ?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
invokeMethod = Method(node.node.name, node.node.desc)
if (needReification) {
//nested classes could also require reification

View File

@@ -418,12 +418,15 @@ class MethodInliner(
private val isInliningLambda = nodeRemapper.isInsideInliningLambda
private fun getNewIndex(`var`: Int): Int {
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo is IrExpressionLambda) {
val lambdaInfo = inliningContext.lambdaInfo
if (inliningContext.isInliningLambda && lambdaInfo is IrExpressionLambda) {
if (`var` < parameters.argsSizeOnStack) {
if (`var` < capturedParamsSize) {
return `var` + realParametersSize
}
else {
val capturedParamsStartIndex =
if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0 //shift by extension
val capturedParamsEndIndex = capturedParamsSize + capturedParamsStartIndex - 1
if (`var` in capturedParamsStartIndex..capturedParamsEndIndex) {
return `var` + realParametersSize - capturedParamsStartIndex //subtract extension
} else if (`var` >= capturedParamsStartIndex) {
return `var` - capturedParamsSize
}
}

View File

@@ -89,7 +89,8 @@ internal fun getMethodNode(
classData: ByteArray,
methodName: String,
methodDescriptor: String,
classType: Type
classType: Type,
signatureAmbiguity: Boolean = false
): SMAPAndMethodNode? {
val cr = ClassReader(classData)
var node: MethodNode? = null
@@ -113,17 +114,28 @@ internal fun getMethodNode(
signature: String?,
exceptions: Array<String>?
): MethodVisitor? {
if (methodName == name && methodDescriptor == desc) {
node = object : MethodNode(API, access, name, desc, signature, exceptions) {
override fun visitLineNumber(line: Int, start: Label) {
super.visitLineNumber(line, start)
lines[0] = Math.min(lines[0], line)
lines[1] = Math.max(lines[1], line)
}
if (methodName != name || (signatureAmbiguity && access.and(Opcodes.ACC_SYNTHETIC) != 0)) return null
if (methodDescriptor != desc) {
val sameNumberOfParameters = Type.getArgumentTypes(methodDescriptor).size == Type.getArgumentTypes(desc).size
if (!signatureAmbiguity || !sameNumberOfParameters) {
return null
}
return node
}
return null
node?.let { existing ->
throw AssertionError("Can't find proper '$name' method for inline: ambiguity between '${existing.name + existing.desc}' and '${name + desc}'")
}
return object : MethodNode(API, access, name, desc, signature, exceptions) {
override fun visitLineNumber(line: Int, start: Label) {
super.visitLineNumber(line, start)
lines[0] = Math.min(lines[0], line)
lines[1] = Math.max(lines[1], line)
}
}.also {
node = it
}
}
}, ClassReader.SKIP_FRAMES or if (GENERATE_SMAP) 0 else ClassReader.SKIP_DEBUG)

View File

@@ -49,7 +49,7 @@ class KClassJavaObjectTypeProperty : IntrinsicPropertyGetter() {
}
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(lhs.type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
}
iv.aconst(AsmUtil.boxType(codegen.asmType(lhs.type)))
iv.aconst(AsmUtil.boxType(codegen.mapTypeAsDeclaration(lhs.type)))
}
}
}

View File

@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.TypeUtils
@@ -32,21 +33,28 @@ class KClassJavaPrimitiveTypeProperty : IntrinsicPropertyGetter() {
val receiverType = codegen.bindingContext.getType(receiverExpression) ?: return null
if (!KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(receiverType)) return null
}
val lhsType = codegen.asmType(lhs.type)
return StackValue.operation(returnType) { iv ->
when {
lhs is DoubleColonLHS.Expression && !lhs.isObjectQualifier -> {
codegen.gen(receiverExpression).put(lhsType, iv)
AsmUtil.pop(iv, lhsType)
if (lhs.type.isInlineClassType())
iv.aconst(null)
else
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
}
!lhs.type.isInlineClassType() && isPrimitiveOrWrapper(lhsType) -> {
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
}
AsmUtil.isPrimitive(lhsType) ||
AsmUtil.unboxPrimitiveTypeOrNull(lhsType) != null ||
AsmTypes.VOID_WRAPPER_TYPE == lhsType -> {
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
}
else -> iv.aconst(null)
}
}
}
private fun isPrimitiveOrWrapper(lhsType: Type) =
AsmUtil.isPrimitive(lhsType) || AsmUtil.unboxPrimitiveTypeOrNull(lhsType) != null || AsmTypes.VOID_WRAPPER_TYPE == lhsType
}

View File

@@ -66,6 +66,8 @@ class OptimizationMethodVisitor(
optimizationTransformer.transform("fake", methodNode)
}
DeadCodeEliminationMethodTransformer().transform("fake", methodNode)
methodNode.prepareForEmitting()
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.IincInsnNode
@@ -78,11 +79,13 @@ private fun useVar(
) {
val index = node.instructions.indexOf(insn)
node.localVariables.filter {
node.instructions.indexOf(it.start) < index && index < node.instructions.indexOf(it.end) &&
// Inliner fake variables, despite being present in LVT, are not read, thus are always dead
!it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT) && !it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) &&
node.instructions.indexOf(it.start) < index && index < node.instructions.indexOf(it.end) &&
Type.getType(it.desc).sort == typeAnnotatedFrame?.getLocal(it.index)?.type?.sort
}.forEach {
frame.markAlive(it.index)
}
frame.markAlive(it.index)
}
if (insn is VarInsnNode && insn.isLoadOperation()) {
frame.markAlive(insn.`var`)

View File

@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.serialization.DescriptorSerializer
@@ -47,6 +48,21 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta
override val metadataVersion = state.metadataVersion
override fun shouldUseTypeTable(): Boolean = useTypeTable
override fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean {
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
}
override fun shouldSerializeProperty(descriptor: PropertyDescriptor): Boolean {
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
}
override fun shouldSerializeTypeAlias(descriptor: TypeAliasDescriptor): Boolean {
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
}
override fun shouldSerializeNestedClass(descriptor: ClassDescriptor): Boolean {
return classBuilderMode != ClassBuilderMode.ABI || !descriptor.isEffectivelyPrivateApi
}
override fun serializeClass(
descriptor: ClassDescriptor,
@@ -103,7 +119,7 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta
for (localVariable in localVariables) {
val propertyDescriptor = createFreeFakeLocalPropertyDescriptor(localVariable)
val serializer = DescriptorSerializer.createForLambda(this)
proto.addExtension(extension, serializer.propertyProto(propertyDescriptor).build())
proto.addExtension(extension, serializer.propertyProto(propertyDescriptor)?.build() ?: continue)
}
}

View File

@@ -73,7 +73,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
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.BindingContextUtils.isBoxedLocalCapturedInClosure;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
@@ -1870,7 +1870,7 @@ public class KotlinTypeMapper {
return null;
}
if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
if (descriptor instanceof VariableDescriptor && isBoxedLocalCapturedInClosure(bindingContext, descriptor)) {
return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
}

View File

@@ -27,7 +27,7 @@ abstract class CommonToolArguments : Freezable(), Serializable {
var freeArgs: List<String> by FreezableVar(emptyList())
@Transient
var errors: ArgumentParseErrors = ArgumentParseErrors()
var errors: ArgumentParseErrors? = null
@Argument(value = "-help", shortName = "-h", description = "Print a synopsis of standard options")
var help: Boolean by FreezableVar(false)

View File

@@ -38,12 +38,12 @@ private const val ADVANCED_ARGUMENT_PREFIX = "-X"
private const val FREE_ARGS_DELIMITER = "--"
data class ArgumentParseErrors(
val unknownArgs: MutableList<String> = SmartList<String>(),
val unknownArgs: MutableList<String> = SmartList(),
val unknownExtraFlags: MutableList<String> = SmartList<String>(),
val unknownExtraFlags: MutableList<String> = SmartList(),
// Names of extra (-X...) arguments which have been passed in an obsolete form ("-Xaaa bbb", instead of "-Xaaa=bbb")
val extraArgumentsPassedInObsoleteForm: MutableList<String> = SmartList<String>(),
val extraArgumentsPassedInObsoleteForm: MutableList<String> = SmartList(),
// Non-boolean arguments which have been passed multiple times, possibly with different values.
// The key in the map is the name of the argument, the value is the last passed value.
@@ -62,11 +62,12 @@ data class ArgumentParseErrors(
// Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors].
fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, result: A) {
val preprocessed = preprocessCommandLineArguments(args, result.errors)
parsePreprocessedCommandLineArguments(preprocessed, result)
val errors = result.errors ?: ArgumentParseErrors().also { result.errors = it }
val preprocessed = preprocessCommandLineArguments(args, errors)
parsePreprocessedCommandLineArguments(preprocessed, result, errors)
}
private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args: List<String>, result: A) {
private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args: List<String>, result: A, errors: ArgumentParseErrors) {
data class ArgumentField(val property: KMutableProperty1<A, Any?>, val argument: Argument)
@Suppress("UNCHECKED_CAST")
@@ -76,7 +77,6 @@ private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args
ArgumentField(property as KMutableProperty1<A, Any?>, argument)
}
val errors = result.errors
val visitedArgs = mutableSetOf<String>()
var freeArgsStarted = false
@@ -198,7 +198,8 @@ private fun <A : CommonToolArguments> updateField(property: KMutableProperty1<A,
/**
* @return error message if arguments are parsed incorrectly, null otherwise
*/
fun validateArguments(errors: ArgumentParseErrors): String? {
fun validateArguments(errors: ArgumentParseErrors?): String? {
if (errors == null) return null
if (errors.argumentWithoutValue != null) {
return "No value passed for argument ${errors.argumentWithoutValue}"
}

View File

@@ -118,7 +118,10 @@ abstract class CLITool<A : CommonToolArguments> {
}
private fun reportArgumentParseProblems(collector: MessageCollector, arguments: A) {
val errors = arguments.errors
reportUnsafeInternalArgumentsIfAny(arguments, collector)
val errors = arguments.errors ?: return
for (flag in errors.unknownExtraFlags) {
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
}
@@ -139,7 +142,6 @@ abstract class CLITool<A : CommonToolArguments> {
collector.report(STRONG_WARNING, argfileError)
}
reportUnsafeInternalArgumentsIfAny(arguments, collector)
for (internalArgumentsError in errors.internalArgumentsParsingProblems) {
collector.report(STRONG_WARNING, internalArgumentsError)
}

View File

@@ -28,6 +28,7 @@ import gnu.trove.THashSet
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
@@ -81,7 +82,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
val (classId, classFileContentFromRequest, outerClassFromRequest) = request
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
if (useFastClassFilesReading && virtualFile.extension == "class") {
@@ -92,13 +96,20 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
// This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary
// When it become wrong because we introduce the modules into CLI, it's worth to consider
// having different KotlinCliJavaFileManagerImpl's for different modules
val classContent = virtualFile.contentsToByteArray()
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
classId.outerClassId?.let { outerClassId ->
val outerClass = findClass(outerClassId, searchScope)
return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
val outerClass = outerClassFromRequest ?: findClass(outerClassId, searchScope)
return if (outerClass is BinaryJavaClass)
outerClass.findInnerClass(classId.shortClassName, classFileContentFromRequest)
else
outerClass?.findInnerClass(classId.shortClassName)
}
// Here, we assume the class is top-level
val classContent = classFileContentFromRequest ?: virtualFile.contentsToByteArray()
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(

View File

@@ -22,7 +22,6 @@ import com.intellij.codeInsight.InferredAnnotationsManager
import com.intellij.codeInsight.runner.JavaMainMethodProvider
import com.intellij.core.*
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.MetaLanguage
import com.intellij.lang.java.JavaParserDefinition
import com.intellij.openapi.Disposable
@@ -69,6 +68,7 @@ import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PRO
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
@@ -241,16 +241,13 @@ class KotlinCoreEnvironment private constructor(
}
sourceFiles += createKtFiles(project)
sourceFiles.sortBy { it.virtualFile.path }
if (scriptDefinitionProvider != null) {
ScriptDependenciesProvider.getInstance(project).let { importsProvider ->
configuration.addJvmClasspathRoots(
sourceFiles.mapNotNull(importsProvider::getScriptDependencies)
.flatMap { it.classpath }
.distinctBy { it.absolutePath })
}
val (classpath, newSources, _) = collectScriptsCompilationDependencies(configuration, project, sourceFiles)
configuration.addJvmClasspathRoots(classpath)
sourceFiles += newSources
}
sourceFiles.sortBy { it.virtualFile.path }
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
@@ -427,58 +424,10 @@ class KotlinCoreEnvironment private constructor(
fun getSourceFiles(): List<KtFile> = sourceFiles
private fun createKtFiles(project: Project): List<KtFile> {
val sourceRoots = getSourceRootsCheckingForDuplicates()
private fun createKtFiles(project: Project): List<KtFile> =
createSourceFilesFromSourceRoots(configuration, project, getSourceRootsCheckingForDuplicates())
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val psiManager = PsiManager.getInstance(project)
val processedFiles = hashSetOf<VirtualFile>()
val result = mutableListOf<KtFile>()
val virtualFileCreator = PreprocessedFileCreator(project)
for ((sourceRootPath, isCommon) in sourceRoots) {
val vFile = localFileSystem.findFileByPath(sourceRootPath)
if (vFile == null) {
val message = "Source file or directory not found: $sourceRootPath"
val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
if (buildFilePath != null && Logger.isInitialized()) {
LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
}
report(ERROR, message)
continue
}
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
report(ERROR, "Source entry is not a Kotlin file: $sourceRootPath")
continue
}
for (file in File(sourceRootPath).walkTopDown()) {
if (!file.isFile) continue
val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
if (virtualFile != null && processedFiles.add(virtualFile)) {
val psiFile = psiManager.findFile(virtualFile)
if (psiFile is KtFile) {
result.add(psiFile)
if (isCommon) {
psiFile.isCommonSource = true
}
}
}
}
}
return result
}
private fun report(severity: CompilerMessageSeverity, message: String) {
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message)
}
internal fun report(severity: CompilerMessageSeverity, message: String) = report(configuration, severity, message)
companion object {
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
@@ -531,6 +480,67 @@ class KotlinCoreEnvironment private constructor(
// used in the daemon for jar cache cleanup
val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
internal fun report(
configuration: CompilerConfiguration,
severity: CompilerMessageSeverity,
message: String,
location: CompilerMessageLocation? = null
) {
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message, location)
}
internal fun createSourceFilesFromSourceRoots(
configuration: CompilerConfiguration,
project: Project,
sourceRoots: List<KotlinSourceRoot>,
reportLocation: CompilerMessageLocation? = null
): MutableList<KtFile> {
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val psiManager = PsiManager.getInstance(project)
val processedFiles = hashSetOf<VirtualFile>()
val result = mutableListOf<KtFile>()
val virtualFileCreator = PreprocessedFileCreator(project)
for ((sourceRootPath, isCommon) in sourceRoots) {
val vFile = localFileSystem.findFileByPath(sourceRootPath)
if (vFile == null) {
val message = "Source file or directory not found: $sourceRootPath"
val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
if (buildFilePath != null && Logger.isInitialized()) {
KotlinCoreEnvironment.LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
}
report(configuration, ERROR, message, reportLocation)
continue
}
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
report(configuration, ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation)
continue
}
for (file in File(sourceRootPath).walkTopDown()) {
if (!file.isFile) continue
val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
if (virtualFile != null && processedFiles.add(virtualFile)) {
val psiFile = psiManager.findFile(virtualFile)
if (psiFile is KtFile) {
result.add(psiFile)
if (isCommon) {
psiFile.isCommonSource = true
}
}
}
}
}
return result
}
private fun getOrCreateApplicationEnvironmentForProduction(configuration: CompilerConfiguration): JavaCoreApplicationEnvironment {
synchronized(APPLICATION_LOCK) {
if (ourApplicationEnvironment != null)
@@ -701,3 +711,4 @@ class KotlinCoreEnvironment private constructor(
}
}
}

View File

@@ -267,7 +267,7 @@ object KotlinToJVMBytecodeCompiler {
}
}
internal fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List<String>): ExitCode {
fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List<String>): ExitCode {
val scriptClass = compileScript(environment) ?: return ExitCode.COMPILATION_ERROR
try {

View File

@@ -0,0 +1,77 @@
/*
* 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.cli.jvm.compiler
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
import java.io.File
data class ScriptsCompilationDependencies(
val classpath: List<File>,
val sources: List<KtFile>,
val sourceDependencies: List<SourceDependencies>
) {
data class SourceDependencies(
val scriptFile: KtFile,
val sourceDependencies: List<KtFile>
)
}
// recursively collect dependencies from initial and imported scripts
fun collectScriptsCompilationDependencies(
configuration: CompilerConfiguration,
project: Project,
initialSources: Iterable<KtFile>
): ScriptsCompilationDependencies {
val collectedClassPath = ArrayList<File>()
val collectedSources = ArrayList<KtFile>()
val collectedSourceDependencies = ArrayList<ScriptsCompilationDependencies.SourceDependencies>()
var remainingSources = initialSources
val knownSourcePaths = initialSources.mapNotNullTo(HashSet()) { it.virtualFile?.path }
val importsProvider = ScriptDependenciesProvider.getInstance(project)
while (true) {
val newRemainingSources = ArrayList<KtFile>()
for (source in remainingSources) {
val dependencies = importsProvider.getScriptDependencies(source)
if (dependencies != null) {
collectedClassPath.addAll(dependencies.classpath)
val sourceDependenciesRoots = dependencies.scripts.map {
KotlinSourceRoot(it.path, false)
}
val sourceDependencies =
KotlinCoreEnvironment.createSourceFilesFromSourceRoots(
configuration, project, sourceDependenciesRoots,
// TODO: consider receiving and using precise location from the resolver in the future
source.virtualFile?.path?.let { CompilerMessageLocation.create(it) }
)
if (sourceDependencies.isNotEmpty()) {
collectedSourceDependencies.add(ScriptsCompilationDependencies.SourceDependencies(source, sourceDependencies))
val newSources = sourceDependencies.filterNot { knownSourcePaths.contains(it.virtualFile.path) }
for (newSource in newSources) {
collectedSources.add(newSource)
newRemainingSources.add(newSource)
knownSourcePaths.add(newSource.virtualFile.path)
}
}
}
}
if (newRemainingSources.isEmpty()) break
else {
remainingSources = newRemainingSources
}
}
return ScriptsCompilationDependencies(
collectedClassPath.distinctBy { it.absolutePath },
collectedSources,
collectedSourceDependencies
)
}

View File

@@ -91,6 +91,7 @@ object TopDownAnalyzerFacadeForJVM {
val analysisHandlerExtensions = AnalysisHandlerExtension.getInstances(project)
fun invokeExtensionsOnAnalysisComplete(): AnalysisResult? {
container.get<JavaClassesTracker>().onCompletedAnalysis(module)
for (extension in analysisHandlerExtensions) {
val result = extension.analysisCompleted(project, module, trace, files)
if (result != null) return result
@@ -108,7 +109,6 @@ object TopDownAnalyzerFacadeForJVM {
}
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
container.get<JavaClassesTracker>().onCompletedAnalysis(module)
invokeExtensionsOnAnalysisComplete()?.let { return it }

View File

@@ -76,7 +76,7 @@ object PluginCliParser {
private fun processPluginOptions(
pluginOptions: Iterable<String>?,
configuration: CompilerConfiguration,
classLoader: ClassLoader
classLoader: URLClassLoader
) {
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
@@ -84,7 +84,7 @@ object PluginCliParser {
} ?: mapOf()
// TODO issue a warning on using deprecated command line processors when all official plugin migrate to the newer convention
val commandLineProcessors = ServiceLoader.load(CommandLineProcessor::class.java, classLoader)
val commandLineProcessors = ServiceLoaderLite.loadImplementations(CommandLineProcessor::class.java, classLoader)
for (processor in commandLineProcessors) {
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }

View File

@@ -11,7 +11,10 @@ import java.lang.Character.isJavaIdentifierPart
import java.lang.Character.isJavaIdentifierStart
import java.lang.IllegalArgumentException
import java.lang.RuntimeException
import java.lang.UnsupportedOperationException
import java.net.URLClassLoader
import java.nio.file.FileSystemNotFoundException
import java.nio.file.Paths
import java.util.zip.ZipFile
/**
@@ -32,9 +35,13 @@ object ServiceLoaderLite {
*/
fun <Service> loadImplementations(service: Class<out Service>, classLoader: URLClassLoader): List<Service> {
val files = classLoader.urLs.map { url ->
if (url.protocol.toLowerCase() != "file") throw IllegalArgumentException("Only local files are supported, got $url")
val path = url.path.takeIf { it.isNotEmpty() } ?: throw IllegalArgumentException("Path is empty for $url")
File(path)
try {
Paths.get(url.toURI()).toFile()
} catch (e: FileSystemNotFoundException) {
throw IllegalArgumentException("Only local URLs are supported, got ${url.protocol}")
} catch (e: UnsupportedOperationException) {
throw IllegalArgumentException("Only local URLs are supported, got ${url.protocol}")
}
}
val implementations = mutableListOf<Service>()

View File

@@ -200,6 +200,7 @@ messages/**)
-keep class org.jetbrains.org.objectweb.asm.tree.FieldNode { *; }
-keep class org.jetbrains.org.objectweb.asm.tree.ParameterNode { *; }
-keep class org.jetbrains.org.objectweb.asm.tree.TypeAnnotationNode { *; }
-keep class org.jetbrains.org.objectweb.asm.tree.InsnList { *; }
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureReader { *; }
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureVisitor { *; }
@@ -236,6 +237,9 @@ messages/**)
# for kapt
-keep class com.intellij.openapi.project.Project { *; }
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
}
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
@@ -245,3 +249,6 @@ messages/**)
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
-keep class net.jpountz.lz4.* { *; }
# used in LazyScriptDescriptor
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }

View File

@@ -219,6 +219,9 @@ messages/**)
# for kapt
-keep class com.intellij.openapi.project.Project { *; }
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
}
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
@@ -228,3 +231,6 @@ messages/**)
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
-keep class net.jpountz.lz4.* { *; }
# used in LazyScriptDescriptor
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }

View File

@@ -237,6 +237,9 @@ messages/**)
# for kapt
-keep class com.intellij.openapi.project.Project { *; }
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
}
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
@@ -246,3 +249,6 @@ messages/**)
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
-keep class net.jpountz.lz4.* { *; }
# used in LazyScriptDescriptor
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }

View File

@@ -220,6 +220,9 @@ messages/**)
# for kapt
-keep class com.intellij.openapi.project.Project { *; }
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
}
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
@@ -227,3 +230,6 @@ messages/**)
# remove when KT-18563 would be fixed
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
# used in LazyScriptDescriptor
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }

View File

@@ -237,6 +237,9 @@ messages/**)
# for kapt
-keep class com.intellij.openapi.project.Project { *; }
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
}
-keepclassmembers class com.intellij.util.PathUtil {
public static java.lang.String getJarPathForClass(java.lang.Class);
@@ -246,3 +249,6 @@ messages/**)
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
-keep class net.jpountz.lz4.* { *; }
# used in LazyScriptDescriptor
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }

View File

@@ -102,7 +102,7 @@ class StorageComponentContainer(private val id: String, parent: StorageComponent
override fun <T> create(request: Class<T>): T {
val constructorBinding = request.bindToConstructor(unknownContext)
val args = constructorBinding.argumentDescriptors.map { it.getValue() }.toTypedArray()
return constructorBinding.constructor.newInstance(*args) as T
return runWithUnwrappingInvocationException { constructorBinding.constructor.newInstance(*args) as T }
}
override fun toString() = "Container $id"

View File

@@ -20,7 +20,7 @@ import java.lang.reflect.Constructor
import java.lang.reflect.Member
import java.lang.reflect.Method
import java.lang.reflect.Type
import java.util.ArrayList
import java.util.*
interface ValueResolver {
fun resolve(request: Type, context: ValueResolveContext): ValueDescriptor?
@@ -45,7 +45,7 @@ class ConstructorBinding(val constructor: Constructor<*>, val argumentDescriptor
class MethodBinding(val method: Method, private val argumentDescriptors: List<ValueDescriptor>) {
fun invoke(instance: Any) {
val arguments = computeArguments(argumentDescriptors).toTypedArray()
method.invoke(instance, *arguments)
runWithUnwrappingInvocationException { method.invoke(instance, *arguments) }
}
}

View File

@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.container
import java.io.Closeable
import java.lang.reflect.Type
import java.util.ArrayList
import java.util.*
enum class ComponentState {
Null,
@@ -131,7 +131,7 @@ open class SingletonTypeComponentDescriptor(container: ComponentContainer, val k
val constructor = binding.constructor
val arguments = computeArguments(binding.argumentDescriptors)
val instance = constructor.newInstance(*arguments.toTypedArray())!!
val instance = runWithUnwrappingInvocationException { constructor.newInstance(*arguments.toTypedArray())!! }
state = ComponentState.Initialized
return instance
}
@@ -154,4 +154,4 @@ class DefaultSingletonTypeComponentDescriptor(container: ComponentContainer, kla
override fun toString(): String {
return "Default: ${klass.simpleName}"
}
}
}

View File

@@ -0,0 +1,15 @@
/*
* 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.container
import java.lang.reflect.InvocationTargetException
inline fun <T> runWithUnwrappingInvocationException(block: () -> T) =
try {
block()
} catch (e: InvocationTargetException) {
throw e.targetException ?: e
}

View File

@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.java.symbols.JavaClassSymbol
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
@@ -38,7 +39,7 @@ class JavaSymbolProvider(val project: Project) : FirSymbolProvider {
override fun getSymbolByFqName(classId: ClassId): ConeSymbol? {
return classCache.lookupCacheOrCalculate(classId) {
val facade = KotlinJavaPsiFacade.getInstance(project)
val foundClass = facade.findClass(classId, allScope)
val foundClass = facade.findClass(JavaClassFinder.Request(classId), allScope)
foundClass?.let { javaClass -> JavaClassSymbol(javaClass) }
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.fir.visitors

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.fir.visitors

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.fir.visitors

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
@@ -33,10 +32,10 @@ class JavaClassFinderImpl : AbstractJavaClassFinder() {
super.initialize(trace, codeAnalyzer)
}
override fun findClass(classId: ClassId): JavaClass? = javaFacade.findClass(classId, javaSearchScope)
override fun findClass(request: JavaClassFinder.Request): JavaClass? = javaFacade.findClass(request, javaSearchScope)
override fun findPackage(fqName: FqName) = javaFacade.findPackage(fqName.asString(), javaSearchScope)?.let { JavaPackageImpl(it, javaSearchScope) }
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String>? = javaFacade.knownClassNamesInPackage(packageFqName)
}
}

View File

@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.load.java.structure.impl;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiAnnotationMethod;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
import org.jetbrains.kotlin.load.java.structure.JavaType;
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter;
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.load.java.structure.*;
import org.jetbrains.kotlin.name.Name;
import java.util.List;
@@ -57,9 +56,17 @@ public class JavaMethodImpl extends JavaMemberImpl<PsiMethod> implements JavaMet
}
@Override
public boolean getHasAnnotationParameterDefaultValue() {
@Nullable
public JavaAnnotationArgument getAnnotationParameterDefaultValue() {
PsiMethod psiMethod = getPsi();
return psiMethod instanceof PsiAnnotationMethod && ((PsiAnnotationMethod) psiMethod).getDefaultValue() != null;
if (psiMethod instanceof PsiAnnotationMethod) {
PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) psiMethod).getDefaultValue();
if (defaultValue != null) {
return JavaAnnotationArgumentImpl.Factory.create(defaultValue, null);
}
}
return null;
}
@Override

View File

@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.*
import java.lang.reflect.Array
@@ -37,11 +36,10 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
private var visibleAnnotableParameterCount = parametersCountInMethodDesc
private var invisibleAnnotableParameterCount = parametersCountInMethodDesc
override fun visitAnnotationDefault(): AnnotationVisitor? {
member.safeAs<BinaryJavaMethod>()?.hasAnnotationParameterDefaultValue = true
// We don't store default value in Java model
return null
}
override fun visitAnnotationDefault(): AnnotationVisitor? =
BinaryJavaAnnotationVisitor(context, signatureParser) {
member.safeAs<BinaryJavaMethod>()?.annotationParameterDefaultValue = it
}
override fun visitParameter(name: String?, access: Int) {
if (name != null) {
@@ -165,19 +163,26 @@ class BinaryJavaAnnotation private constructor(
}
class BinaryJavaAnnotationVisitor(
private val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
private val arguments: MutableCollection<JavaAnnotationArgument>
private val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
private val sink: (JavaAnnotationArgument) -> Unit
) : AnnotationVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
constructor(
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser,
arguments: MutableCollection<JavaAnnotationArgument>
) : this(context, signatureParser, { arguments.add(it) })
private fun addArgument(argument: JavaAnnotationArgument?) {
arguments.addIfNotNull(argument)
if (argument != null) {
sink(argument)
}
}
override fun visitAnnotation(name: String?, desc: String): AnnotationVisitor {
val (annotation, visitor) =
BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser)
val (annotation, visitor) = BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser)
arguments.add(PlainJavaAnnotationAsAnnotationArgument(name, annotation))
sink(PlainJavaAnnotationAsAnnotationArgument(name, annotation))
return visitor
}

View File

@@ -31,13 +31,13 @@ import java.text.CharacterIterator
import java.text.StringCharacterIterator
class BinaryJavaClass(
override val virtualFile: VirtualFile,
override val fqName: FqName,
internal val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
override var access: Int = 0,
override val outerClass: JavaClass?,
classContent: ByteArray? = null
override val virtualFile: VirtualFile,
override val fqName: FqName,
internal val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
override var access: Int = 0,
override val outerClass: JavaClass?,
classContent: ByteArray? = null
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MapBasedJavaAnnotationOwner {
private lateinit var myInternalName: String
@@ -74,8 +74,8 @@ class BinaryJavaClass(
init {
ClassReader(classContent ?: virtualFile.contentsToByteArray()).accept(
this,
ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
this,
ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
)
}
@@ -115,20 +115,19 @@ class BinaryJavaClass(
}
override fun visit(
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
this.access = this.access or access
this.myInternalName = name
if (signature != null) {
parseClassSignature(signature)
}
else {
} else {
this.typeParameters = emptyList()
this.supertypes = mutableListOf<JavaClassifierType>().apply {
addIfNotNull(superName?.convertInternalNameToClassifierType())
@@ -142,9 +141,9 @@ class BinaryJavaClass(
private fun parseClassSignature(signature: String) {
val iterator = StringCharacterIterator(signature)
this.typeParameters =
signatureParser
.parseTypeParametersDeclaration(iterator, context)
.also(context::addTypeParameters)
signatureParser
.parseTypeParametersDeclaration(iterator, context)
.also(context::addTypeParameters)
val supertypes = ContainerUtil.newSmartList<JavaClassifierType>()
supertypes.addIfNotNull(signatureParser.parseClassifierRefSignature(iterator, context))
@@ -155,7 +154,7 @@ class BinaryJavaClass(
}
private fun String.convertInternalNameToClassifierType(): JavaClassifierType =
PlainJavaClassifierType({ context.resolveByInternalName(this) }, emptyList())
PlainJavaClassifierType({ context.resolveByInternalName(this) }, emptyList())
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
if (access.isSet(Opcodes.ACC_SYNTHETIC)) return null
@@ -169,13 +168,13 @@ class BinaryJavaClass(
object : FieldVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean) =
if (typePath == null)
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
else
null
if (typePath == null)
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
else
null
}
}
}
@@ -187,7 +186,7 @@ class BinaryJavaClass(
if (fieldType !is JavaPrimitiveType || fieldType.type == null || value !is Int) return value
return when (fieldType.type) {
PrimitiveType.BOOLEAN -> {
PrimitiveType.BOOLEAN -> {
when (value) {
0 -> false
1 -> true
@@ -200,13 +199,18 @@ class BinaryJavaClass(
}
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
override fun findInnerClass(name: Name): JavaClass? {
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
fun findInnerClass(name: Name, classFileContent: ByteArray?): JavaClass? {
val access = ownInnerClassNameToAccess[name] ?: return null
return virtualFile.parent.findChild("${virtualFile.nameWithoutExtension}$$name.class")?.let {
BinaryJavaClass(it, fqName.child(name), context.copyForMember(), signatureParser, access, this)
BinaryJavaClass(
it, fqName.child(name), context.copyForMember(), signatureParser, access, this,
classFileContent
)
}
}
}

View File

@@ -169,7 +169,15 @@ class BinaryJavaMethod(
) : BinaryJavaMethodBase(
flags, containingClass, valueParameters, typeParameters, name
), JavaMethod {
override var hasAnnotationParameterDefaultValue: Boolean = false
override var annotationParameterDefaultValue: JavaAnnotationArgument? = null
internal set(value) {
if (field != null) {
throw AssertionError(
"Annotation method cannot have two default values: $this (old=$field, new=$value)"
)
}
field = value
}
}
class BinaryJavaConstructor(

View File

@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaModifierListOwner
import org.jetbrains.kotlin.load.java.structure.MapBasedJavaAnnotationOwner
import org.jetbrains.org.objectweb.asm.Opcodes
internal val ASM_API_VERSION_FOR_CLASS_READING = Opcodes.ASM5
internal const val ASM_API_VERSION_FOR_CLASS_READING = Opcodes.API_VERSION
internal interface BinaryJavaModifierListOwner : JavaModifierListOwner, MapBasedJavaAnnotationOwner {
val access: Int

View File

@@ -85,7 +85,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
// TODO public to be accessible in companion object of subclass, workaround for KT-3974
@Nullable
public static <T extends FileBasedKotlinClass> T create(
public static <T> T create(
@NotNull byte[] fileContents,
@NotNull Function4<ClassId, Integer, KotlinClassHeader, InnerClassesInfo, T> factory
) {

View File

@@ -28,14 +28,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -53,7 +56,9 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
if (file.name == PsiJavaModule.MODULE_INFO_CLS_FILE) return null
@@ -62,7 +67,7 @@ class KotlinBinaryClassCache : Disposable {
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {

View File

@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {

View File

@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {

View File

@@ -27,12 +27,12 @@ import org.jetbrains.kotlin.utils.sure
abstract class VirtualFileFinder : KotlinClassFinder {
abstract fun findVirtualFileWithHeader(classId: ClassId): VirtualFile?
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? {
val file = findVirtualFileWithHeader(classId) ?: return null
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
}
override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? {
override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? {
var file = (javaClass as? VirtualFileBoundJavaClass)?.virtualFile ?: return null
if (javaClass.outerClass != null) {
@@ -41,7 +41,7 @@ abstract class VirtualFileFinder : KotlinClassFinder {
file = file.parent!!.findChild(classFileName(javaClass) + ".class").sure { "Virtual file not found for $javaClass" }
}
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
}
private fun classFileName(jClass: JavaClass): String {

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.util.PerformanceCounter
@@ -56,17 +57,19 @@ class VirtualFileKotlinClass private constructor(
private val perfCounter = PerformanceCounter.create("Binary class from Kotlin file")
@Deprecated("Use KotlinBinaryClassCache")
fun create(file: VirtualFile, fileContent: ByteArray?): VirtualFileKotlinClass? {
fun create(file: VirtualFile, fileContent: ByteArray?): KotlinClassFinder.Result? {
return perfCounter.time {
assert(file.fileType == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
try {
val byteContent = fileContent ?: file.contentsToByteArray(false)
if (!byteContent.isEmpty()) {
return@time FileBasedKotlinClass.create(byteContent) {
name, classVersion, header, innerClasses ->
val kotlinJvmBinaryClass = FileBasedKotlinClass.create(byteContent) { name, classVersion, header, innerClasses ->
VirtualFileKotlinClass(file, name, classVersion, header, innerClasses)
}
return@time kotlinJvmBinaryClass?.let(::KotlinClass)
?: KotlinClassFinder.Result.ClassFileContent(byteContent)
}
}
catch (e: FileNotFoundException) {

View File

@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.load.kotlin.findKotlinClass
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil

View File

@@ -87,5 +87,5 @@ fun getSourceElement(descriptor: DeclarationDescriptor): SourceElement =
descriptor.toSourceElement
}
private val DeclarationDescriptor.toSourceElement: SourceElement
val DeclarationDescriptor.toSourceElement: SourceElement
get() = if (this is DeclarationDescriptorWithSource) source else SourceElement.NO_SOURCE

View File

@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.resolve.jvm
import com.intellij.psi.impl.file.impl.JavaFileManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
interface KotlinCliJavaFileManager : JavaFileManager {
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass?
fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass?
fun knownClassNamesInPackage(packageFqName: FqName): Set<String>?
}

View File

@@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.KtLightClassMarker;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jetbrains.kotlin.load.java.JavaClassFinder;
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl;
import org.jetbrains.kotlin.load.java.structure.JavaClass;
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl;
@@ -104,9 +105,10 @@ public class KotlinJavaPsiFacade {
return emptyModifierList;
}
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
ClassId classId = request.getClassId();
String qualifiedName = classId.asSingleFqName().asString();
if (shouldUseSlowResolve()) {
@@ -119,7 +121,7 @@ public class KotlinJavaPsiFacade {
for (KotlinPsiElementFinderWrapper finder : finders()) {
if (finder instanceof CliFinder) {
JavaClass aClass = ((CliFinder) finder).findClass(classId, scope);
JavaClass aClass = ((CliFinder) finder).findClass(request, scope);
if (aClass != null) return aClass;
}
else {
@@ -383,8 +385,8 @@ public class KotlinJavaPsiFacade {
return javaFileManager.findClass(qualifiedName, scope);
}
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
return javaFileManager.findClass(classId, scope);
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
return javaFileManager.findClass(request, scope);
}
@Nullable

View File

@@ -0,0 +1,50 @@
/*
* 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.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtBinaryExpression
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.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.util.OperatorNameConventions
/**
* This checker detects if call by operator convention to a Java method violates some expected contract:
* - "key in map" commonly resolves to an stdlib extension that calls Map.containsKey(),
* but there's a member in ConcurrentHashMap with acceptable signature that delegates to `containsValue` instead
*/
object InconsistentOperatorFromJavaCallChecker : CallChecker {
private val CONCURRENT_HASH_MAP_FQ_NAME = FqName("java.util.concurrent.ConcurrentHashMap")
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val candidateDescriptor = resolvedCall.candidateDescriptor
if (candidateDescriptor.name != OperatorNameConventions.CONTAINS) return
if (candidateDescriptor.valueParameters.singleOrNull()?.type?.isAnyOrNullableAny() != true) return
if (resolvedCall.call.callElement !is KtBinaryExpression || !resolvedCall.status.possibleTransformToSuccess()) return
for (callableDescriptor in candidateDescriptor.overriddenTreeUniqueAsSequence(useOriginal = false)) {
val containingClass = callableDescriptor.containingDeclaration as? ClassDescriptor ?: continue
if (containingClass.fqNameOrNull() != CONCURRENT_HASH_MAP_FQ_NAME) continue
val diagnosticFactory =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitConcurrentHashMapContains))
ErrorsJvm.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR
else
ErrorsJvm.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
context.trace.report(diagnosticFactory.on(reportOn))
break
}
}
}

View File

@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorrespondingExpectedDefault
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
@@ -194,21 +195,34 @@ class OverloadsAnnotationChecker: DeclarationChecker {
descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
if (annotationEntry != null) {
checkDeclaration(annotationEntry, descriptor, context.trace)
checkDeclaration(annotationEntry, descriptor, context)
}
}
}
private fun checkDeclaration(annotationEntry: KtAnnotationEntry, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
private fun checkDeclaration(
annotationEntry: KtAnnotationEntry,
descriptor: DeclarationDescriptor,
context: DeclarationCheckerContext
) {
val diagnosticHolder = context.trace
if (descriptor !is CallableDescriptor) {
return
}
if ((descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE) {
} else if ((descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_INTERFACE.on(annotationEntry))
} else if (descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(annotationEntry))
} else if (DescriptorUtils.isLocal(descriptor)) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_LOCAL.on(annotationEntry))
} else if (descriptor.isAnnotationConstructor()) {
val diagnostic =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses))
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
else
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING
diagnosticHolder.report(diagnostic.on(annotationEntry))
} else if (!descriptor.visibility.isPublicAPI && descriptor.visibility != Visibilities.INTERNAL) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(annotationEntry))
} else if (descriptor.valueParameters.none { it.declaresDefaultValue() || it.isActualParameterWithCorrespondingExpectedDefault }) {

View File

@@ -50,6 +50,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(OVERLOADS_INTERFACE, "'@JvmOverloads' annotation cannot be used on interface methods");
MAP.put(OVERLOADS_PRIVATE, "'@JvmOverloads' annotation has no effect on private declarations");
MAP.put(OVERLOADS_LOCAL, "'@JvmOverloads' annotation cannot be used on local declarations");
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING, "'@JvmOverloads' annotation on constructors of annotation classes is deprecated");
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR, "'@JvmOverloads' annotation cannot be used on constructors of annotation classes");
MAP.put(INAPPLICABLE_JVM_NAME, "'@JvmName' annotation is not applicable to this declaration");
MAP.put(ILLEGAL_JVM_NAME, "Illegal JVM name");
MAP.put(VOLATILE_ON_VALUE, "'@Volatile' annotation cannot be used on immutable properties");
@@ -138,6 +140,13 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(EXPLICIT_METADATA_IS_DISALLOWED, "Explicit @Metadata is disallowed");
MAP.put(SUSPENSION_POINT_INSIDE_MONITOR, "A suspension point at {0} is inside a critical section", STRING);
MAP.put(SUSPENSION_POINT_INSIDE_SYNCHRONIZED, "The ''{0}'' suspension point is inside a synchronized block", NAME);
String MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS =
"Method 'contains' from ConcurrentHashMap may have unexpected semantics: it calls 'containsValue' instead of 'containsKey'. " +
"Use explicit form of the call to 'containsKey'/'containsValue'/'contains' or cast the value to kotlin.collections.Map instead. " +
"See https://youtrack.jetbrains.com/issue/KT-18053 for more details";
MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS);
MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS);
}
@NotNull

View File

@@ -54,6 +54,9 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_PRIVATE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_LOCAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, ABSTRACT_MODIFIER);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_HAVE_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
@@ -125,6 +128,9 @@ public interface ErrorsJvm {
DiagnosticFactory1<PsiElement, String> SUSPENSION_POINT_INSIDE_MONITOR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, CallableDescriptor> SUSPENSION_POINT_INSIDE_SYNCHRONIZED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> CONCURRENT_HASH_MAP_CONTAINS_OPERATOR = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR = DiagnosticFactory0.create(ERROR);
@SuppressWarnings("UnusedDeclaration")
Object _initializer = new Object() {
{

View File

@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.resolve.jvm.multiplatform
import com.intellij.psi.PsiAnnotationMethod
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluatorImpl
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationArgumentImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
@@ -23,11 +22,10 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
class JavaActualAnnotationArgumentExtractor : ExpectedActualDeclarationChecker.ActualAnnotationArgumentExtractor {
override fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>? =
(argument as? PsiAnnotationMethod)
?.defaultValue
?.let { JavaAnnotationArgumentImpl.create(it, null) }
?.convert(expectedType)
override fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>? {
val element = (parameter.source as? JavaSourceElement)?.javaElement
return (element as? JavaMethod)?.annotationParameterDefaultValue?.convert(expectedType)
}
// This code is similar to LazyJavaAnnotationDescriptor.resolveAnnotationArgument, but cannot be reused until
// KClassValue/AnnotationValue are untied from descriptors/types, because here we do not have an instance of LazyJavaResolverContext.

View File

@@ -50,7 +50,8 @@ object JvmPlatformConfigurator : PlatformConfigurator(
ProtectedSyntheticExtensionCallChecker,
ReifiedTypeParameterSubstitutionChecker(),
RuntimeAssertionsOnExtensionReceiverCallChecker,
ApiVersionIsAtLeastArgumentsChecker
ApiVersionIsAtLeastArgumentsChecker,
InconsistentOperatorFromJavaCallChecker
),
additionalTypeCheckers = listOf(

View File

@@ -92,7 +92,7 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor, SyntheticPropert
}
}
class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val lookupTracker: LookupTracker) : SyntheticScope {
class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val lookupTracker: LookupTracker) : SyntheticScope.Default() {
private val syntheticPropertyInClass =
storageManager.createMemoizedFunction<Pair<ClassDescriptor, Name>, SyntheticPropertyHolder> { pair ->
syntheticPropertyInClassNotCached(pair.first, pair.second)
@@ -205,18 +205,6 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
}
}
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
emptyList()
override fun getSyntheticConstructors(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
emptyList()
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor> = emptyList()
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> = emptyList()
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? = null
private fun collectSyntheticPropertiesByName(
result: SmartList<PropertyDescriptor>?,
type: TypeConstructor,
@@ -239,7 +227,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
return result
}
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> {
override fun getSyntheticExtensionProperties(
receiverTypes: Collection<KotlinType>,
location: LookupLocation
): Collection<PropertyDescriptor> {
val result = ArrayList<PropertyDescriptor>()
val processedTypes = HashSet<TypeConstructor>()
receiverTypes.forEach { result.collectSyntheticProperties(it.constructor, processedTypes) }

View File

@@ -16,25 +16,46 @@
package org.jetbrains.kotlin.synthetic
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager
class JavaSyntheticScopes(
private val project: Project,
private val moduleDescriptor: ModuleDescriptor,
storageManager: StorageManager,
lookupTracker: LookupTracker,
languageVersionSettings: LanguageVersionSettings,
samConventionResolver: SamConversionResolver,
deprecationResolver: DeprecationResolver
): SyntheticScopes {
override val scopes = listOf(
JavaSyntheticPropertiesScope(storageManager, lookupTracker),
override val scopes = run {
val javaSyntheticPropertiesScope = JavaSyntheticPropertiesScope(storageManager, lookupTracker)
val scopesFromExtensions = SyntheticScopeProviderExtension
.getInstances(project)
.flatMap { it.getScopes(moduleDescriptor, javaSyntheticPropertiesScope) }
listOf(
javaSyntheticPropertiesScope,
SamAdapterFunctionsScope(
storageManager, languageVersionSettings, samConventionResolver, deprecationResolver,
lookupTracker
storageManager, languageVersionSettings, samConventionResolver, deprecationResolver,
lookupTracker
)
)
) + scopesFromExtensions
}
}
interface SyntheticScopeProviderExtension {
companion object : ProjectExtensionDescriptor<SyntheticScopeProviderExtension>(
"org.jetbrains.kotlin.syntheticScopeProviderExtension", SyntheticScopeProviderExtension::class.java)
fun getScopes(moduleDescriptor: ModuleDescriptor, javaSyntheticPropertiesScope: JavaSyntheticPropertiesScope): List<SyntheticScope>
}

View File

@@ -59,7 +59,7 @@ class SamAdapterFunctionsScope(
private val samResolver: SamConversionResolver,
private val deprecationResolver: DeprecationResolver,
private val lookupTracker: LookupTracker
) : SyntheticScope {
) : SyntheticScope.Default() {
private val samViaSyntheticScopeDisabled = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
private val extensionForFunction =
@@ -150,10 +150,6 @@ class SamAdapterFunctionsScope(
}
}
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<PropertyDescriptor> = emptyList()
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> = emptyList()
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
if (samViaSyntheticScopeDisabled) return emptyList()

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.script
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import kotlin.reflect.*
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.jvm.jvmErasure
@@ -160,18 +159,6 @@ private class StringArgsConverter : ArgsConverter<String> {
override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<String>, restArgsIt: Iterator<NamedArgument<String>>): ArgsConverter.Result {
fun convertAnyArray(classifier: KClassifier?, args: Sequence<String?>): Any? =
when (classifier) {
String::class -> args.toList().toTypedArray()
is KClass<*> -> classifier.constructors.firstNotNullResult { ctor ->
try {
args.map { ctor.call(it) }.toList().toTypedArray()
}
catch (e: Exception) { null }
}
else -> null
}
fun convertPrimitivesArray(type: KType, args: Sequence<String?>): Any? =
when (type.classifier) {
IntArray::class -> args.map { it?.toIntOrNull() }
@@ -228,9 +215,42 @@ private class AnyArgsConverter : ArgsConverter<Any> {
?: ArgsConverter.Result.Failure
}
override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>): ArgsConverter.Result =
ArgsConverter.Result.Failure
override fun tryConvertVararg(
parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>
): ArgsConverter.Result {
val parameterType = parameter.type
if (parameterType.jvmErasure.java.isArray) {
val argsSequence = sequenceOf(firstArg.value) + restArgsIt.asSequence().map { it.value }
val arrayElementType = parameterType.arguments.firstOrNull()?.type
val arrayArgCandidate = convertAnyArray(arrayElementType?.classifier, argsSequence)
if (arrayArgCandidate != null)
return ArgsConverter.Result.Success(arrayArgCandidate)
}
return ArgsConverter.Result.Failure
}
override fun tryConvertTail(parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>): ArgsConverter.Result =
tryConvertSingle(parameter, firstArg)
}
@Suppress("UNCHECKED_CAST")
private inline fun <reified T> convertAnyArray(classifier: KClassifier?, args: Sequence<T?>): Any? =
if (classifier == T::class) args.toList().toTypedArray() // simple case
else convertAnyArrayImpl<T>(classifier, args)
private fun <T> convertAnyArrayImpl(classifier: KClassifier?, args: Sequence<T?>): Any? {
val elementClass = (classifier as? KClass<*>) ?: return null
val argsList = args.toList()
val result = java.lang.reflect.Array.newInstance(elementClass.java, argsList.size)
argsList.forEachIndexed { idx, arg ->
try {
java.lang.reflect.Array.set(result, idx, arg)
} catch (e: IllegalArgumentException) {
return@convertAnyArrayImpl null
}
}
return result
}

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.cfg.TailRecursionKind.*
import org.jetbrains.kotlin.cfg.VariableUseState.*
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstruction
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
@@ -118,32 +120,69 @@ class ControlFlowInformationProvider private constructor(
markAndCheckTailCalls()
}
private fun collectReturnExpressions(returnedExpressions: MutableCollection<KtElement>) {
/**
* Collects returned expressions from current pseudocode.
*
* "Returned expression" here == "last expression" in *control-flow terms*. Intuitively,
* it considers all execution paths, takes last expression on each path and returns them.
*
* More specifically, this function starts from EXIT instruction, and performs DFS-search
* on reversed control-flow edges in a following manner:
* - if the current instruction is a Return-instruction, then add it's expression to result
* - if the current instruction is a Element-instruction, then add it's element to result
* - if the current instruction is a Jump-instruction, then process it's predecessors
* recursively
*
* NB. The second case (Element-instruction) means that notion of "returned expression"
* here differs from what the language treats as "returned expression" (notably in the
* presence of Unit-coercion). Example:
*
* fun foo() {
* val x = 42
* x.inc() // This call will be in a [returnedExpressions], even though this expression
* // isn't actually returned
* }
*/
private fun collectReturnExpressions(): ReturnedExpressionsInfo {
val instructions = pseudocode.instructions.toHashSet()
val exitInstruction = pseudocode.exitInstruction
val returnedExpressions = arrayListOf<KtElement>()
var hasReturnsInInlinedLambda = false
for (previousInstruction in exitInstruction.previousInstructions) {
previousInstruction.accept(object : InstructionVisitor() {
override fun visitReturnValue(instruction: ReturnValueInstruction) {
if (instructions.contains(instruction)) { //exclude non-local return expressions
returnedExpressions.add(instruction.element)
}
if (instruction.owner.isInlined) {
hasReturnsInInlinedLambda = true
}
}
override fun visitReturnNoValue(instruction: ReturnNoValueInstruction) {
if (instructions.contains(instruction)) {
returnedExpressions.add(instruction.element)
}
}
override fun visitJump(instruction: AbstractJumpInstruction) {
// Nothing
if (instruction.owner.isInlined) {
hasReturnsInInlinedLambda = true
}
}
override fun visitUnconditionalJump(instruction: UnconditionalJumpInstruction) {
redirectToPrevInstructions(instruction)
}
override fun visitConditionalJump(instruction: ConditionalJumpInstruction) {
redirectToPrevInstructions(instruction)
}
// Note that there's no need to overload `visitThrowException`, because
// it can never be a predecessor of EXIT (throwing always leads to ERROR)
private fun redirectToPrevInstructions(instruction: Instruction) {
for (redirectInstruction in instruction.previousInstructions) {
redirectInstruction.accept(this)
@@ -160,6 +199,9 @@ class ControlFlowInformationProvider private constructor(
override fun visitInstruction(instruction: Instruction) {
if (instruction is KtElementInstruction) {
// Caveats:
// - for empty block-bodies, read(Unit) is emitted and will be processed here
// - for Unit-coerced blocks, last expression will be processed here
returnedExpressions.add(instruction.element)
} else {
throw IllegalStateException("$instruction precedes the exit point")
@@ -167,6 +209,8 @@ class ControlFlowInformationProvider private constructor(
}
})
}
return ReturnedExpressionsInfo(returnedExpressions, hasReturnsInInlinedLambda)
}
private fun checkLocalFunctions() {
@@ -192,8 +236,7 @@ class ControlFlowInformationProvider private constructor(
if (!function.hasBody()) return
val returnedExpressions = arrayListOf<KtElement>()
collectReturnExpressions(returnedExpressions)
val (returnedExpressions, hasReturnsInInlinedLambdas) = collectReturnExpressions()
val blockBody = function.hasBlockBody()
@@ -211,17 +254,25 @@ class ControlFlowInformationProvider private constructor(
if (blockBody && !noExpectedType(expectedReturnType)
&& !KotlinBuiltIns.isUnit(expectedReturnType)
&& !unreachableCode.elements.contains(element)) {
&& !unreachableCode.elements.contains(element)
) {
noReturnError = true
}
}
})
}
if (noReturnError) {
trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(function))
if (hasReturnsInInlinedLambdas) {
trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY_MIGRATION.on(function))
} else {
trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(function))
}
}
}
private data class ReturnedExpressionsInfo(val returnedExpressions: Collection<KtElement>, val hasReturnsInInlinedLambda: Boolean)
private fun reportUnreachableCode(unreachableCode: UnreachableCode) {
for (element in unreachableCode.elements) {
trace.report(Errors.UNREACHABLE_CODE.on(element, unreachableCode.getUnreachableTextRanges(element)))

View File

@@ -28,10 +28,14 @@ import org.jetbrains.kotlin.metadata.deserialization.isInstanceType
import org.jetbrains.kotlin.serialization.deserialization.ContractDeserializer
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.TypeDeserializer
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addIfNotNull
class ContractDeserializerImpl(private val configuration: DeserializationConfiguration) : ContractDeserializer {
class ContractDeserializerImpl(
private val configuration: DeserializationConfiguration,
private val storageManager: StorageManager
) : ContractDeserializer {
override fun deserializeContractFromFunction(
proto: ProtoBuf.Function,
ownerFunction: FunctionDescriptor,
@@ -42,7 +46,7 @@ class ContractDeserializerImpl(private val configuration: DeserializationConfigu
if (!configuration.readDeserializedContracts) return null
val worker = ContractDeserializationWorker(typeTable, typeDeserializer, ownerFunction)
val worker = ContractDeserializationWorker(typeTable, typeDeserializer, ownerFunction, storageManager)
val contract = worker.deserializeContract(proto.contract)
return ContractProviderKey to LazyContractProvider.createInitialized(contract)
}
@@ -50,12 +54,13 @@ class ContractDeserializerImpl(private val configuration: DeserializationConfigu
private class ContractDeserializationWorker(
private val typeTable: TypeTable,
private val typeDeserializer: TypeDeserializer,
private val ownerFunction: FunctionDescriptor
private val ownerFunction: FunctionDescriptor,
private val storageManager: StorageManager
) {
fun deserializeContract(proto: ProtoBuf.Contract): ContractDescription? {
val effects = proto.effectList.map { deserializePossiblyConditionalEffect(it) ?: return null }
return ContractDescription(effects, ownerFunction)
return ContractDescription(effects, ownerFunction, storageManager)
}
private fun deserializePossiblyConditionalEffect(proto: ProtoBuf.Effect): EffectDeclaration? {
@@ -75,7 +80,7 @@ class ContractDeserializerImpl(private val configuration: DeserializationConfigu
val argument = proto.effectConstructorArgumentList.getOrNull(0)
val returnValue =
if (argument == null) ConstantReference.WILDCARD else deserializeExpression(argument) as? ConstantReference
?: return null
?: return null
ReturnsEffectDeclaration(returnValue)
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.contracts
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
import org.jetbrains.kotlin.contracts.interpretation.ContractInterpretationDispatcher
import org.jetbrains.kotlin.contracts.model.Computation
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
@@ -168,11 +169,8 @@ class EffectsExtractingVisitor(
}
private fun FunctionDescriptor.getFunctor(): Functor? {
trace[BindingContext.FUNCTOR, this]?.let { return it }
val functor = ContractInterpretationDispatcher().resolveFunctor(this) ?: return null
trace.record(BindingContext.FUNCTOR, this, functor)
return functor
val contractDescription = getUserData(ContractProviderKey)?.getContractDescription() ?: return null
return contractDescription.functor
}
private fun ResolvedCall<*>.isCallWithUnsupportedReceiver(): Boolean =

View File

@@ -32,8 +32,9 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.storage.StorageManager
class ContractParsingServices(val languageVersionSettings: LanguageVersionSettings) {
class ContractParsingServices(val languageVersionSettings: LanguageVersionSettings, private val storageManager: StorageManager) {
/**
* ! IMPORTANT NOTICE !
*
@@ -77,7 +78,7 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
// Small optimization: do not even try to parse contract if we already have errors
if (collector.hasErrors()) return null
val parsedContract = PsiContractParserDispatcher(collector, callContext).parseContract()
val parsedContract = PsiContractParserDispatcher(collector, callContext, storageManager).parseContract()
// Make sure that at least generic error will be reported if we couldn't parse contract
// (null returned => at least one error was reported)

View File

@@ -40,10 +40,12 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.storage.StorageManager
internal class PsiContractParserDispatcher(
private val collector: ContractParsingDiagnosticsCollector,
private val callContext: ContractCallContext
private val callContext: ContractCallContext,
private val storageManager: StorageManager
) {
private val conditionParser = PsiConditionParser(collector, callContext, this)
private val constantParser = PsiConstantParser(callContext)
@@ -71,7 +73,7 @@ internal class PsiContractParserDispatcher(
if (effects.isEmpty()) return null
return ContractDescription(effects, callContext.functionDescriptor)
return ContractDescription(effects, callContext.functionDescriptor, storageManager)
}
fun parseCondition(expression: KtExpression?): BooleanExpression? = expression?.accept(conditionParser, Unit)

View File

@@ -101,7 +101,9 @@ public interface Errors {
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_BASE_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_STANDARD_TEMPLATE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_RECEIVER_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_IMPORTED_SCRIPT_FILE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_IMPORTED_SCRIPT_PSI = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<PsiElement, String, IncompatibleVersionErrorData<?>> INCOMPATIBLE_CLASS = DiagnosticFactory2.create(ERROR);
@@ -952,6 +954,8 @@ public interface Errors {
DiagnosticFactory0<KtTypeReference> LOCAL_EXTENSION_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_GETTER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_SETTER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory3<KtExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
@@ -1014,6 +1018,8 @@ public interface Errors {
DiagnosticFactory0<KtReturnExpression> RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = DiagnosticFactory0.create(ERROR, PositioningStrategies.RETURN_WITH_LABEL);
DiagnosticFactory0<KtDeclarationWithBody>
NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_WITH_BODY);
DiagnosticFactory0<KtDeclarationWithBody>
NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY_MIGRATION = DiagnosticFactory0.create(ERROR, DECLARATION_WITH_BODY);
DiagnosticFactory0<KtAnonymousInitializer> ANONYMOUS_INITIALIZER_IN_INTERFACE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);

View File

@@ -365,7 +365,9 @@ public class DefaultErrorMessages {
MAP.put(MISSING_SCRIPT_BASE_CLASS, "Cannot access script base class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
MAP.put(MISSING_SCRIPT_STANDARD_TEMPLATE, "No script runtime was found in the classpath: class ''{0}'' not found. Please add kotlin-script-runtime.jar to the module dependencies.", TO_STRING);
MAP.put(MISSING_SCRIPT_RECEIVER_CLASS, "Cannot access implicit script receiver class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
MAP.put(MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS, "Cannot access script environment property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
MAP.put(MISSING_IMPORTED_SCRIPT_FILE, "Cannot find imported script file ''{0}''. Check your script imports", TO_STRING);
MAP.put(MISSING_IMPORTED_SCRIPT_PSI, "Imported script file ''{0}'' is not loaded. Check your script imports", TO_STRING);
MAP.put(MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS, "Cannot access script provided property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING);
MAP.put(INCOMPATIBLE_CLASS,
"{0} was compiled with an incompatible version of Kotlin. {1}",
@@ -397,6 +399,8 @@ public class DefaultErrorMessages {
MAP.put(LOCAL_EXTENSION_PROPERTY, "Local extension properties are not allowed");
MAP.put(LOCAL_VARIABLE_WITH_GETTER, "Local variables are not allowed to have getters");
MAP.put(LOCAL_VARIABLE_WITH_SETTER, "Local variables are not allowed to have setters");
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated");
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters");
MAP.put(VAL_WITH_SETTER, "A 'val'-property cannot have a setter");
MAP.put(DEPRECATED_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is deprecated", RENDER_TYPE, RENDER_TYPE);
@@ -495,6 +499,9 @@ public class DefaultErrorMessages {
MAP.put(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY,
"Returns are not allowed for functions with expression body. Use block body in '{...}'");
MAP.put(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY, "A 'return' expression required in a function with a block body ('{...}')");
MAP.put(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY_MIGRATION, "A 'return' expression required in a function with a block body ('{...}'). " +
"If you got this error after the compiler update, then it's most likely due to a fix of a bug " +
"introduced in 1.3.0 (see KT-28061 for details)");
MAP.put(RETURN_TYPE_MISMATCH, "This function must return a value of type {0}", RENDER_TYPE);
MAP.put(EXPECTED_TYPE_MISMATCH, "Expected a value of type {0}", RENDER_TYPE);
MAP.put(ASSIGNMENT_TYPE_MISMATCH,

View File

@@ -98,7 +98,6 @@ public interface BindingContext {
WritableSlice<KtExpression, DataFlowInfo> DATA_FLOW_INFO_BEFORE = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<KtExpression, KotlinType> EXPECTED_EXPRESSION_TYPE = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<KtElement, Computation> EXPRESSION_EFFECTS = Slices.createSimpleSlice();
WritableSlice<FunctionDescriptor, Functor> FUNCTOR = Slices.createSimpleSlice();
WritableSlice<KtFunction, KotlinType> EXPECTED_RETURN_TYPE = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<KtExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
WritableSlice<VariableDescriptor, DataFlowValue> BOUND_INITIALIZER_VALUE = Slices.createSimpleSlice();

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-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;
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.TowerLevelsKt;
import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.expressions.CaptureKind;
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
import org.jetbrains.kotlin.util.slicedMap.MutableSlicedMap;
@@ -204,8 +194,15 @@ public class BindingContextUtils {
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null;
}
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
return isCapturedInClosure(bindingContext, descriptor) && ((VariableDescriptor) descriptor).isVar();
public static boolean isCapturedInClosureWithExactlyOnceEffect(BindingContext bindingContext, DeclarationDescriptor descriptor) {
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) == CaptureKind.EXACTLY_ONCE_EFFECT;
}
public static boolean isBoxedLocalCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
return (isCapturedInClosure(bindingContext, descriptor) && ((VariableDescriptor) descriptor).isVar()) ||
isCapturedInClosureWithExactlyOnceEffect(bindingContext, descriptor);
}
@NotNull

View File

@@ -122,7 +122,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
PropertiesWithBackingFieldsInsideInlineClass(),
AnnotationClassTargetAndRetentionChecker(),
ReservedMembersAndConstructsForInlineClass(),
ResultClassInReturnTypeChecker()
ResultClassInReturnTypeChecker(),
LocalVariableTypeParametersChecker()
)
private val DEFAULT_CALL_CHECKERS = listOf(

View File

@@ -1,28 +1,24 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-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
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.contracts.description.CallsEffectDeclaration
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
import org.jetbrains.kotlin.contracts.description.InvocationKind
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.inline.InlineUtil
@@ -43,8 +39,7 @@ class CapturingInClosureChecker : CallChecker {
val scopeContainer = scope.ownerDescriptor
if (isCapturedVariable(variableParent, scopeContainer)) {
if (trace.get(CAPTURED_IN_CLOSURE, variable) != CaptureKind.NOT_INLINE) {
val inline = isCapturedInInline(trace.bindingContext, scopeContainer, variableParent)
trace.record(CAPTURED_IN_CLOSURE, variable, if (inline) CaptureKind.INLINE_ONLY else CaptureKind.NOT_INLINE)
trace.record(CAPTURED_IN_CLOSURE, variable, getCaptureKind(trace.bindingContext, scopeContainer, variableParent))
}
}
}
@@ -61,17 +56,34 @@ class CapturingInClosureChecker : CallChecker {
return true
}
private fun isCapturedInInline(
private fun getCaptureKind(
context: BindingContext, scopeContainer: DeclarationDescriptor, variableParent: DeclarationDescriptor
): Boolean {
): CaptureKind {
val scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer)
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return false
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return CaptureKind.NOT_INLINE
if (InlineUtil.isInlinedArgument(scopeDeclaration as KtFunction, context, false)) {
val exactlyOnceContract = isExactlyOnceContract(context, scopeDeclaration as KtFunction)
if (InlineUtil.isInlinedArgument(scopeDeclaration, context, exactlyOnceContract)) {
val scopeContainerParent = scopeContainer.containingDeclaration ?: error("parent is null for $scopeContainer")
return !isCapturedVariable(variableParent, scopeContainerParent) ||
isCapturedInInline(context, scopeContainerParent, variableParent)
return if (
!isCapturedVariable(variableParent, scopeContainerParent) ||
getCaptureKind(context, scopeContainerParent, variableParent) == CaptureKind.INLINE_ONLY
) CaptureKind.INLINE_ONLY else CaptureKind.NOT_INLINE
}
return false
if (exactlyOnceContract) return CaptureKind.EXACTLY_ONCE_EFFECT
return CaptureKind.NOT_INLINE
}
private fun isExactlyOnceContract(bindingContext: BindingContext, argument: KtFunction): Boolean {
val call = KtPsiUtil.getParentCallIfPresent(argument) ?: return false
val resolvedCall = call.getResolvedCall(bindingContext) ?: return false
val descriptor = resolvedCall.getResultingDescriptor()
val valueArgument = resolvedCall.call.getValueArgumentForExpression(argument) ?: return false
val mapping = resolvedCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return false
val parameter = mapping.valueParameter
val contractDescription = descriptor.getUserData(ContractProviderKey)?.getContractDescription() ?: return false
val effect = contractDescription.effects.filterIsInstance<CallsEffectDeclaration>()
.find { it.variableReference.descriptor == parameter } ?: return false
return effect.kind == InvocationKind.EXACTLY_ONCE
}
}

View File

@@ -43,7 +43,7 @@ import java.io.File
class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnotationArgumentExtractor> = emptyList()) : DeclarationChecker {
interface ActualAnnotationArgumentExtractor {
fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>?
fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>?
}
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
@@ -233,14 +233,15 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
if (expectedParameterDescriptor.declaresDefaultValue() && actualParameterDescriptor.declaresDefaultValue()) {
val expectedParameter =
DescriptorToSourceUtils.descriptorToDeclaration(expectedParameterDescriptor) as? KtParameter ?: continue
val actualParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualParameterDescriptor)
val expectedValue = trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expectedParameter.defaultValue)
?.toConstantValue(expectedParameterDescriptor.type)
val actualValue = getActualAnnotationParameterValue(actualParameter, trace.bindingContext, expectedParameterDescriptor.type)
val actualValue =
getActualAnnotationParameterValue(actualParameterDescriptor, trace.bindingContext, expectedParameterDescriptor.type)
if (expectedValue != actualValue) {
val target = (actualParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn
val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualParameterDescriptor)
val target = (ktParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn
trace.report(Errors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE.on(target, actualParameterDescriptor))
}
}
@@ -248,16 +249,15 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
}
private fun getActualAnnotationParameterValue(
actualParameter: PsiElement?, bindingContext: BindingContext, expectedType: KotlinType
actualParameter: ValueParameterDescriptor, bindingContext: BindingContext, expectedType: KotlinType
): ConstantValue<*>? {
if (actualParameter is KtParameter) {
return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, actualParameter.defaultValue)?.toConstantValue(expectedType)
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(actualParameter)
if (declaration is KtParameter) {
return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, declaration.defaultValue)?.toConstantValue(expectedType)
}
if (actualParameter != null) {
for (extractor in argumentExtractors) {
extractor.extractActualValue(actualParameter, expectedType)?.let { return it }
}
for (extractor in argumentExtractors) {
extractor.extractDefaultValue(actualParameter, expectedType)?.let { return it }
}
return null

View File

@@ -0,0 +1,31 @@
/*
* 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.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
class LocalVariableTypeParametersChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtProperty || descriptor !is LocalVariableDescriptor) return
val typeParameters = declaration.typeParameters
val typeParametersList = declaration.typeParameterList
if (typeParameters.isEmpty() || typeParametersList == null) return
val diagnostic =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitTypeParametersForLocalVariables))
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS
else
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING
context.trace.report(diagnostic.on(typeParametersList))
}
}

View File

@@ -41,10 +41,13 @@ class LazyScriptClassMemberScope(
if (baseConstructorDescriptor != null) {
val implicitReceiversParamTypes =
scriptDescriptor.implicitReceivers.mapIndexed { idx, receiver ->
"$IMPLICIT_RECEIVER_PARAM_NAME_PREFIX$idx" to receiver.defaultType
val name =
if (receiver is ScriptDescriptor) "$IMPORTED_SCRIPT_PARAM_NAME_PREFIX${receiver.name}"
else "$IMPLICIT_RECEIVER_PARAM_NAME_PREFIX$idx"
name to receiver.defaultType
}
val environmentVarsParamTypes =
scriptDescriptor.scriptEnvironmentProperties.map {
val providedPropertiesParamTypes =
scriptDescriptor.scriptProvidedProperties.map {
it.name.identifier to it.type
}
val annotations = baseConstructorDescriptor.annotations
@@ -53,7 +56,7 @@ class LazyScriptClassMemberScope(
)
var paramsIndexBase = baseConstructorDescriptor.valueParameters.lastIndex + 1
val syntheticParameters =
(implicitReceiversParamTypes + environmentVarsParamTypes).map { param: Pair<String, KotlinType> ->
(implicitReceiversParamTypes + providedPropertiesParamTypes).map { param: Pair<String, KotlinType> ->
ValueParameterDescriptorImpl(
constructorDescriptor,
null,
@@ -103,6 +106,7 @@ class LazyScriptClassMemberScope(
companion object {
const val IMPLICIT_RECEIVER_PARAM_NAME_PREFIX = "\$\$implicitReceiver"
const val IMPORTED_SCRIPT_PARAM_NAME_PREFIX = "\$\$importedScript"
}
}

View File

@@ -16,17 +16,20 @@
package org.jetbrains.kotlin.resolve.lazy.descriptors
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.local.CoreLocalFileSystem
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtScriptInitializer
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
import org.jetbrains.kotlin.resolve.BindingContext
@@ -37,17 +40,20 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ReplResultPropertyDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptProvidedPropertiesDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.classId
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
import org.jetbrains.kotlin.script.ScriptPriorities
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.io.File
import kotlin.reflect.KClass
import kotlin.reflect.KType
@@ -143,10 +149,48 @@ class LazyScriptDescriptor(
override fun computeSupertypes() = listOf(baseClassDescriptor()?.defaultType ?: builtIns.anyType)
private inner class ImportedScriptDescriptorsFinder {
val fileManager = VirtualFileManager.getInstance()
val localFS = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val psiManager = PsiManager.getInstance(scriptInfo.script.project)
operator fun invoke(importedScriptFile: File): ScriptDescriptor? {
fun errorDescriptor(errorDiagnostic: DiagnosticFactory1<PsiElement, String>?): ScriptDescriptor? {
reportErrorString1(errorDiagnostic, importedScriptFile.path)
return null
}
val vfile = localFS.findFileByPath(importedScriptFile.path)
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_FILE)
val psiFile = psiManager.findFile(vfile)
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_PSI)
// Note: is not an error now - if import references other valid source file, it is simply compiled along with script
// TODO: check if this is the behavior we want to have - see #KT-28916
val ktScript = (psiFile as? KtFile)?.declarations?.firstIsInstanceOrNull<KtScript>()
?: return null
return resolveSession.getScriptDescriptor(ktScript)
}
}
private val scriptImplicitReceivers: () -> List<ClassDescriptor> = resolveSession.storageManager.createLazyValue {
scriptDefinition().implicitReceivers.mapNotNull { receiver ->
val res = ArrayList<ClassDescriptor>()
val importedScriptsFiles = ScriptDependenciesProvider.getInstance(scriptInfo.script.project)
.getScriptDependencies(scriptInfo.script.containingKtFile)?.scripts
if (importedScriptsFiles != null) {
val findImportedScriptDescriptor = ImportedScriptDescriptorsFinder()
importedScriptsFiles.mapNotNullTo(res) {
findImportedScriptDescriptor(it)
}
}
scriptDefinition().implicitReceivers.mapNotNullTo(res) { receiver ->
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
}
res
}
internal fun findTypeDescriptor(kClass: KClass<*>, errorDiagnostic: DiagnosticFactory1<PsiElement, String>?): ClassDescriptor? =
@@ -160,33 +204,39 @@ class LazyScriptDescriptor(
errorDiagnostic: DiagnosticFactory1<PsiElement, String>?
): ClassDescriptor? {
val typeDescriptor = classId?.let { module.findClassAcrossModuleDependencies(it) }
if (typeDescriptor == null && errorDiagnostic != null) {
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
resolveSession.trace.report(
errorDiagnostic.on(
scriptInfo.script,
classId?.asSingleFqName()?.toString() ?: typeName
)
)
if (typeDescriptor == null) {
reportErrorString1(errorDiagnostic, classId?.asSingleFqName()?.toString() ?: typeName)
}
return typeDescriptor
}
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
private val scriptEnvironment: () -> ScriptEnvironmentDescriptor = resolveSession.storageManager.createLazyValue {
ScriptEnvironmentDescriptor(this)
private fun reportErrorString1(errorDiagnostic: DiagnosticFactory1<PsiElement, String>?, arg: String) {
if (errorDiagnostic != null) {
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
resolveSession.trace.report(
errorDiagnostic.on(
scriptInfo.script,
arg
)
)
}
}
override fun getScriptEnvironmentProperties(): List<PropertyDescriptor> = scriptEnvironment().properties()
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
private val scriptProvidedProperties: () -> ScriptProvidedPropertiesDescriptor = resolveSession.storageManager.createLazyValue {
ScriptProvidedPropertiesDescriptor(this)
}
override fun getScriptProvidedProperties(): List<PropertyDescriptor> = scriptProvidedProperties().properties()
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
var outerScope = super.getOuterScope()
val outerScopeReceivers = implicitReceivers.let {
if (scriptDefinition().environmentVariables.isEmpty()) {
if (scriptDefinition().providedProperties.isEmpty()) {
it
} else {
it + ScriptEnvironmentDescriptor(this)
it + ScriptProvidedPropertiesDescriptor(this)
}
}
for (receiverClassDescriptor in outerScopeReceivers.asReversed()) {

View File

@@ -17,11 +17,11 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.Printer
class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) :
MutableClassDescriptor(
script,
ClassKind.CLASS, false, false,
Name.special("<synthetic script environment for ${script.name}>"),
Name.special("<synthetic script provided properties for ${script.name}>"),
SourceElement.NO_SOURCE,
LockBasedStorageManager.NO_LOCKS
) {
@@ -33,8 +33,8 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
createTypeConstructor()
}
private val memberScope: () -> ScriptEnvironmentMemberScope = script.resolveSession.storageManager.createLazyValue {
ScriptEnvironmentMemberScope(
private val memberScope: () -> ScriptProvidedPropertiesMemberScope = script.resolveSession.storageManager.createLazyValue {
ScriptProvidedPropertiesMemberScope(
script.name.identifier,
properties()
)
@@ -42,13 +42,13 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
val properties: () -> List<ScriptEnvironmentPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
script.scriptDefinition().environmentVariables.mapNotNull { (name, type) ->
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS)?.let {
val properties: () -> List<ScriptProvidedPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
script.scriptDefinition().providedProperties.mapNotNull { (name, type) ->
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)?.let {
name to it
}
}.map { (name, classDescriptor) ->
ScriptEnvironmentPropertyDescriptor(
ScriptProvidedPropertyDescriptor(
Name.identifier(name),
classDescriptor,
thisAsReceiverParameter,
@@ -58,21 +58,21 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
}
}
private class ScriptEnvironmentMemberScope(
private class ScriptProvidedPropertiesMemberScope(
private val scriptId: String,
private val environmentProperties: List<PropertyDescriptor>
private val providedProperties: List<PropertyDescriptor>
) : MemberScopeImpl() {
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> =
environmentProperties
providedProperties
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> =
environmentProperties.filter { it.name == name }
providedProperties.filter { it.name == name }
override fun printScopeStructure(p: Printer) {
p.println("Scope of script environment: $scriptId")
p.println("Scope of script provided properties: $scriptId")
}
}
}

View File

@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
class ScriptEnvironmentPropertyDescriptor(
class ScriptProvidedPropertyDescriptor(
name: Name,
typeDescriptor: ClassDescriptor,
receiver: ReceiverParameterDescriptor?,

View File

@@ -1,22 +1,12 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-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.types.expressions;
public enum CaptureKind {
NOT_INLINE,
INLINE_ONLY
INLINE_ONLY,
EXACTLY_ONCE_EFFECT
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 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.
*/

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