Compare commits

...

242 Commits

Author SHA1 Message Date
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
1238 changed files with 19442 additions and 10209 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

@@ -479,6 +479,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

@@ -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

@@ -97,8 +97,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 +453,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);
@@ -1881,7 +1885,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 +2055,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 +2082,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 +2110,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 +3031,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 +3127,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 +4040,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
else if (property.hasModifier(KtTokens.LATEINIT_KEYWORD)) {
initializeLocalVariable(property, null);
}
else if (!property.isVar()) {
initializeLocalVariableWithFakeDefaultValue(property);
}
return StackValue.none();
}
@@ -4173,6 +4186,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);
// For this kind of variables we generate boxes, i.e. we regard them as
if (isCapturedInClosureWithExactlyOnceEffect(bindingContext, variableDescriptor)) return;
assert !variableDeclaration.isVar() && !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,

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

@@ -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

@@ -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
@@ -497,6 +498,12 @@ class CoroutineTransformerMethodVisitor(
val frames = performRefinedTypeAnalysis(methodNode, containingClassInternalName)
fun AbstractInsnNode.index() = instructions.indexOf(this)
fun Int.isInlinerFakeVariable(index: Int) = methodNode.localVariables.any {
(it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT) || it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION))
&& it.index == this
&& it.start.index() <= index && index <= it.end.index()
}
// We postpone these actions because they change instruction indices that we use when obtaining frames
val postponedActions = mutableListOf<() -> Unit>()
val maxVarsCountByType = mutableMapOf<Type, Int>()
@@ -538,8 +545,9 @@ class CoroutineTransformerMethodVisitor(
// k + 2 - exception
val variablesToSpill =
(0 until localsCount)
.filter { it !in setOf(continuationIndex, dataIndex, exceptionIndex) }
.map { Pair(it, frame.getLocal(it)) }
.filterNot {
it in setOf(continuationIndex, dataIndex, exceptionIndex) || it.isInlinerFakeVariable(suspensionCallBegin.index())
}.map { Pair(it, frame.getLocal(it)) }
.filter { (index, value) ->
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
(value != StrictBasicValue.UNINITIALIZED_VALUE && livenessFrame.isAlive(index))

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

@@ -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

@@ -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

@@ -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

@@ -118,6 +118,29 @@ class ControlFlowInformationProvider private constructor(
markAndCheckTailCalls()
}
/**
* 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(returnedExpressions: MutableCollection<KtElement>) {
val instructions = pseudocode.instructions.toHashSet()
val exitInstruction = pseudocode.exitInstruction
@@ -135,15 +158,17 @@ class ControlFlowInformationProvider private constructor(
}
}
override fun visitJump(instruction: AbstractJumpInstruction) {
// Nothing
}
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 +185,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")

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);

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);

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.
*/

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.
*/

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.
*/

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.
*/

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.
*/

View File

@@ -1053,16 +1053,16 @@ class ExpressionCodegen(
} else {
val classType = classReference.classType
if (classType is CrIrType) {
putJavaLangClassInstance(mv, classType.type)
putJavaLangClassInstance(mv, classType.type, null, state)
return
} else {
val type = classType.toKotlinType()
if (TypeUtils.isTypeParameter(type)) {
assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
val kotlinType = classType.toKotlinType()
if (TypeUtils.isTypeParameter(kotlinType)) {
assert(TypeUtils.isReifiedTypeParameter(kotlinType)) { "Non-reified type parameter under ::class should be rejected by type checker: " + kotlinType }
putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
}
putJavaLangClassInstance(mv, typeMapper.mapType(type))
putJavaLangClassInstance(mv, typeMapper.mapType(kotlinType), kotlinType, state)
}
}

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.JvmKotlinType
import org.jetbrains.kotlin.codegen.StackValue
@@ -34,9 +35,8 @@ class IrInlineCodegen(
val lambdaInfo = next as IrExpressionLambda
activeLambda = lambdaInfo
val argumentTypes = lambdaInfo.loweredMethod.argumentTypes
lambdaInfo.reference.getArguments().forEachIndexed { index, (_, ir) ->
putCapturedValueOnStack(ir, argumentTypes[index], index)
putCapturedValueOnStack(ir, lambdaInfo.capturedParamsInDesc[index], index)
}
activeLambda = null
}
@@ -70,10 +70,10 @@ class IrInlineCodegen(
putArgumentOrCapturedToLocalVal(JvmKotlinType(value.type, value.kotlinType), value, -1, parameterIndex, ValueKind.CAPTURED /*kind*/)
}
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamindex: Int) {
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamIndex: Int) {
val onStack = codegen.gen(argumentExpression, valueType, BlockInfo.create())
putArgumentOrCapturedToLocalVal(
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamindex, capturedParamindex, ValueKind.CAPTURED
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamIndex, capturedParamIndex, ValueKind.CAPTURED
)
}
@@ -93,10 +93,10 @@ class IrInlineCodegen(
private fun rememberClosure(irReference: IrFunctionReference, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
//assert(InlineUtil.isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
val expression = irReference.symbol.owner as IrFunction
return IrExpressionLambda(
irReference, expression, typeMapper, parameter.isCrossinline, false/*TODO*/
irReference, expression, typeMapper, parameter.isCrossinline, false/*TODO*/,
parameter.type.isExtensionFunctionType
).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda
@@ -110,7 +110,8 @@ class IrExpressionLambda(
val function: IrFunction,
typeMapper: KotlinTypeMapper,
isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
override val isBoundCallableReference: Boolean,
val isExtensionLambda: Boolean
) : ExpressionLambda(typeMapper, isCrossInline) {
override fun isMyLabel(name: String): Boolean {
@@ -118,30 +119,35 @@ class IrExpressionLambda(
return false
}
override val lambdaClassType: Type
get() = Type.getObjectType("test123")
override val lambdaClassType: Type = Type.getObjectType("test123")
override val capturedVars: List<CapturedParamDesc> by lazy {
override val capturedVars: List<CapturedParamDesc> =
arrayListOf<CapturedParamDesc>().apply {
reference.getArguments().forEachIndexed { _, (_, ir) ->
val getValue = ir as? IrGetValue ?: error("Unrecognized expression: $ir")
add(capturedParamDesc(getValue.descriptor.name.asString(), typeMapper.mapType(getValue.descriptor.type)))
}
}
}
val loweredMethod: Method
get() = typeMapper.mapAsmMethod(function.descriptor)
private val loweredMethod = typeMapper.mapAsmMethod(function.descriptor)
val capturedParamsInDesc: List<Type> =
loweredMethod.argumentTypes.drop(if (isExtensionLambda) 1 else 0).take(capturedVars.size)
override val invokeMethod: Method = loweredMethod.let {
Method(it.name, it.returnType, it.argumentTypes.drop(capturedVars.size).toTypedArray())
Method(
it.name,
it.returnType,
(
(if (isExtensionLambda) it.argumentTypes.take(1) else emptyList()) +
it.argumentTypes.drop((if (isExtensionLambda) 1 else 0) + capturedVars.size)
).toTypedArray()
)
}
override val invokeMethodDescriptor: FunctionDescriptor
get() = function.descriptor
override val invokeMethodDescriptor: FunctionDescriptor = function.descriptor
override val hasDispatchReceiver: Boolean
get() = false
override val hasDispatchReceiver: Boolean = false
}
fun isInlineIrExpression(argumentExpression: IrExpression) =

View File

@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.javac.components
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
@@ -32,10 +32,12 @@ class JavacBasedClassFinder : AbstractJavaClassFinder() {
super.initialize(trace, codeAnalyzer)
}
override fun findClass(classId: ClassId) = javac.findClass(classId, javaSearchScope)
override fun findClass(request: JavaClassFinder.Request) =
// TODO: reuse previouslyFoundClassFileContent if it's possible in javac
javac.findClass(request.classId, javaSearchScope)
override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope)
override fun knownClassNamesInPackage(packageFqName: FqName) = javac.knownClassNamesInPackage(packageFqName)
}
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.ExecutableElement
class SymbolBasedMethod(
@@ -35,7 +36,9 @@ class SymbolBasedMethod(
override val returnType: JavaType
get() = SymbolBasedType.create(element.returnType, javac)
override val hasAnnotationParameterDefaultValue: Boolean
get() = element.defaultValue != null
// TODO: allow nullable names in Symbol-based annotation arguments and pass null instead of a synthetic name
override val annotationParameterDefaultValue: JavaAnnotationArgument?
get() = element.defaultValue?.let { defaultValue ->
SymbolBasedAnnotationArgument.create(defaultValue, Name.identifier("value"), javac)
}
}

View File

@@ -100,46 +100,50 @@ class TreeBasedAnnotationAsAnnotationArgument(private val annotation: JCTree.JCA
}
private fun createAnnotationArguments(annotation: TreeBasedAnnotation,
javac: JavacWrapper,
onElement: JavaElement): Collection<JavaAnnotationArgument> =
private fun createAnnotationArguments(
annotation: TreeBasedAnnotation, javac: JavacWrapper, onElement: JavaElement
): Collection<JavaAnnotationArgument> =
annotation.annotation.arguments.mapNotNull {
val name = if (it is JCTree.JCAssign) Name.identifier(it.lhs.toString()) else Name.identifier("value")
createAnnotationArgument(it, name, annotation.compilationUnit, javac, annotation, onElement)
createAnnotationArgument(it, name, annotation.compilationUnit, javac, annotation.resolve(), onElement)
}
private fun createAnnotationArgument(argument: JCTree.JCExpression,
name: Name,
compilationUnit: CompilationUnitTree,
javac: JavacWrapper,
annotation: TreeBasedAnnotation,
onElement: JavaElement): JavaAnnotationArgument? =
when (argument) {
is JCTree.JCLiteral -> TreeBasedLiteralAnnotationArgument(name, argument.value, javac)
is JCTree.JCFieldAccess -> {
if (argument.name.contentEquals("class")) {
TreeBasedJavaClassObjectAnnotationArgument(argument.selected, name, compilationUnit, javac, onElement)
}
else {
TreeBasedReferenceAnnotationArgument(name, compilationUnit, argument, javac, onElement)
}
internal fun createAnnotationArgument(
argument: JCTree.JCExpression,
name: Name,
compilationUnit: CompilationUnitTree,
javac: JavacWrapper,
containingClass: JavaClass?,
onElement: JavaElement
): JavaAnnotationArgument? =
when (argument) {
is JCTree.JCLiteral -> TreeBasedLiteralAnnotationArgument(name, argument.value, javac)
is JCTree.JCFieldAccess -> {
if (argument.name.contentEquals("class")) {
TreeBasedJavaClassObjectAnnotationArgument(argument.selected, name, compilationUnit, javac, onElement)
} else {
TreeBasedReferenceAnnotationArgument(name, compilationUnit, argument, javac, onElement)
}
is JCTree.JCAssign -> createAnnotationArgument(argument.rhs, name, compilationUnit, javac, annotation, onElement)
is JCTree.JCNewArray -> TreeBasedArrayAnnotationArgument(argument.elems.mapNotNull { createAnnotationArgument(it, name, compilationUnit, javac, annotation, onElement) }, name, javac)
is JCTree.JCAnnotation -> TreeBasedAnnotationAsAnnotationArgument(argument, name, compilationUnit, javac, onElement)
is JCTree.JCParens -> createAnnotationArgument(argument.expr, name, compilationUnit, javac, annotation, onElement)
is JCTree.JCBinary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac)
is JCTree.JCUnary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac)
else -> throw UnsupportedOperationException("Unknown annotation argument $argument")
}
is JCTree.JCAssign -> createAnnotationArgument(argument.rhs, name, compilationUnit, javac, containingClass, onElement)
is JCTree.JCNewArray -> TreeBasedArrayAnnotationArgument(argument.elems.mapNotNull {
createAnnotationArgument(it, name, compilationUnit, javac, containingClass, onElement)
}, name, javac)
is JCTree.JCAnnotation -> TreeBasedAnnotationAsAnnotationArgument(argument, name, compilationUnit, javac, onElement)
is JCTree.JCParens -> createAnnotationArgument(argument.expr, name, compilationUnit, javac, containingClass, onElement)
is JCTree.JCBinary -> resolveArgumentValue(argument, containingClass, name, compilationUnit, javac)
is JCTree.JCUnary -> resolveArgumentValue(argument, containingClass, name, compilationUnit, javac)
else -> throw UnsupportedOperationException("Unknown annotation argument $argument")
}
private fun resolveArgumentValue(argument: JCTree.JCExpression,
annotation: TreeBasedAnnotation,
name: Name,
compilationUnit: CompilationUnitTree,
javac: JavacWrapper): JavaAnnotationArgument? {
val containingAnnotation = annotation.resolve() ?: return null
val evaluator = ConstantEvaluator(containingAnnotation, javac, compilationUnit)
private fun resolveArgumentValue(
argument: JCTree.JCExpression,
containingClass: JavaClass?,
name: Name,
compilationUnit: CompilationUnitTree,
javac: JavacWrapper
): JavaAnnotationArgument? {
if (containingClass == null) return null
val evaluator = ConstantEvaluator(containingClass, javac, compilationUnit)
return evaluator.getValue(argument)?.let { TreeBasedLiteralAnnotationArgument(name, it, javac) }
}
}

View File

@@ -55,6 +55,9 @@ class TreeBasedMethod(
override val returnType: JavaType
get() = TreeBasedType.create(tree.returnType, compilationUnit, javac, annotations, this)
override val hasAnnotationParameterDefaultValue: Boolean
get() = tree.defaultValue != null
}
// TODO: allow nullable names in Tree-based annotation arguments and pass null instead of a synthetic name
override val annotationParameterDefaultValue: JavaAnnotationArgument?
get() = tree.defaultValue?.let { defaultValue ->
createAnnotationArgument(defaultValue, Name.identifier("value"), compilationUnit, javac, containingClass, this)
}
}

View File

@@ -23,12 +23,15 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.light.AbstractLightClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation;
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind;
import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.psi.KtFile;
import java.util.List;
/**
* This class serves as a workaround for usages of {@link JavaElementFinder#findClasses} which eventually only need names of files
* containing the class. When queried for a package class (e.g. test/TestPackage), {@code findClasses} along with a
@@ -111,4 +114,10 @@ public class FakeLightClassForFileOfPackage extends AbstractLightClass implement
public LightClassOriginKind getOriginKind() {
return LightClassOriginKind.SOURCE;
}
@Nullable
@Override
public List<KtLightAbstractAnnotation> getGivenAnnotations() {
return null;
}
}

View File

@@ -362,8 +362,13 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
return InvalidLightClassDataHolder
}
return classOrObject.containingKtFile.script?.let { KtLightClassForScript.getLightClassCachedValue(it).value }
?: getLightClassCachedValue(classOrObject).value
val containingScript = classOrObject.containingKtFile.script
return when {
!classOrObject.isLocal && containingScript != null ->
KtLightClassForScript.getLightClassCachedValue(containingScript).value
else ->
getLightClassCachedValue(classOrObject).value
}
}
private fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder.ForClass> {

View File

@@ -2,9 +2,21 @@ package org.jetbrains.kotlin.asJava.classes
import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.*
import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.light.LightIdentifier
import com.intellij.psi.meta.PsiMetaData
import com.intellij.psi.util.TypeConversionUtil
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
import org.jetbrains.kotlin.asJava.elements.psiType
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isError
@@ -35,6 +47,128 @@ class KtUltraLightNullabilityAnnotation(
}
}
fun DeclarationDescriptor.obtainLightAnnotations(
ultraLightSupport: UltraLightSupport,
parent: PsiElement
): List<KtLightAbstractAnnotation> = annotations.map { KtUltraLightAnnotationForDescriptor(it, ultraLightSupport, parent) }
class KtUltraLightAnnotationForDescriptor(
private val annotationDescriptor: AnnotationDescriptor,
private val ultraLightSupport: UltraLightSupport,
parent: PsiElement
) : KtLightAbstractAnnotation(parent, { error("clsDelegate for annotation based on descriptor: $annotationDescriptor") }) {
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = null
override fun getMetaData(): PsiMetaData? = null
private val parameterList = ParameterListImpl()
override fun getParameterList(): PsiAnnotationParameterList = parameterList
override val kotlinOrigin: KtCallElement? get() = null
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(p0: String?, p1: T?) = cannotModify()
override fun findAttributeValue(attributeName: String?): PsiAnnotationMemberValue? =
PsiImplUtil.findAttributeValue(this, attributeName)
override fun findDeclaredAttributeValue(attributeName: String?) =
PsiImplUtil.findDeclaredAttributeValue(this, attributeName)
override fun getQualifiedName() = annotationDescriptor.fqName?.asString()
private inner class ParameterListImpl : KtLightElementBase(this@KtUltraLightAnnotationForDescriptor), PsiAnnotationParameterList {
private val _attributes: Array<PsiNameValuePair> by lazyPub {
annotationDescriptor.allValueArguments.map {
PsiNameValuePairForAnnotationArgument(it.key.asString(), it.value, ultraLightSupport, this)
}.toTypedArray()
}
override fun getAttributes(): Array<PsiNameValuePair> = _attributes
override val kotlinOrigin: KtElement? get() = null
}
override fun getText() = "@$qualifiedName(" + parameterList.attributes.joinToString { it.name + "=" + it.value?.text } + ")"
}
private class PsiNameValuePairForAnnotationArgument(
private val _name: String = "",
private val constantValue: ConstantValue<*>,
private val ultraLightSupport: UltraLightSupport,
parent: PsiElement
) : KtLightElementBase(parent), PsiNameValuePair {
override val kotlinOrigin: KtElement? get() = null
private val _value by lazyPub {
constantValue.toAnnotationMemberValue(this, ultraLightSupport)
}
override fun setValue(p0: PsiAnnotationMemberValue) = cannotModify()
override fun getNameIdentifier() = LightIdentifier(parent.manager, _name)
override fun getValue(): PsiAnnotationMemberValue? = _value
override fun getLiteralValue(): String? = (value as? PsiLiteralExpression)?.value?.toString()
override fun getName() = _name
}
private fun ConstantValue<*>.toAnnotationMemberValue(
parent: PsiElement, ultraLightSupport: UltraLightSupport
): PsiAnnotationMemberValue? = when (this) {
is AnnotationValue -> KtUltraLightAnnotationForDescriptor(value, ultraLightSupport, parent)
is ArrayValue ->
KtUltraLightPsiArrayInitializerMemberValue(lightParent = parent) { arrayLiteralParent ->
this.value.mapNotNull { element -> element.toAnnotationMemberValue(arrayLiteralParent, ultraLightSupport) }
}
is ErrorValue -> null
else -> createPsiLiteral(parent)
}
private fun ConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral(parent)
val instance = PsiElementFactory.SERVICE.getInstance(parent.project)
return instance.createExpressionFromText(asString, parent)
}
private fun ConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
when (this) {
is NullValue -> "null"
is StringValue -> "\"$value\""
is KClassValue -> {
val arrayPart = "[]".repeat(value.arrayNestedness)
val fqName = value.classId.asSingleFqName()
val canonicalText = psiType(
fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0
).let(TypeConversionUtil::erasure).getCanonicalText(false)
"$canonicalText$arrayPart.class"
}
is EnumValue -> "${enumClassId.asSingleFqName().asString()}.$enumEntryName"
else -> value.toString()
}
private class KtUltraLightPsiArrayInitializerMemberValue(
val lightParent: PsiElement,
private val arguments: (KtUltraLightPsiArrayInitializerMemberValue) -> List<PsiAnnotationMemberValue>
) : KtLightElementBase(lightParent), PsiArrayInitializerMemberValue {
override val kotlinOrigin: KtElement? get() = null
override fun getInitializers(): Array<PsiAnnotationMemberValue> = arguments(this).toTypedArray()
override fun getParent(): PsiElement = lightParent
override fun isPhysical(): Boolean = false
override fun getText(): String = "{" + initializers.joinToString { it.text } + "}"
}
fun PsiModifierListOwner.isPrivateOrParameterInPrivateMethod(): Boolean {
if (hasModifier(JvmModifier.PRIVATE)) return true
if (this !is PsiParameter) return false

View File

@@ -10,16 +10,19 @@ import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.PsiSuperMethodImplUtil
import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.SearchScope
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
import org.jetbrains.kotlin.asJava.elements.KtLightSimpleModifierList
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.types.KotlinType
@@ -56,7 +59,8 @@ internal abstract class KtUltraLightMethod(
val list = KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST)
computeDescriptor()?.let {
for (ex in FunctionCodegen.getThrownExceptions(it)) {
list.addReference(ex.fqNameSafe.asString())
val psiClassType = ex.defaultType.asPsiType(support, TypeMappingMode.DEFAULT, list) as? PsiClassType ?: continue
list.addReference(psiClassType)
}
}
list
@@ -109,12 +113,15 @@ internal class KtUltraLightMethodForDescriptor(
override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() = descriptor.returnType
override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = descriptor.obtainLightAnnotations(support, this)
}
internal abstract class KtUltraLightParameter(
name: String,
override val kotlinOrigin: KtDeclaration?,
private val support: UltraLightSupport,
protected val support: UltraLightSupport,
method: KtLightMethod
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
name,
@@ -131,6 +138,7 @@ internal abstract class KtUltraLightParameter(
override fun getModifierList(): PsiModifierList = lightModifierList
override fun getNavigationElement(): PsiElement = kotlinOrigin ?: method.navigationElement
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: LocalSearchScope(this)
override fun isValid() = parent.isValid
@@ -246,4 +254,7 @@ internal class KtUltraLightParameterForDescriptor(
override fun computeContainingDescriptor() = descriptor.containingDeclaration as? CallableMemberDescriptor
override fun isVarArgs() = (descriptor as? ValueParameterDescriptor)?.varargElementType != null
override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = descriptor.obtainLightAnnotations(support, this)
}

View File

@@ -377,6 +377,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
private fun shouldGenerateNoArgOverload(primary: KtPrimaryConstructor): Boolean {
return !primary.hasModifier(PRIVATE_KEYWORD) &&
!classOrObject.hasModifier(INNER_KEYWORD) && !isEnum &&
!classOrObject.hasModifier(SEALED_KEYWORD) &&
primary.valueParameters.isNotEmpty() &&
primary.valueParameters.all { it.defaultValue != null } &&
classOrObject.allConstructors.none { it.valueParameters.isEmpty() }
@@ -669,6 +670,8 @@ interface UltraLightSupport {
fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>?
fun isTooComplexForUltraLightGeneration(element: KtClassOrObject): Boolean
val deprecationResolver: DeprecationResolver
val typeMapper: KotlinTypeMapper
val moduleDescriptor: ModuleDescriptor
}
interface KtUltraLightElementWithNullabilityAnnotation<out T : KtDeclaration, out D : PsiModifierListOwner> : KtLightDeclaration<T, D>,

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