mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-17 00:21:29 +00:00
Compare commits
342 Commits
rr/mitropo
...
1.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2bc2cc53c | ||
|
|
2e7da8fcae | ||
|
|
e14de32939 | ||
|
|
40b00ee5b5 | ||
|
|
47369d1191 | ||
|
|
e85d6d9803 | ||
|
|
4d26204ef9 | ||
|
|
e62255b517 | ||
|
|
073c3bd7da | ||
|
|
87cc248fca | ||
|
|
5110affb2c | ||
|
|
7a8b85a916 | ||
|
|
d363ae94d8 | ||
|
|
9cf54bf83f | ||
|
|
63b6f90926 | ||
|
|
b8b9e43c05 | ||
|
|
98f0acdb8c | ||
|
|
ce1be19da6 | ||
|
|
6c1bb136ad | ||
|
|
c6a33fb9cb | ||
|
|
dc065cb362 | ||
|
|
f3d769d8d5 | ||
|
|
2c235b0585 | ||
|
|
161c67c2ac | ||
|
|
1bf290903a | ||
|
|
b7888138cf | ||
|
|
c25e26fd0d | ||
|
|
ec6189a860 | ||
|
|
4c4c62e815 | ||
|
|
da50776e80 | ||
|
|
6bcffb8289 | ||
|
|
072524946f | ||
|
|
a02ffd6d2b | ||
|
|
20d92e161e | ||
|
|
94cbe71eff | ||
|
|
97420afb3d | ||
|
|
8c2bcc6eaa | ||
|
|
a4ea155d22 | ||
|
|
fe956668b3 | ||
|
|
1e8e740816 | ||
|
|
f177af12d7 | ||
|
|
7a63d1af24 | ||
|
|
7e59108cae | ||
|
|
b18f790d10 | ||
|
|
b861a432c9 | ||
|
|
951b1d527a | ||
|
|
8c3d13b31f | ||
|
|
fc135efb21 | ||
|
|
596adb9b1e | ||
|
|
c506871195 | ||
|
|
15b99c3629 | ||
|
|
4f859fd727 | ||
|
|
716d00338e | ||
|
|
d2ab12bc97 | ||
|
|
cefa344a77 | ||
|
|
19814558f8 | ||
|
|
c8a00fc012 | ||
|
|
9d942383f1 | ||
|
|
e81f19c30a | ||
|
|
896be11aaa | ||
|
|
a9b5ddd7d2 | ||
|
|
340036fbcb | ||
|
|
4d80738dd6 | ||
|
|
307a5001ac | ||
|
|
0cfaea28a1 | ||
|
|
6f651d7338 | ||
|
|
9329eaa457 | ||
|
|
50ffc8d0c5 | ||
|
|
01a1aa9b62 | ||
|
|
4b2f4f0bc2 | ||
|
|
6a449faf5d | ||
|
|
d0f7edab08 | ||
|
|
716956f917 | ||
|
|
daf4711478 | ||
|
|
30c2c2f17f | ||
|
|
b9efc2e1ac | ||
|
|
9e0d31714c | ||
|
|
1e8c4933f1 | ||
|
|
6648a1f669 | ||
|
|
37f0bc1716 | ||
|
|
8a0a9152da | ||
|
|
53c3e75740 | ||
|
|
a9ef3845fd | ||
|
|
17d05bb7fd | ||
|
|
fbe67da5f1 | ||
|
|
02d8c193c8 | ||
|
|
9240d7695c | ||
|
|
f16f97583f | ||
|
|
50be60d71b | ||
|
|
e30cd05bea | ||
|
|
9c831cca8b | ||
|
|
4467ac0b42 | ||
|
|
07a48b080b | ||
|
|
09c6feddb6 | ||
|
|
9b44a7ea82 | ||
|
|
9013f50b28 | ||
|
|
5614874bf7 | ||
|
|
009f991ac3 | ||
|
|
9711854a2c | ||
|
|
ed98ff3dc0 | ||
|
|
7e098e8827 | ||
|
|
4b011767ef | ||
|
|
324819d20b | ||
|
|
4897af1ef9 | ||
|
|
be0537f3f8 | ||
|
|
899ca8bc65 | ||
|
|
86ffd634ec | ||
|
|
f30d0904fc | ||
|
|
d9b45f667d | ||
|
|
e159028c97 | ||
|
|
11847c121a | ||
|
|
ba857a83ff | ||
|
|
7019dcf3b1 | ||
|
|
46f7c37021 | ||
|
|
70de1a7d2a | ||
|
|
ec7b3c6240 | ||
|
|
499b6c2b91 | ||
|
|
5d56da2567 | ||
|
|
0e030241a6 | ||
|
|
1d3ff1d81a | ||
|
|
358f572b1f | ||
|
|
5a14d97642 | ||
|
|
d1f4c4c348 | ||
|
|
44dd831e71 | ||
|
|
da5ddd76c8 | ||
|
|
fe62995274 | ||
|
|
f67f387daa | ||
|
|
e9f33c4045 | ||
|
|
5f24329dca | ||
|
|
c6e9e992a4 | ||
|
|
c38180efa8 | ||
|
|
683f61fdc2 | ||
|
|
8e5853e5c3 | ||
|
|
4bbdeb00be | ||
|
|
45b060d0dd | ||
|
|
5c065efa20 | ||
|
|
83ca7d9b64 | ||
|
|
9166f5ba9d | ||
|
|
7a65e59d39 | ||
|
|
c91f6fabd1 | ||
|
|
49f1c95171 | ||
|
|
d77f20dc63 | ||
|
|
f9fb6c6a34 | ||
|
|
29eb286df4 | ||
|
|
becd00f33d | ||
|
|
9beabdeb34 | ||
|
|
9c738177b8 | ||
|
|
8f3cfb5b1b | ||
|
|
c2fd91da65 | ||
|
|
a574943696 | ||
|
|
69b302e4f6 | ||
|
|
9eb3925048 | ||
|
|
ee977bc0a1 | ||
|
|
07629e8a48 | ||
|
|
8197240eec | ||
|
|
175d74ce5f | ||
|
|
c06592ed6c | ||
|
|
b34363317a | ||
|
|
2ab47b4d6b | ||
|
|
aee36ac552 | ||
|
|
48c64e9b43 | ||
|
|
d2284af69d | ||
|
|
f9e45a1cea | ||
|
|
7710d4576d | ||
|
|
733f1166af | ||
|
|
b98b2b6846 | ||
|
|
f0fcb4c513 | ||
|
|
d265383968 | ||
|
|
103cd381f4 | ||
|
|
c8c8894f91 | ||
|
|
8c829564f1 | ||
|
|
9d1fec77b8 | ||
|
|
7000b3ef33 | ||
|
|
8ab204819d | ||
|
|
6a31cd834a | ||
|
|
8ba9e0271f | ||
|
|
9391ff4141 | ||
|
|
d73d42cc23 | ||
|
|
832e777b2a | ||
|
|
c1cd139396 | ||
|
|
09a6e9c591 | ||
|
|
4101206e12 | ||
|
|
fbe49d0cc9 | ||
|
|
78e4295c2c | ||
|
|
426944744d | ||
|
|
52a310f202 | ||
|
|
894ee4ce4f | ||
|
|
08915389e2 | ||
|
|
fc6465084b | ||
|
|
beff463a92 | ||
|
|
b67e3f824c | ||
|
|
c578e8b8f1 | ||
|
|
0395d90ef7 | ||
|
|
dfb21a81a0 | ||
|
|
4c69df28b4 | ||
|
|
da1dc9cfe7 | ||
|
|
3413cb977c | ||
|
|
d9c54449a4 | ||
|
|
cc6127a343 | ||
|
|
e44d0c4d5d | ||
|
|
e6c27e7f32 | ||
|
|
82c2ce3a33 | ||
|
|
679efb61ab | ||
|
|
ab44f5cc0e | ||
|
|
277b1cbf1e | ||
|
|
1ceb7f5656 | ||
|
|
ccffa26add | ||
|
|
cfc08328e0 | ||
|
|
f53c5ed30e | ||
|
|
fe44159962 | ||
|
|
74e9a632a9 | ||
|
|
bb1354660d | ||
|
|
b95875536f | ||
|
|
fb74040dde | ||
|
|
4cf2bce003 | ||
|
|
982e67276f | ||
|
|
9a255169ee | ||
|
|
cdeb2e80b5 | ||
|
|
b2c7521277 | ||
|
|
b416769434 | ||
|
|
ad5e3a52ff | ||
|
|
0a54b6104a | ||
|
|
f516b21e5b | ||
|
|
f64a25801f | ||
|
|
77fc61ce73 | ||
|
|
eaaf656ec9 | ||
|
|
bb892a8510 | ||
|
|
936e787d58 | ||
|
|
b82ad57472 | ||
|
|
1c4ac5a74b | ||
|
|
1a74058dc8 | ||
|
|
5ed5008db4 | ||
|
|
34192a1785 | ||
|
|
9ce396ad54 | ||
|
|
04364f4b3e | ||
|
|
6028a4facc | ||
|
|
1aba4fe4da | ||
|
|
54367bd8e8 | ||
|
|
5c73c59b9e | ||
|
|
a0c3187a93 | ||
|
|
9b118ff81d | ||
|
|
483b59516c | ||
|
|
607db11011 | ||
|
|
d04b7e9784 | ||
|
|
0320fe8261 | ||
|
|
cf99fc4908 | ||
|
|
52c7bdf280 | ||
|
|
7ab3afd00d | ||
|
|
f49ef8e919 | ||
|
|
0e1b61b422 | ||
|
|
aaddfa8561 | ||
|
|
05cfe4ca39 | ||
|
|
65437a5c21 | ||
|
|
1026605627 | ||
|
|
a08bc11064 | ||
|
|
5c694bf95b | ||
|
|
44ea407de5 | ||
|
|
a455b46073 | ||
|
|
3c22087a50 | ||
|
|
52aead1143 | ||
|
|
7ee259de02 | ||
|
|
1102517554 | ||
|
|
3518cbeb12 | ||
|
|
ef519dc14f | ||
|
|
d6663a0c77 | ||
|
|
536181bf06 | ||
|
|
0e30e13dec | ||
|
|
8a345be259 | ||
|
|
1608fde341 | ||
|
|
f7d731d1b9 | ||
|
|
00018650f8 | ||
|
|
cc4ee6d888 | ||
|
|
ac241e2676 | ||
|
|
d59b9e7059 | ||
|
|
10079ceba3 | ||
|
|
4c3f221c38 | ||
|
|
66db1449d1 | ||
|
|
0bbb53a03d | ||
|
|
e069aad656 | ||
|
|
5823d05d32 | ||
|
|
a8c35f3cb7 | ||
|
|
3befac7138 | ||
|
|
b4e2705a99 | ||
|
|
b22044216a | ||
|
|
1531915c1b | ||
|
|
273ea38e01 | ||
|
|
0b5baabfb2 | ||
|
|
d4a82ffafe | ||
|
|
6d489f2d17 | ||
|
|
4eca1585e7 | ||
|
|
0ada85d692 | ||
|
|
7726e01bcc | ||
|
|
44867affbe | ||
|
|
42dd6453fe | ||
|
|
cf9af05420 | ||
|
|
db77866cb7 | ||
|
|
3e40bc15b3 | ||
|
|
1bf7e9cbad | ||
|
|
f516a08415 | ||
|
|
c6ad7ffeca | ||
|
|
2fe8f449b3 | ||
|
|
d5f692c206 | ||
|
|
24c0e4fea8 | ||
|
|
9b75934b47 | ||
|
|
70703c6184 | ||
|
|
d0cb701907 | ||
|
|
4b41ccdb72 | ||
|
|
d7640a7047 | ||
|
|
5adc19e4da | ||
|
|
9f9287368c | ||
|
|
f1970ac7c8 | ||
|
|
141803b156 | ||
|
|
fbca946420 | ||
|
|
a7054bce15 | ||
|
|
0d8a4b61a6 | ||
|
|
fd349ae104 | ||
|
|
0ad979823e | ||
|
|
fcb2e5ed19 | ||
|
|
57a9ec8b29 | ||
|
|
3373e49fd0 | ||
|
|
a008a4e8c3 | ||
|
|
17d0daff86 | ||
|
|
2be9922b71 | ||
|
|
e25ce9548e | ||
|
|
45a7fa9f08 | ||
|
|
b1bf048295 | ||
|
|
4f906ac65f | ||
|
|
eb03c50ca8 | ||
|
|
44b156e1a7 | ||
|
|
b3754e7194 | ||
|
|
fde2b7607d | ||
|
|
51c510fb0c | ||
|
|
770cbad36f | ||
|
|
350b89e14e | ||
|
|
5002f7159a | ||
|
|
34ca29cee7 | ||
|
|
2db2c449f5 | ||
|
|
1fe5fbff5b | ||
|
|
3ede93d496 | ||
|
|
00ffa08659 | ||
|
|
4cc3212c9a | ||
|
|
b1b0770a86 |
1
.idea/artifacts/KotlinPlugin.xml
generated
1
.idea/artifacts/KotlinPlugin.xml
generated
@@ -25,6 +25,7 @@
|
||||
<element id="module-output" name="js.parser" />
|
||||
<element id="module-output" name="cli-common" />
|
||||
<element id="module-output" name="idea-jps-common" />
|
||||
<element id="module-output" name="build-common" />
|
||||
<element id="module-output" name="preloader" />
|
||||
<element id="module-output" name="deserialization" />
|
||||
<element id="module-output" name="backend-common" />
|
||||
|
||||
4
.idea/kotlinc.xml
generated
4
.idea/kotlinc.xml
generated
@@ -1,5 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
</component>
|
||||
<component name="KotlinCompilerSettings">
|
||||
<option name="additionalArguments" value="-version -Xallow-kotlin-package -Xskip-metadata-version-check" />
|
||||
</component>
|
||||
|
||||
2189
ChangeLog.md
2189
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ import java.io.File
|
||||
class Kotlin2JsTask : KotlinCompilerBaseTask() {
|
||||
override val compilerFqName = "org.jetbrains.kotlin.cli.js.K2JSCompiler"
|
||||
|
||||
var library: Path? = null
|
||||
var libraries: Path? = null
|
||||
var outputPrefix: File? = null
|
||||
var outputPostfix: File? = null
|
||||
var sourceMap: Boolean = false
|
||||
@@ -35,15 +35,9 @@ class Kotlin2JsTask : KotlinCompilerBaseTask() {
|
||||
*/
|
||||
var main: String? = null
|
||||
|
||||
fun createLibrary(): Path {
|
||||
val libraryPath = library
|
||||
if (libraryPath == null) {
|
||||
val t = Path(getProject())
|
||||
library = t
|
||||
return t
|
||||
}
|
||||
|
||||
return libraryPath.createPath()
|
||||
fun createLibraries(): Path {
|
||||
val libraryPaths = libraries ?: return Path(getProject()).also { libraries = it }
|
||||
return libraryPaths.createPath()
|
||||
}
|
||||
|
||||
override fun fillSpecificArguments() {
|
||||
@@ -51,9 +45,9 @@ class Kotlin2JsTask : KotlinCompilerBaseTask() {
|
||||
args.add(output!!.canonicalPath)
|
||||
|
||||
// TODO: write test
|
||||
library?.let {
|
||||
args.add("-library-files")
|
||||
args.add(it.list().joinToString(separator = ",") { File(it).canonicalPath })
|
||||
libraries?.let {
|
||||
args.add("-libraries")
|
||||
args.add(it.list().joinToString(File.pathSeparator) { File(it).canonicalPath })
|
||||
}
|
||||
|
||||
outputPrefix?.let {
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.full.createType
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
|
||||
inline fun <reified T : Any> serializeToPlainText(instance: T): String {
|
||||
inline fun <reified T : Any> serializeToPlainText(instance: T): String = serializeToPlainText(instance, T::class)
|
||||
|
||||
fun <T : Any> serializeToPlainText(instance: T, klass: KClass<T>): String {
|
||||
val lines = ArrayList<String>()
|
||||
for (property in T::class.memberProperties) {
|
||||
for (property in klass.memberProperties) {
|
||||
val value = property.get(instance)
|
||||
if (value != null) {
|
||||
lines.add("${property.name}=$value")
|
||||
@@ -33,18 +33,18 @@ inline fun <reified T : Any> serializeToPlainText(instance: T): String {
|
||||
return lines.joinToString("\n")
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> deserializeFromPlainText(str: String): T? {
|
||||
inline fun <reified T : Any> deserializeFromPlainText(str: String): T? = deserializeFromPlainText(str, T::class)
|
||||
|
||||
fun <T : Any> deserializeFromPlainText(str: String, klass: KClass<T>): T? {
|
||||
val args = ArrayList<Any?>()
|
||||
val properties = str
|
||||
.split("\n")
|
||||
.filter(String::isNotBlank)
|
||||
.associate { it.substringBefore("=") to it.substringAfter("=") }
|
||||
|
||||
val primaryConstructor = T::class.primaryConstructor
|
||||
?: throw IllegalStateException("Class ${T::class.java} does not have primary constructor")
|
||||
val params = primaryConstructor.parameters
|
||||
val sortedBy = params.sortedBy { it.index }
|
||||
for (param in sortedBy) {
|
||||
val primaryConstructor = klass.primaryConstructor
|
||||
?: throw IllegalStateException("${klass.java} does not have primary constructor")
|
||||
for (param in primaryConstructor.parameters.sortedBy { it.index }) {
|
||||
val argumentString = properties[param.name]
|
||||
|
||||
if (argumentString == null) {
|
||||
@@ -57,10 +57,10 @@ inline fun <reified T : Any> deserializeFromPlainText(str: String): T? {
|
||||
}
|
||||
}
|
||||
|
||||
val argument: Any? = when {
|
||||
param.isTypeOrNullableType(Int::class) -> argumentString.toInt()
|
||||
param.isTypeOrNullableType(Boolean::class) -> argumentString.toBoolean()
|
||||
param.isTypeOrNullableType(String::class) -> argumentString
|
||||
val argument: Any? = when (param.type.classifier) {
|
||||
Int::class -> argumentString.toInt()
|
||||
Boolean::class -> argumentString.toBoolean()
|
||||
String::class -> argumentString
|
||||
else -> throw IllegalStateException("Unexpected property type: ${param.type}")
|
||||
}
|
||||
|
||||
@@ -69,9 +69,3 @@ inline fun <reified T : Any> deserializeFromPlainText(str: String): T? {
|
||||
|
||||
return primaryConstructor.call(*args.toTypedArray())
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Any> KParameter.isTypeOrNullableType(klass: KClass<T>): Boolean =
|
||||
this.type == klass.createType(nullable = true) || this.type == klass.createType(nullable = false)
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.io.File
|
||||
|
||||
private val NORMAL_VERSION = 8
|
||||
private val EXPERIMENTAL_VERSION = 4
|
||||
private val DATA_CONTAINER_VERSION = 1
|
||||
private val DATA_CONTAINER_VERSION = 2
|
||||
|
||||
private val NORMAL_VERSION_FILE_NAME = "format-version.txt"
|
||||
private val EXPERIMENTAL_VERSION_FILE_NAME = "experimental-format-version.txt"
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.build
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
@@ -28,27 +30,26 @@ class JvmBuildMetaInfoTest : TestCase() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo(args)
|
||||
val actual = JvmBuildMetaInfo.serializeToString(info)
|
||||
val expectedTempalte =
|
||||
"""apiVersionString=1.1
|
||||
bytecodeVersionMajor=1
|
||||
bytecodeVersionMinor=0
|
||||
bytecodeVersionPatch=1
|
||||
compilerBuildVersion=@snapshot@
|
||||
coroutinesEnable=false
|
||||
coroutinesError=false
|
||||
coroutinesVersion=0
|
||||
coroutinesWarn=false
|
||||
isEAP=@isEAP@
|
||||
languageVersionString=1.1
|
||||
metadataVersionMajor=1
|
||||
metadataVersionMinor=1
|
||||
metadataVersionPatch=3
|
||||
multiplatformEnable=false
|
||||
multiplatformVersion=0
|
||||
ownVersion=0"""
|
||||
val expected = expectedTempalte.replace("@snapshot@", KotlinCompilerVersion.VERSION)
|
||||
.replace("@isEAP@", KotlinCompilerVersion.IS_PRE_RELEASE.toString())
|
||||
assertEquals(expected, actual)
|
||||
val expectedKeys = listOf(
|
||||
"apiVersionString",
|
||||
"bytecodeVersionMajor",
|
||||
"bytecodeVersionMinor",
|
||||
"bytecodeVersionPatch",
|
||||
"compilerBuildVersion",
|
||||
"coroutinesEnable",
|
||||
"coroutinesError",
|
||||
"coroutinesVersion",
|
||||
"coroutinesWarn",
|
||||
"isEAP",
|
||||
"languageVersionString",
|
||||
"metadataVersionMajor",
|
||||
"metadataVersionMinor",
|
||||
"metadataVersionPatch",
|
||||
"multiplatformEnable",
|
||||
"multiplatformVersion",
|
||||
"ownVersion"
|
||||
)
|
||||
assertEquals(expectedKeys, actual.split("\r\n", "\n").map { line -> line.split("=").first() })
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
21
build.xml
21
build.xml
@@ -314,6 +314,7 @@
|
||||
|
||||
<macrodef name="new-kotlin2js">
|
||||
<attribute name="output"/>
|
||||
<attribute name="additionalOptions" default=""/>
|
||||
<element name="src"/>
|
||||
|
||||
<sequential>
|
||||
@@ -341,8 +342,7 @@
|
||||
<arg value="@{output}"/>
|
||||
<arg value="-no-stdlib"/>
|
||||
<arg value="-version"/>
|
||||
<arg value="-meta-info"/>
|
||||
<arg value="-kjsm"/>
|
||||
<arg line="@{additionalOptions}"/>
|
||||
<arg line="-main noCall"/>
|
||||
<arg line="-module-kind commonjs"/>
|
||||
<arg value="-Xallow-kotlin-package"/>
|
||||
@@ -406,9 +406,13 @@
|
||||
byline="true" encoding="UTF-8" />
|
||||
</target>
|
||||
|
||||
<target name="js-stdlib">
|
||||
<property environment="env"/>
|
||||
<target name="js-stdlib-preprocess">
|
||||
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
|
||||
</target>
|
||||
|
||||
<target name="js-stdlib" depends="js-stdlib-preprocess">
|
||||
<property environment="env"/>
|
||||
<cleandir dir="${js.stdlib.output.dir}"/>
|
||||
|
||||
<!-- We don't want descriptors for built-ins to be serialized, so we compile these files separately. -->
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/tmp-builtins/kotlin.js">
|
||||
@@ -419,7 +423,7 @@
|
||||
</src>
|
||||
</new-kotlin2js>
|
||||
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/tmp/kotlin.js">
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/tmp/kotlin.js" additionalOptions="-meta-info">
|
||||
<src>
|
||||
<union>
|
||||
<fileset refid="kotlin.builtin.files"/>
|
||||
@@ -473,7 +477,7 @@
|
||||
<copy file="${kotlin-home}/lib/kotlin-stdlib-js.jar" tofile="${kotlin-home}/lib/kotlin-jslib.jar" />
|
||||
</target>
|
||||
|
||||
<target name="pack-js-stdlib-sources">
|
||||
<target name="pack-js-stdlib-sources" depends="js-stdlib-preprocess">
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-stdlib-js-sources.jar" duplicate="fail">
|
||||
<resources refid="js.lib.files" />
|
||||
<fileset refid="kotlin.builtin.files" />
|
||||
@@ -1023,13 +1027,13 @@
|
||||
<sequential>
|
||||
<java classname="org.jetbrains.kotlin.preloading.Preloader" failonerror="true" fork="true" maxmemory="${max.heap.size.for.forked.jvm}">
|
||||
<classpath>
|
||||
<pathelement location="${kotlin-home}/lib/kotlin-preloader.jar"/>
|
||||
<pathelement location="${bootstrap.compiler.home}/lib/kotlin-preloader.jar"/>
|
||||
</classpath>
|
||||
<assertions>
|
||||
<enable/>
|
||||
</assertions>
|
||||
<arg value="-cp"/>
|
||||
<arg value="${kotlin-home}/lib/kotlin-compiler.jar"/>
|
||||
<arg value="${bootstrap.compiler.home}/lib/kotlin-compiler.jar"/>
|
||||
<arg value="org.jetbrains.kotlin.preprocessor.PreprocessorCLI"/>
|
||||
<arg value="@{src}"/>
|
||||
<arg value="@{output}"/>
|
||||
@@ -1118,7 +1122,6 @@
|
||||
<arg value="${output}/classes/kotlin-test-js/kotlin-test.js"/>
|
||||
<arg value="-version"/>
|
||||
<arg value="-meta-info"/>
|
||||
<arg value="-kjsm"/>
|
||||
<arg line="-main noCall"/>
|
||||
<arg line="-module-kind umd"/>
|
||||
<arg value="-Xmulti-platform"/>
|
||||
|
||||
@@ -168,6 +168,11 @@ public class AsmUtil {
|
||||
return Type.getType(internalName.substring(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type getArrayType(@NotNull Type componentType) {
|
||||
return Type.getType("[" + componentType.getDescriptor());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PrimitiveType asmPrimitiveTypeToLangPrimitiveType(Type type) {
|
||||
JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort());
|
||||
@@ -587,6 +592,10 @@ public class AsmUtil {
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||
}
|
||||
|
||||
public static void genIEEE754EqualForNullableTypesCall(InstructionAdapter v, Type left, Type right) {
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(" + left.getDescriptor() + right.getDescriptor() + ")Z", false);
|
||||
}
|
||||
|
||||
public static void numConst(int value, Type type, InstructionAdapter v) {
|
||||
if (type == Type.FLOAT_TYPE) {
|
||||
v.fconst(value);
|
||||
|
||||
@@ -232,9 +232,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
@Override
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(funDescriptor);
|
||||
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, funDescriptor);
|
||||
assert method != null : "No method for " + funDescriptor;
|
||||
FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
|
||||
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
|
||||
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
|
||||
assert method != null : "No method for " + frontendFunDescriptor;
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
|
||||
|
||||
final DescriptorSerializer serializer =
|
||||
|
||||
@@ -17,12 +17,8 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
|
||||
class ClosureGenerationStrategy(
|
||||
state: GenerationState,
|
||||
@@ -30,35 +26,8 @@ class ClosureGenerationStrategy(
|
||||
) : FunctionGenerationStrategy.FunctionDefault(state, declaration) {
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
processDestructuringInLambdaParameters(codegen)
|
||||
initializeVariablesForDestructuredLambdaParameters(codegen, codegen.context.functionDescriptor.valueParameters)
|
||||
|
||||
super.doGenerateBody(codegen, signature)
|
||||
}
|
||||
|
||||
private fun processDestructuringInLambdaParameters(codegen: ExpressionCodegen) {
|
||||
val savedIsShouldMarkLineNumbers = codegen.isShouldMarkLineNumbers
|
||||
// Do not write line numbers until destructuring happens
|
||||
// (otherwise destructuring variables will be uninitialized in the beginning of lambda)
|
||||
codegen.isShouldMarkLineNumbers = false
|
||||
|
||||
for (parameterDescriptor in codegen.context.functionDescriptor.valueParameters) {
|
||||
if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue
|
||||
|
||||
for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) {
|
||||
codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type))
|
||||
}
|
||||
|
||||
val destructuringDeclaration =
|
||||
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
|
||||
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
|
||||
|
||||
codegen.initializeDestructuringDeclarationVariables(
|
||||
destructuringDeclaration,
|
||||
TransientReceiver(parameterDescriptor.type),
|
||||
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
|
||||
)
|
||||
}
|
||||
|
||||
codegen.isShouldMarkLineNumbers = savedIsShouldMarkLineNumbers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.config.ApiVersion;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||
@@ -2942,13 +2943,35 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// The solution is to spill stack just after receiver is loaded (after IFNULL) in case of safe call.
|
||||
// But the problem is that we should leave the receiver itself on the stack, so we store it in a temporary variable.
|
||||
if (isSuspensionPoint && isSafeCallOrOnStack) {
|
||||
int tmpVar = myFrameMap.enterTemp(receiver.type);
|
||||
boolean bothReceivers =
|
||||
receiver instanceof StackValue.CallReceiver
|
||||
&& ((StackValue.CallReceiver) receiver).getDispatchReceiver().type.getSort() != Type.VOID
|
||||
&& ((StackValue.CallReceiver) receiver).getExtensionReceiver().type.getSort() != Type.VOID;
|
||||
Type firstReceiverType =
|
||||
bothReceivers
|
||||
? ((StackValue.CallReceiver) receiver).getDispatchReceiver().type
|
||||
: receiver.type;
|
||||
|
||||
Type secondReceiverType = bothReceivers ? receiver.type : null;
|
||||
|
||||
int tmpVarForFirstReceiver = myFrameMap.enterTemp(firstReceiverType);
|
||||
int tmpVarForSecondReceiver = -1;
|
||||
|
||||
if (secondReceiverType != null) {
|
||||
tmpVarForSecondReceiver = myFrameMap.enterTemp(secondReceiverType);
|
||||
v.store(tmpVarForSecondReceiver, secondReceiverType);
|
||||
}
|
||||
v.store(tmpVarForFirstReceiver, firstReceiverType);
|
||||
|
||||
v.store(tmpVar, receiver.type);
|
||||
addInlineMarker(v, true);
|
||||
v.load(tmpVar, receiver.type);
|
||||
|
||||
myFrameMap.leaveTemp(receiver.type);
|
||||
v.load(tmpVarForFirstReceiver, firstReceiverType);
|
||||
if (secondReceiverType != null) {
|
||||
v.load(tmpVarForSecondReceiver, secondReceiverType);
|
||||
myFrameMap.leaveTemp(secondReceiverType);
|
||||
}
|
||||
|
||||
myFrameMap.leaveTemp(firstReceiverType);
|
||||
}
|
||||
|
||||
callableMethod.afterReceiverGeneration(v);
|
||||
@@ -3362,7 +3385,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
KotlinType type = lhs.getType();
|
||||
if (lhs instanceof DoubleColonLHS.Expression && !((DoubleColonLHS.Expression) lhs).isObject()) {
|
||||
if (lhs instanceof DoubleColonLHS.Expression && !((DoubleColonLHS.Expression) lhs).isObjectQualifier()) {
|
||||
JavaClassProperty.INSTANCE.generateImpl(v, gen(receiverExpression));
|
||||
}
|
||||
else {
|
||||
@@ -3604,18 +3627,43 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
/*tries to use IEEE 754 arithmetic*/
|
||||
private StackValue genEqualsForExpressionsPreferIEEE754Arithmetic(
|
||||
@Nullable KtExpression left,
|
||||
@Nullable KtExpression right,
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable final KtExpression left,
|
||||
@Nullable final KtExpression right,
|
||||
@NotNull final IElementType opToken,
|
||||
@NotNull Type leftType,
|
||||
@NotNull Type rightType,
|
||||
@Nullable StackValue pregeneratedLeft
|
||||
@Nullable final StackValue pregeneratedLeft
|
||||
) {
|
||||
Type left754Type = calcTypeForIEEE754ArithmeticIfNeeded(left);
|
||||
Type right754Type = calcTypeForIEEE754ArithmeticIfNeeded(right);
|
||||
if (left754Type != null && right754Type != null && left754Type.equals(right754Type)) {
|
||||
leftType = left754Type;
|
||||
rightType = right754Type;
|
||||
assert (opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) : "Optoken should be '==' or '!=', but: " + opToken;
|
||||
|
||||
final TypeAndNullability left754Type = calcTypeForIEEE754ArithmeticIfNeeded(left);
|
||||
final TypeAndNullability right754Type = calcTypeForIEEE754ArithmeticIfNeeded(right);
|
||||
if (left754Type != null && right754Type != null && left754Type.type.equals(right754Type.type)) {
|
||||
//check nullability cause there is some optimizations in codegen for non-nullable case
|
||||
if (left754Type.isNullable || right754Type.isNullable) {
|
||||
if (state.getLanguageVersionSettings().getApiVersion().compareTo(ApiVersion.KOTLIN_1_1) >= 0) {
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
generate754EqualsForNullableTypesViaIntrinsic(v, opToken, pregeneratedLeft, left, left754Type, right, right754Type);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
generate754EqualsForNullableTypes(v, opToken, pregeneratedLeft, left, left754Type, right, right754Type);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
leftType = left754Type.type;
|
||||
rightType = right754Type.type;
|
||||
}
|
||||
}
|
||||
|
||||
return genEqualsForExpressionsOnStack(
|
||||
@@ -3625,6 +3673,126 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
);
|
||||
}
|
||||
|
||||
private void generate754EqualsForNullableTypesViaIntrinsic(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable StackValue pregeneratedLeft,
|
||||
@Nullable KtExpression left,
|
||||
@NotNull TypeAndNullability left754Type,
|
||||
@Nullable KtExpression right,
|
||||
@NotNull TypeAndNullability right754Type
|
||||
) {
|
||||
Type leftType = left754Type.isNullable ? AsmUtil.boxType(left754Type.type) : left754Type.type;
|
||||
|
||||
if (pregeneratedLeft != null) {
|
||||
StackValue.coercion(pregeneratedLeft, leftType).put(leftType, v);
|
||||
}
|
||||
else {
|
||||
gen(left, leftType);
|
||||
}
|
||||
Type rightType = right754Type.isNullable ? AsmUtil.boxType(right754Type.type) : right754Type.type;
|
||||
gen(right, rightType);
|
||||
|
||||
AsmUtil.genIEEE754EqualForNullableTypesCall(v, leftType, rightType);
|
||||
|
||||
if (opToken == KtTokens.EXCLEQ) {
|
||||
genInvertBoolean(v);
|
||||
}
|
||||
}
|
||||
|
||||
private void generate754EqualsForNullableTypes(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable StackValue pregeneratedLeft,
|
||||
@Nullable KtExpression left,
|
||||
@NotNull TypeAndNullability left754Type,
|
||||
@Nullable KtExpression right,
|
||||
@NotNull TypeAndNullability right754Type
|
||||
) {
|
||||
int equals = opToken == KtTokens.EQEQ ? 1 : 0;
|
||||
int notEquals = opToken != KtTokens.EQEQ ? 1 : 0;
|
||||
Label end = new Label();
|
||||
StackValue leftValue = pregeneratedLeft != null ? pregeneratedLeft : gen(left);
|
||||
leftValue.put(leftValue.type, v);
|
||||
leftValue = StackValue.onStack(leftValue.type);
|
||||
Type leftType = left754Type.type;
|
||||
Type rightType = right754Type.type;
|
||||
if (left754Type.isNullable) {
|
||||
leftValue.dup(v, false);
|
||||
Label leftIsNull = new Label();
|
||||
v.ifnull(leftIsNull);
|
||||
StackValue.coercion(leftValue, leftType).put(leftType, v);
|
||||
StackValue nonNullLeftValue = StackValue.onStack(leftType);
|
||||
|
||||
StackValue rightValue = gen(right);
|
||||
rightValue.put(rightValue.type, v);
|
||||
rightValue = StackValue.onStack(rightValue.type);
|
||||
if (right754Type.isNullable) {
|
||||
rightValue.dup(v, false);
|
||||
Label rightIsNotNull = new Label();
|
||||
v.ifnonnull(rightIsNotNull);
|
||||
AsmUtil.pop(v, rightValue.type);
|
||||
AsmUtil.pop(v, nonNullLeftValue.type);
|
||||
v.iconst(notEquals);
|
||||
v.goTo(end);
|
||||
v.mark(rightIsNotNull);
|
||||
}
|
||||
|
||||
StackValue.coercion(rightValue, rightType).put(rightType, v);
|
||||
StackValue nonNullRightValue = StackValue.onStack(rightType);
|
||||
StackValue.cmp(opToken, leftType, nonNullLeftValue, nonNullRightValue).put(Type.BOOLEAN_TYPE, v);
|
||||
v.goTo(end);
|
||||
|
||||
//left is null case
|
||||
v.mark(leftIsNull);
|
||||
AsmUtil.pop(v, leftValue.type);//pop null left
|
||||
rightValue = gen(right);
|
||||
rightValue.put(rightValue.type, v);
|
||||
rightValue = StackValue.onStack(rightValue.type);
|
||||
if (right754Type.isNullable) {
|
||||
Label rightIsNotNull = new Label();
|
||||
v.ifnonnull(rightIsNotNull);
|
||||
v.iconst(equals);
|
||||
v.goTo(end);
|
||||
v.mark(rightIsNotNull);
|
||||
v.iconst(notEquals);
|
||||
//v.goTo(end);
|
||||
}
|
||||
else {
|
||||
AsmUtil.pop(v, rightValue.type);
|
||||
v.iconst(notEquals);
|
||||
//v.goTo(end);
|
||||
}
|
||||
|
||||
v.mark(end);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
StackValue.coercion(leftValue, leftType).put(leftType, v);
|
||||
leftValue = StackValue.onStack(leftType);
|
||||
}
|
||||
|
||||
//right is nullable cause left is not
|
||||
StackValue rightValue = gen(right);
|
||||
rightValue.put(rightValue.type, v);
|
||||
rightValue = StackValue.onStack(rightValue.type);
|
||||
|
||||
rightValue.dup(v, false);
|
||||
Label rightIsNotNull = new Label();
|
||||
v.ifnonnull(rightIsNotNull);
|
||||
AsmUtil.pop(v, rightValue.type);
|
||||
AsmUtil.pop(v, leftValue.type);
|
||||
v.iconst(notEquals);
|
||||
v.goTo(end);
|
||||
|
||||
v.mark(rightIsNotNull);
|
||||
StackValue.coercion(rightValue, rightType).put(rightType, v);
|
||||
StackValue nonNullRightValue = StackValue.onStack(rightType);
|
||||
StackValue.cmp(opToken, leftType, leftValue, nonNullRightValue).put(Type.BOOLEAN_TYPE, v);
|
||||
|
||||
v.mark(end);
|
||||
}
|
||||
|
||||
private boolean isIntZero(KtExpression expr, Type exprType) {
|
||||
ConstantValue<?> exprValue = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext, state.getShouldInlineConstVals());
|
||||
return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue());
|
||||
@@ -3686,12 +3854,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
StackValue rightValue;
|
||||
Type leftType = expressionType(left);
|
||||
Type rightType = expressionType(right);
|
||||
Type left754Type = calcTypeForIEEE754ArithmeticIfNeeded(left);
|
||||
Type right754Type = calcTypeForIEEE754ArithmeticIfNeeded(right);
|
||||
TypeAndNullability left754Type = calcTypeForIEEE754ArithmeticIfNeeded(left);
|
||||
TypeAndNullability right754Type = calcTypeForIEEE754ArithmeticIfNeeded(right);
|
||||
Callable callable = resolveToCallable((FunctionDescriptor) resolvedCall.getResultingDescriptor(), false, resolvedCall);
|
||||
boolean is754Arithmetic = left754Type != null && right754Type != null && left754Type.equals(right754Type);
|
||||
boolean is754Arithmetic = left754Type != null && right754Type != null && left754Type.type.equals(right754Type.type);
|
||||
if (callable instanceof IntrinsicCallable && ((isPrimitive(leftType) && isPrimitive(rightType)) || is754Arithmetic)) {
|
||||
type = is754Arithmetic ? left754Type : comparisonOperandType(leftType, rightType);
|
||||
type = is754Arithmetic ? left754Type.type : comparisonOperandType(leftType, rightType);
|
||||
leftValue = gen(left);
|
||||
rightValue = gen(right);
|
||||
}
|
||||
@@ -3703,7 +3871,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.cmp(expression.getOperationToken(), type, leftValue, rightValue);
|
||||
}
|
||||
|
||||
private Type calcTypeForIEEE754ArithmeticIfNeeded(@Nullable KtExpression expression) {
|
||||
private TypeAndNullability calcTypeForIEEE754ArithmeticIfNeeded(@Nullable KtExpression expression) {
|
||||
return CodegenUtilKt.calcTypeForIEEE754ArithmeticIfNeeded(expression, bindingContext, context.getFunctionDescriptor());
|
||||
}
|
||||
|
||||
@@ -4705,7 +4873,8 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
public NameGenerator getInlineNameGenerator() {
|
||||
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
|
||||
Name name = context.getContextDescriptor().getName();
|
||||
return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" );
|
||||
String inlinedName = name.isSpecial() ? InlineCodegenUtil.SPECIAL_TRANSFORMATION_NAME : name.asString();
|
||||
return nameGenerator.subGenerator(inlinedName + InlineCodegenUtil.INLINE_CALL_TRANSFORMATION_SUFFIX);
|
||||
}
|
||||
|
||||
public Type getReturnType() {
|
||||
|
||||
@@ -209,7 +209,11 @@ public class FunctionCodegen {
|
||||
getThrownExceptions(functionDescriptor, typeMapper));
|
||||
|
||||
if (CodegenContextUtil.isImplClassOwner(owner)) {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
||||
v.getSerializationBindings().put(
|
||||
METHOD_FOR_FUNCTION,
|
||||
CodegenUtilKt.<FunctionDescriptor>unwrapFrontendVersion(functionDescriptor),
|
||||
asmMethod
|
||||
);
|
||||
}
|
||||
|
||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
|
||||
|
||||
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||
private final ResolvedCall<?> resolvedCall;
|
||||
private final FunctionDescriptor referencedFunction;
|
||||
@@ -146,6 +148,12 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0) -
|
||||
(receiverType != null ? 1 : 0);
|
||||
|
||||
if (receivers < 0 && referencedFunction instanceof ConstructorDescriptor && isObject(referencedFunction.getContainingDeclaration().getContainingDeclaration())) {
|
||||
//reference to object nested class
|
||||
//TODO: seems problem should be fixed on frontend side (note that object instance are captured by generated class)
|
||||
receivers = 0;
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> parameters = CollectionsKt.drop(functionDescriptor.getValueParameters(), receivers);
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
ValueParameterDescriptor parameter = parameters.get(i);
|
||||
|
||||
@@ -492,10 +492,11 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
int indexOfDelegatedProperty = PropertyCodegen.indexOfDelegatedProperty(property);
|
||||
|
||||
StackValue delegateValue = PropertyCodegen.invokeDelegatedPropertyConventionMethodWithReceiver(
|
||||
codegen, typeMapper, provideDelegateResolvedCall, indexOfDelegatedProperty, 1, provideDelegateReceiver);
|
||||
codegen, typeMapper, provideDelegateResolvedCall, indexOfDelegatedProperty, 1,
|
||||
provideDelegateReceiver, propertyDescriptor
|
||||
);
|
||||
|
||||
propValue.store(delegateValue, codegen.v);
|
||||
|
||||
}
|
||||
|
||||
protected boolean shouldInitializeProperty(@NotNull KtProperty property) {
|
||||
@@ -583,7 +584,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
if (delegatedProperties.isEmpty()) return;
|
||||
|
||||
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
|
||||
v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
|
||||
"[" + K_PROPERTY_TYPE, null, null);
|
||||
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
|
||||
@@ -58,6 +58,9 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPropertyWithBackingFieldCopyInOuterClass;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.FIELD_FOR_PROPERTY;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY;
|
||||
@@ -540,7 +543,7 @@ public class PropertyCodegen {
|
||||
StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
|
||||
return invokeDelegatedPropertyConventionMethodWithReceiver(
|
||||
codegen, typeMapper, resolvedCall, indexInPropertyMetadataArray, propertyMetadataArgumentIndex,
|
||||
receiver
|
||||
receiver, propertyDescriptor
|
||||
);
|
||||
}
|
||||
|
||||
@@ -550,9 +553,12 @@ public class PropertyCodegen {
|
||||
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
|
||||
final int indexInPropertyMetadataArray,
|
||||
int propertyMetadataArgumentIndex,
|
||||
@Nullable StackValue receiver
|
||||
@Nullable StackValue receiver,
|
||||
@NotNull PropertyDescriptor propertyDescriptor
|
||||
) {
|
||||
final Type owner = getDelegatedPropertyMetadataOwner(codegen, typeMapper);
|
||||
final Type owner = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor) ?
|
||||
codegen.getState().getTypeMapper().mapOwner(propertyDescriptor) :
|
||||
getDelegatedPropertyMetadataOwner(codegen, typeMapper);
|
||||
|
||||
codegen.tempVariables.put(
|
||||
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
|
||||
|
||||
@@ -281,33 +281,24 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private static void box(Type type, Type toType, InstructionAdapter v) {
|
||||
if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.cast(type, Type.BYTE_TYPE);
|
||||
v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";", false);
|
||||
}
|
||||
else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.cast(type, Type.SHORT_TYPE);
|
||||
v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";", false);
|
||||
}
|
||||
else if (type == Type.LONG_TYPE || toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.cast(type, Type.LONG_TYPE);
|
||||
v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME + ";", false);
|
||||
}
|
||||
else if (type == Type.INT_TYPE) {
|
||||
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
}
|
||||
else if (type == Type.BOOLEAN_TYPE) {
|
||||
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
}
|
||||
else if (type == Type.CHAR_TYPE) {
|
||||
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
}
|
||||
else if (type == Type.FLOAT_TYPE) {
|
||||
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
}
|
||||
else if (type == Type.DOUBLE_TYPE) {
|
||||
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
if (type == Type.INT_TYPE) {
|
||||
if (toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME)) {
|
||||
type = Type.BYTE_TYPE;
|
||||
}
|
||||
else if (toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME)) {
|
||||
type = Type.SHORT_TYPE;
|
||||
}
|
||||
else if (toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME)) {
|
||||
type = Type.LONG_TYPE;
|
||||
}
|
||||
v.cast(Type.INT_TYPE, type);
|
||||
}
|
||||
|
||||
Type boxedType = AsmUtil.boxType(type);
|
||||
if (boxedType == type) return;
|
||||
|
||||
v.invokestatic(boxedType.getInternalName(), "valueOf", Type.getMethodDescriptor(boxedType, type), false);
|
||||
coerce(boxedType, toType, v);
|
||||
}
|
||||
|
||||
private static void unbox(Type type, InstructionAdapter v) {
|
||||
@@ -1596,6 +1587,16 @@ public abstract class StackValue {
|
||||
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
|
||||
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getDispatchReceiver() {
|
||||
return dispatchReceiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getExtensionReceiver() {
|
||||
return extensionReceiver;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class StackValueWithSimpleReceiver extends StackValue {
|
||||
|
||||
@@ -21,11 +21,13 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.context.PackageContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
|
||||
@@ -33,12 +35,10 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubclass
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
||||
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -270,25 +271,27 @@ private fun CallableDescriptor.isJvmStaticIn(predicate: (DeclarationDescriptor)
|
||||
fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filterNot { it.name.isSpecial }
|
||||
|
||||
|
||||
fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingContext: BindingContext, descriptor: DeclarationDescriptor): Type? {
|
||||
class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boolean)
|
||||
|
||||
fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingContext: BindingContext, descriptor: DeclarationDescriptor): TypeAndNullability? {
|
||||
val ktType = expression.kotlinType(bindingContext) ?: return null
|
||||
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) {
|
||||
return Type.DOUBLE_TYPE
|
||||
return TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(ktType))
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isFloatOrNullableFloat(ktType)) {
|
||||
return Type.FLOAT_TYPE
|
||||
return TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(ktType))
|
||||
}
|
||||
|
||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow)
|
||||
return stableTypes.firstNotNullResult {
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(it)) {
|
||||
Type.DOUBLE_TYPE
|
||||
TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
||||
}
|
||||
else if (KotlinBuiltIns.isFloatOrNullableFloat(it)) {
|
||||
Type.FLOAT_TYPE
|
||||
TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(it))
|
||||
}
|
||||
else {
|
||||
null
|
||||
@@ -345,3 +348,32 @@ fun MemberDescriptor.isToArrayFromCollection(): Boolean {
|
||||
|
||||
fun FqName.topLevelClassInternalName() = JvmClassName.byClassId(ClassId(parent(), shortName())).internalName
|
||||
fun FqName.topLevelClassAsmType(): Type = Type.getObjectType(topLevelClassInternalName())
|
||||
|
||||
fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodegen, valueParameters: List<ValueParameterDescriptor>) {
|
||||
val savedIsShouldMarkLineNumbers = codegen.isShouldMarkLineNumbers
|
||||
// Do not write line numbers until destructuring happens
|
||||
// (otherwise destructuring variables will be uninitialized in the beginning of lambda)
|
||||
codegen.isShouldMarkLineNumbers = false
|
||||
|
||||
for (parameterDescriptor in valueParameters) {
|
||||
if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue
|
||||
|
||||
for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) {
|
||||
codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type))
|
||||
}
|
||||
|
||||
val destructuringDeclaration =
|
||||
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
|
||||
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
|
||||
|
||||
codegen.initializeDestructuringDeclarationVariables(
|
||||
destructuringDeclaration,
|
||||
TransientReceiver(parameterDescriptor.type),
|
||||
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
|
||||
)
|
||||
}
|
||||
|
||||
codegen.isShouldMarkLineNumbers = savedIsShouldMarkLineNumbers
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()
|
||||
|
||||
@@ -110,6 +110,8 @@ class CoroutineCodegen private constructor(
|
||||
setReturnType(
|
||||
funDescriptor.module.getContinuationOfTypeOrAny(builtIns.unitType)
|
||||
)
|
||||
// 'create' method should not inherit initial descriptor for suspend function from original descriptor
|
||||
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, null)
|
||||
setVisibility(Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
@@ -268,6 +270,9 @@ class CoroutineCodegen private constructor(
|
||||
generateLoadField(parameter.getFieldInfoForCoroutineLambdaParameter())
|
||||
v.store(newIndex, mappedType)
|
||||
}
|
||||
if (isSuspendLambda) {
|
||||
initializeVariablesForDestructuredLambdaParameters(this, originalSuspendFunctionDescriptor.valueParameters)
|
||||
}
|
||||
}
|
||||
|
||||
private fun allLambdaParameters() =
|
||||
@@ -316,6 +321,11 @@ class CoroutineCodegen private constructor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun shouldCreateByLambda(
|
||||
originalSuspendLambdaDescriptor: CallableDescriptor,
|
||||
declaration: KtElement): Boolean {
|
||||
return (declaration is KtFunctionLiteral && originalSuspendLambdaDescriptor.isSuspendLambda)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createByLambda(
|
||||
@@ -324,8 +334,7 @@ class CoroutineCodegen private constructor(
|
||||
declaration: KtElement,
|
||||
classBuilder: ClassBuilder
|
||||
): ClosureCodegen? {
|
||||
if (declaration !is KtFunctionLiteral) return null
|
||||
if (!originalSuspendLambdaDescriptor.isSuspendLambda) return null
|
||||
if (!shouldCreateByLambda(originalSuspendLambdaDescriptor, declaration)) return null
|
||||
|
||||
return CoroutineCodegen(
|
||||
expressionCodegen,
|
||||
|
||||
@@ -229,6 +229,18 @@ class CoroutineTransformerMethodVisitor(
|
||||
}
|
||||
|
||||
for ((index, basicValue) in variablesToSpill) {
|
||||
if (basicValue === StrictBasicValue.NULL_VALUE) {
|
||||
postponedActions.add {
|
||||
with(instructions) {
|
||||
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
||||
aconst(null)
|
||||
store(index, AsmTypes.OBJECT_TYPE)
|
||||
})
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
val type = basicValue.type
|
||||
val normalizedType = type.normalize()
|
||||
|
||||
|
||||
@@ -239,12 +239,12 @@ public class InlineCodegen extends CallGenerator {
|
||||
assert resolvedCall != null : "Resolved call for " + functionDescriptor + " should be not null";
|
||||
Map<TypeParameterDescriptor, KotlinType> arguments = resolvedCall.getTypeArguments();
|
||||
assert arguments.size() == 1 : "Resolved call for " + functionDescriptor + " should have 1 type argument";
|
||||
KotlinType type = arguments.values().iterator().next();
|
||||
|
||||
MethodNode node =
|
||||
InlineCodegenUtil.createSpecialEnumMethodBody(
|
||||
codegen,
|
||||
functionDescriptor.getName().asString(),
|
||||
type,
|
||||
arguments.keySet().iterator().next().getDefaultType(),
|
||||
codegen.getState().getTypeMapper()
|
||||
);
|
||||
return new SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1));
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil;
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.kotlin.codegen.MemberCodegen;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
@@ -60,6 +61,9 @@ import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.ENUM_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_CLASS_TYPE;
|
||||
|
||||
public class InlineCodegenUtil {
|
||||
public static final boolean GENERATE_SMAP = true;
|
||||
public static final int API = Opcodes.ASM5;
|
||||
@@ -77,7 +81,9 @@ public class InlineCodegenUtil {
|
||||
private static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
|
||||
private static final String INLINE_MARKER_FINALLY_START = "finallyStart";
|
||||
private static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
|
||||
public static final String SPECIAL_TRANSFORMATION_NAME = "$special";
|
||||
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
|
||||
public static final String INLINE_CALL_TRANSFORMATION_SUFFIX = "$" + INLINE_TRANSFORMATION_SUFFIX;
|
||||
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
||||
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
||||
|
||||
@@ -530,7 +536,7 @@ public class InlineCodegenUtil {
|
||||
if (!(containingDeclaration instanceof PackageFragmentDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
if (!containingDeclaration.getName().equals(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) {
|
||||
if (!((PackageFragmentDescriptor) containingDeclaration).getFqName().equals(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)) {
|
||||
return false;
|
||||
}
|
||||
if (functionDescriptor.getTypeParameters().size() != 1) {
|
||||
@@ -548,23 +554,30 @@ public class InlineCodegenUtil {
|
||||
@NotNull KotlinType type,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
) {
|
||||
boolean isEnumValues = "enumValues".equals(name);
|
||||
boolean isValueOf = "enumValueOf".equals(name);
|
||||
Type invokeType = typeMapper.mapType(type);
|
||||
String desc = getSpecialEnumFunDescriptor(invokeType, isEnumValues);
|
||||
|
||||
String desc = getSpecialEnumFunDescriptor(invokeType, isValueOf);
|
||||
MethodNode node = new MethodNode(API, Opcodes.ACC_STATIC, "fake", desc, null, null);
|
||||
if (!isEnumValues) {
|
||||
node.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
}
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED, new InstructionAdapter(node));
|
||||
node.visitMethodInsn(Opcodes.INVOKESTATIC, invokeType.getInternalName(), isEnumValues ? "values" : "valueOf", desc, false);
|
||||
if (isValueOf) {
|
||||
node.visitInsn(Opcodes.ACONST_NULL);
|
||||
node.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
node.visitMethodInsn(Opcodes.INVOKESTATIC, ENUM_TYPE.getInternalName(), "valueOf",
|
||||
Type.getMethodDescriptor(ENUM_TYPE, JAVA_CLASS_TYPE, AsmTypes.JAVA_STRING_TYPE), false);
|
||||
}
|
||||
else {
|
||||
node.visitInsn(Opcodes.ICONST_0);
|
||||
node.visitTypeInsn(Opcodes.ANEWARRAY, ENUM_TYPE.getInternalName());
|
||||
}
|
||||
node.visitInsn(Opcodes.ARETURN);
|
||||
node.visitMaxs(isEnumValues ? 2 : 3, isEnumValues ? 0 : 1);
|
||||
node.visitMaxs(isValueOf ? 3 : 2, isValueOf ? 1 : 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
public static String getSpecialEnumFunDescriptor(@NotNull Type type, boolean isEnumValues) {
|
||||
return (isEnumValues ? "()[" : "(Ljava/lang/String;)") + "L" + type.getInternalName() + ";";
|
||||
@NotNull
|
||||
public static String getSpecialEnumFunDescriptor(@NotNull Type type, boolean isValueOf) {
|
||||
return isValueOf ? Type.getMethodDescriptor(type, AsmTypes.JAVA_STRING_TYPE) : Type.getMethodDescriptor(AsmUtil.getArrayType(type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.generateAsCast
|
||||
import org.jetbrains.kotlin.codegen.generateIsCheck
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||
import org.jetbrains.kotlin.codegen.optimization.removeNodeGetNext
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -139,7 +141,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
||||
OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true)
|
||||
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
||||
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
|
||||
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, asmType)
|
||||
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
|
||||
}) {
|
||||
instructions.remove(insn.previous.previous!!) // PUSH operation ID
|
||||
instructions.remove(insn.previous!!) // PUSH type parameter
|
||||
@@ -221,12 +223,27 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processSpecialEnumFunction(insn: MethodInsnNode, parameter: Type): Boolean {
|
||||
val next = insn.next
|
||||
if (next !is MethodInsnNode) return false
|
||||
next.owner = parameter.internalName
|
||||
next.desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, "values" == next.name)
|
||||
return true
|
||||
private fun processSpecialEnumFunction(insn: MethodInsnNode, instructions: InsnList, parameter: Type): Boolean {
|
||||
val next1 = insn.next ?: return false
|
||||
val next2 = next1.next ?: return false
|
||||
if (next1.opcode == Opcodes.ACONST_NULL && next2.opcode == Opcodes.ALOAD) {
|
||||
val next3 = next2.next ?: return false
|
||||
if (next3 is MethodInsnNode && next3.name == "valueOf") {
|
||||
instructions.remove(next1)
|
||||
next3.owner = parameter.internalName
|
||||
next3.desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) {
|
||||
instructions.remove(next1)
|
||||
instructions.remove(next2)
|
||||
val desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, false)
|
||||
instructions.insert(insn, MethodInsnNode(Opcodes.INVOKESTATIC, parameter.internalName, "values", desc, false))
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,13 +72,9 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
|
||||
|
||||
@Override
|
||||
public BasicValue newOperation(@NotNull AbstractInsnNode insn) throws AnalyzerException {
|
||||
if (insn.getOpcode() == Opcodes.ACONST_NULL) {
|
||||
return newValue(Type.getObjectType("java/lang/Object"));
|
||||
}
|
||||
|
||||
switch (insn.getOpcode()) {
|
||||
case ACONST_NULL:
|
||||
return newValue(Type.getObjectType("null"));
|
||||
return NULL_VALUE;
|
||||
case ICONST_M1:
|
||||
case ICONST_0:
|
||||
case ICONST_1:
|
||||
@@ -362,6 +358,9 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
|
||||
// if merge of two references then `lub` is java/lang/Object
|
||||
// arrays also are BasicValues with reference type's
|
||||
if (isReference(v) && isReference(w)) {
|
||||
if (v == NULL_VALUE) return newValue(w.getType());
|
||||
if (w == NULL_VALUE) return newValue(v.getType());
|
||||
|
||||
return StrictBasicValue.REFERENCE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ open class StrictBasicValue(type: Type?) : BasicValue(type) {
|
||||
val SHORT_VALUE = StrictBasicValue(Type.SHORT_TYPE)
|
||||
@JvmField
|
||||
val REFERENCE_VALUE = StrictBasicValue(Type.getObjectType("java/lang/Object"))
|
||||
|
||||
@JvmField
|
||||
val NULL_VALUE = StrictBasicValue(Type.getObjectType("java/lang/Object"))
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@@ -60,4 +63,9 @@ open class StrictBasicValue(type: Type?) : BasicValue(type) {
|
||||
}
|
||||
|
||||
override fun hashCode() = (type?.hashCode() ?: 0)
|
||||
|
||||
override fun toString(): String {
|
||||
if (this === UNINITIALIZED_VALUE) return "."
|
||||
return super.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -958,7 +958,7 @@ public class KotlinTypeMapper {
|
||||
|
||||
if (!(descriptor instanceof ConstructorDescriptor) &&
|
||||
descriptor.getVisibility() == Visibilities.INTERNAL &&
|
||||
!descriptor.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)) {
|
||||
!DescriptorUtilsKt.isPublishedApi(descriptor)) {
|
||||
return name + "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.serialization.builtins
|
||||
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
@@ -26,12 +28,16 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.serialization.MetadataSerializer
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import java.io.File
|
||||
|
||||
class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(dependOnOldBuiltIns) {
|
||||
@@ -88,11 +94,21 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(depe
|
||||
fqName ->
|
||||
val packageView = module.getPackage(fqName)
|
||||
PackageSerializer(
|
||||
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS),
|
||||
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
|
||||
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
|
||||
packageView.fqName,
|
||||
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
|
||||
).run()
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize metadata for kotlin.Cloneable manually for compatibility with kotlin-reflect 1.0 which expects this metadata to be there.
|
||||
// Since Kotlin 1.1, we always discard this class during deserialization (see ClassDeserializer.kt).
|
||||
private fun createCloneable(module: ModuleDescriptor): ClassDescriptor {
|
||||
val factory = JvmBuiltInClassDescriptorFactory(LockBasedStorageManager.NO_LOCKS, module) {
|
||||
EmptyPackageFragmentDescriptor(module, KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
}
|
||||
return factory.createClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe()))
|
||||
?: error("Could not create kotlin.Cloneable in $module")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,9 @@ public abstract class CommonCompilerArguments implements Serializable {
|
||||
@Argument(value = "Xno-check-impl", description = "Do not check presence of 'impl' modifier in multi-platform projects")
|
||||
public boolean noCheckImpl;
|
||||
|
||||
@Argument(value = "Xskip-java-check", description = "Do not warn when running the compiler under Java 6 or 7")
|
||||
public boolean noJavaVersionWarning;
|
||||
|
||||
@Argument(value = "Xcoroutines=warn")
|
||||
public boolean coroutinesWarn;
|
||||
|
||||
|
||||
@@ -35,22 +35,18 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
|
||||
@Argument(value = "no-stdlib", description = "Don't use bundled Kotlin stdlib")
|
||||
public boolean noStdlib;
|
||||
|
||||
@Argument(value = "library-files", description = "Path to zipped library sources or kotlin files separated by commas")
|
||||
@ValueDescription("<path[,]>")
|
||||
public String[] libraryFiles;
|
||||
@Argument(value = "libraries", description = "Paths to Kotlin libraries with .meta.js and .kjsm files, separated by system file separator")
|
||||
@ValueDescription("<path>")
|
||||
public String libraries;
|
||||
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault.class)
|
||||
@Argument(value = "source-map", description = "Generate source map")
|
||||
public boolean sourceMap;
|
||||
|
||||
@GradleOption(DefaultValues.BooleanTrueDefault.class)
|
||||
@Argument(value = "meta-info", description = "Generate metadata")
|
||||
@Argument(value = "meta-info", description = "Generate .meta.js and .kjsm files with metadata. Use to create a library")
|
||||
public boolean metaInfo;
|
||||
|
||||
@GradleOption(DefaultValues.BooleanTrueDefault.class)
|
||||
@Argument(value = "kjsm", description = "Generate kjsm-files (for creating libraries)")
|
||||
public boolean kjsm;
|
||||
|
||||
@GradleOption(DefaultValues.JsEcmaVersions.class)
|
||||
@Argument(value = "target", description = "Generate JS files for specific ECMA version")
|
||||
@ValueDescription("{ v5 }")
|
||||
|
||||
@@ -37,16 +37,22 @@ import java.util.*
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> copyBean(bean: T) = copyFields(bean, bean.javaClass.newInstance(), true)
|
||||
fun <T : Any> copyBean(bean: T) = copyFields(bean, bean.javaClass.newInstance(), true, collectFieldsToCopy(bean.javaClass, false))
|
||||
|
||||
fun <From : Any, To : From> mergeBeans(from: From, to: To): To {
|
||||
// TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity
|
||||
return copyFields(from, XmlSerializerUtil.createCopy(to), false)
|
||||
return copyFields(from, XmlSerializerUtil.createCopy(to), false, collectFieldsToCopy(from.javaClass, false))
|
||||
}
|
||||
|
||||
private fun <From : Any, To : From> copyFields(from: From, to: To, deepCopyWhenNeeded: Boolean = false): To {
|
||||
val fromFields = collectFieldsToCopy(from.javaClass)
|
||||
for (fromField in fromFields) {
|
||||
fun <From : Any, To : Any> copyInheritedFields(from: From, to: To) = copyFields(from, to, true, collectFieldsToCopy(from.javaClass, true))
|
||||
|
||||
fun <From : Any, To : Any> copyFieldsSatisfying(from: From, to: To, predicate: (Field) -> Boolean) =
|
||||
copyFields(from, to, true, collectFieldsToCopy(from.javaClass, false).filter(predicate))
|
||||
|
||||
private fun <From : Any, To : Any> copyFields(from: From, to: To, deepCopyWhenNeeded: Boolean, fieldsToCopy: List<Field>): To {
|
||||
if (from == to) return to
|
||||
|
||||
for (fromField in fieldsToCopy) {
|
||||
val toField = to.javaClass.getField(fromField.name)
|
||||
val fromValue = fromField.get(from)
|
||||
toField.set(to, if (deepCopyWhenNeeded) fromValue?.copyValueIfNeeded() else fromValue)
|
||||
@@ -83,10 +89,10 @@ private fun Any.copyValueIfNeeded(): Any {
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectFieldsToCopy(clazz: Class<*>): List<Field> {
|
||||
private fun collectFieldsToCopy(clazz: Class<*>, inheritedOnly: Boolean): List<Field> {
|
||||
val fromFields = ArrayList<Field>()
|
||||
|
||||
var currentClass: Class<*>? = clazz
|
||||
var currentClass: Class<*>? = if (inheritedOnly) clazz.superclass else clazz
|
||||
while (currentClass != null) {
|
||||
for (field in currentClass.declaredFields) {
|
||||
val modifiers = field.modifiers
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.messages;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum CompilerMessageSeverity {
|
||||
INFO,
|
||||
ERROR,
|
||||
WARNING,
|
||||
EXCEPTION,
|
||||
ERROR,
|
||||
STRONG_WARNING,
|
||||
WARNING,
|
||||
INFO,
|
||||
LOGGING,
|
||||
OUTPUT;
|
||||
|
||||
@@ -32,4 +35,25 @@ public enum CompilerMessageSeverity {
|
||||
public boolean isError() {
|
||||
return ERRORS.contains(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPresentableName() {
|
||||
switch (this) {
|
||||
case EXCEPTION:
|
||||
return "exception";
|
||||
case ERROR:
|
||||
return "error";
|
||||
case STRONG_WARNING:
|
||||
case WARNING:
|
||||
return "warning";
|
||||
case INFO:
|
||||
return "info";
|
||||
case LOGGING:
|
||||
return "logging";
|
||||
case OUTPUT:
|
||||
return "output";
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown severity: " + this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
|
||||
for (String path : sortedKeys()) {
|
||||
for (Message message : groupedMessages.get(path)) {
|
||||
if (!hasErrors || message.severity.isError()) {
|
||||
if (!hasErrors || message.severity.isError() || message.severity == CompilerMessageSeverity.STRONG_WARNING) {
|
||||
delegate.report(message.severity, message.message, message.location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.concurrency.AppScheduledExecutorService;
|
||||
import com.sampullara.cli.Args;
|
||||
import kotlin.Pair;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -44,6 +41,7 @@ import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -158,6 +156,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
}
|
||||
|
||||
reportUnknownExtraFlags(messageCollector, arguments);
|
||||
reportUnsupportedJavaVersion(messageCollector, arguments);
|
||||
|
||||
GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector);
|
||||
|
||||
@@ -278,7 +277,12 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
|
||||
configuration.put(
|
||||
CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
|
||||
new LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(apiVersion), extraLanguageFeatures)
|
||||
new LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
extraLanguageFeatures,
|
||||
arguments.apiVersion != null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -339,13 +343,23 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
private void reportUnknownExtraFlags(@NotNull MessageCollector collector, @NotNull A arguments) {
|
||||
for (String flag : arguments.unknownExtraFlags) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.WARNING,
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Flag is not supported by this version of the compiler: " + flag,
|
||||
CompilerMessageLocation.NO_LOCATION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportUnsupportedJavaVersion(MessageCollector collector, A arguments) {
|
||||
if (!SystemInfo.isJavaVersionAtLeast("1.8") && !arguments.noJavaVersionWarning) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Running the Kotlin compiler under Java 6 or 7 is unsupported and will no longer be possible in a future update.",
|
||||
CompilerMessageLocation.NO_LOCATION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract ExitCode doExecute(
|
||||
@NotNull A arguments,
|
||||
|
||||
@@ -206,7 +206,7 @@ class AnalyzerWithCompilerReport(private val messageCollector: MessageCollector)
|
||||
|
||||
fun reportBytecodeVersionErrors(bindingContext: BindingContext, messageCollector: MessageCollector) {
|
||||
val severity = if (System.getProperty("kotlin.jvm.disable.bytecode.version.error") == "true")
|
||||
CompilerMessageSeverity.WARNING
|
||||
CompilerMessageSeverity.STRONG_WARNING
|
||||
else
|
||||
CompilerMessageSeverity.ERROR
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
|
||||
private static final String LINE_SEPARATOR = LineSeparator.getSystemLineSeparator().getSeparatorString();
|
||||
|
||||
private static final Set<CompilerMessageSeverity> IMPORTANT_MESSAGE_SEVERITIES = EnumSet.of(EXCEPTION, ERROR, WARNING);
|
||||
private static final Set<CompilerMessageSeverity> IMPORTANT_MESSAGE_SEVERITIES = EnumSet.of(EXCEPTION, ERROR, STRONG_WARNING, WARNING);
|
||||
|
||||
@Override
|
||||
public String renderPreamble() {
|
||||
@@ -83,7 +83,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
Ansi ansi = Ansi.ansi()
|
||||
.bold()
|
||||
.fg(severityColor(severity))
|
||||
.a(severity.name().toLowerCase())
|
||||
.a(severity.getPresentableName())
|
||||
.a(": ")
|
||||
.reset();
|
||||
|
||||
@@ -102,7 +102,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.append(severity.name().toLowerCase());
|
||||
result.append(severity.getPresentableName());
|
||||
result.append(": ");
|
||||
result.append(decapitalizeIfNeeded(message));
|
||||
}
|
||||
@@ -141,6 +141,8 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
return Ansi.Color.RED;
|
||||
case ERROR:
|
||||
return Ansi.Color.RED;
|
||||
case STRONG_WARNING:
|
||||
return Ansi.Color.YELLOW;
|
||||
case WARNING:
|
||||
return Ansi.Color.YELLOW;
|
||||
case INFO:
|
||||
|
||||
@@ -28,7 +28,8 @@ public class XmlMessageRenderer implements MessageRenderer {
|
||||
@Override
|
||||
public String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append("<").append(severity.toString());
|
||||
String tagName = severity.getPresentableName();
|
||||
out.append("<").append(tagName);
|
||||
if (location.getPath() != null) {
|
||||
out.append(" path=\"").append(e(location.getPath())).append("\"");
|
||||
out.append(" line=\"").append(location.getLine()).append("\"");
|
||||
@@ -38,11 +39,11 @@ public class XmlMessageRenderer implements MessageRenderer {
|
||||
|
||||
out.append(e(message));
|
||||
|
||||
out.append("</").append(severity.toString()).append(">\n");
|
||||
out.append("</").append(tagName).append(">\n");
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private String e(String str) {
|
||||
private static String e(String str) {
|
||||
return StringUtil.escapeXml(str);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
||||
@@ -58,8 +56,8 @@ import org.jetbrains.kotlin.js.facade.MainCallParameters;
|
||||
import org.jetbrains.kotlin.js.facade.TranslationResult;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -140,11 +138,15 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, FileUtil.getNameWithoutExtension(outputFile));
|
||||
|
||||
JsConfig config = new LibrarySourcesConfig(project, configuration);
|
||||
if (config.checkLibFilesAndReportErrors(new Function1<String, Unit>() {
|
||||
if (config.checkLibFilesAndReportErrors(new JsConfig.Reporter() {
|
||||
@Override
|
||||
public Unit invoke(String message) {
|
||||
public void error(@NotNull String message) {
|
||||
messageCollector.report(CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(@NotNull String message) {
|
||||
messageCollector.report(CompilerMessageSeverity.STRONG_WARNING, message, CompilerMessageLocation.NO_LOCATION);
|
||||
}
|
||||
})) {
|
||||
return COMPILATION_ERROR;
|
||||
@@ -275,20 +277,17 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
if (arguments.metaInfo) {
|
||||
configuration.put(JSConfigurationKeys.META_INFO, true);
|
||||
}
|
||||
if (arguments.kjsm) {
|
||||
configuration.put(JSConfigurationKeys.KJSM, true);
|
||||
}
|
||||
|
||||
List<String> libraryFiles = new SmartList<String>();
|
||||
List<String> libraries = new SmartList<String>();
|
||||
if (!arguments.noStdlib) {
|
||||
libraryFiles.add(0, PathUtil.getKotlinPathsForCompiler().getJsStdLibJarPath().getAbsolutePath());
|
||||
libraries.add(0, PathUtil.getKotlinPathsForCompiler().getJsStdLibJarPath().getAbsolutePath());
|
||||
}
|
||||
|
||||
if (arguments.libraryFiles != null) {
|
||||
ContainerUtil.addAllNotNull(libraryFiles, arguments.libraryFiles);
|
||||
if (arguments.libraries != null) {
|
||||
ContainerUtil.addAllNotNull(libraries, arguments.libraries.split(File.pathSeparator));
|
||||
}
|
||||
|
||||
configuration.put(JSConfigurationKeys.LIBRARY_FILES, libraryFiles);
|
||||
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
|
||||
|
||||
String moduleKindName = arguments.moduleKind;
|
||||
ModuleKind moduleKind = moduleKindName != null ? moduleKindMap.get(moduleKindName) : ModuleKind.PLAIN;
|
||||
|
||||
@@ -16,22 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.MavenComparableVersion
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.jar.Attributes
|
||||
import java.util.jar.Manifest
|
||||
|
||||
internal inline fun Properties.getString(propertyName: String, otherwise: () -> String): String =
|
||||
getProperty(propertyName) ?: otherwise()
|
||||
|
||||
object JvmRuntimeVersionsConsistencyChecker {
|
||||
private val LOG = Logger.getInstance(JvmRuntimeVersionsConsistencyChecker::class.java)
|
||||
|
||||
@@ -43,8 +40,6 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
private fun <T> T?.assertNotNull(message: () -> String): T =
|
||||
if (this == null) fatal(message()) else this
|
||||
|
||||
private val VERSION_ISSUE_SEVERITY = CompilerMessageSeverity.ERROR
|
||||
|
||||
private const val META_INF = "META-INF"
|
||||
private const val MANIFEST_MF = "$META_INF/MANIFEST.MF"
|
||||
|
||||
@@ -56,7 +51,10 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
|
||||
private const val KOTLIN_STDLIB_MODULE = "$META_INF/kotlin-stdlib.kotlin_module"
|
||||
private const val KOTLIN_REFLECT_MODULE = "$META_INF/kotlin-reflection.kotlin_module"
|
||||
private const val KOTLIN_COMPILER_MODULE = "$META_INF/kotlin-compiler.kotlin_module"
|
||||
|
||||
private val RUNTIME_IMPLEMENTATION_TITLES = setOf(
|
||||
"kotlin-runtime", "kotlin-stdlib", "kotlin-reflect", "Kotlin Runtime", "Kotlin Standard Library", "Kotlin Reflect"
|
||||
)
|
||||
|
||||
private val KOTLIN_VERSION_ATTRIBUTE: String
|
||||
private val CURRENT_COMPILER_VERSION: MavenComparableVersion
|
||||
@@ -86,8 +84,8 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
MavenComparableVersion(kotlinVersionString)
|
||||
}
|
||||
|
||||
if (CURRENT_COMPILER_VERSION != MavenComparableVersion(LanguageVersion.LATEST)) {
|
||||
fatal("Kotlin compiler version $CURRENT_COMPILER_VERSION in kotlinManifest.properties doesn't match ${LanguageVersion.LATEST}")
|
||||
if (CURRENT_COMPILER_VERSION != ApiVersion.LATEST.version) {
|
||||
fatal("Kotlin compiler version $CURRENT_COMPILER_VERSION in kotlinManifest.properties doesn't match ${ApiVersion.LATEST}")
|
||||
}
|
||||
|
||||
KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT)
|
||||
@@ -98,141 +96,278 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN not found in kotlinManifest.properties" }
|
||||
}
|
||||
|
||||
private class KotlinLibraryFile(val component: String, val file: VirtualFile, val version: MavenComparableVersion) {
|
||||
private class KotlinLibraryFile(val file: VirtualFile, val version: MavenComparableVersion) {
|
||||
override fun toString(): String =
|
||||
"${file.name}:$version ($component)"
|
||||
"${file.name}:$version"
|
||||
}
|
||||
|
||||
private class RuntimeJarsInfo(
|
||||
// Runtime jars with components "Main" and "Core"
|
||||
val jars: List<KotlinLibraryFile>,
|
||||
// Runtime jars with components "Core" only (a subset of [jars])
|
||||
val coreJars: List<KotlinLibraryFile>
|
||||
val coreJars: List<KotlinLibraryFile>,
|
||||
// Library jars which have some Kotlin Runtime library bundled into them
|
||||
val otherLibrariesWithBundledRuntime: List<VirtualFile>
|
||||
)
|
||||
|
||||
fun checkCompilerClasspathConsistency(
|
||||
messageCollector: MessageCollector,
|
||||
languageVersionSettings: LanguageVersionSettings?,
|
||||
configuration: CompilerConfiguration,
|
||||
classpathJarRoots: List<VirtualFile>
|
||||
) {
|
||||
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
|
||||
if (runtimeJarsInfo.jars.isEmpty()) return
|
||||
|
||||
val languageVersion = languageVersionSettings?.let { MavenComparableVersion(it.languageVersion) } ?: CURRENT_COMPILER_VERSION
|
||||
val languageVersionSettings = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)
|
||||
val apiVersion = languageVersionSettings?.apiVersion?.version ?: CURRENT_COMPILER_VERSION
|
||||
|
||||
if (checkCompilerClasspathConsistency(messageCollector, languageVersion, runtimeJarsInfo)) {
|
||||
messageCollector.issue(null, "Some runtime JAR files in the classpath have an incompatible version. " +
|
||||
"Remove them from the classpath or use '-Xskip-runtime-version-check' to suppress errors")
|
||||
val consistency = checkCompilerClasspathConsistency(messageCollector, apiVersion, runtimeJarsInfo)
|
||||
if (consistency is ClasspathConsistency.InconsistentWithApiVersion) {
|
||||
val actualRuntimeVersion = consistency.actualRuntimeVersion
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Runtime JAR files in the classpath have the version $actualRuntimeVersion, " +
|
||||
"which is older than the API version $apiVersion. " +
|
||||
"Consider using the runtime of version $apiVersion, or pass '-api-version $actualRuntimeVersion' explicitly to " +
|
||||
"restrict the available APIs to the runtime of version $actualRuntimeVersion. " +
|
||||
"You can also pass '-language-version $actualRuntimeVersion' instead, which will restrict " +
|
||||
"not only the APIs to the specified version, but also the language features. " +
|
||||
"Alternatively, you can use '-Xskip-runtime-version-check' to suppress this warning"
|
||||
)
|
||||
|
||||
val actualApi = ApiVersion.parse(actualRuntimeVersion.toString())
|
||||
if (actualApi != null) {
|
||||
val newSettings = if (languageVersionSettings == null) {
|
||||
LanguageVersionSettingsImpl(
|
||||
LanguageVersionSettingsImpl.DEFAULT.languageVersion,
|
||||
actualApi,
|
||||
listOf(LanguageFeature.WarnOnCoroutines)
|
||||
)
|
||||
}
|
||||
else {
|
||||
val inferredApiVersion =
|
||||
if (@Suppress("DEPRECATION") languageVersionSettings.isApiVersionExplicit)
|
||||
languageVersionSettings.apiVersion
|
||||
else
|
||||
minOf(languageVersionSettings.apiVersion, actualApi)
|
||||
|
||||
// "minOf" is needed in case when API version was inferred from language version and it's older than actualApi.
|
||||
// For example, in "kotlinc-1.2 -language-version 1.0 -cp kotlin-runtime-1.1.jar" we should still infer API = 1.0
|
||||
LanguageVersionSettingsImpl(
|
||||
languageVersionSettings.languageVersion,
|
||||
inferredApiVersion,
|
||||
languageVersionSettings.additionalFeatures,
|
||||
isApiVersionExplicit = false
|
||||
)
|
||||
}
|
||||
|
||||
messageCollector.issue(null, "Old runtime has been found in the classpath. " +
|
||||
"Initial language version settings: $languageVersionSettings. " +
|
||||
"Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING)
|
||||
|
||||
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, newSettings)
|
||||
}
|
||||
else {
|
||||
messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion")
|
||||
}
|
||||
}
|
||||
else if (consistency != ClasspathConsistency.Consistent) {
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Some runtime JAR files in the classpath have an incompatible version. " +
|
||||
"Consider removing them from the classpath or use '-Xskip-runtime-version-check' to suppress this warning"
|
||||
)
|
||||
}
|
||||
|
||||
val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime
|
||||
if (librariesWithBundled.isNotEmpty()) {
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Some JAR files in the classpath have the Kotlin Runtime library bundled into them. " +
|
||||
"This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the classpath. " +
|
||||
"Consider removing these libraries from the classpath or use '-Xskip-runtime-version-check' to suppress this warning"
|
||||
)
|
||||
|
||||
for (library in librariesWithBundled) {
|
||||
messageCollector.issue(library, "Library has Kotlin runtime bundled into it")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ClasspathConsistency {
|
||||
object Consistent : ClasspathConsistency()
|
||||
class InconsistentWithApiVersion(val actualRuntimeVersion: MavenComparableVersion) : ClasspathConsistency()
|
||||
object InconsistentWithCompilerVersion : ClasspathConsistency()
|
||||
object InconsistentBecauseOfRuntimesWithDifferentVersions : ClasspathConsistency()
|
||||
}
|
||||
|
||||
private fun checkCompilerClasspathConsistency(
|
||||
messageCollector: MessageCollector,
|
||||
languageVersion: MavenComparableVersion,
|
||||
apiVersion: MavenComparableVersion,
|
||||
runtimeJarsInfo: RuntimeJarsInfo
|
||||
): Boolean {
|
||||
): ClasspathConsistency {
|
||||
// The "Core" jar files should not be newer than the compiler. This behavior is reserved for the future if we realise that we're
|
||||
// going to break language/library compatibility in such a way that it's easier to make the old compiler just report an error
|
||||
// in the case the new runtime library is specified in the classpath, rather than employing any other compatibility breakage tools
|
||||
// we have at our disposal (Deprecated, SinceKotlin, SinceKotlinInfo in metadata, etc.)
|
||||
if (runtimeJarsInfo.coreJars.map {
|
||||
checkNotNewerThanCompiler(messageCollector, it)
|
||||
}.any { it }) return true
|
||||
}.any { it }) return ClasspathConsistency.InconsistentWithCompilerVersion
|
||||
|
||||
if (runtimeJarsInfo.jars.map {
|
||||
checkCompatibleWithLanguageVersion(messageCollector, it, languageVersion)
|
||||
}.any { it }) return true
|
||||
val jars = runtimeJarsInfo.jars
|
||||
if (jars.isEmpty()) return ClasspathConsistency.Consistent
|
||||
|
||||
return checkMatchingVersions(messageCollector, runtimeJarsInfo)
|
||||
val runtimeVersion = checkMatchingVersionsAndGetRuntimeVersion(messageCollector, jars)
|
||||
?: return ClasspathConsistency.InconsistentBecauseOfRuntimesWithDifferentVersions
|
||||
|
||||
if (jars.map {
|
||||
checkCompatibleWithApiVersion(messageCollector, it, apiVersion)
|
||||
}.any { it }) return ClasspathConsistency.InconsistentWithApiVersion(runtimeVersion)
|
||||
|
||||
return ClasspathConsistency.Consistent
|
||||
}
|
||||
|
||||
private fun checkNotNewerThanCompiler(messageCollector: MessageCollector, jar: KotlinLibraryFile): Boolean {
|
||||
if (jar.version > CURRENT_COMPILER_VERSION) {
|
||||
messageCollector.issue(jar.file, "Runtime JAR file has version ${jar.version} which is newer than compiler version $CURRENT_COMPILER_VERSION")
|
||||
messageCollector.issue(
|
||||
jar.file,
|
||||
"Runtime JAR file has version ${jar.version} which is newer than compiler version $CURRENT_COMPILER_VERSION",
|
||||
CompilerMessageSeverity.ERROR
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkCompatibleWithLanguageVersion(
|
||||
messageCollector: MessageCollector, jar: KotlinLibraryFile, languageVersion: MavenComparableVersion
|
||||
private fun checkCompatibleWithApiVersion(
|
||||
messageCollector: MessageCollector, jar: KotlinLibraryFile, apiVersion: MavenComparableVersion
|
||||
): Boolean {
|
||||
if (jar.version < languageVersion) {
|
||||
messageCollector.issue(jar.file, "Runtime JAR file has version ${jar.version} which is older than required for language version $languageVersion")
|
||||
if (jar.version < apiVersion) {
|
||||
messageCollector.issue(
|
||||
jar.file,
|
||||
"Runtime JAR file has version ${jar.version} which is older than required for API version $apiVersion"
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkMatchingVersions(messageCollector: MessageCollector, runtimeJarsInfo: RuntimeJarsInfo): Boolean {
|
||||
val oldestJar = runtimeJarsInfo.jars.minBy { it.version } ?: return false
|
||||
val newestJar = runtimeJarsInfo.jars.maxBy { it.version } ?: return false
|
||||
// Returns the version if it's the same across all jars, or null if versions of some jars differ.
|
||||
private fun checkMatchingVersionsAndGetRuntimeVersion(
|
||||
messageCollector: MessageCollector,
|
||||
jars: List<KotlinLibraryFile>
|
||||
): MavenComparableVersion? {
|
||||
assert(jars.isNotEmpty()) { "'jars' must not be empty" }
|
||||
val oldestVersion = jars.minBy { it.version }!!.version
|
||||
val newestVersion = jars.maxBy { it.version }!!.version
|
||||
|
||||
if (oldestJar.version != newestJar.version) {
|
||||
messageCollector.issue(null, buildString {
|
||||
appendln("Runtime JAR files in the classpath must have the same version. These files were found in the classpath:")
|
||||
for (jar in runtimeJarsInfo.jars) {
|
||||
appendln(" ${jar.file.path} (version ${jar.version})")
|
||||
}
|
||||
}.trimEnd())
|
||||
return true
|
||||
// If the oldest version is the same as the newest version, then all jars have the same version
|
||||
if (oldestVersion == newestVersion) return oldestVersion
|
||||
|
||||
messageCollector.issue(null, buildString {
|
||||
appendln("Runtime JAR files in the classpath should have the same version. These files were found in the classpath:")
|
||||
for (jar in jars) {
|
||||
appendln(" ${jar.file.path} (version ${jar.version})")
|
||||
}
|
||||
}.trimEnd())
|
||||
|
||||
// If there's kotlin-stdlib of version X in the classpath and kotlin-reflect of version Y < X,
|
||||
// we suggest to provide an explicit dependency on version X.
|
||||
// TODO: report this depending on the content of the jars instead
|
||||
val minReflectJar =
|
||||
jars.filter { it.file.name.startsWith("kotlin-reflect") }.minBy { it.version }
|
||||
val maxStdlibJar =
|
||||
jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxBy { it.version }
|
||||
if (minReflectJar != null && maxStdlibJar != null && minReflectJar.version < maxStdlibJar.version) {
|
||||
messageCollector.issue(
|
||||
null,
|
||||
"Consider providing an explicit dependency on kotlin-reflect ${maxStdlibJar.version} to prevent strange errors"
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
private fun MessageCollector.issue(file: VirtualFile?, message: String) {
|
||||
report(VERSION_ISSUE_SEVERITY, message, CompilerMessageLocation.create(file?.let(VfsUtilCore::virtualToIoFile)?.path))
|
||||
private fun MessageCollector.issue(
|
||||
file: VirtualFile?,
|
||||
message: String,
|
||||
severity: CompilerMessageSeverity = CompilerMessageSeverity.STRONG_WARNING
|
||||
) {
|
||||
report(severity, message, CompilerMessageLocation.create(file?.let(VfsUtilCore::virtualToIoFile)?.path))
|
||||
}
|
||||
|
||||
private fun collectRuntimeJarsInfo(classpathJarRoots: List<VirtualFile>): RuntimeJarsInfo {
|
||||
val jars = ArrayList<KotlinLibraryFile>(2)
|
||||
val coreJars = ArrayList<KotlinLibraryFile>(2)
|
||||
val otherLibrariesWithBundledRuntime = ArrayList<VirtualFile>(0)
|
||||
|
||||
val visitedPaths = hashSetOf<String>()
|
||||
|
||||
for (jarRoot in classpathJarRoots) {
|
||||
val manifest = try {
|
||||
val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF) ?: continue
|
||||
Manifest(manifestFile.inputStream)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
continue
|
||||
}
|
||||
|
||||
val runtimeComponent = getKotlinRuntimeComponent(jarRoot, manifest) ?: continue
|
||||
val version = manifest.getKotlinLanguageVersion()
|
||||
val fileKind = determineFileKind(jarRoot)
|
||||
if (fileKind is FileKind.Irrelevant) continue
|
||||
|
||||
val jarFile = VfsUtilCore.getVirtualFileForJar(jarRoot) ?: continue
|
||||
val file = KotlinLibraryFile(runtimeComponent, jarFile, version)
|
||||
if (!visitedPaths.add(jarFile.path)) continue
|
||||
|
||||
if (runtimeComponent == KOTLIN_RUNTIME_COMPONENT_CORE) {
|
||||
jars.add(file)
|
||||
coreJars.add(file)
|
||||
}
|
||||
else if (runtimeComponent == KOTLIN_RUNTIME_COMPONENT_MAIN) {
|
||||
jars.add(file)
|
||||
when (fileKind) {
|
||||
is FileKind.Runtime -> {
|
||||
val file = KotlinLibraryFile(jarFile, fileKind.version)
|
||||
jars.add(file)
|
||||
if (fileKind.isCoreComponent) {
|
||||
coreJars.add(file)
|
||||
}
|
||||
}
|
||||
FileKind.OldRuntime -> jars.add(KotlinLibraryFile(jarFile, ApiVersion.KOTLIN_1_0.version))
|
||||
FileKind.LibraryWithBundledRuntime -> otherLibrariesWithBundledRuntime.add(jarFile)
|
||||
}
|
||||
}
|
||||
|
||||
return RuntimeJarsInfo(jars, coreJars)
|
||||
return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime)
|
||||
}
|
||||
|
||||
private fun getKotlinRuntimeComponent(jar: VirtualFile, manifest: Manifest): String? {
|
||||
manifest.mainAttributes.getValue(KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE)?.let { return it }
|
||||
private sealed class FileKind {
|
||||
class Runtime(val version: MavenComparableVersion, val isCoreComponent: Boolean) : FileKind()
|
||||
|
||||
// Do not treat kotlin-compiler and kotlin-compiler-embeddable as Kotlin runtime libraries.
|
||||
// The second condition is needed because when the compiler is built with "compiler-quick", there's no kotlin-compiler.kotlin_module
|
||||
if (jar.findFileByRelativePath(KOTLIN_COMPILER_MODULE) != null ||
|
||||
jar.findFileByRelativePath(this::class.java.name.replace('.', '/') + "." + JavaClassFileType.INSTANCE.defaultExtension) != null) return null
|
||||
// Runtime library of Kotlin 1.0
|
||||
object OldRuntime : FileKind()
|
||||
|
||||
if (jar.findFileByRelativePath(KOTLIN_STDLIB_MODULE) != null) return KOTLIN_RUNTIME_COMPONENT_MAIN
|
||||
if (jar.findFileByRelativePath(KOTLIN_REFLECT_MODULE) != null) return KOTLIN_RUNTIME_COMPONENT_MAIN
|
||||
object LibraryWithBundledRuntime : FileKind()
|
||||
|
||||
return null
|
||||
object Irrelevant : FileKind()
|
||||
}
|
||||
|
||||
private fun determineFileKind(jarRoot: VirtualFile): FileKind {
|
||||
val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF)
|
||||
val manifest = try {
|
||||
manifestFile?.let { Manifest(it.inputStream) }
|
||||
}
|
||||
catch (e: IOException) {
|
||||
return FileKind.Irrelevant
|
||||
}
|
||||
|
||||
val runtimeComponent = manifest?.mainAttributes?.getValue(KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE)
|
||||
return when (runtimeComponent) {
|
||||
KOTLIN_RUNTIME_COMPONENT_MAIN ->
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = false)
|
||||
KOTLIN_RUNTIME_COMPONENT_CORE ->
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = true)
|
||||
null -> when {
|
||||
jarRoot.findFileByRelativePath(KOTLIN_STDLIB_MODULE) == null &&
|
||||
jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant
|
||||
isGenuineKotlinRuntime(manifest) -> FileKind.OldRuntime
|
||||
else -> FileKind.LibraryWithBundledRuntime
|
||||
}
|
||||
else -> FileKind.Irrelevant
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the manifest is from the original Kotlin Runtime jar, false if it's from a library with a bundled runtime
|
||||
private fun isGenuineKotlinRuntime(manifest: Manifest?): Boolean {
|
||||
return manifest != null &&
|
||||
manifest.mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE) in RUNTIME_IMPLEMENTATION_TITLES
|
||||
}
|
||||
|
||||
private fun Manifest.getKotlinLanguageVersion(): MavenComparableVersion =
|
||||
MavenComparableVersion(mainAttributes.getValue(KOTLIN_VERSION_ATTRIBUTE) ?: LanguageVersion.KOTLIN_1_0.versionString)
|
||||
|
||||
private fun MavenComparableVersion(languageVersion: LanguageVersion): MavenComparableVersion =
|
||||
MavenComparableVersion(languageVersion.versionString)
|
||||
(mainAttributes.getValue(KOTLIN_VERSION_ATTRIBUTE)?.let((ApiVersion)::parse) ?: ApiVersion.KOTLIN_1_0).version
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
if (destination != null) {
|
||||
messageCollector.report(
|
||||
CompilerMessageSeverity.WARNING,
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"The '-d' option with a directory destination is ignored because '-module' is specified",
|
||||
CompilerMessageLocation.NO_LOCATION
|
||||
)
|
||||
@@ -365,7 +365,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
else {
|
||||
if (arguments.jdkHome != null) {
|
||||
messageCollector.report(CompilerMessageSeverity.WARNING,
|
||||
messageCollector.report(CompilerMessageSeverity.STRONG_WARNING,
|
||||
"The '-jdk-home' option is ignored because '-no-jdk' is specified",
|
||||
CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
|
||||
@@ -67,8 +67,7 @@ import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
|
||||
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
|
||||
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.WARNING
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
|
||||
@@ -160,7 +159,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
if (messageCollector != null) {
|
||||
JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency(
|
||||
messageCollector,
|
||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS),
|
||||
configuration,
|
||||
initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null }
|
||||
)
|
||||
}
|
||||
@@ -217,7 +216,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
FqName(it)
|
||||
}
|
||||
else {
|
||||
report(WARNING, "Invalid package prefix name is ignored: $it")
|
||||
report(STRONG_WARNING, "Invalid package prefix name is ignored: $it")
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -273,7 +272,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
val path = root.file
|
||||
val localFile = findLocalDirectory(path.absolutePath)
|
||||
if (localFile == null) {
|
||||
report(WARNING, "Classpath entry points to a non-existent location: $path")
|
||||
report(STRONG_WARNING, "Classpath entry points to a non-existent location: $path")
|
||||
return null
|
||||
}
|
||||
return localFile
|
||||
@@ -286,7 +285,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
val path = root.file
|
||||
val jarFile = applicationEnvironment.jarFileSystem.findFileByPath("$path${URLUtil.JAR_SEPARATOR}")
|
||||
if (jarFile == null) {
|
||||
report(WARNING, "Classpath entry points to a file that is not a JAR archive: $path")
|
||||
report(STRONG_WARNING, "Classpath entry points to a file that is not a JAR archive: $path")
|
||||
return null
|
||||
}
|
||||
return jarFile
|
||||
@@ -297,7 +296,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
configuration.kotlinSourceRoots.forEach { path ->
|
||||
if (!uniqueSourceRoots.add(path)) {
|
||||
report(WARNING, "Duplicate source root: $path")
|
||||
report(STRONG_WARNING, "Duplicate source root: $path")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,17 @@ import com.intellij.core.JavaCoreApplicationEnvironment
|
||||
import com.intellij.core.JavaCoreProjectEnvironment
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.controlFlow.ControlFlowFactory
|
||||
|
||||
open class KotlinCoreProjectEnvironment(
|
||||
disposable: Disposable,
|
||||
applicationEnvironment: JavaCoreApplicationEnvironment
|
||||
) : JavaCoreProjectEnvironment(disposable, applicationEnvironment) {
|
||||
init {
|
||||
myProject.registerService<ControlFlowFactory>(ControlFlowFactory::class.java,
|
||||
ControlFlowFactory(myPsiManager))
|
||||
|
||||
}
|
||||
|
||||
override fun createCoreFileManager() = KotlinCliJavaFileManagerImpl(PsiManager.getInstance(project))
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.repl
|
||||
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplTerminalDiagnosticMessageHolder
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -42,6 +44,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
|
||||
const val KOTLIN_REPL_JVM_TARGET_PROPERTY = "kotlin.repl.jvm.target"
|
||||
|
||||
open class GenericReplChecker(
|
||||
disposable: Disposable,
|
||||
val scriptDefinition: KotlinScriptDefinition,
|
||||
@@ -54,6 +58,12 @@ open class GenericReplChecker(
|
||||
add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
||||
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||
|
||||
if (get(JVMConfigurationKeys.JVM_TARGET) == null) {
|
||||
put(JVMConfigurationKeys.JVM_TARGET,
|
||||
System.getProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY)?.let { JvmTarget.fromString(it) }
|
||||
?: if (getJavaVersion() >= 0x10008) JvmTarget.JVM_1_8 else JvmTarget.JVM_1_6)
|
||||
}
|
||||
}
|
||||
KotlinCoreEnvironment.createForProduction(disposable, compilerConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
}
|
||||
@@ -76,7 +86,7 @@ open class GenericReplChecker(
|
||||
stateLock.write {
|
||||
val scriptFileName = makeScriptBaseName(codeLine, generation)
|
||||
val virtualFile =
|
||||
LightVirtualFile("$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, codeLine.code).apply {
|
||||
LightVirtualFile("$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, StringUtil.convertLineSeparators(codeLine.code)).apply {
|
||||
charset = CharsetToolkit.UTF8_CHARSET
|
||||
}
|
||||
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||
@@ -98,3 +108,21 @@ open class GenericReplChecker(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initially taken from libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt
|
||||
// fixed according to JEP 223 - http://openjdk.java.net/jeps/223
|
||||
// TODO: consider to place it to some common place
|
||||
private fun getJavaVersion(): Int {
|
||||
val default = 0x10006
|
||||
val version = System.getProperty("java.specification.version") ?: return default
|
||||
val components = version.split('.')
|
||||
return try {
|
||||
when (components.size) {
|
||||
0 -> default
|
||||
1 -> components[0].toInt() * 0x10000
|
||||
else -> components[0].toInt() * 0x10000 + components[1].toInt()
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
|
||||
if (destination.endsWith(".jar")) {
|
||||
// TODO: support .jar destination
|
||||
collector.report(
|
||||
CompilerMessageSeverity.WARNING,
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
".jar destination is not yet supported, results will be written to the directory with the given name",
|
||||
CompilerMessageLocation.NO_LOCATION
|
||||
)
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="daemon-common" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="library" name="native-platform-uberjar" level="project" />
|
||||
<orderEntry type="module" module-name="cli-common" />
|
||||
<orderEntry type="module" module-name="descriptors" />
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="daemon-common" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="util" scope="PROVIDED" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="native-platform-uberjar" level="project" />
|
||||
<orderEntry type="module" module-name="cli-common" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="descriptors" scope="PROVIDED" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
|
||||
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
|
||||
import org.jetbrains.kotlin.daemon.common.RmiFriendlyCompilationCanceledException
|
||||
@@ -27,7 +26,9 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompil
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.utils.rethrow
|
||||
import java.rmi.server.UnicastRemoteObject
|
||||
import kotlin.reflect.full.allSuperclasses
|
||||
|
||||
|
||||
open class CompilerCallbackServicesFacadeServer(
|
||||
@@ -83,10 +84,12 @@ open class CompilerCallbackServicesFacadeServer(
|
||||
try {
|
||||
compilationCanceledStatus!!.checkCanceled()
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
catch (e: Exception) {
|
||||
// avoid passing exceptions that may have different serialVersionUID on across rmi border
|
||||
// TODO: doublecheck whether we need to distinguish different cancellation exceptions
|
||||
throw RmiFriendlyCompilationCanceledException()
|
||||
// removing dependency from openapi (this is obsolete part anyway, and will be removed soon)
|
||||
if ((e::class.allSuperclasses + e::class).any { it.qualifiedName == "com.intellij.openapi.progress.ProcessCanceledException" })
|
||||
throw RmiFriendlyCompilationCanceledException()
|
||||
else throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
import java.net.SocketException
|
||||
import java.rmi.ConnectException
|
||||
import java.rmi.ConnectIOException
|
||||
import java.rmi.UnmarshalException
|
||||
import java.rmi.server.UnicastRemoteObject
|
||||
import java.util.concurrent.Semaphore
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -70,32 +74,49 @@ object KotlinCompilerClient {
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean = true
|
||||
): CompileService? {
|
||||
): CompileService? =
|
||||
connectAndLease(compilerId,
|
||||
clientAliveFlagFile,
|
||||
daemonJVMOptions,
|
||||
daemonOptions,
|
||||
reportingTargets,
|
||||
autostart,
|
||||
leaseSession = false,
|
||||
sessionAliveFlagFile = null)?.first
|
||||
|
||||
var attempts = 0
|
||||
try {
|
||||
while (attempts++ < DAEMON_CONNECT_CYCLE_ATTEMPTS) {
|
||||
val (service, newJVMOptions) = tryFindSuitableDaemonOrNewOpts(File(daemonOptions.runFilesPath), compilerId, daemonJVMOptions, { cat, msg -> reportingTargets.report(cat, msg) })
|
||||
if (service != null) {
|
||||
// the newJVMOptions could be checked here for additional parameters, if needed
|
||||
service.registerClient(clientAliveFlagFile.absolutePath)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
|
||||
return service
|
||||
}
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "no suitable daemon found")
|
||||
if (autostart) {
|
||||
startDaemon(compilerId, newJVMOptions, daemonOptions, reportingTargets)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
|
||||
}
|
||||
|
||||
fun connectAndLease(compilerId: CompilerId,
|
||||
clientAliveFlagFile: File,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean,
|
||||
leaseSession: Boolean,
|
||||
sessionAliveFlagFile: File? = null
|
||||
): Pair<CompileService, Int>? = connectLoop(reportingTargets) {
|
||||
val (service, newJVMOptions) = tryFindSuitableDaemonOrNewOpts(File(daemonOptions.runFilesPath), compilerId, daemonJVMOptions, { cat, msg -> reportingTargets.report(cat, msg) })
|
||||
if (service != null) {
|
||||
// the newJVMOptions could be checked here for additional parameters, if needed
|
||||
service.registerClient(clientAliveFlagFile.absolutePath)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
|
||||
if (!leaseSession) service to CompileService.NO_SESSION
|
||||
else {
|
||||
val sessionId = service.leaseCompileSession(sessionAliveFlagFile?.absolutePath)
|
||||
if (sessionId is CompileService.CallResult.Dying)
|
||||
null
|
||||
else
|
||||
service to sessionId.get()
|
||||
}
|
||||
} else {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "no suitable daemon found")
|
||||
if (autostart) {
|
||||
startDaemon(compilerId, newJVMOptions, daemonOptions, reportingTargets)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
|
||||
}
|
||||
null
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
reportingTargets.report(DaemonReportCategory.EXCEPTION, e.toString())
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
fun shutdownCompileService(compilerId: CompilerId, daemonOptions: DaemonOptions): Unit {
|
||||
connectToCompileService(compilerId, DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false)
|
||||
?.shutdown()
|
||||
@@ -107,6 +128,13 @@ object KotlinCompilerClient {
|
||||
}
|
||||
|
||||
|
||||
fun leaseCompileSession(compilerService: CompileService, aliveFlagPath: String?): Int =
|
||||
compilerService.leaseCompileSession(aliveFlagPath).get()
|
||||
|
||||
fun releaseCompileSession(compilerService: CompileService, sessionId: Int): Unit {
|
||||
compilerService.releaseCompileSession(sessionId)
|
||||
}
|
||||
|
||||
fun compile(compilerService: CompileService,
|
||||
sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -270,6 +298,33 @@ object KotlinCompilerClient {
|
||||
|
||||
// --- Implementation ---------------------------------------
|
||||
|
||||
private inline fun <R> connectLoop(reportingTargets: DaemonReportingTargets, body: () -> R?): R? {
|
||||
try {
|
||||
var attempts = 0
|
||||
while (attempts < DAEMON_CONNECT_CYCLE_ATTEMPTS) {
|
||||
attempts += 1
|
||||
val (res, err) = try {
|
||||
body() to null
|
||||
}
|
||||
catch (e: SocketException) { null to e }
|
||||
catch (e: ConnectException) { null to e }
|
||||
catch (e: ConnectIOException) { null to e }
|
||||
catch (e: UnmarshalException) { null to e }
|
||||
|
||||
when {
|
||||
res != null -> return res
|
||||
err != null && attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS -> throw err
|
||||
err != null ->
|
||||
reportingTargets.report(DaemonReportCategory.INFO, "retrying($attempts) on: " + err.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
reportingTargets.report(DaemonReportCategory.EXCEPTION, e.toString())
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = "daemon client") {
|
||||
if (category == DaemonReportCategory.DEBUG && !verboseReporting) return
|
||||
out?.println("[$source] ${category.name}: $message")
|
||||
@@ -291,23 +346,33 @@ object KotlinCompilerClient {
|
||||
}
|
||||
|
||||
private fun tryFindSuitableDaemonOrNewOpts(registryDir: File, compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, report: (DaemonReportCategory, String) -> Unit): Pair<CompileService?, DaemonJVMOptions> {
|
||||
val aliveWithOpts = walkDaemons(registryDir, compilerId, report = report)
|
||||
.map { Pair(it, it.getDaemonJVMOptions()) }
|
||||
.filter { it.second.isGood }
|
||||
.sortedWith(compareByDescending(DaemonJVMOptionsMemoryComparator(), { it.second.get() }))
|
||||
registryDir.mkdirs()
|
||||
val timestampMarker = createTempFile("kotlin-daemon-client-tsmarker", directory = registryDir)
|
||||
val aliveWithMetadata = try {
|
||||
walkDaemons(registryDir, compilerId, timestampMarker, report = report).toList()
|
||||
}
|
||||
finally {
|
||||
timestampMarker.delete()
|
||||
}
|
||||
val comparator = compareByDescending<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
|
||||
.thenBy(FileAgeComparator()) { it.runFile }
|
||||
val optsCopy = daemonJVMOptions.copy()
|
||||
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
|
||||
return aliveWithOpts.firstOrNull()?.check { daemonJVMOptions memorywiseFitsInto it.second.get() }?.let {
|
||||
Pair(it.first, optsCopy.updateMemoryUpperBounds(it.second.get()))
|
||||
return aliveWithMetadata.maxWith(comparator)?.takeIf { daemonJVMOptions memorywiseFitsInto it.jvmOptions }?.let {
|
||||
Pair(it.daemon, optsCopy.updateMemoryUpperBounds(it.jvmOptions))
|
||||
}
|
||||
// else combine all options from running daemon to get fattest option for a new daemon to run
|
||||
?: Pair(null, aliveWithOpts.fold(optsCopy, { opts, d -> opts.updateMemoryUpperBounds(d.second.get()) }))
|
||||
?: Pair(null, aliveWithMetadata.fold(optsCopy, { opts, d -> opts.updateMemoryUpperBounds(d.jvmOptions) }))
|
||||
}
|
||||
|
||||
|
||||
private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets) {
|
||||
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
||||
val platformSpecificOptions = listOf("-Djava.awt.headless=true") // hide daemon window
|
||||
val platformSpecificOptions = listOf(
|
||||
// hide daemon window
|
||||
"-Djava.awt.headless=true",
|
||||
// prevent host name resolution
|
||||
"-Djava.rmi.server.hostname=${LoopbackNetworkInterface.loopbackInetAddressName}")
|
||||
val args = listOf(
|
||||
javaExecutable.absolutePath, "-cp", compilerId.compilerClasspath.joinToString(File.pathSeparator)) +
|
||||
platformSpecificOptions +
|
||||
@@ -331,7 +396,7 @@ object KotlinCompilerClient {
|
||||
daemon.inputStream
|
||||
.reader()
|
||||
.forEachLine {
|
||||
if (daemonOptions.runFilesPath.isNotEmpty() && it.contains(daemonOptions.runFilesPath)) {
|
||||
if (it == COMPILE_DAEMON_IS_READY_MESSAGE) {
|
||||
isEchoRead.release()
|
||||
return@forEachLine
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.kotlin.cli.common.repl.*
|
||||
import org.jetbrains.kotlin.daemon.common.CompileService
|
||||
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
|
||||
@@ -29,7 +27,6 @@ import java.io.OutputStream
|
||||
// TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls)
|
||||
|
||||
open class KotlinRemoteReplClientBase(
|
||||
disposable: Disposable,
|
||||
protected val compileService: CompileService,
|
||||
clientAliveFlagFile: File?,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -60,20 +57,18 @@ open class KotlinRemoteReplClientBase(
|
||||
operationsTracer
|
||||
).get()
|
||||
|
||||
init {
|
||||
Disposer.register(disposable, Disposable {
|
||||
try {
|
||||
compileService.releaseReplSession(sessionId)
|
||||
}
|
||||
catch (ex: java.rmi.RemoteException) {
|
||||
// assuming that communication failed and daemon most likely is already down
|
||||
}
|
||||
})
|
||||
// dispose should be called at the end of the repl lifetime to free daemon repl session and appropriate resources
|
||||
open fun dispose() {
|
||||
try {
|
||||
compileService.releaseReplSession(sessionId)
|
||||
}
|
||||
catch (ex: java.rmi.RemoteException) {
|
||||
// assuming that communication failed and daemon most likely is already down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinRemoteReplCompiler(
|
||||
disposable: Disposable,
|
||||
compileService: CompileService,
|
||||
clientAliveFlagFile: File?,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -83,7 +78,6 @@ class KotlinRemoteReplCompiler(
|
||||
port: Int = SOCKET_ANY_FREE_PORT,
|
||||
operationsTracer: RemoteOperationsTracer? = null
|
||||
) : KotlinRemoteReplClientBase(
|
||||
disposable = disposable,
|
||||
compileService = compileService,
|
||||
clientAliveFlagFile = clientAliveFlagFile,
|
||||
targetPlatform = targetPlatform,
|
||||
@@ -114,7 +108,6 @@ class KotlinRemoteReplCompiler(
|
||||
|
||||
// TODO: consider removing daemon eval completely - it is not required now and has questionable security. This will simplify daemon interface as well
|
||||
class KotlinRemoteReplEvaluator(
|
||||
disposable: Disposable,
|
||||
compileService: CompileService,
|
||||
clientAliveFlagFile: File?,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -129,7 +122,6 @@ class KotlinRemoteReplEvaluator(
|
||||
port: Int = SOCKET_ANY_FREE_PORT,
|
||||
operationsTracer: RemoteOperationsTracer? = null
|
||||
) : KotlinRemoteReplClientBase(
|
||||
disposable = disposable,
|
||||
compileService = compileService,
|
||||
clientAliveFlagFile = clientAliveFlagFile,
|
||||
targetPlatform = targetPlatform,
|
||||
|
||||
@@ -40,30 +40,48 @@ fun makePortFromRunFilenameExtractor(digest: String): (String) -> Int? {
|
||||
}
|
||||
}
|
||||
|
||||
private const val ORPHANED_RUN_FILE_AGE_THRESHOLD_MS = 1000000L
|
||||
|
||||
data class DaemonWithMetadata(val daemon: CompileService, val runFile: File, val jvmOptions: DaemonJVMOptions)
|
||||
|
||||
fun walkDaemons(registryDir: File,
|
||||
compilerId: CompilerId,
|
||||
filter: (File, Int) -> Boolean = { f, p -> true },
|
||||
report: (DaemonReportCategory, String) -> Unit = { cat, msg -> }
|
||||
): Sequence<CompileService> {
|
||||
fileToCompareTimestamp: File,
|
||||
filter: (File, Int) -> Boolean = { _, _ -> true },
|
||||
report: (DaemonReportCategory, String) -> Unit = { _, _ -> }
|
||||
): Sequence<DaemonWithMetadata> {
|
||||
val classPathDigest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest().toHexString()
|
||||
val portExtractor = makePortFromRunFilenameExtractor(classPathDigest)
|
||||
return registryDir.walk()
|
||||
.map { Pair(it, portExtractor(it.name)) }
|
||||
.filter { it.second != null && filter(it.first, it.second!!) }
|
||||
.mapNotNull {
|
||||
assert(it.second!! > 0 && it.second!! < MAX_PORT_NUMBER)
|
||||
report(DaemonReportCategory.DEBUG, "found daemon on port ${it.second}, trying to connect")
|
||||
val daemon = tryConnectToDaemon(it.second!!, report)
|
||||
.filter { (file, port) -> port != null && filter(file, port) }
|
||||
.mapNotNull { (file, port) ->
|
||||
assert(port!! in 1..(MAX_PORT_NUMBER - 1))
|
||||
val relativeAge = fileToCompareTimestamp.lastModified() - file.lastModified()
|
||||
report(DaemonReportCategory.DEBUG, "found daemon on port $port ($relativeAge ms old), trying to connect")
|
||||
val daemon = tryConnectToDaemon(port, report)
|
||||
// cleaning orphaned file; note: daemon should shut itself down if it detects that the run file is deleted
|
||||
if (daemon == null && !it.first.delete()) {
|
||||
report(DaemonReportCategory.INFO, "WARNING: unable to delete seemingly orphaned file '${it.first.absolutePath}', cleanup recommended")
|
||||
if (daemon == null) {
|
||||
if (relativeAge - ORPHANED_RUN_FILE_AGE_THRESHOLD_MS <= 0) {
|
||||
report(DaemonReportCategory.DEBUG, "found fresh run file '${file.absolutePath}' ($relativeAge ms old), but no daemon, ignoring it")
|
||||
}
|
||||
else {
|
||||
report(DaemonReportCategory.DEBUG, "found seemingly orphaned run file '${file.absolutePath}' ($relativeAge ms old), deleting it")
|
||||
if (!file.delete()) {
|
||||
report(DaemonReportCategory.INFO, "WARNING: unable to delete seemingly orphaned file '${file.absolutePath}', cleanup recommended")
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
daemon?.let { DaemonWithMetadata(it, file, it.getDaemonJVMOptions().get()) }
|
||||
}
|
||||
catch (e: Exception) {
|
||||
report(DaemonReportCategory.INFO, "ERROR: unable to retrieve daemon JVM options, assuming daemon is dead: ${e.message}")
|
||||
null
|
||||
}
|
||||
daemon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private inline fun tryConnectToDaemon(port: Int, report: (DaemonReportCategory, String) -> Unit): CompileService? {
|
||||
|
||||
try {
|
||||
@@ -88,3 +106,19 @@ fun makeAutodeletingFlagFile(keyword: String = "compiler-client", baseDir: File?
|
||||
flagFile.deleteOnExit()
|
||||
return flagFile
|
||||
}
|
||||
|
||||
// Comparator for reliable choice between daemons
|
||||
class FileAgeComparator : Comparator<File> {
|
||||
override fun compare(left: File, right: File): Int {
|
||||
val leftTS = left.lastModified()
|
||||
val rightTS = right.lastModified()
|
||||
return when {
|
||||
leftTS == 0L || rightTS == 0L -> 0 // cannot read any file timestamp, => undecidable
|
||||
leftTS > rightTS -> -1
|
||||
leftTS < rightTS -> 1
|
||||
else -> compareValues(left.canonicalPath, right.canonicalPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val LOG_PREFIX_ASSUMING_OTHER_DAEMONS_HAVE = "Assuming other daemons have"
|
||||
|
||||
@@ -48,6 +48,7 @@ val COMPILE_DAEMON_DEFAULT_SHUTDOWN_DELAY_MS: Long = 1000L // 1 sec
|
||||
val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L
|
||||
val COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS: Long = 10000L // 10 secs
|
||||
val COMPILE_DAEMON_TIMEOUT_INFINITE_MS: Long = 0L
|
||||
val COMPILE_DAEMON_IS_READY_MESSAGE = "Kotlin compile daemon is ready"
|
||||
|
||||
val COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH: String get() =
|
||||
FileSystem.getRuntimeStateFilesPath("kotlin", "daemon")
|
||||
|
||||
@@ -272,22 +272,30 @@ class CompileServiceImpl(
|
||||
}
|
||||
|
||||
override fun scheduleShutdown(graceful: Boolean): CompileService.CallResult<Boolean> = ifAlive(minAliveness = Aliveness.Alive) {
|
||||
CompileService.CallResult.Good(
|
||||
if (!graceful || state.alive.compareAndSet(Aliveness.Alive.ordinal, Aliveness.LastSession.ordinal)) {
|
||||
timer.schedule(0) {
|
||||
ifAliveExclusive(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
|
||||
if (!graceful || state.sessions.isEmpty()) {
|
||||
shutdownImpl()
|
||||
}
|
||||
else {
|
||||
when {
|
||||
!graceful -> {
|
||||
shutdownWithDelay()
|
||||
CompileService.CallResult.Good(true)
|
||||
}
|
||||
state.alive.compareAndSet(Aliveness.Alive.ordinal, Aliveness.LastSession.ordinal) -> {
|
||||
timer.schedule(1) {
|
||||
ifAliveExclusive(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
|
||||
when {
|
||||
state.sessions.isEmpty() -> shutdownWithDelay()
|
||||
else -> {
|
||||
daemonOptions.autoshutdownIdleSeconds = TimeUnit.MILLISECONDS.toSeconds(daemonOptions.forceShutdownTimeoutMilliseconds).toInt()
|
||||
daemonOptions.autoshutdownUnusedSeconds = daemonOptions.autoshutdownIdleSeconds
|
||||
log.info("Graceful shutdown signalled; unused/idle timeouts are set to ${daemonOptions.autoshutdownUnusedSeconds}/${daemonOptions.autoshutdownIdleSeconds}s")
|
||||
log.info("Some sessions are active, waiting for them to finish")
|
||||
}
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
true
|
||||
}
|
||||
else false)
|
||||
CompileService.CallResult.Good(true)
|
||||
}
|
||||
else -> CompileService.CallResult.Good(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun remoteCompile(sessionId: Int,
|
||||
@@ -529,7 +537,7 @@ class CompileServiceImpl(
|
||||
val stub = UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory) as CompileService
|
||||
registry.rebind (COMPILER_SERVICE_RMI_NAME, stub)
|
||||
|
||||
timer.schedule(0) {
|
||||
timer.schedule(10) {
|
||||
initiateElections()
|
||||
}
|
||||
timer.schedule(delay = DAEMON_PERIODIC_CHECK_INTERVAL_MS, period = DAEMON_PERIODIC_CHECK_INTERVAL_MS) {
|
||||
@@ -552,7 +560,7 @@ class CompileServiceImpl(
|
||||
// 1. check if unused for a timeout - shutdown
|
||||
if (shutdownCondition({ daemonOptions.autoshutdownUnusedSeconds != COMPILE_DAEMON_TIMEOUT_INFINITE_S && compilationsCounter.get() == 0 && nowSeconds() - lastUsedSeconds > daemonOptions.autoshutdownUnusedSeconds },
|
||||
"Unused timeout exceeded ${daemonOptions.autoshutdownUnusedSeconds}s, shutting down")) {
|
||||
shutdown()
|
||||
scheduleShutdown(true)
|
||||
}
|
||||
else {
|
||||
var anyDead = state.sessions.cleanDead()
|
||||
@@ -600,39 +608,61 @@ class CompileServiceImpl(
|
||||
}
|
||||
|
||||
|
||||
// TODO: handover should include mechanism for client to switch to a new daemon then previous "handed over responsibilities" and shot down
|
||||
private fun initiateElections() {
|
||||
|
||||
ifAlive {
|
||||
|
||||
val aliveWithOpts = walkDaemons(File(daemonOptions.runFilesPathOrDefault), compilerId, filter = { f, p -> p != port }, report = { lvl, msg -> log.info(msg) })
|
||||
.map { Pair(it, it.getDaemonJVMOptions()) }
|
||||
.filter { it.second.isGood }
|
||||
.sortedWith(compareByDescending(DaemonJVMOptionsMemoryComparator(), { it.second.get() }))
|
||||
if (aliveWithOpts.any()) {
|
||||
val fattestOpts = aliveWithOpts.first().second.get()
|
||||
// second part of the condition means that we prefer other daemon if is "equal" to the current one
|
||||
if (fattestOpts memorywiseFitsInto daemonJVMOptions && !(daemonJVMOptions memorywiseFitsInto fattestOpts)) {
|
||||
val aliveWithOpts = walkDaemons(File(daemonOptions.runFilesPathOrDefault), compilerId, runFile, filter = { f, p -> p != port }, report = { _, msg -> log.info(msg) }).toList()
|
||||
val comparator = compareByDescending<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
|
||||
.thenBy(FileAgeComparator()) { it.runFile }
|
||||
aliveWithOpts.maxWith(comparator)?.let { bestDaemonWithMetadata ->
|
||||
val fattestOpts = bestDaemonWithMetadata.jvmOptions
|
||||
if (fattestOpts memorywiseFitsInto daemonJVMOptions && FileAgeComparator().compare(bestDaemonWithMetadata.runFile, runFile) < 0 ) {
|
||||
// all others are smaller that me, take overs' clients and shut them down
|
||||
aliveWithOpts.forEach {
|
||||
it.first.getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { registerClient(it) }
|
||||
log.info("$LOG_PREFIX_ASSUMING_OTHER_DAEMONS_HAVE lower prio, taking clients from them and schedule them to shutdown: my runfile: ${runFile.name} (${runFile.lastModified()}) vs best other runfile: ${bestDaemonWithMetadata.runFile.name} (${bestDaemonWithMetadata.runFile.lastModified()})")
|
||||
aliveWithOpts.forEach { (daemon, runFile, _) ->
|
||||
try {
|
||||
daemon.getClients().takeIf { it.isGood }?.let {
|
||||
it.get().forEach { clientAliveFile -> registerClient(clientAliveFile) }
|
||||
}
|
||||
daemon.scheduleShutdown(true)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
log.info("Cannot connect to a daemon, assuming dying ('${runFile.canonicalPath}'): ${e.message}")
|
||||
}
|
||||
it.first.scheduleShutdown(true)
|
||||
}
|
||||
}
|
||||
else if (daemonJVMOptions memorywiseFitsInto fattestOpts) {
|
||||
// TODO: seems that the second part of condition is incorrect, reconsider:
|
||||
// the comment by @tsvtkv from review:
|
||||
// Algorithm in plain english:
|
||||
// (1) If the best daemon fits into me and the best daemon is younger than me, then I take over all other daemons clients.
|
||||
// (2) If I fit into the best daemon and the best daemon is older than me, then I give my clients to that daemon.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// daemon A starts with params: maxMem=100, codeCache=50
|
||||
// daemon B starts with params: maxMem=200, codeCache=50
|
||||
// daemon C starts with params: maxMem=150, codeCache=100
|
||||
// A performs election: (1) is false because neither B nor C does not fit into A, (2) is false because both B and C are younger than A.
|
||||
// B performs election: (1) is false because neither A nor C does not fit into B, (2) is false because B does not fit into neither A nor C.
|
||||
// C performs election: (1) is false because B is better than A and B does not fit into C, (2) is false C does not fit into neither A nor B.
|
||||
// Result: all daemons are alive and well.
|
||||
else if (daemonJVMOptions memorywiseFitsInto fattestOpts && FileAgeComparator().compare(bestDaemonWithMetadata.runFile, runFile) > 0) {
|
||||
// there is at least one bigger, handover my clients to it and shutdown
|
||||
scheduleShutdown(true)
|
||||
aliveWithOpts.first().first.let { fattest ->
|
||||
getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { fattest.registerClient(it) }
|
||||
}
|
||||
log.info("$LOG_PREFIX_ASSUMING_OTHER_DAEMONS_HAVE higher prio, handover clients to it and schedule shutdown: my runfile: ${runFile.name} (${runFile.lastModified()}) vs best other runfile: ${bestDaemonWithMetadata.runFile.name} (${bestDaemonWithMetadata.runFile.lastModified()})")
|
||||
getClients().takeIf { it.isGood }?.let {
|
||||
it.get().forEach { bestDaemonWithMetadata.daemon.registerClient(it) }
|
||||
}
|
||||
scheduleShutdown(true)
|
||||
}
|
||||
else {
|
||||
// undecided, do nothing
|
||||
log.info("$LOG_PREFIX_ASSUMING_OTHER_DAEMONS_HAVE equal prio, continue: ${runFile.name} (${runFile.lastModified()}) vs best other runfile: ${bestDaemonWithMetadata.runFile.name} (${bestDaemonWithMetadata.runFile.lastModified()})")
|
||||
// TODO: implement some behaviour here, e.g.:
|
||||
// - shutdown/takeover smaller daemon
|
||||
// - run (or better persuade client to run) a bigger daemon (in fact may be even simple shutdown will do, because of client's daemon choosing logic)
|
||||
}
|
||||
// else - do nothing, all daemons are staying
|
||||
// TODO: implement some behaviour here, e.g.:
|
||||
// - shutdown/takeover smaller daemon
|
||||
// - run (or better persuade client to run) a bigger daemon (in fact may be even simple shutdown will do, because of client's daemon choosing logic)
|
||||
}
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
@@ -653,8 +683,11 @@ class CompileServiceImpl(
|
||||
timer.schedule(daemonOptions.shutdownDelayMilliseconds) {
|
||||
state.delayedShutdownQueued.set(false)
|
||||
if (currentCompilationsCount == compilationsCounter.get()) {
|
||||
log.fine("Execute delayed shutdown")
|
||||
shutdown()
|
||||
ifAliveExclusive(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
|
||||
log.fine("Execute delayed shutdown")
|
||||
shutdownImpl()
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("Cancel delayed shutdown due to new client")
|
||||
@@ -801,7 +834,7 @@ class CompileServiceImpl(
|
||||
state.alive.get() < minAliveness.ordinal -> CompileService.CallResult.Dying()
|
||||
!ignoreCompilerChanged && classpathWatcher.isChanged -> {
|
||||
log.info("Compiler changed, scheduling shutdown")
|
||||
timer.schedule(0) { shutdown() }
|
||||
shutdownWithDelay()
|
||||
CompileService.CallResult.Dying()
|
||||
}
|
||||
else -> {
|
||||
|
||||
@@ -30,9 +30,7 @@ import java.net.URLClassLoader
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.jar.Manifest
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.LogManager
|
||||
import java.util.logging.Logger
|
||||
import java.util.logging.*
|
||||
import kotlin.concurrent.schedule
|
||||
|
||||
val DAEMON_PERIODIC_CHECK_INTERVAL_MS = 1000L
|
||||
@@ -55,7 +53,6 @@ class LogStream(name: String) : OutputStream() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object KotlinCompileDaemon {
|
||||
|
||||
init {
|
||||
@@ -71,7 +68,7 @@ object KotlinCompileDaemon {
|
||||
"java.util.logging.FileHandler.count = ${if (fileIsGiven) 1 else 3}\n" +
|
||||
"java.util.logging.FileHandler.append = $fileIsGiven\n" +
|
||||
"java.util.logging.FileHandler.pattern = ${if (fileIsGiven) logPath else (logPath + File.separator + "${COMPILE_DAEMON_DEFAULT_FILES_PREFIX}.$logTime.%u%g.log")}\n" +
|
||||
"java.util.logging.SimpleFormatter.format = %1\$tF %1\$tT.%1\$tL [%3\$s] %4\$s: %5\$s\\n\n"
|
||||
"java.util.logging.SimpleFormatter.format = %1\$tF %1\$tT.%1\$tL [%3\$s] %4\$s: %5\$s%n\n"
|
||||
|
||||
LogManager.getLogManager().readConfiguration(cfg.byteInputStream())
|
||||
}
|
||||
@@ -96,6 +93,7 @@ object KotlinCompileDaemon {
|
||||
log.info("Kotlin compiler daemon version " + (loadVersionFromResource() ?: "<unknown>"))
|
||||
log.info("daemon JVM args: " + ManagementFactory.getRuntimeMXBean().inputArguments.joinToString(" "))
|
||||
log.info("daemon args: " + args.joinToString(" "))
|
||||
log.info("daemon process name: " + ManagementFactory.getRuntimeMXBean().name)
|
||||
|
||||
val compilerId = CompilerId()
|
||||
val daemonOptions = DaemonOptions()
|
||||
@@ -156,8 +154,10 @@ object KotlinCompileDaemon {
|
||||
}
|
||||
})
|
||||
|
||||
if (daemonOptions.runFilesPath.isNotEmpty())
|
||||
println(daemonOptions.runFilesPath)
|
||||
println(COMPILE_DAEMON_IS_READY_MESSAGE)
|
||||
log.info("daemon is listening on port: $port")
|
||||
|
||||
log.info("daemon is listening on port: $port")
|
||||
|
||||
// this supposed to stop redirected streams reader(s) on the client side and prevent some situations with hanging threads, but doesn't work reliably
|
||||
// TODO: implement more reliable scheme
|
||||
|
||||
@@ -46,7 +46,7 @@ internal class CompileServicesFacadeMessageCollector(
|
||||
else -> {
|
||||
val reportSeverity = when (severity) {
|
||||
CompilerMessageSeverity.ERROR -> ReportSeverity.ERROR
|
||||
CompilerMessageSeverity.WARNING -> ReportSeverity.WARNING
|
||||
CompilerMessageSeverity.WARNING, CompilerMessageSeverity.STRONG_WARNING -> ReportSeverity.WARNING
|
||||
CompilerMessageSeverity.INFO -> ReportSeverity.INFO
|
||||
else -> ReportSeverity.DEBUG
|
||||
}
|
||||
@@ -57,7 +57,7 @@ internal class CompileServicesFacadeMessageCollector(
|
||||
}
|
||||
}
|
||||
|
||||
hasErrors = hasErrors || severity == CompilerMessageSeverity.ERROR || severity == CompilerMessageSeverity.EXCEPTION
|
||||
hasErrors = hasErrors || severity.isError
|
||||
}
|
||||
|
||||
override fun hasErrors(): Boolean = hasErrors
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
package org.jetbrains.kotlin.fileClasses;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
|
||||
public final class OldPackageFacadeClassUtils {
|
||||
private static final String PACKAGE_CLASS_NAME_SUFFIX = "Package";
|
||||
@@ -41,14 +39,4 @@ public final class OldPackageFacadeClassUtils {
|
||||
private static String capitalizeNonEmptyString(@NotNull String s) {
|
||||
return Character.isUpperCase(s.charAt(0)) ? s : Character.toUpperCase(s.charAt(0)) + s.substring(1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FqName getPackageClassFqName(@NotNull FqName packageFQN) {
|
||||
return packageFQN.child(Name.identifier(getPackageClassName(packageFQN)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassId getPackageClassId(@NotNull FqName packageFQN) {
|
||||
return new ClassId(packageFQN, Name.identifier(getPackageClassName(packageFQN)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.sam;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
|
||||
@@ -25,18 +24,18 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE;
|
||||
|
||||
@@ -134,6 +133,10 @@ public class SingleAbstractMethodUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DescriptorUtilsKt.getFqNameSafe(klass).asString().equals("android.databinding.DataBindingComponent")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
|
||||
if (abstractMembers.size() == 1) {
|
||||
CallableMemberDescriptor member = abstractMembers.get(0);
|
||||
|
||||
@@ -29,6 +29,7 @@ public class AsmTypes {
|
||||
public static final Type JAVA_STRING_TYPE = getType(String.class);
|
||||
public static final Type JAVA_THROWABLE_TYPE = getType(Throwable.class);
|
||||
public static final Type JAVA_CLASS_TYPE = getType(Class.class);
|
||||
public static final Type ENUM_TYPE = getType(Enum.class);
|
||||
|
||||
public static final Type UNIT_TYPE = Type.getObjectType("kotlin/Unit");
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
|
||||
targetEnvironment,
|
||||
LookupTracker.DO_NOTHING,
|
||||
packagePartProvider,
|
||||
languageSettingsProvider.getLanguageVersionSettings(moduleInfo),
|
||||
languageSettingsProvider.getLanguageVersionSettings(moduleInfo, project),
|
||||
useBuiltInsProvider = false, // TODO: load built-ins from module dependencies in IDE
|
||||
useLazyResolve = true,
|
||||
compilerConfiguration = compilerConfiguration
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -29,7 +29,8 @@ import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANN
|
||||
object JvmDelegationFilter : DelegationFilter {
|
||||
|
||||
override fun filter(interfaceMember: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
if (languageVersionSettings.languageVersion == LanguageVersion.KOTLIN_1_0) return true
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.NoDelegationToJavaDefaultInterfaceMembers)) return true
|
||||
|
||||
//We always have only one implementation otherwise it's an error in kotlin and java
|
||||
val realMember = DescriptorUtils.unwrapFakeOverride(interfaceMember)
|
||||
return !isJavaDefaultMethod(realMember) && !isBuiltInMemberMappedToJavaDefault(realMember)
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
@@ -56,7 +57,6 @@ import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
@@ -253,6 +253,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
fun createContextWithSealedModule(project: Project, configuration: CompilerConfiguration): MutableModuleContext =
|
||||
createModuleContext(project, configuration, false).apply {
|
||||
setDependencies(module, module.builtIns.builtInsModule)
|
||||
(module.builtIns as JvmBuiltIns).initialize(module, configuration.get(LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT))
|
||||
}
|
||||
|
||||
private fun createModuleContext(
|
||||
|
||||
@@ -1,67 +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.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
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.checkers.DeclarationChecker
|
||||
|
||||
object AdditionalBuiltInsMembersCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
|
||||
if (resultingDescriptor.isAdditionalBuiltInMember()) {
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.AdditionalBuiltInsMembers))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object AdditionalBuiltInsMemberOverrideDeclarationChecker : DeclarationChecker {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
|
||||
val resultingDescriptor = descriptor as? CallableMemberDescriptor ?: return
|
||||
val overrideKeyword = declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: return
|
||||
|
||||
val overriddenDescriptors = resultingDescriptor.original.overriddenDescriptors
|
||||
if (overriddenDescriptors.isNotEmpty() && overriddenDescriptors.all { it.isAdditionalBuiltInMember() }) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(overrideKeyword, LanguageFeature.AdditionalBuiltInsMembers))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.isAdditionalBuiltInMember() =
|
||||
KotlinBuiltIns.isBuiltIn(this) && this is JavaCallableMemberDescriptor
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.platform
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -24,8 +25,8 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import java.util.*
|
||||
|
||||
object JvmPlatform : TargetPlatform("JVM") {
|
||||
override val defaultImports: List<ImportPath> = ArrayList<ImportPath>().apply {
|
||||
addAll(Default.defaultImports)
|
||||
override fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath> = ArrayList<ImportPath>().apply {
|
||||
addAll(Default.getDefaultImports(languageVersionSettings))
|
||||
|
||||
add(ImportPath("java.lang.*"))
|
||||
add(ImportPath("kotlin.jvm.*"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,21 +44,18 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
TypeParameterBoundIsNotArrayChecker(),
|
||||
JvmSyntheticApplicabilityChecker(),
|
||||
StrictfpApplicabilityChecker(),
|
||||
AdditionalBuiltInsMemberOverrideDeclarationChecker,
|
||||
HeaderImplDeclarationChecker()
|
||||
),
|
||||
|
||||
additionalCallCheckers = listOf(
|
||||
JavaAnnotationCallChecker(),
|
||||
InterfaceDefaultMethodCallChecker(),
|
||||
JavaClassOnCompanionChecker(),
|
||||
ProtectedInSuperClassCompanionCallChecker(),
|
||||
UnsupportedSyntheticCallableReferenceChecker(),
|
||||
SuperCallWithDefaultArgumentsChecker(),
|
||||
MissingDependencyClassChecker,
|
||||
ProtectedSyntheticExtensionCallChecker,
|
||||
ReifiedTypeParameterSubstitutionChecker(),
|
||||
AdditionalBuiltInsMembersCallChecker
|
||||
ReifiedTypeParameterSubstitutionChecker()
|
||||
),
|
||||
|
||||
additionalTypeCheckers = listOf(
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@@ -58,10 +59,8 @@ class SamAdapterFunctionsScope(
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
var result: SmartList<FunctionDescriptor>? = null
|
||||
for (type in receiverTypes) {
|
||||
val substitutorForType by lazy { buildMemberScopeSubstitutorForType(type) }
|
||||
|
||||
for (function in type.memberScope.getContributedFunctions(name, location)) {
|
||||
val extension = extensionForFunction(function.original)?.substitute(substitutorForType)
|
||||
val extension = extensionForFunction(function.original)?.substituteForReceiverType(type)
|
||||
if (extension != null) {
|
||||
if (result == null) {
|
||||
result = SmartList()
|
||||
@@ -77,15 +76,24 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildMemberScopeSubstitutorForType(type: KotlinType) =
|
||||
TypeConstructorSubstitution.create(type).wrapWithCapturingSubstitution(needApproximation = true).buildSubstitutor()
|
||||
private fun FunctionDescriptor.substituteForReceiverType(receiverType: KotlinType): FunctionDescriptor? {
|
||||
val containingClass = containingDeclaration as? ClassDescriptor ?: return null
|
||||
val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null
|
||||
|
||||
return substitute(
|
||||
TypeConstructorSubstitution
|
||||
.create(correspondingSupertype)
|
||||
.wrapWithCapturingSubstitution(needApproximation = true)
|
||||
.buildSubstitutor()
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
|
||||
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
|
||||
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filterIsInstance<FunctionDescriptor>()
|
||||
.mapNotNull {
|
||||
extensionForFunction(it.original)?.substitute(buildMemberScopeSubstitutorForType(type))
|
||||
extensionForFunction(it.original)?.substituteForReceiverType(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,10 +167,13 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
}
|
||||
|
||||
override fun newCopyBuilder(substitutor: TypeSubstitutor): CopyConfiguration =
|
||||
super.newCopyBuilder(substitutor).setOriginal(this.original)
|
||||
|
||||
override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? {
|
||||
val descriptor = super.doSubstitute(configuration) as MyFunctionDescriptor? ?: return null
|
||||
val original = configuration.original
|
||||
?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension")
|
||||
?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension $this")
|
||||
|
||||
original as MyFunctionDescriptor
|
||||
assert(original.original == original) { "original in doSubstitute should have no other original" }
|
||||
|
||||
@@ -259,12 +259,12 @@ private class DelegatingPackageFragmentProvider(
|
||||
}
|
||||
|
||||
interface LanguageSettingsProvider {
|
||||
fun getLanguageVersionSettings(moduleInfo: ModuleInfo): LanguageVersionSettings
|
||||
fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project): LanguageVersionSettings
|
||||
|
||||
fun getTargetPlatform(moduleInfo: ModuleInfo): DescriptionAware
|
||||
|
||||
object Default : LanguageSettingsProvider {
|
||||
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo) = LanguageVersionSettingsImpl.DEFAULT
|
||||
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project) = LanguageVersionSettingsImpl.DEFAULT
|
||||
|
||||
override fun getTargetPlatform(moduleInfo: ModuleInfo): DescriptionAware = DescriptionAware.NoVersion
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cfg.WhenMissingCase;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.config.LanguageVersion;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
|
||||
@@ -63,11 +64,11 @@ public interface Errors {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DiagnosticFactory1<PsiElement, String> UNSUPPORTED = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, LanguageFeature> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, Throwable> EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, LanguageFeature> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, LanguageFeature> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -193,6 +194,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
@@ -452,7 +454,6 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyDelegate> DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyDelegate> LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
@@ -701,7 +702,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<KtExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_PD_METHOD_NONE_APPLICABLE = DiagnosticFactory2.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<KtSimpleNameExpression, KotlinType> COMPARE_TO_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, String> YIELD_IS_RESERVED = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> UNDERSCORE_IS_RESERVED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> INVALID_CHARACTERS = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
@@ -910,7 +911,7 @@ public interface Errors {
|
||||
|
||||
|
||||
DiagnosticFactory0<PsiElement> NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> ILLEGAL_SUSPEND_FUNCTION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> ILLEGAL_SUSPEND_FUNCTION_CALL = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not fully supported. Add 'noinline' modifier.");
|
||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||
@@ -236,7 +237,6 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract");
|
||||
MAP.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations");
|
||||
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
|
||||
MAP.put(LOCAL_VARIABLE_WITH_DELEGATE, "Local variables are not allowed to have delegates");
|
||||
|
||||
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
|
||||
|
||||
@@ -462,6 +462,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(COMPARE_TO_TYPE_MISMATCH, "''compareTo()'' must return Int, but returns {0}", RENDER_TYPE);
|
||||
|
||||
MAP.put(UNDERSCORE_IS_RESERVED, "Names _, __, ___, ..., are reserved in Kotlin");
|
||||
MAP.put(YIELD_IS_RESERVED, "{0}", STRING);
|
||||
MAP.put(INVALID_CHARACTERS, "Name {0}", STRING);
|
||||
|
||||
MAP.put(INAPPLICABLE_OPERATOR_MODIFIER, "''operator'' modifier is inapplicable on this function: {0}", STRING);
|
||||
@@ -596,30 +597,11 @@ public class DefaultErrorMessages {
|
||||
MAP.put(UNSAFE_IMPLICIT_INVOKE_CALL, "Reference has a nullable type ''{0}'', use explicit ''?.invoke()'' to make a function-like call instead", RENDER_TYPE);
|
||||
MAP.put(AMBIGUOUS_LABEL, "Ambiguous label");
|
||||
MAP.put(UNSUPPORTED, "Unsupported [{0}]", STRING);
|
||||
MAP.put(UNSUPPORTED_FEATURE, "The feature is {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
|
||||
LanguageVersion version = feature.getSinceVersion();
|
||||
return version != null
|
||||
? "only available since Kotlin " + version.getVersionString() + ": " + feature.getPresentableText()
|
||||
: "experimental and should be turned on explicitly via a command line option or in IDE settings: " + feature.getPresentableText();
|
||||
}
|
||||
});
|
||||
MAP.put(EXPERIMENTAL_FEATURE_WARNING, "The feature is experimental: {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
|
||||
return feature.getPresentableText();
|
||||
}
|
||||
});
|
||||
MAP.put(EXPERIMENTAL_FEATURE_ERROR, "The experimental feature is disabled: {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
|
||||
return feature.getPresentableText();
|
||||
}
|
||||
});
|
||||
|
||||
MAP.put(UNSUPPORTED_FEATURE, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.UNSUPPORTED));
|
||||
MAP.put(EXPERIMENTAL_FEATURE_WARNING, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.WARNING));
|
||||
MAP.put(EXPERIMENTAL_FEATURE_ERROR, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR));
|
||||
|
||||
MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE);
|
||||
MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE);
|
||||
MAP.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here");
|
||||
@@ -904,7 +886,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME);
|
||||
MAP.put(NON_LOCAL_RETURN_IN_DISABLED_INLINE, "Non-local returns are not allowed with inlining disabled");
|
||||
MAP.put(NON_LOCAL_SUSPENSION_POINT, "Suspension functions can be called only within coroutine body");
|
||||
MAP.put(ILLEGAL_SUSPEND_FUNCTION_CALL, "Suspend functions are only allowed to be called from a coroutine or another suspend function");
|
||||
MAP.put(ILLEGAL_SUSPEND_FUNCTION_CALL, "Suspend function ''{0}'' should be called only from a coroutine or another suspend function", NAME);
|
||||
MAP.put(ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL, "Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope");
|
||||
|
||||
MAP.setImmutable();
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.diagnostics.rendering
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
|
||||
class LanguageFeatureMessageRenderer @JvmOverloads constructor(
|
||||
private val type: Type,
|
||||
private val useHtml: Boolean = false
|
||||
): DiagnosticParameterRenderer<Pair<LanguageFeature, LanguageVersionSettings>> {
|
||||
|
||||
enum class Type {
|
||||
UNSUPPORTED,
|
||||
WARNING,
|
||||
ERROR
|
||||
}
|
||||
|
||||
override fun render(obj: Pair<LanguageFeature, LanguageVersionSettings>, renderingContext: RenderingContext): String {
|
||||
val (feature, settings) = obj
|
||||
val since = feature.sinceVersion
|
||||
|
||||
val sb = StringBuilder()
|
||||
sb.append("The feature \"").append(feature.presentableName).append("\" is ")
|
||||
|
||||
when (type) {
|
||||
Type.UNSUPPORTED ->
|
||||
when {
|
||||
since == null ->
|
||||
sb.append("experimental and should be enabled explicitly")
|
||||
since > settings.languageVersion ->
|
||||
sb.append("only available since language version ").append(since.versionString)
|
||||
feature.sinceApiVersion > settings.apiVersion ->
|
||||
sb.append("only available since API version ").append(feature.sinceApiVersion.versionString)
|
||||
else ->
|
||||
sb.append("disabled")
|
||||
}
|
||||
|
||||
Type.WARNING -> sb.append("experimental")
|
||||
Type.ERROR -> sb.append("experimental and disabled")
|
||||
}
|
||||
|
||||
val hintUrl = feature.hintUrl
|
||||
if (hintUrl != null) {
|
||||
if (useHtml) {
|
||||
sb.append(" (").append("see more <a href=\"").append(hintUrl).append("\">here</a>)")
|
||||
}
|
||||
else {
|
||||
sb.append(" (see: ").append(hintUrl).append(")")
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -123,5 +123,6 @@ private val MODIFIERS_TO_REPLACE = mapOf(
|
||||
private val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
|
||||
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD,
|
||||
OVERRIDE_KEYWORD,
|
||||
SUSPEND_KEYWORD,
|
||||
INNER_KEYWORD,
|
||||
ENUM_KEYWORD, COMPANION_KEYWORD, INFIX_KEYWORD, OPERATOR_KEYWORD, DATA_KEYWORD)
|
||||
|
||||
@@ -461,6 +461,25 @@ fun checkReservedPrefixWord(sink: DiagnosticSink, element: PsiElement, word: Str
|
||||
}
|
||||
}
|
||||
|
||||
fun checkReservedYield(expression: KtSimpleNameExpression?, sink: DiagnosticSink) {
|
||||
// do not force identifier calculation for elements from stubs.
|
||||
if (expression?.getReferencedName() != "yield") return
|
||||
|
||||
val identifier = expression.getIdentifier() ?: return
|
||||
|
||||
if (identifier.node.elementType == KtTokens.IDENTIFIER && "yield" == identifier.text) {
|
||||
sink.report(Errors.YIELD_IS_RESERVED.on(identifier, "Identifier 'yield' is reserved. Use backticks to call it: `yield`"))
|
||||
}
|
||||
}
|
||||
|
||||
val MESSAGE_FOR_YIELD_BEFORE_LAMBDA = "Reserved yield block/lambda. Use 'yield() { ... }' or 'yield(fun...)'"
|
||||
|
||||
fun checkReservedYieldBeforeLambda(element: PsiElement, sink: DiagnosticSink) {
|
||||
KtPsiUtil.getPreviousWord(element, "yield")?.let {
|
||||
sink.report(Errors.YIELD_IS_RESERVED.on(it, MESSAGE_FOR_YIELD_BEFORE_LAMBDA))
|
||||
}
|
||||
}
|
||||
|
||||
fun KtElement.nonStaticOuterClasses(): Sequence<KtClass> {
|
||||
return generateSequence(containingClass()) { if (it.isInner()) it.containingClass() else null }
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ object KotlinStubVersions {
|
||||
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
|
||||
// if you are not 100% sure it can be avoided.
|
||||
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
|
||||
const val SOURCE_STUB_VERSION = 120
|
||||
const val SOURCE_STUB_VERSION = 121
|
||||
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 57
|
||||
private const val BINARY_STUB_VERSION = 58
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
@@ -40,5 +40,5 @@ object KotlinStubVersions {
|
||||
|
||||
// JS stub version should be increased if changes are made to js stub building subsystem (org.jetbrains.kotlin.idea.decompiler.js)
|
||||
// Increasing this version will lead to reindexing of js binary files (see KotlinJavaScriptMetaFileType).
|
||||
const val JS_STUB_VERSION = BINARY_STUB_VERSION + 0
|
||||
const val JS_STUB_VERSION = BINARY_STUB_VERSION + 1
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ class DeclarationsChecker(
|
||||
}
|
||||
}
|
||||
else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(property, LanguageFeature.ShortSyntaxForPropertyGetters))
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(property, LanguageFeature.ShortSyntaxForPropertyGetters to languageVersionSettings))
|
||||
}
|
||||
else if (noExplicitTypeOrGetterType(property)) {
|
||||
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.Pair;
|
||||
import kotlin.TuplesKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.collections.SetsKt;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
@@ -324,7 +325,8 @@ public class DescriptorResolver {
|
||||
Function0<List<VariableDescriptor>> destructuringVariables;
|
||||
if (destructuringDeclaration != null) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.DestructuringLambdaParameters)) {
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(valueParameter, LanguageFeature.DestructuringLambdaParameters));
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(valueParameter,
|
||||
TuplesKt.to(LanguageFeature.DestructuringLambdaParameters, languageVersionSettings)));
|
||||
}
|
||||
|
||||
destructuringVariables = new Function0<List<VariableDescriptor>>() {
|
||||
@@ -742,7 +744,8 @@ public class DescriptorResolver {
|
||||
else if (!languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)) {
|
||||
typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace);
|
||||
PsiElement typeAliasKeyword = typeAlias.getTypeAliasKeyword();
|
||||
trace.report(UNSUPPORTED_FEATURE.on(typeAliasKeyword != null ? typeAliasKeyword : typeAlias, LanguageFeature.TypeAliases));
|
||||
trace.report(UNSUPPORTED_FEATURE.on(typeAliasKeyword != null ? typeAliasKeyword : typeAlias,
|
||||
TuplesKt.to(LanguageFeature.TypeAliases, languageVersionSettings)));
|
||||
typeAliasDescriptor.initialize(
|
||||
typeParameterDescriptors,
|
||||
ErrorUtils.createErrorType(name.asString()),
|
||||
|
||||
@@ -77,7 +77,7 @@ class LocalVariableResolver(
|
||||
val delegateExpression = property.delegateExpression
|
||||
if (delegateExpression != null) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.LocalDelegatedProperties)) {
|
||||
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.delegate!!))
|
||||
context.trace.report(UNSUPPORTED_FEATURE.on(property.delegate!!, LanguageFeature.LocalDelegatedProperties to languageVersionSettings))
|
||||
}
|
||||
|
||||
if (propertyDescriptor is VariableDescriptorWithAccessors) {
|
||||
|
||||
@@ -277,6 +277,7 @@ object ModifierCheckerCore {
|
||||
val errorOnDependencyFeature = errorOnFeature[dependency]?.let { languageVersionSettings.supportsFeature(it) } ?: false
|
||||
val supportsFeature = languageVersionSettings.supportsFeature(dependency)
|
||||
|
||||
val diagnosticData = dependency to languageVersionSettings
|
||||
if (!supportsFeature || errorOnDependencyFeature) {
|
||||
val restrictedTargets = featureDependenciesTargets[dependency]
|
||||
if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) {
|
||||
@@ -284,17 +285,17 @@ object ModifierCheckerCore {
|
||||
}
|
||||
|
||||
if (!supportsFeature) {
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, dependency))
|
||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, diagnosticData))
|
||||
}
|
||||
else if (errorOnDependencyFeature) {
|
||||
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, dependency))
|
||||
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, diagnosticData))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val pairedWarningFeature = warningOnFeature[dependency]
|
||||
if (pairedWarningFeature != null && languageVersionSettings.supportsFeature(pairedWarningFeature)) {
|
||||
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, dependency))
|
||||
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, diagnosticData))
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
@@ -66,7 +66,7 @@ object OperatorModifierChecker {
|
||||
|
||||
private fun checkSupportsFeature(feature: LanguageFeature, languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, modifier: PsiElement) {
|
||||
if (!languageVersionSettings.supportsFeature(feature)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature))
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature to languageVersionSettings))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.composeContainer
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
@@ -33,20 +36,24 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
override fun toString() = platformName
|
||||
|
||||
abstract val platformConfigurator: PlatformConfigurator
|
||||
abstract val defaultImports: List<ImportPath>
|
||||
abstract fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath>
|
||||
open val excludedImports: List<FqName> get() = emptyList()
|
||||
|
||||
abstract val multiTargetPlatform: MultiTargetPlatform
|
||||
|
||||
object Default : TargetPlatform("Default") {
|
||||
override val defaultImports: List<ImportPath> = ArrayList<ImportPath>().apply {
|
||||
override fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath> = ArrayList<ImportPath>().apply {
|
||||
add(ImportPath("kotlin.*"))
|
||||
add(ImportPath("kotlin.annotation.*"))
|
||||
add(ImportPath("kotlin.collections.*"))
|
||||
add(ImportPath("kotlin.ranges.*"))
|
||||
add(ImportPath("kotlin.sequences.*"))
|
||||
add(ImportPath("kotlin.text.*"))
|
||||
add(ImportPath("kotlin.comparisons.*"))
|
||||
add(ImportPath("kotlin.io.*"))
|
||||
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.DefaultImportOfPackageKotlinComparisons)) {
|
||||
add(ImportPath("kotlin.comparisons.*"))
|
||||
}
|
||||
}
|
||||
|
||||
override val platformConfigurator =
|
||||
@@ -77,14 +84,16 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
ReifiedTypeParameterAnnotationChecker(),
|
||||
DynamicReceiverChecker,
|
||||
DelegationChecker(),
|
||||
KClassWithIncorrectTypeArgumentChecker
|
||||
KClassWithIncorrectTypeArgumentChecker,
|
||||
SuspendOperatorsCheckers
|
||||
)
|
||||
|
||||
private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
CapturingInClosureChecker(), InlineCheckerWrapper(), SafeCallChecker(),
|
||||
DeprecatedCallChecker, CallReturnsArrayOfNothingChecker(), InfixCallChecker(), OperatorCallChecker(),
|
||||
ConstructorHeaderCallChecker, ProtectedConstructorCallChecker, ApiVersionCallChecker,
|
||||
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker
|
||||
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker,
|
||||
CallableReferenceCompatibilityChecker()
|
||||
)
|
||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker)
|
||||
|
||||
@@ -116,12 +116,9 @@ private class AbbreviatedTypeBinding(
|
||||
override val isInAbbreviation: Boolean get() = true
|
||||
|
||||
override val arguments: List<TypeArgumentBinding<KtTypeElement>?>
|
||||
get() = type.arguments.mapIndexed { index, argument ->
|
||||
TypeArgumentBindingImpl(
|
||||
argument,
|
||||
type.constructor.parameters[index],
|
||||
AbbreviatedTypeBinding(argument.type, psiElement)
|
||||
)
|
||||
get() = createTypeArgumentBindingsWithSinglePsiElement(type) {
|
||||
argumentType ->
|
||||
AbbreviatedTypeBinding(argumentType, psiElement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,16 +130,22 @@ private class NoTypeElementBinding<out P : PsiElement>(
|
||||
override val isInAbbreviation: Boolean get() = false
|
||||
|
||||
override val arguments: List<TypeArgumentBinding<P>?>
|
||||
get() {
|
||||
val isErrorBinding = type.isError || type.constructor.parameters.size != type.arguments.size
|
||||
return type.arguments.indices.map {
|
||||
val typeProjection = type.arguments[it]
|
||||
TypeArgumentBindingImpl(
|
||||
typeProjection,
|
||||
if (isErrorBinding) null else type.constructor.parameters[it],
|
||||
NoTypeElementBinding(trace, psiElement, typeProjection.type)
|
||||
)
|
||||
}
|
||||
get() = createTypeArgumentBindingsWithSinglePsiElement(type) {
|
||||
argumentType ->
|
||||
NoTypeElementBinding(trace, psiElement, argumentType)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <P : PsiElement> createTypeArgumentBindingsWithSinglePsiElement(
|
||||
type: KotlinType,
|
||||
createBinding: (KotlinType) -> TypeBinding<P>
|
||||
) : List<TypeArgumentBinding<P>> {
|
||||
val isErrorBinding = type.isError || type.constructor.parameters.size != type.arguments.size
|
||||
return type.arguments.mapIndexed { index, typeProjection ->
|
||||
TypeArgumentBindingImpl(
|
||||
typeProjection,
|
||||
if (isErrorBinding) null else type.constructor.parameters[index],
|
||||
createBinding(typeProjection.type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||
@@ -227,6 +228,8 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
val referenceExpression = type.referenceExpression ?: return
|
||||
|
||||
checkReservedYield(referenceExpression, c.trace)
|
||||
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifier)
|
||||
|
||||
result = resolveTypeForClassifier(c, classifier, qualifierResolutionResult, type, annotations)
|
||||
@@ -509,7 +512,7 @@ class TypeResolver(
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
}
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)) {
|
||||
c.trace.report(UNSUPPORTED_FEATURE.on(type, LanguageFeature.TypeAliases))
|
||||
c.trace.report(UNSUPPORTED_FEATURE.on(type, LanguageFeature.TypeAliases to languageVersionSettings))
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
@@ -185,7 +186,9 @@ public class ValueArgumentsToParametersMapper {
|
||||
ValueArgumentName argumentName = argument.getArgumentName();
|
||||
assert argumentName != null;
|
||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(argumentName.getAsName());
|
||||
KtReferenceExpression nameReference = argumentName.getReferenceExpression();
|
||||
KtSimpleNameExpression nameReference = argumentName.getReferenceExpression();
|
||||
|
||||
KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace());
|
||||
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||
nameReference,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class CallableReferenceCompatibilityChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val typeInferenceForCallableReferencesFeature = LanguageFeature.TypeInferenceOnGenericsForCallableReferences
|
||||
if (context.languageVersionSettings.supportsFeature(typeInferenceForCallableReferencesFeature)) return
|
||||
|
||||
for ((_, resolvedArgument) in resolvedCall.valueArguments) {
|
||||
inner@ for (argument in resolvedArgument.arguments) {
|
||||
val argumentExpression = argument.getArgumentExpression() as? KtCallableReferenceExpression ?: continue@inner
|
||||
val callableReferenceResolvedCall = argumentExpression.callableReference.getResolvedCall(context.trace.bindingContext) ?: continue@inner
|
||||
if (callableReferenceResolvedCall.call.isCallableReference() &&
|
||||
callableReferenceResolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(argumentExpression,
|
||||
typeInferenceForCallableReferencesFeature to context.languageVersionSettings))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspensionAnnotation
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
@@ -59,18 +60,24 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
if (!InlineUtil.checkNonLocalReturnUsage(enclosingSuspendFunction, callElement, context.resolutionContext)) {
|
||||
context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn))
|
||||
}
|
||||
else if (context.scope.parentsWithSelf.any { it.isScopeForDefaultParameterValuesOf(enclosingSuspendFunction) }) {
|
||||
context.trace.report(Errors.UNSUPPORTED.on(reportOn, "suspend function calls in a context of default parameter value"))
|
||||
}
|
||||
|
||||
context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction)
|
||||
|
||||
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
||||
}
|
||||
else -> {
|
||||
context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn))
|
||||
context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn, resolvedCall.candidateDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun HierarchicalScope.isScopeForDefaultParameterValuesOf(enclosingSuspendFunction: FunctionDescriptor) =
|
||||
this is LexicalScope && this.kind == LexicalScopeKind.DEFAULT_VALUE && this.ownerDescriptor == enclosingSuspendFunction
|
||||
|
||||
object BuilderFunctionsCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
|
||||
@@ -81,14 +88,15 @@ object BuilderFunctionsCallChecker : CallChecker {
|
||||
}
|
||||
|
||||
fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) {
|
||||
val diagnosticData = LanguageFeature.Coroutines to languageVersionSettings
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines))
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, diagnosticData))
|
||||
}
|
||||
else if (languageVersionSettings.supportsFeature(LanguageFeature.ErrorOnCoroutines)) {
|
||||
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, LanguageFeature.Coroutines))
|
||||
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, diagnosticData))
|
||||
}
|
||||
else if (languageVersionSettings.supportsFeature(LanguageFeature.WarnOnCoroutines)) {
|
||||
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, LanguageFeature.Coroutines))
|
||||
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, diagnosticData))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -35,10 +37,15 @@ object InlineParameterChecker : SimpleDeclarationChecker {
|
||||
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||
for (parameter in declaration.valueParameters) {
|
||||
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, parameter)
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isFunctionType)) {
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
|
||||
parameter.reportIncorrectInline(KtTokens.NOINLINE_KEYWORD, diagnosticHolder)
|
||||
parameter.reportIncorrectInline(KtTokens.CROSSINLINE_KEYWORD, diagnosticHolder)
|
||||
}
|
||||
|
||||
if (inline && !parameter.hasModifier(KtTokens.NOINLINE_KEYWORD) &&
|
||||
parameterDescriptor?.type?.isSuspendFunctionType == true) {
|
||||
diagnosticHolder.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object SuspendOperatorsCheckers : SimpleDeclarationChecker {
|
||||
private val UNSUPPORTED_OPERATOR_NAMES = setOf(
|
||||
OperatorNameConventions.CONTAINS,
|
||||
OperatorNameConventions.GET, OperatorNameConventions.SET
|
||||
)
|
||||
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
if (descriptor is FunctionDescriptor && descriptor.isSuspend && descriptor.isOperator &&
|
||||
descriptor.name in UNSUPPORTED_OPERATOR_NAMES) {
|
||||
declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD)?.let {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED.on(it, "suspend operator \"${descriptor.name}\""))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ object UnderscoreChecker : DeclarationChecker {
|
||||
diagnosticHolder.report(Errors.UNDERSCORE_IS_RESERVED.on(identifier))
|
||||
}
|
||||
else if (isValidSingleUnderscore && !languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName))
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName to languageVersionSettings))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ class ConstantExpressionEvaluator(
|
||||
val lhsExpression = argumentExpression.receiverExpression
|
||||
if (lhsExpression != null) {
|
||||
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObject) {
|
||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ internal val unaryOperations: HashMap<UnaryOperationKey<*>, Pair<Function1<Any?,
|
||||
= hashMapOf<UnaryOperationKey<*>, Pair<Function1<Any?, Any>, Function1<Long, Long>>>(
|
||||
unaryOperation(BOOLEAN, "not", { a -> a.not() }, emptyUnaryFun),
|
||||
unaryOperation(BOOLEAN, "toString", { a -> a.toString() }, emptyUnaryFun),
|
||||
unaryOperation(BYTE, "inv", { a -> a.inv() }, emptyUnaryFun),
|
||||
unaryOperation(BYTE, "toByte", { a -> a.toByte() }, emptyUnaryFun),
|
||||
unaryOperation(BYTE, "toChar", { a -> a.toChar() }, emptyUnaryFun),
|
||||
unaryOperation(BYTE, "toDouble", { a -> a.toDouble() }, emptyUnaryFun),
|
||||
@@ -89,7 +88,6 @@ internal val unaryOperations: HashMap<UnaryOperationKey<*>, Pair<Function1<Any?,
|
||||
unaryOperation(LONG, "toString", { a -> a.toString() }, emptyUnaryFun),
|
||||
unaryOperation(LONG, "unaryMinus", { a -> a.unaryMinus() }, { a -> a.unaryMinus() }),
|
||||
unaryOperation(LONG, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun),
|
||||
unaryOperation(SHORT, "inv", { a -> a.inv() }, emptyUnaryFun),
|
||||
unaryOperation(SHORT, "toByte", { a -> a.toByte() }, emptyUnaryFun),
|
||||
unaryOperation(SHORT, "toChar", { a -> a.toChar() }, emptyUnaryFun),
|
||||
unaryOperation(SHORT, "toDouble", { a -> a.toDouble() }, emptyUnaryFun),
|
||||
@@ -111,7 +109,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(BOOLEAN, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun),
|
||||
binaryOperation(BOOLEAN, BOOLEAN, "or", { a, b -> a.or(b) }, emptyBinaryFun),
|
||||
binaryOperation(BOOLEAN, BOOLEAN, "xor", { a, b -> a.xor(b) }, emptyBinaryFun),
|
||||
binaryOperation(BYTE, BYTE, "and", { a, b -> a.and(b) }, { a, b -> a.and(b) }),
|
||||
binaryOperation(BYTE, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(BYTE, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(BYTE, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
@@ -137,7 +134,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(BYTE, INT, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(BYTE, LONG, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(BYTE, SHORT, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(BYTE, BYTE, "or", { a, b -> a.or(b) }, { a, b -> a.or(b) }),
|
||||
binaryOperation(BYTE, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }),
|
||||
binaryOperation(BYTE, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun),
|
||||
binaryOperation(BYTE, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun),
|
||||
@@ -156,7 +152,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(BYTE, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(BYTE, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(BYTE, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(BYTE, BYTE, "xor", { a, b -> a.xor(b) }, { a, b -> a.xor(b) }),
|
||||
binaryOperation(CHAR, CHAR, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(CHAR, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun),
|
||||
binaryOperation(CHAR, CHAR, "minus", { a, b -> a.minus(b) }, emptyBinaryFun),
|
||||
@@ -346,7 +341,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(LONG, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(LONG, INT, "ushr", { a, b -> a.ushr(b) }, emptyBinaryFun),
|
||||
binaryOperation(LONG, LONG, "xor", { a, b -> a.xor(b) }, { a, b -> a.xor(b) }),
|
||||
binaryOperation(SHORT, SHORT, "and", { a, b -> a.and(b) }, { a, b -> a.and(b) }),
|
||||
binaryOperation(SHORT, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(SHORT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(SHORT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
@@ -372,7 +366,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(SHORT, INT, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(SHORT, LONG, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(SHORT, SHORT, "mod", { a, b -> a.mod(b) }, { a, b -> a.mod(b) }),
|
||||
binaryOperation(SHORT, SHORT, "or", { a, b -> a.or(b) }, { a, b -> a.or(b) }),
|
||||
binaryOperation(SHORT, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }),
|
||||
binaryOperation(SHORT, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun),
|
||||
binaryOperation(SHORT, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun),
|
||||
@@ -391,7 +384,6 @@ internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<
|
||||
binaryOperation(SHORT, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(SHORT, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(SHORT, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }),
|
||||
binaryOperation(SHORT, SHORT, "xor", { a, b -> a.xor(b) }, { a, b -> a.xor(b) }),
|
||||
binaryOperation(STRING, STRING, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||
binaryOperation(STRING, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun),
|
||||
binaryOperation(STRING, INT, "get", { a, b -> a.get(b) }, emptyBinaryFun),
|
||||
|
||||
@@ -39,7 +39,7 @@ class DefaultImportProvider(
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
val defaultImports: List<ImportPath>
|
||||
get() = targetPlatform.defaultImports
|
||||
by storageManager.createLazyValue { targetPlatform.getDefaultImports(languageVersionSettings) }
|
||||
|
||||
val excludedImports: List<FqName> by storageManager.createLazyValue {
|
||||
val packagesWithAliases = listOf(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.TEXT_PACKAGE_FQ_NAME)
|
||||
@@ -63,6 +63,6 @@ class DefaultImportProvider(
|
||||
.mapNotNull { it.expandedType.constructor.declarationDescriptor?.fqNameSafe }
|
||||
.filter { nonKotlinDefaultImportedPackages.any(it::isChildOf) }
|
||||
|
||||
nonKotlinAliasedTypeFqNames
|
||||
nonKotlinAliasedTypeFqNames + targetPlatform.excludedImports
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
||||
?: if (cacheOfNulls.contains(path)) null
|
||||
else scriptDefinitionProvider.findScriptDefinition(file)?.getDependenciesFor(file, project, null)
|
||||
.apply {
|
||||
log.info("[kts] new cached deps for $path: ${this?.classpath?.joinToString(File.pathSeparator)}")
|
||||
if (this != null) {
|
||||
log.info("[kts] new cached deps for $path: ${this.classpath.joinToString(File.pathSeparator)}")
|
||||
}
|
||||
cacheLock.write {
|
||||
if (this == null) {
|
||||
cacheOfNulls.add(path)
|
||||
|
||||
@@ -55,4 +55,10 @@ internal fun constructAnnotation(psi: KtAnnotationEntry, targetClass: KClass<out
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidScriptResolverAnnotation(val name: String, val annParams: List<Pair<String?, Any?>>?, val error: Exception? = null) : Annotation
|
||||
// NOTE: this class is used for error reporting. But in order to pass plugin verification, it should derive directly from java's Annotation
|
||||
// and implement annotationType method (see #KT-16621 for details).
|
||||
// TODO: instead of the workaround described above, consider using a sum-type for returning errors from constructAnnotation
|
||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
class InvalidScriptResolverAnnotation(val name: String, val annParams: List<Pair<String?, Any?>>?, val error: Exception? = null) : Annotation, java.lang.annotation.Annotation {
|
||||
override fun annotationType(): Class<out Annotation> = InvalidScriptResolverAnnotation::class.java
|
||||
}
|
||||
|
||||
@@ -89,11 +89,11 @@ public class CommonSupertypes {
|
||||
for (KotlinType type : types) {
|
||||
UnwrappedType unwrappedType = type.unwrap();
|
||||
if (unwrappedType instanceof FlexibleType) {
|
||||
if (DynamicTypesKt.isDynamic(type)) {
|
||||
return type;
|
||||
if (DynamicTypesKt.isDynamic(unwrappedType)) {
|
||||
return unwrappedType;
|
||||
}
|
||||
hasFlexible = true;
|
||||
FlexibleType flexibleType = (FlexibleType) type;
|
||||
FlexibleType flexibleType = (FlexibleType) unwrappedType;
|
||||
upper.add(flexibleType.getUpperBound());
|
||||
lower.add(flexibleType.getLowerBound());
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import kotlin.TuplesKt;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
@@ -162,6 +164,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||
KtPsiUtilKt.checkReservedYield(expression, context.trace);
|
||||
|
||||
// TODO : other members
|
||||
// TODO : type substitutions???
|
||||
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
||||
@@ -235,7 +239,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (!text.contains("_")) return;
|
||||
|
||||
if (!components.languageVersionSettings.supportsFeature(LanguageFeature.UnderscoresInNumericLiterals)) {
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(expression, LanguageFeature.UnderscoresInNumericLiterals));
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(expression,
|
||||
TuplesKt.to(LanguageFeature.UnderscoresInNumericLiterals, components.languageVersionSettings)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -942,6 +947,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
boolean isStatement
|
||||
) {
|
||||
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
||||
KtPsiUtilKt.checkReservedYield(labelExpression, context.trace);
|
||||
if (labelExpression != null) {
|
||||
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
||||
UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace, components.languageVersionSettings);
|
||||
|
||||
@@ -29,15 +29,18 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.context.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.calls.util.createValueParametersForInvokeInFunctionType
|
||||
@@ -52,14 +55,25 @@ import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
sealed class DoubleColonLHS(val type: KotlinType) {
|
||||
class Expression(typeInfo: KotlinTypeInfo, val isObject: Boolean) : DoubleColonLHS(typeInfo.type!!) {
|
||||
/**
|
||||
* [isObjectQualifier] is true iff the LHS of a callable reference is a qualified expression which references a named object.
|
||||
* Note that such LHS can be treated both as a type and as an expression, so special handling may be required.
|
||||
*
|
||||
* For example, if `Obj` is an object:
|
||||
*
|
||||
* Obj::class // object qualifier
|
||||
* test.Obj::class // object qualifier
|
||||
* (Obj)::class // not an object qualifier (can only be treated as an expression, not as a type)
|
||||
* { Obj }()::class // not an object qualifier
|
||||
*/
|
||||
class Expression(typeInfo: KotlinTypeInfo, val isObjectQualifier: Boolean) : DoubleColonLHS(typeInfo.type!!) {
|
||||
val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo
|
||||
}
|
||||
|
||||
@@ -94,12 +108,20 @@ class DoubleColonExpressionResolver(
|
||||
}
|
||||
else {
|
||||
val result = resolveDoubleColonLHS(expression, c)
|
||||
val type = result?.type
|
||||
if (type != null && !type.isError) {
|
||||
checkClassLiteral(c, expression, result)
|
||||
val variance = if (result is DoubleColonLHS.Expression && !result.isObject) Variance.OUT_VARIANCE else Variance.INVARIANT
|
||||
val kClassType = reflectionTypes.getKClassType(Annotations.EMPTY, type, variance)
|
||||
if (result != null && !result.type.isError) {
|
||||
val inherentType = result.type
|
||||
val dataFlowInfo = (result as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression.receiverExpression!!, inherentType, c)
|
||||
val type =
|
||||
if (!dataFlowInfo.getStableNullability(dataFlowValue).canBeNull()) inherentType.makeNotNullable()
|
||||
else inherentType
|
||||
checkClassLiteral(c, expression, type, result)
|
||||
val variance =
|
||||
if (result is DoubleColonLHS.Expression && !result.isObjectQualifier) Variance.OUT_VARIANCE else Variance.INVARIANT
|
||||
val kClassType = reflectionTypes.getKClassType(Annotations.EMPTY, type, variance)
|
||||
if (kClassType.isError) {
|
||||
c.trace.report(MISSING_DEPENDENCY_CLASS.on(expression.receiverExpression!!, KotlinBuiltIns.FQ_NAMES.kClass.toSafe()))
|
||||
}
|
||||
return dataFlowAnalyzer.checkType(createTypeInfo(kClassType, dataFlowInfo), expression, c)
|
||||
}
|
||||
}
|
||||
@@ -107,11 +129,14 @@ class DoubleColonExpressionResolver(
|
||||
return createTypeInfo(ErrorUtils.createErrorType("Unresolved class"), c)
|
||||
}
|
||||
|
||||
private fun checkClassLiteral(c: ExpressionTypingContext, expression: KtClassLiteralExpression, result: DoubleColonLHS) {
|
||||
val type = result.type
|
||||
|
||||
private fun checkClassLiteral(
|
||||
c: ExpressionTypingContext,
|
||||
expression: KtClassLiteralExpression,
|
||||
type: KotlinType,
|
||||
result: DoubleColonLHS
|
||||
) {
|
||||
if (result is DoubleColonLHS.Expression) {
|
||||
if (!result.isObject) {
|
||||
if (!result.isObjectQualifier) {
|
||||
if (!type.isSubtypeOf(type.builtIns.anyType)) {
|
||||
c.trace.report(EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS.on(expression.receiverExpression!!, type))
|
||||
}
|
||||
@@ -181,7 +206,7 @@ class DoubleColonExpressionResolver(
|
||||
|
||||
private fun reportUnsupportedIfNeeded(expression: KtDoubleColonExpression, c: ExpressionTypingContext) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) {
|
||||
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences))
|
||||
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences to languageVersionSettings))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +337,7 @@ class DoubleColonExpressionResolver(
|
||||
val lhs = resultForExpr.lhs
|
||||
// If expression result is an object, we remember this and skip it here, because there are valid situations where
|
||||
// another type (representing another classifier) should win
|
||||
if (lhs != null && !lhs.isObject) {
|
||||
if (lhs != null && !lhs.isObjectQualifier) {
|
||||
return resultForExpr.commit()
|
||||
}
|
||||
}
|
||||
@@ -400,7 +425,7 @@ class DoubleColonExpressionResolver(
|
||||
if (classDescriptor.companionObjectDescriptor != null) return null
|
||||
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
return DoubleColonLHS.Expression(typeInfo, isObject = true)
|
||||
return DoubleColonLHS.Expression(typeInfo, isObjectQualifier = true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +433,7 @@ class DoubleColonExpressionResolver(
|
||||
if (expression.canBeConsideredProperType() && resultingDescriptor !is VariableDescriptor) return null
|
||||
}
|
||||
|
||||
return DoubleColonLHS.Expression(typeInfo, isObject = false)
|
||||
return DoubleColonLHS.Expression(typeInfo, isObjectQualifier = false)
|
||||
}
|
||||
|
||||
private fun resolveTypeOnLHS(
|
||||
@@ -509,6 +534,9 @@ class DoubleColonExpressionResolver(
|
||||
checkReferenceIsToAllowedMember(descriptor, context.trace, expression)
|
||||
|
||||
val type = createKCallableTypeForReference(descriptor, lhs, reflectionTypes, context.scope.ownerDescriptor) ?: return null
|
||||
if (type.isError) {
|
||||
context.trace.report(MISSING_DEPENDENCY_CLASS.on(expression, KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()))
|
||||
}
|
||||
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> bindFunctionReference(expression, type, context)
|
||||
@@ -551,10 +579,13 @@ class DoubleColonExpressionResolver(
|
||||
/* isCoroutine = */ false
|
||||
)
|
||||
|
||||
val parameterTypes = if (type.isError) emptyList() else type.arguments.dropLast(1)
|
||||
val returnType = if (type.isError) null else type.arguments.last().type
|
||||
|
||||
functionDescriptor.initialize(
|
||||
null, null, emptyList(),
|
||||
createValueParametersForInvokeInFunctionType(functionDescriptor, type.arguments.dropLast(1)),
|
||||
type.arguments.last().type,
|
||||
createValueParametersForInvokeInFunctionType(functionDescriptor, parameterTypes),
|
||||
returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
@@ -580,27 +611,30 @@ class DoubleColonExpressionResolver(
|
||||
if (expression.isEmptyLHS) null
|
||||
else resolveDoubleColonLHS(expression, context)
|
||||
|
||||
if (lhsResult is DoubleColonLHS.Expression) {
|
||||
reportUnsupportedIfNeeded(expression, context)
|
||||
}
|
||||
val resolutionResults = resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
|
||||
|
||||
val resolutionResults =
|
||||
resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
|
||||
|
||||
reportUnsupportedReferenceToSuspendFunction(resolutionResults, expression, context)
|
||||
reportUnsupportedCallableReferenceIfNeeded(expression, context, lhsResult, resolutionResults)
|
||||
|
||||
return lhsResult to resolutionResults
|
||||
}
|
||||
|
||||
private fun reportUnsupportedReferenceToSuspendFunction(
|
||||
resolutionResults: OverloadResolutionResults<CallableDescriptor>?,
|
||||
private fun reportUnsupportedCallableReferenceIfNeeded(
|
||||
expression: KtCallableReferenceExpression,
|
||||
context: ExpressionTypingContext
|
||||
context: ExpressionTypingContext,
|
||||
lhsResult: DoubleColonLHS?,
|
||||
resolutionResults: OverloadResolutionResults<CallableDescriptor>?
|
||||
) {
|
||||
if (resolutionResults?.isSingleResult == true &&
|
||||
resolutionResults.resultingDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true) {
|
||||
val descriptor =
|
||||
if (resolutionResults?.isSingleResult == true) resolutionResults.resultingDescriptor as? FunctionDescriptor else null
|
||||
if (descriptor?.isSuspend == true) {
|
||||
context.trace.report(UNSUPPORTED.on(expression.callableReference, "Callable references to suspend functions"))
|
||||
}
|
||||
|
||||
val expressionResult = lhsResult as? DoubleColonLHS.Expression ?: return
|
||||
// "<expr>::foo" was not supported without bound callable references, except the case of a nested class constructor in an object
|
||||
if (!expressionResult.isObjectQualifier || descriptor !is ConstructorDescriptor) {
|
||||
reportUnsupportedIfNeeded(expression, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryResolveRHSWithReceiver(
|
||||
@@ -610,6 +644,8 @@ class DoubleColonExpressionResolver(
|
||||
outerContext: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
checkReservedYield(reference, outerContext.trace)
|
||||
|
||||
// we should preserve information about `call` because callable references are analyzed two times,
|
||||
// otherwise there will be not completed calls in trace
|
||||
val call = outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||
@@ -673,6 +709,18 @@ class DoubleColonExpressionResolver(
|
||||
"resolve bound callable reference", expressionReceiver, reference, c, mode
|
||||
)
|
||||
if (result != null) return result
|
||||
|
||||
if (lhs.isObjectQualifier) {
|
||||
val classifier = lhsType.constructor.declarationDescriptor
|
||||
val calleeExpression = expression.receiverExpression?.getCalleeExpressionIfAny()
|
||||
if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor) {
|
||||
val qualifier = ClassQualifier(calleeExpression, classifier)
|
||||
val possibleStatic = tryResolveRHSWithReceiver(
|
||||
"resolve object callable reference in static scope", qualifier, reference, c, mode
|
||||
)
|
||||
if (possibleStatic != null) return possibleStatic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
@@ -27,6 +28,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedPrefixWord
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYieldBeforeLambda
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
||||
@@ -137,6 +140,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
}
|
||||
|
||||
override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? {
|
||||
checkReservedYieldBeforeLambda(expression, context.trace)
|
||||
if (!expression.functionLiteral.hasBody()) return null
|
||||
|
||||
val expectedType = context.expectedType
|
||||
@@ -160,6 +164,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression)
|
||||
}
|
||||
|
||||
private fun checkReservedYield(context: ExpressionTypingContext, expression: PsiElement) {
|
||||
checkReservedPrefixWord(context.trace, expression, "yield", "yield block/lambda. Use 'yield() { ... }' or 'yield(fun...)'")
|
||||
}
|
||||
|
||||
private fun createFunctionLiteralDescriptor(
|
||||
expression: KtLambdaExpression,
|
||||
context: ExpressionTypingContext
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
||||
@@ -138,6 +139,8 @@ public class LabelResolver {
|
||||
@NotNull ResolutionContext context
|
||||
) {
|
||||
KtSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
KtPsiUtilKt.checkReservedYield(labelElement, context.trace);
|
||||
|
||||
Name labelName = expression.getLabelNameAsName();
|
||||
if (labelElement == null || labelName == null) return null;
|
||||
|
||||
|
||||
@@ -839,7 +839,7 @@ class ExpressionCodegen(
|
||||
wrapIntoKClass: Boolean,
|
||||
data: BlockInfo
|
||||
) {
|
||||
if (receiverExpression !is IrClassReference /* && DescriptorUtils.isObject(receiverExpression.descriptor)*/) {
|
||||
if (receiverExpression !is IrClassReference /* && DescriptorUtils.isObjectQualifier(receiverExpression.descriptor)*/) {
|
||||
JavaClassProperty.generateImpl(mv, gen(receiverExpression, data))
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -35,9 +35,9 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
||||
val lhs = getOrFail(BindingContext.DOUBLE_COLON_LHS, ktArgument)
|
||||
val resultType = getInferredTypeWithImplicitCastsOrFail(ktClassLiteral)
|
||||
|
||||
return if (lhs is DoubleColonLHS.Expression && !lhs.isObject) {
|
||||
return if (lhs is DoubleColonLHS.Expression && !lhs.isObjectQualifier) {
|
||||
IrGetClassImpl(ktClassLiteral.startOffset, ktClassLiteral.endOffset, resultType,
|
||||
statementGenerator.generateExpression(ktArgument))
|
||||
statementGenerator.generateExpression(ktArgument))
|
||||
}
|
||||
else {
|
||||
val typeConstructorDeclaration = lhs.type.constructor.declarationDescriptor
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
@@ -451,6 +452,12 @@ class DescriptorSerializer private constructor(
|
||||
return lowerBound
|
||||
}
|
||||
|
||||
if (type.isSuspendFunctionType) {
|
||||
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type))
|
||||
functionType.flags = Flags.getTypeFlags(true)
|
||||
return functionType
|
||||
}
|
||||
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
when (descriptor) {
|
||||
is ClassDescriptor, is TypeAliasDescriptor -> {
|
||||
@@ -489,25 +496,12 @@ class DescriptorSerializer private constructor(
|
||||
}
|
||||
|
||||
private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: PossiblyInnerType) {
|
||||
val classifierDescriptor: ClassifierDescriptorWithTypeParameters
|
||||
val isSuspendType: Boolean
|
||||
|
||||
val originalClassifierDescriptor = type.classifierDescriptor
|
||||
if (originalClassifierDescriptor.getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction) {
|
||||
classifierDescriptor = originalClassifierDescriptor.builtIns.getFunction(originalClassifierDescriptor.declaredTypeParameters.size)
|
||||
isSuspendType = true
|
||||
}
|
||||
else {
|
||||
classifierDescriptor = originalClassifierDescriptor
|
||||
isSuspendType = false
|
||||
}
|
||||
|
||||
val classifierDescriptor = type.classifierDescriptor
|
||||
val classifierId = getClassifierId(classifierDescriptor)
|
||||
when (classifierDescriptor) {
|
||||
is ClassDescriptor -> builder.className = classifierId
|
||||
is TypeAliasDescriptor -> builder.typeAliasName = classifierId
|
||||
}
|
||||
builder.flags = Flags.getTypeFlags(isSuspendType)
|
||||
|
||||
for (projection in type.arguments) {
|
||||
builder.addArgument(typeArgument(projection))
|
||||
|
||||
@@ -53,7 +53,6 @@ public final class BooleanArray {
|
||||
|
||||
public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
|
||||
/*primary*/ private constructor Byte()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -68,7 +67,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Byte
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -81,7 +79,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -113,7 +110,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
@@ -613,7 +609,6 @@ public abstract class Number {
|
||||
|
||||
public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
|
||||
/*primary*/ private constructor Short()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -628,7 +623,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Short
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -641,7 +635,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -673,7 +666,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
|
||||
@@ -55,7 +55,6 @@ public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializ
|
||||
|
||||
public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io.Serializable {
|
||||
/*primary*/ private constructor Byte()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -70,7 +69,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Byte
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -83,7 +81,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -115,7 +112,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
@@ -629,7 +625,6 @@ public abstract class Number : kotlin.Any, java.io.Serializable {
|
||||
|
||||
public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.io.Serializable {
|
||||
/*primary*/ private constructor Short()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -644,7 +639,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Short
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -657,7 +651,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -689,7 +682,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
|
||||
@@ -55,7 +55,6 @@ public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializ
|
||||
|
||||
public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io.Serializable {
|
||||
/*primary*/ private constructor Byte()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -70,7 +69,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Byte
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -83,7 +81,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -115,7 +112,6 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte>, java.io
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
@@ -631,7 +627,6 @@ public abstract class Number : kotlin.Any, java.io.Serializable {
|
||||
|
||||
public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.io.Serializable {
|
||||
/*primary*/ private constructor Short()
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int
|
||||
public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int
|
||||
@@ -646,7 +641,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
public final operator fun inc(): kotlin.Short
|
||||
@kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short
|
||||
public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -659,7 +653,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long
|
||||
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "Use rem(other) instead", replaceWith = kotlin.ReplaceWith(expression = "rem(other)", imports = {})) public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int
|
||||
public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double
|
||||
public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float
|
||||
@@ -691,7 +684,6 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short>, java.
|
||||
public open override /*1*/ fun toShort(): kotlin.Short
|
||||
public final operator fun unaryMinus(): kotlin.Int
|
||||
public final operator fun unaryPlus(): kotlin.Int
|
||||
@kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short
|
||||
|
||||
public companion object Companion {
|
||||
/*primary*/ private constructor Companion()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user