mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-06 00:21:32 +00:00
Compare commits
309 Commits
rr/pdn_nul
...
push/igor/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6129c5d3de | ||
|
|
790a1e3b2f | ||
|
|
ad42941679 | ||
|
|
c3344549a8 | ||
|
|
cb92413cd8 | ||
|
|
f16b1c2d69 | ||
|
|
395b2119a1 | ||
|
|
11f951e6d1 | ||
|
|
8d27f102e7 | ||
|
|
469b3b9d02 | ||
|
|
22ccb7a943 | ||
|
|
e924ee3150 | ||
|
|
ee0b64cb29 | ||
|
|
e897c60ef1 | ||
|
|
79565da904 | ||
|
|
82a70a205b | ||
|
|
a22ef02e47 | ||
|
|
4abbac1ff1 | ||
|
|
02d8c7527e | ||
|
|
6f0bf766f2 | ||
|
|
c8386ad1c7 | ||
|
|
13b5f87f3a | ||
|
|
d7368c341e | ||
|
|
adbeda12a6 | ||
|
|
79ff02fd97 | ||
|
|
0925e1b497 | ||
|
|
29ac9b33ca | ||
|
|
5004735366 | ||
|
|
d7b10f31b4 | ||
|
|
e691de6e4c | ||
|
|
126f6eff28 | ||
|
|
8578f0beea | ||
|
|
60195114c1 | ||
|
|
4c58954967 | ||
|
|
13cb3c138a | ||
|
|
b6cb393796 | ||
|
|
cf3bd016be | ||
|
|
dc8dbad0bc | ||
|
|
7567597be6 | ||
|
|
93f9d9dacd | ||
|
|
3eaa452f9e | ||
|
|
6ab632f6ad | ||
|
|
c46a393a19 | ||
|
|
e56deb4525 | ||
|
|
b2f3485d7c | ||
|
|
dabc983f6a | ||
|
|
efce3fc2e0 | ||
|
|
46d1b63f70 | ||
|
|
38cecf8b12 | ||
|
|
29dbaa4ae1 | ||
|
|
d8b7b7b2dc | ||
|
|
4e06814bc5 | ||
|
|
015c2d1875 | ||
|
|
28344c8530 | ||
|
|
bc75a21852 | ||
|
|
4e66fd29e0 | ||
|
|
6cd3d84e74 | ||
|
|
f81f28569f | ||
|
|
d46f7738c6 | ||
|
|
d8569b6a03 | ||
|
|
af865544ff | ||
|
|
c526145a48 | ||
|
|
80140207b5 | ||
|
|
468fe4196d | ||
|
|
0eba74a9d2 | ||
|
|
f34a079699 | ||
|
|
2538caa84f | ||
|
|
ebde1e5491 | ||
|
|
fc0ae851a2 | ||
|
|
d90e3618f9 | ||
|
|
0f84525bdc | ||
|
|
9ccdffe8ad | ||
|
|
59ad7e0e04 | ||
|
|
c597ee0e34 | ||
|
|
c559adc0fb | ||
|
|
5b40f291bd | ||
|
|
d4e1ecd9d3 | ||
|
|
748a2d2e7c | ||
|
|
e9a2997f7e | ||
|
|
cea6081d36 | ||
|
|
ec4cbfef59 | ||
|
|
dcd61c292d | ||
|
|
d5e2ac0efc | ||
|
|
3c3e51c6de | ||
|
|
5291648d39 | ||
|
|
bd71fbe982 | ||
|
|
37050e0616 | ||
|
|
32b380e187 | ||
|
|
872b6b7e81 | ||
|
|
a7961a4a45 | ||
|
|
97bfc49ed6 | ||
|
|
1188d311b3 | ||
|
|
77f0bd3834 | ||
|
|
bb718f2e0b | ||
|
|
fa9f0d588d | ||
|
|
2266a348c3 | ||
|
|
42b2605c2a | ||
|
|
1a262c9c31 | ||
|
|
920d57563b | ||
|
|
cd51264940 | ||
|
|
979f5e8443 | ||
|
|
edf9f5e647 | ||
|
|
956bf22191 | ||
|
|
1654824467 | ||
|
|
73bb6d5d34 | ||
|
|
6bbfe0d503 | ||
|
|
2656c94535 | ||
|
|
ba5bd0b069 | ||
|
|
ad2fabb7cb | ||
|
|
afa8e16c25 | ||
|
|
5338705402 | ||
|
|
cbe0de6111 | ||
|
|
ca9cbf7eb7 | ||
|
|
0a5991d6e7 | ||
|
|
fb27459b2e | ||
|
|
e177cecd50 | ||
|
|
b37cdae966 | ||
|
|
84d06f35e9 | ||
|
|
7d8360f38b | ||
|
|
adc1ca76f4 | ||
|
|
bfc3f35d94 | ||
|
|
8803a69c9d | ||
|
|
922fcc4049 | ||
|
|
c7c78e0e1a | ||
|
|
6e093b0beb | ||
|
|
a525f3f357 | ||
|
|
66ddd15798 | ||
|
|
a78fcd6b64 | ||
|
|
fbbbc1c092 | ||
|
|
a783ee9ae7 | ||
|
|
0d39442a5e | ||
|
|
1c7a27ce42 | ||
|
|
e8b025f267 | ||
|
|
572f08151a | ||
|
|
02aebd6565 | ||
|
|
601465fa81 | ||
|
|
493fa1c1e3 | ||
|
|
023c775188 | ||
|
|
7dda04a1c9 | ||
|
|
44256db824 | ||
|
|
017c8d8211 | ||
|
|
0923d13d55 | ||
|
|
6c49a18770 | ||
|
|
0ac96b4973 | ||
|
|
b584fed93d | ||
|
|
adfeab1bd0 | ||
|
|
d17f984edf | ||
|
|
7c73840e4a | ||
|
|
ff9643b70e | ||
|
|
153df1dd1a | ||
|
|
db10732d6c | ||
|
|
4ae51e1d02 | ||
|
|
02d4c866ca | ||
|
|
a7e81d5154 | ||
|
|
bbd21da835 | ||
|
|
0f3f56f676 | ||
|
|
8fd2ddad12 | ||
|
|
c0949fbc18 | ||
|
|
9fdd3dc53f | ||
|
|
71def0666e | ||
|
|
afb85026c4 | ||
|
|
b264a2e5dd | ||
|
|
17bbedbc50 | ||
|
|
ca40cbede5 | ||
|
|
d43d0071a4 | ||
|
|
08a1134fff | ||
|
|
90e06bf403 | ||
|
|
a66f3d26fd | ||
|
|
ba48f80e53 | ||
|
|
b42d6a3e85 | ||
|
|
4c3fb8697b | ||
|
|
2c068b8c5a | ||
|
|
da4113af88 | ||
|
|
ed07e1c778 | ||
|
|
8e890eba3e | ||
|
|
7422571c72 | ||
|
|
947e97511b | ||
|
|
4ce3f87361 | ||
|
|
329991217a | ||
|
|
7b5a3f8d1b | ||
|
|
8e6f84d5cd | ||
|
|
a353719a6b | ||
|
|
199ec60742 | ||
|
|
5206b45ce3 | ||
|
|
fd537e7d5a | ||
|
|
17fc1da719 | ||
|
|
8dad8fa813 | ||
|
|
fa1d09c778 | ||
|
|
972211f8e6 | ||
|
|
1fa74ef939 | ||
|
|
89bd52c7d2 | ||
|
|
de73622af9 | ||
|
|
c2e2068682 | ||
|
|
b9c549803d | ||
|
|
c168a561df | ||
|
|
4f73ebbcbd | ||
|
|
ca214bef30 | ||
|
|
04d9d243de | ||
|
|
4a09fba3a4 | ||
|
|
e4d2351e03 | ||
|
|
448376f073 | ||
|
|
9c6943b8c4 | ||
|
|
b11201be81 | ||
|
|
504449f03e | ||
|
|
0627dbcb78 | ||
|
|
5283f7b7c6 | ||
|
|
3636118743 | ||
|
|
847c58d574 | ||
|
|
5f7803f2db | ||
|
|
e20b354dbd | ||
|
|
0a6d010d1c | ||
|
|
67128c022a | ||
|
|
b2550f69bc | ||
|
|
26043f3968 | ||
|
|
92a73d7636 | ||
|
|
87130edfa2 | ||
|
|
f723389565 | ||
|
|
ebf837c135 | ||
|
|
1a40164ef0 | ||
|
|
8bfaa39a5c | ||
|
|
10d9988824 | ||
|
|
83895c49c5 | ||
|
|
63fc3645ab | ||
|
|
2fbb700ec6 | ||
|
|
b307358f69 | ||
|
|
f5d8535dc5 | ||
|
|
354a06b94a | ||
|
|
3c2e266c31 | ||
|
|
e0b1d0db53 | ||
|
|
807f031dcc | ||
|
|
229dfd3f5f | ||
|
|
391c4db87c | ||
|
|
2397650c24 | ||
|
|
8f1d07084b | ||
|
|
e4992176c1 | ||
|
|
767af0dae0 | ||
|
|
0e2d765a2d | ||
|
|
b3d7ed569d | ||
|
|
ca4410aa53 | ||
|
|
edaf925b19 | ||
|
|
033a9f1589 | ||
|
|
e45b13d582 | ||
|
|
5ee87e126d | ||
|
|
d72a399982 | ||
|
|
90d15f156b | ||
|
|
bab5a4a6c9 | ||
|
|
9148094bbd | ||
|
|
d9483ccb08 | ||
|
|
d18ade088d | ||
|
|
9142b03df5 | ||
|
|
ca5ebdc13c | ||
|
|
cdbd0eb932 | ||
|
|
824d6ab5cc | ||
|
|
1e2547d0d0 | ||
|
|
588952bc9a | ||
|
|
a1bd728aef | ||
|
|
55f7bb2756 | ||
|
|
d36c56497e | ||
|
|
262c9e88d1 | ||
|
|
ee68962c02 | ||
|
|
4fe846fb81 | ||
|
|
1347ee8c7d | ||
|
|
d2ad421e0b | ||
|
|
8f484fcf88 | ||
|
|
cba224b7b8 | ||
|
|
baaa615e09 | ||
|
|
70e4472c99 | ||
|
|
d2a7434cff | ||
|
|
f34726ff91 | ||
|
|
2ae546576c | ||
|
|
b1d17cfd7b | ||
|
|
e316cd04b6 | ||
|
|
699d53e7f9 | ||
|
|
0c419eac1a | ||
|
|
0f216f4d37 | ||
|
|
a544d6948b | ||
|
|
f84adcb378 | ||
|
|
ca0b8be53b | ||
|
|
0ed9b75428 | ||
|
|
b442e598d3 | ||
|
|
f1ac5796ed | ||
|
|
2d0d83a54b | ||
|
|
6af042c1dd | ||
|
|
95492f7370 | ||
|
|
7250aed3b5 | ||
|
|
c9c82ab3a6 | ||
|
|
c8094f7439 | ||
|
|
f590c3201a | ||
|
|
70fe984738 | ||
|
|
cc5ba4c0af | ||
|
|
0cccb76652 | ||
|
|
235359e028 | ||
|
|
390eda1b9d | ||
|
|
7854e9c3d7 | ||
|
|
1187e786f4 | ||
|
|
5f3f2e762a | ||
|
|
1fe1c197ee | ||
|
|
29f6ec4f40 | ||
|
|
38fb5e16ef | ||
|
|
805778e782 | ||
|
|
7cbd6908f9 | ||
|
|
228100ef09 | ||
|
|
a919aab3ab | ||
|
|
ee07ff7982 | ||
|
|
caa13b33b1 | ||
|
|
b93dff003f | ||
|
|
38d6c8ded0 | ||
|
|
d0f207071c | ||
|
|
352c624601 |
1
.idea/dictionaries/igor.xml
generated
1
.idea/dictionaries/igor.xml
generated
@@ -1,6 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="igor">
|
||||
<words>
|
||||
<w>addr</w>
|
||||
<w>descr</w>
|
||||
<w>exprs</w>
|
||||
</words>
|
||||
|
||||
2
.idea/runConfigurations/Test__Commonizer.xml
generated
2
.idea/runConfigurations/Test__Commonizer.xml
generated
@@ -4,7 +4,7 @@
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="--tests "org.jetbrains.kotlin.gradle.CommonizerHierarchicalIT" --tests "org.jetbrains.kotlin.gradle.CommonizerIT" --tests "org.jetbrains.kotlin.commonizer.**"" />
|
||||
<option name="scriptParameters" value="--tests "org.jetbrains.kotlin.gradle.CommonizerHierarchicalIT" --tests "org.jetbrains.kotlin.gradle.CommonizerIT" --tests "org.jetbrains.kotlin.commonizer.**" --tests "org.jetbrains.kotlin.gradle.native.CocoaPodsIT.testCinteropCommonization*"" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
|
||||
@@ -48,12 +48,14 @@ open class LookupStorage(
|
||||
|
||||
@Volatile
|
||||
private var size: Int = 0
|
||||
private var oldSize: Int = 0
|
||||
|
||||
init {
|
||||
try {
|
||||
if (countersFile.exists()) {
|
||||
val lines = countersFile.readLines()
|
||||
size = lines[0].toInt()
|
||||
oldSize = size
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
throw IOException("Could not read $countersFile", e)
|
||||
@@ -120,13 +122,15 @@ open class LookupStorage(
|
||||
@Synchronized
|
||||
override fun flush(memoryCachesOnly: Boolean) {
|
||||
try {
|
||||
if (size > 0) {
|
||||
if (!countersFile.exists()) {
|
||||
countersFile.parentFile.mkdirs()
|
||||
countersFile.createNewFile()
|
||||
}
|
||||
if (size != oldSize) {
|
||||
if (size > 0) {
|
||||
if (!countersFile.exists()) {
|
||||
countersFile.parentFile.mkdirs()
|
||||
countersFile.createNewFile()
|
||||
}
|
||||
|
||||
countersFile.writeText("$size\n0")
|
||||
countersFile.writeText("$size\n0")
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
super.flush(memoryCachesOnly)
|
||||
|
||||
@@ -33,15 +33,19 @@ class CachingLazyStorage<K, V>(
|
||||
private val valueExternalizer: DataExternalizer<V>
|
||||
) : LazyStorage<K, V> {
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
private var isStorageFileExist = true
|
||||
|
||||
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
|
||||
if (storage != null) return storage
|
||||
|
||||
if (!isStorageFileExist) return null
|
||||
|
||||
if (storageFile.exists()) {
|
||||
storage = createMap()
|
||||
return storage
|
||||
}
|
||||
|
||||
isStorageFileExist = false
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import com.intellij.util.io.IOUtil
|
||||
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import java.io.DataInput
|
||||
import java.io.DataInputStream
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ object ConstantsMapExternalizer : DataExternalizer<Map<String, Any>> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun read(input: DataInput): Map<String, Any>? {
|
||||
override fun read(input: DataInput): Map<String, Any> {
|
||||
val size = input.readInt()
|
||||
val map = HashMap<String, Any>(size)
|
||||
|
||||
@@ -197,15 +197,33 @@ object IntExternalizer : DataExternalizer<Int> {
|
||||
}
|
||||
}
|
||||
|
||||
object PathStringDescriptor : EnumeratorStringDescriptor() {
|
||||
override fun getHashCode(value: String) = FileUtil.pathHashCode(value)
|
||||
|
||||
override fun isEqual(val1: String, val2: String?) = FileUtil.pathsEqual(val1, val2)
|
||||
// Should be consistent with org.jetbrains.jps.incremental.storage.PathStringDescriptor for correct work of portable caches
|
||||
object PathStringDescriptor : EnumeratorStringDescriptor() {
|
||||
private const val PORTABLE_CACHES_PROPERTY = "org.jetbrains.jps.portable.caches"
|
||||
private val PORTABLE_CACHES = java.lang.Boolean.getBoolean(PORTABLE_CACHES_PROPERTY)
|
||||
|
||||
override fun getHashCode(path: String): Int {
|
||||
if (!PORTABLE_CACHES) return FileUtil.pathHashCode(path)
|
||||
// On case insensitive OS hash calculated from value converted to lower case
|
||||
return if (StringUtil.isEmpty(path)) 0 else FileUtil.toCanonicalPath(path).hashCode()
|
||||
}
|
||||
|
||||
override fun isEqual(val1: String, val2: String?): Boolean {
|
||||
if (!PORTABLE_CACHES) return FileUtil.pathsEqual(val1, val2)
|
||||
// On case insensitive OS hash calculated from path converted to lower case
|
||||
if (val1 == val2) return true
|
||||
if (val2 == null) return false
|
||||
|
||||
val path1 = FileUtil.toCanonicalPath(val1)
|
||||
val path2 = FileUtil.toCanonicalPath(val2)
|
||||
return path1 == path2
|
||||
}
|
||||
}
|
||||
|
||||
open class CollectionExternalizer<T>(
|
||||
private val elementExternalizer: DataExternalizer<T>,
|
||||
private val newCollection: () -> MutableCollection<T>
|
||||
private val elementExternalizer: DataExternalizer<T>,
|
||||
private val newCollection: () -> MutableCollection<T>
|
||||
) : DataExternalizer<Collection<T>> {
|
||||
override fun read(input: DataInput): Collection<T> {
|
||||
val result = newCollection()
|
||||
|
||||
@@ -29,7 +29,7 @@ buildscript {
|
||||
dependencies {
|
||||
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
|
||||
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.32")
|
||||
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
|
||||
classpath(kotlin("serialization", bootstrapKotlinVersion))
|
||||
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
|
||||
|
||||
@@ -22,7 +22,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.32")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
|
||||
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
|
||||
}
|
||||
@@ -143,7 +143,7 @@ java {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib", embeddedKotlinVersion))
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.32")
|
||||
implementation("com.gradle.publish:plugin-publish-plugin:0.14.0")
|
||||
|
||||
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
|
||||
@@ -22,5 +22,14 @@ val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignore
|
||||
val KotlinBuildProperties.disableWerror: Boolean
|
||||
get() = getBoolean("kotlin.build.disable.werror") || useFir || isInJpsBuildIdeaSync || getBoolean("test.progressive.mode")
|
||||
|
||||
val KotlinBuildProperties.pathToKotlinModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.kotlin") as? String
|
||||
|
||||
val KotlinBuildProperties.pathToIntellijModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.intellij") as? String
|
||||
|
||||
val KotlinBuildProperties.pathToYoutrackModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.youtrack") as? String
|
||||
|
||||
val KotlinBuildProperties.isObsoleteJdkOverrideEnabled: Boolean
|
||||
get() = getBoolean("kotlin.build.isObsoleteJdkOverrideEnabled", false)
|
||||
|
||||
@@ -22,7 +22,8 @@ enum class JdkMajorVersion(
|
||||
JDK_10(10, mandatory = false, overrideMajorVersion = 11),
|
||||
JDK_11(11, mandatory = false),
|
||||
JDK_15(15, mandatory = false),
|
||||
JDK_16(16, mandatory = false);
|
||||
JDK_16(16, mandatory = false),
|
||||
JDK_17(17, mandatory = false);
|
||||
|
||||
fun isMandatory(): Boolean = mandatory
|
||||
|
||||
@@ -180,4 +181,4 @@ fun Project.getJdkVersionWithOverride(jdkVersion: JdkMajorVersion): JdkMajorVers
|
||||
} else {
|
||||
jdkVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ configurations {
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.languageVersion = "1.3"
|
||||
kotlinOptions.apiVersion = "1.3"
|
||||
kotlinOptions.languageVersion = "1.4"
|
||||
kotlinOptions.apiVersion = "1.4"
|
||||
kotlinOptions.freeCompilerArgs += listOf(
|
||||
"-Xskip-prerelease-check",
|
||||
"-Xskip-runtime-version-check",
|
||||
|
||||
@@ -171,16 +171,18 @@ fun Project.configureDefaultPublishing() {
|
||||
.all { configureRepository() }
|
||||
}
|
||||
|
||||
private fun Project.getSensitiveProperty(name: String): String? {
|
||||
return project.findProperty(name) as? String ?: System.getenv(name)
|
||||
}
|
||||
|
||||
private fun Project.configureSigning() {
|
||||
configure<SigningExtension> {
|
||||
sign(extensions.getByType<PublishingExtension>().publications) // all publications
|
||||
|
||||
val signKeyId = project.findProperty("signKeyId") as? String
|
||||
val signKeyId = project.getSensitiveProperty("signKeyId")
|
||||
if (!signKeyId.isNullOrBlank()) {
|
||||
val signKeyPrivate = project.findProperty("signKeyPrivate") as? String
|
||||
?: error("Parameter `signKeyPrivate` not found")
|
||||
val signKeyPassphrase = project.findProperty("signKeyPassphrase") as? String
|
||||
?: error("Parameter `signKeyPassphrase` not found")
|
||||
val signKeyPrivate = project.getSensitiveProperty("signKeyPrivate") ?: error("Parameter `signKeyPrivate` not found")
|
||||
val signKeyPassphrase = project.getSensitiveProperty("signKeyPassphrase") ?: error("Parameter `signKeyPassphrase` not found")
|
||||
useInMemoryPgpKeys(signKeyId, signKeyPrivate, signKeyPassphrase)
|
||||
} else {
|
||||
useGpgCmd()
|
||||
|
||||
@@ -15,7 +15,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -23,11 +26,11 @@ import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.model.ResultingArtifact
|
||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.impl.BackendKindExtractorImpl
|
||||
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.CodegenHelpersSourceFilesProvider
|
||||
@@ -382,6 +385,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
"test${testDataFile.nameWithoutExtension.replaceFirstChar(Char::uppercaseChar)}",
|
||||
emptySet()
|
||||
)
|
||||
startingArtifactFactory = { ResultingArtifact.Source() }
|
||||
}.build(testDataFile.path)
|
||||
}
|
||||
|
||||
@@ -406,7 +410,6 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
|
||||
assertions = JUnit5Assertions
|
||||
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
|
||||
useAdditionalService<BackendKindExtractor>(::BackendKindExtractorImpl)
|
||||
useSourcePreprocessor(*AbstractKotlinCompilerTest.defaultPreprocessors.toTypedArray())
|
||||
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
|
||||
paramTypes.add(type)
|
||||
paramSlots += type.size
|
||||
template.append("\u0001")
|
||||
if (paramSlots >= 200) {
|
||||
if (paramSlots >= 199) {
|
||||
// Concatenate current arguments into string
|
||||
// because of `StringConcatFactory` limitation add use it as new argument for further processing:
|
||||
// "The number of parameter slots in {@code concatType} is less than or equal to 200"
|
||||
@@ -166,4 +166,4 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
|
||||
StringConcatGenerator(state.runtimeStringConcat, mv)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1288,8 +1288,8 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
fun nextLabel(node: AbstractInsnNode?): LabelNode? {
|
||||
var current = node
|
||||
while (current != null) {
|
||||
if (current is LabelNode) return current
|
||||
current = current.next
|
||||
if (current is LabelNode) return current as LabelNode
|
||||
current = current!!.next
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -1302,6 +1302,8 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
oldLvt += record
|
||||
}
|
||||
method.localVariables.clear()
|
||||
|
||||
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
|
||||
// Skip `this` for suspend lambda
|
||||
val start = if (isForNamedFunction) 0 else 1
|
||||
for (variableIndex in start until method.maxLocals) {
|
||||
@@ -1341,33 +1343,41 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
val endLabel = nextLabel(insn.next)?.let { min(lvtRecord.end, it) } ?: lvtRecord.end
|
||||
// startLabel can be null in case of parameters
|
||||
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
|
||||
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
||||
method.localVariables.add(node)
|
||||
|
||||
// Attempt to extend existing local variable node corresponding to the record in
|
||||
// the original local variable table, if there is no back-edge
|
||||
val recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
|
||||
var recordExtended = false
|
||||
if (recordToExtend != null) {
|
||||
var hasBackEdgeOrStore = false
|
||||
var current: AbstractInsnNode? = recordToExtend.end
|
||||
while (current != null && current != endLabel) {
|
||||
if (current is JumpInsnNode) {
|
||||
if (method.instructions.indexOf((current as JumpInsnNode).label) < method.instructions.indexOf(current)) {
|
||||
hasBackEdgeOrStore = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (current!!.isStoreOperation() && (current as VarInsnNode).`var` == recordToExtend.index) {
|
||||
hasBackEdgeOrStore = true
|
||||
break
|
||||
}
|
||||
current = current!!.next
|
||||
}
|
||||
if (!hasBackEdgeOrStore) {
|
||||
recordToExtend.end = endLabel
|
||||
recordExtended = true
|
||||
}
|
||||
}
|
||||
if (!recordExtended) {
|
||||
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
||||
method.localVariables.add(node)
|
||||
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge consequent LVT records, otherwise, atomicfu goes crazy (KT-47749)
|
||||
val toRemove = arrayListOf<LocalVariableNode>()
|
||||
val sortedLVT = method.localVariables.sortedBy { method.instructions.indexOf(it.start) }
|
||||
for (i in sortedLVT.indices) {
|
||||
var endIndex = method.instructions.indexOf(sortedLVT[i].end)
|
||||
for (j in (i + 1) until sortedLVT.size) {
|
||||
val startIndex = method.instructions.indexOf(sortedLVT[j].start)
|
||||
if (endIndex < startIndex) break
|
||||
if (endIndex != startIndex ||
|
||||
sortedLVT[i].index != sortedLVT[j].index ||
|
||||
sortedLVT[i].name != sortedLVT[j].name ||
|
||||
sortedLVT[i].desc != sortedLVT[j].desc
|
||||
) continue
|
||||
sortedLVT[i].end = sortedLVT[j].end
|
||||
endIndex = method.instructions.indexOf(sortedLVT[j].end)
|
||||
toRemove += sortedLVT[j]
|
||||
}
|
||||
}
|
||||
|
||||
method.localVariables.removeAll(toRemove)
|
||||
|
||||
for (variable in oldLvt) {
|
||||
// $continuation and $result are dead, but they are used by debugger, as well as fake inliner variables
|
||||
// For example, $continuation is used to create async stack trace
|
||||
|
||||
@@ -320,7 +320,8 @@ class AnonymousObjectTransformer(
|
||||
inliningContext.callSiteInfo.isInlineOrInsideInline,
|
||||
inliningContext.callSiteInfo.file,
|
||||
inliningContext.callSiteInfo.lineNumber
|
||||
), null
|
||||
),
|
||||
null
|
||||
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
|
||||
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
|
||||
deferringVisitor.visitMaxs(-1, -1)
|
||||
|
||||
@@ -13,12 +13,8 @@ import org.jetbrains.kotlin.codegen.inline.coroutines.markNoinlineLambdaIfSuspen
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.surroundInvokesWithSuspendMarkersIfNeeded
|
||||
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer
|
||||
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
@@ -747,6 +743,8 @@ class MethodInliner(
|
||||
ApiVersionCallsPreprocessingMethodTransformer(targetApiVersion).transform("fake", node)
|
||||
}
|
||||
|
||||
removeFakeVariablesInitializationIfPresent(node)
|
||||
|
||||
val frames = FastStackAnalyzer("<fake>", node, FixStackInterpreter()).analyze()
|
||||
|
||||
val localReturnsNormalizer = LocalReturnsNormalizer()
|
||||
@@ -769,6 +767,73 @@ class MethodInliner(
|
||||
localReturnsNormalizer.transform(node)
|
||||
}
|
||||
|
||||
private fun removeFakeVariablesInitializationIfPresent(node: MethodNode) {
|
||||
// Before 1.6, we generated fake variable initialization instructions
|
||||
// ICONST_0
|
||||
// ISTORE x
|
||||
// for all inline functions. Original intent was to mark inline function body for the debugger with corresponding LVT entry.
|
||||
// However, for @InlineOnly functions corresponding LVT entries were not copied (assuming that nobody is actually debugging
|
||||
// @InlineOnly functions).
|
||||
// Since 1.6, we no longer generate fake variables for @InlineOnly functions
|
||||
// Here we erase fake variable initialization for @InlineOnly functions inlined into existing bytecode (e.g., inline function
|
||||
// inside third-party library).
|
||||
// We consider a sequence of instructions 'ICONST_0; ISTORE x' a fake variable initialization if the corresponding variable 'x'
|
||||
// is not used in the bytecode (see below).
|
||||
|
||||
val insnArray = node.instructions.toArray()
|
||||
|
||||
// Very conservative variable usage check.
|
||||
// Here we look at integer variables only (this includes integral primitive types: byte, char, short, boolean).
|
||||
// Variable is considered "used" if:
|
||||
// - it's loaded with ILOAD instruction
|
||||
// - it's incremented with IINC instruction
|
||||
// - there's a local variable table entry for this variable
|
||||
val usedIntegerVar = BooleanArray(node.maxLocals)
|
||||
for (insn in insnArray) {
|
||||
if (insn.type == AbstractInsnNode.VAR_INSN && insn.opcode == Opcodes.ILOAD) {
|
||||
usedIntegerVar[(insn as VarInsnNode).`var`] = true
|
||||
} else if (insn.type == AbstractInsnNode.IINC_INSN) {
|
||||
usedIntegerVar[(insn as IincInsnNode).`var`] = true
|
||||
}
|
||||
}
|
||||
for (localVariable in node.localVariables) {
|
||||
val d0 = localVariable.desc[0]
|
||||
// byte || char || short || int || boolean
|
||||
if (d0 == 'B' || d0 == 'C' || d0 == 'S' || d0 == 'I' || d0 == 'Z') {
|
||||
usedIntegerVar[localVariable.index] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Looking for sequences of instructions:
|
||||
// p0: ICONST_0
|
||||
// p1: ISTORE x
|
||||
// p2: <label>
|
||||
// If variable 'x' is not "used" (see above), remove p0 and p1 instructions.
|
||||
var changes = false
|
||||
for (p0 in insnArray) {
|
||||
if (p0.opcode != Opcodes.ICONST_0) continue
|
||||
|
||||
val p1 = p0.next ?: break
|
||||
if (p1.opcode != Opcodes.ISTORE) continue
|
||||
|
||||
val p2 = p1.next ?: break
|
||||
if (p2.type != AbstractInsnNode.LABEL) continue
|
||||
|
||||
val varIndex = (p1 as VarInsnNode).`var`
|
||||
if (!usedIntegerVar[varIndex]) {
|
||||
changes = true
|
||||
node.instructions.remove(p0)
|
||||
node.instructions.remove(p1)
|
||||
}
|
||||
}
|
||||
|
||||
if (changes) {
|
||||
// If we removed some instructions, some TCBs could (in theory) become empty.
|
||||
// Remove empty TCBs if there are any.
|
||||
node.removeEmptyCatchBlocks()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAnonymousClassThatMustBeRegenerated(type: Type?): Boolean {
|
||||
if (type == null || type.sort != Type.OBJECT) return false
|
||||
return inliningContext.isRegeneratedAnonymousObject(type.internalName)
|
||||
|
||||
@@ -23,13 +23,11 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.expressions.LabelResolver
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
package org.jetbrains.kotlin.codegen.optimization
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicVerifier
|
||||
|
||||
class MethodVerifier(private val checkPoint: String) : MethodTransformer() {
|
||||
class MethodVerifier(private val checkPoint: String, private val generationState: GenerationState) : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
if (!generationState.shouldValidateBytecode) return
|
||||
try {
|
||||
analyze(internalClassName, methodNode, BasicVerifier())
|
||||
} catch (e: Throwable) {
|
||||
|
||||
@@ -41,7 +41,7 @@ class OptimizationMethodVisitor(
|
||||
|
||||
val normalizationMethodTransformer = CompositeMethodTransformer(
|
||||
FixStackWithLabelNormalizationMethodTransformer(),
|
||||
MethodVerifier("AFTER mandatory stack transformations")
|
||||
MethodVerifier("AFTER mandatory stack transformations", generationState)
|
||||
)
|
||||
|
||||
val optimizationTransformer = CompositeMethodTransformer(
|
||||
@@ -55,7 +55,7 @@ class OptimizationMethodVisitor(
|
||||
DeadCodeEliminationMethodTransformer(),
|
||||
RedundantGotoMethodTransformer(),
|
||||
RedundantNopsCleanupMethodTransformer(),
|
||||
MethodVerifier("AFTER optimizations")
|
||||
MethodVerifier("AFTER optimizations", generationState)
|
||||
)
|
||||
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
|
||||
@@ -299,6 +299,8 @@ class GenerationState private constructor(
|
||||
!configuration.getBoolean(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS)
|
||||
val functionsWithInlineClassReturnTypesMangled: Boolean =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
|
||||
val shouldValidateIr = configuration.getBoolean(JVMConfigurationKeys.VALIDATE_IR)
|
||||
val shouldValidateBytecode = configuration.getBoolean(JVMConfigurationKeys.VALIDATE_BYTECODE)
|
||||
|
||||
val rootContext: CodegenContext<*> = RootContext(this)
|
||||
|
||||
@@ -405,8 +407,8 @@ class GenerationState private constructor(
|
||||
this[KOTLIN_1_2] = oldMetadataVersion
|
||||
this[KOTLIN_1_3] = oldMetadataVersion
|
||||
this[KOTLIN_1_4] = JvmMetadataVersion(1, 4, 3)
|
||||
this[KOTLIN_1_5] = JvmMetadataVersion.INSTANCE
|
||||
this[KOTLIN_1_6] = JvmMetadataVersion(1, 6, 0)
|
||||
this[KOTLIN_1_5] = JvmMetadataVersion(1, 5, 1)
|
||||
this[KOTLIN_1_6] = JvmMetadataVersion.INSTANCE
|
||||
this[KOTLIN_1_7] = JvmMetadataVersion(1, 7, 0)
|
||||
|
||||
check(size == LanguageVersion.values().size) {
|
||||
|
||||
@@ -57,8 +57,8 @@ sourceSets {
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||
kotlinOptions {
|
||||
languageVersion = "1.3"
|
||||
apiVersion = "1.3"
|
||||
languageVersion = "1.4"
|
||||
apiVersion = "1.4"
|
||||
freeCompilerArgs = freeCompilerArgs - "-progressive" + listOf(
|
||||
"-Xskip-prerelease-check", "-Xsuppress-version-warnings", "-Xuse-mixed-named-arguments", "-Xnew-inference"
|
||||
)
|
||||
|
||||
@@ -381,6 +381,12 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
)
|
||||
var unrestrictedBuilderInference: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xself-upper-bound-inference",
|
||||
description = "Support inferring type arguments based on only self upper bounds of the corresponding type parameters"
|
||||
)
|
||||
var selfUpperBoundInference: Boolean by FreezableVar(false)
|
||||
|
||||
open fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
|
||||
return HashMap<AnalysisFlag<*>, Any>().apply {
|
||||
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
|
||||
@@ -423,6 +429,10 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
put(LanguageFeature.UnrestrictedBuilderInference, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (selfUpperBoundInference) {
|
||||
put(LanguageFeature.TypeInferenceOnCallsWithSelfTypes, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (newInference) {
|
||||
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
|
||||
put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED)
|
||||
|
||||
@@ -511,6 +511,18 @@ default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise""
|
||||
)
|
||||
var serializeIr: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xvalidate-ir",
|
||||
description = "Validate IR before and after lowering"
|
||||
)
|
||||
var validateIr: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xvalidate-bytecode",
|
||||
description = "Validate generated JVM bytecode before and after optimizations"
|
||||
)
|
||||
var validateBytecode: Boolean by FreezableVar(false)
|
||||
|
||||
override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
|
||||
val result = super.configureAnalysisFlags(collector, languageVersion)
|
||||
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
|
||||
|
||||
@@ -278,7 +278,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
val runner = """
|
||||
const wasmBinary = read(String.raw`${outputWasmFile.absoluteFile}`, 'binary');
|
||||
const wasmModule = new WebAssembly.Module(wasmBinary);
|
||||
const wasmInstance = new WebAssembly.Instance(wasmModule, { runtime, js_code });
|
||||
wasmInstance = new WebAssembly.Instance(wasmModule, { runtime, js_code });
|
||||
wasmInstance.exports.main();
|
||||
""".trimIndent()
|
||||
|
||||
|
||||
@@ -233,8 +233,8 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
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
|
||||
val oldestVersion = jars.minOf { it.version }
|
||||
val newestVersion = jars.maxOf { it.version }
|
||||
|
||||
// If the oldest version is the same as the newest version, then all jars have the same version
|
||||
if (oldestVersion == newestVersion) return oldestVersion
|
||||
@@ -250,9 +250,9 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
// 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 }
|
||||
jars.filter { it.file.name.startsWith("kotlin-reflect") }.minByOrNull { it.version }
|
||||
val maxStdlibJar =
|
||||
jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxBy { it.version }
|
||||
jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxByOrNull { it.version }
|
||||
if (minReflectJar != null && maxStdlibJar != null && minReflectJar.version < maxStdlibJar.version) {
|
||||
messageCollector.issue(
|
||||
null,
|
||||
|
||||
@@ -267,11 +267,14 @@ class KotlinCoreEnvironment private constructor(
|
||||
this.initialRoots.addAll(initialRoots)
|
||||
|
||||
if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK) && messageCollector != null) {
|
||||
/*
|
||||
// Temporarily disable until compiler is bootstrapped to 1.6.
|
||||
JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency(
|
||||
messageCollector,
|
||||
configuration,
|
||||
initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null }
|
||||
)
|
||||
*/
|
||||
}
|
||||
|
||||
val (roots, singleJavaFileRoots) =
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
||||
|
||||
class ByteArrayCharSequence(
|
||||
private val bytes: ByteArray,
|
||||
private val start: Int = 0,
|
||||
private val end: Int = bytes.size
|
||||
) : CharSequence {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
error("Do not try computing hashCode ByteArrayCharSequence")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
error("Do not try comparing ByteArrayCharSequence")
|
||||
}
|
||||
|
||||
override val length get() = end - start
|
||||
|
||||
override fun get(index: Int): Char = bytes[index + start].toChar()
|
||||
|
||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
|
||||
if (startIndex == 0 && endIndex == length) return this
|
||||
return ByteArrayCharSequence(bytes, start + startIndex, start + endIndex)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val chars = CharArray(length)
|
||||
|
||||
for (i in 0 until length) {
|
||||
chars[i] = bytes[i + start].toChar()
|
||||
}
|
||||
|
||||
return String(chars)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,26 +6,26 @@ package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.impl.ZipHandler
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
import com.intellij.util.text.ByteArrayCharSequence
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.channels.FileChannel
|
||||
|
||||
class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandler(path) {
|
||||
class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
||||
private val myRoot: VirtualFile?
|
||||
internal val file = File(path)
|
||||
|
||||
private val ourEntryMap: Map<String, ZipEntryDescription>
|
||||
private val cachedManifest: ByteArray?
|
||||
|
||||
init {
|
||||
val entries: List<ZipEntryDescription>
|
||||
RandomAccessFile(file, "r").use { randomAccessFile ->
|
||||
val mappedByteBuffer = randomAccessFile.channel.map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length())
|
||||
try {
|
||||
ourEntryMap = mappedByteBuffer.parseCentralDirectory().associateBy { it.relativePath }
|
||||
cachedManifest = ourEntryMap[MANIFEST_PATH]?.let(mappedByteBuffer::contentsToByteArray)
|
||||
entries = mappedByteBuffer.parseCentralDirectory()
|
||||
cachedManifest =
|
||||
entries.singleOrNull { StringUtil.equals(MANIFEST_PATH, it.relativePath) }
|
||||
?.let(mappedByteBuffer::contentsToByteArray)
|
||||
} finally {
|
||||
with(fileSystem) {
|
||||
mappedByteBuffer.unmapBuffer()
|
||||
@@ -33,114 +33,69 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandl
|
||||
}
|
||||
}
|
||||
|
||||
val entries: MutableMap<EntryInfo, FastJarVirtualFile> = HashMap()
|
||||
val entriesMap = entriesMap
|
||||
val childrenMap = FactoryMap.create<FastJarVirtualFile, MutableList<VirtualFile>> { ArrayList() }
|
||||
for (info in entriesMap.values) {
|
||||
val file = getOrCreateFile(info, entries)
|
||||
val parent = file.parent
|
||||
if (parent != null) {
|
||||
childrenMap[parent]?.add(file)
|
||||
myRoot = FastJarVirtualFile(this, "", -1, parent = null, entryDescription = null)
|
||||
|
||||
// ByteArrayCharSequence should not be used instead of String
|
||||
// because the former class does not support equals/hashCode properly
|
||||
val filesByRelativePath = HashMap<String, FastJarVirtualFile>(entries.size)
|
||||
filesByRelativePath[""] = myRoot
|
||||
|
||||
for (entryDescription in entries) {
|
||||
if (!entryDescription.isDirectory) {
|
||||
createFile(entryDescription, filesByRelativePath)
|
||||
} else {
|
||||
getOrCreateDirectory(entryDescription.relativePath, filesByRelativePath)
|
||||
}
|
||||
}
|
||||
|
||||
val rootInfo = getEntryInfo("")
|
||||
myRoot = rootInfo?.let { getOrCreateFile(it, entries) }
|
||||
|
||||
for ((key, childList) in childrenMap) {
|
||||
key.children = childList.toTypedArray()
|
||||
for (node in filesByRelativePath.values) {
|
||||
node.initChildrenArrayFromList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrCreateFile(info: EntryInfo, entries: MutableMap<EntryInfo, FastJarVirtualFile>): FastJarVirtualFile {
|
||||
var file = entries[info]
|
||||
if (file == null) {
|
||||
val parent = info.parent
|
||||
file = FastJarVirtualFile(this, info.shortName,
|
||||
if (info.isDirectory) -1 else info.length,
|
||||
info.timestamp,
|
||||
parent?.let { getOrCreateFile(it, entries) })
|
||||
entries[info] = file
|
||||
private fun createFile(entry: ZipEntryDescription, directories: MutableMap<String, FastJarVirtualFile>): FastJarVirtualFile {
|
||||
val (parentName, shortName) = entry.relativePath.splitPath()
|
||||
|
||||
val parentFile = getOrCreateDirectory(parentName, directories)
|
||||
if ("." == shortName) {
|
||||
return parentFile
|
||||
}
|
||||
return file
|
||||
|
||||
return FastJarVirtualFile(
|
||||
this, shortName,
|
||||
if (entry.isDirectory) -1 else entry.uncompressedSize,
|
||||
parentFile,
|
||||
entry,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getOrCreateDirectory(entryName: CharSequence, directories: MutableMap<String, FastJarVirtualFile>): FastJarVirtualFile {
|
||||
return directories.getOrPut(entryName.toString()) {
|
||||
val (parentPath, shortName) = entryName.splitPath()
|
||||
val parentFile = getOrCreateDirectory(parentPath, directories)
|
||||
|
||||
FastJarVirtualFile(this, shortName, -1, parentFile, entryDescription = null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CharSequence.splitPath(): Pair<CharSequence, CharSequence> {
|
||||
var slashIndex = this.length - 1
|
||||
|
||||
while (slashIndex >= 0 && this[slashIndex] != '/') {
|
||||
slashIndex--
|
||||
}
|
||||
|
||||
if (slashIndex == -1) return Pair("", this)
|
||||
return Pair(subSequence(0, slashIndex), subSequence(slashIndex + 1, this.length))
|
||||
}
|
||||
|
||||
fun findFileByPath(pathInJar: String): VirtualFile? {
|
||||
return myRoot?.findFileByRelativePath(pathInJar)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun createEntriesMap(): Map<String, EntryInfo> {
|
||||
val mapToEntryInfo = mutableMapOf<String, EntryInfo>()
|
||||
mapToEntryInfo[""] = EntryInfo("", true, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, null)
|
||||
for (zipEntry in ourEntryMap.values) {
|
||||
getOrCreate(zipEntry, mapToEntryInfo)
|
||||
}
|
||||
|
||||
return mapToEntryInfo
|
||||
}
|
||||
|
||||
private fun getOrCreate(entry: ZipEntryDescription, map: MutableMap<String, EntryInfo>): EntryInfo {
|
||||
var isDirectory = entry.isDirectory
|
||||
var entryName = entry.relativePath
|
||||
if (StringUtil.endsWithChar(entryName, '/')) {
|
||||
entryName = entryName.substring(0, entryName.length - 1)
|
||||
isDirectory = true
|
||||
}
|
||||
if (StringUtil.startsWithChar(entryName, '/') || StringUtil.startsWithChar(entryName, '\\')) {
|
||||
entryName = entryName.substring(1)
|
||||
}
|
||||
|
||||
var info = map[entryName]
|
||||
if (info != null) return info
|
||||
|
||||
val path = splitPathAndFix(entryName)
|
||||
|
||||
val parentInfo = getOrCreateDirectory(path.first, map)
|
||||
if ("." == path.second) {
|
||||
return parentInfo
|
||||
}
|
||||
info = store(map, parentInfo, path.second, isDirectory, entry.uncompressedSize.toLong(), 0, path.third)
|
||||
return info
|
||||
}
|
||||
|
||||
private fun getOrCreateDirectory(entryName: String, map: MutableMap<String, EntryInfo>): EntryInfo {
|
||||
var info = map[entryName]
|
||||
|
||||
if (info == null) {
|
||||
val entry = ourEntryMap["$entryName/"]
|
||||
if (entry != null) {
|
||||
return getOrCreate(entry, map)
|
||||
}
|
||||
val path = splitPathAndFix(entryName)
|
||||
require(entryName != path.first) {
|
||||
"invalid entry name: '" + entryName + "' in " + this.file.absolutePath + "; after split: " + path
|
||||
}
|
||||
val parentInfo = getOrCreateDirectory(path.first, map)
|
||||
info = store(map, parentInfo, path.second, true, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, path.third)
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
private fun store(
|
||||
map: MutableMap<String, EntryInfo>,
|
||||
parentInfo: EntryInfo?,
|
||||
shortName: CharSequence,
|
||||
isDirectory: Boolean,
|
||||
size: Long,
|
||||
time: Long,
|
||||
entryName: String
|
||||
): EntryInfo {
|
||||
val sequence = ByteArrayCharSequence.convertToBytesIfPossible(shortName)
|
||||
val info = EntryInfo(sequence, isDirectory, size, time, parentInfo)
|
||||
map[entryName] = info
|
||||
return info
|
||||
}
|
||||
|
||||
override fun contentsToByteArray(relativePath: String): ByteArray {
|
||||
if (relativePath == MANIFEST_PATH) return cachedManifest ?: throw FileNotFoundException("$file!/$relativePath")
|
||||
val zipEntryDescription = ourEntryMap[relativePath] ?: throw FileNotFoundException("$file!/$relativePath")
|
||||
fun contentsToByteArray(zipEntryDescription: ZipEntryDescription): ByteArray {
|
||||
val relativePath = zipEntryDescription.relativePath
|
||||
if (StringUtil.equals(relativePath, MANIFEST_PATH)) return cachedManifest ?: throw FileNotFoundException("$file!/$relativePath")
|
||||
return fileSystem.cachedOpenFileHandles[file].use {
|
||||
synchronized(it) {
|
||||
it.get().second.contentsToByteArray(zipEntryDescription)
|
||||
@@ -150,5 +105,3 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) : ZipHandl
|
||||
}
|
||||
|
||||
private const val MANIFEST_PATH = "META-INF/MANIFEST.MF"
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
||||
|
||||
import com.intellij.openapi.util.Couple
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
@@ -14,41 +13,48 @@ import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
internal class FastJarVirtualFile(
|
||||
private val myHandler: FastJarHandler,
|
||||
private val myName: CharSequence,
|
||||
private val myLength: Long,
|
||||
private val myTimestamp: Long,
|
||||
parent: FastJarVirtualFile?
|
||||
private val handler: FastJarHandler,
|
||||
private val name: CharSequence,
|
||||
private val length: Int,
|
||||
private val parent: FastJarVirtualFile?,
|
||||
private val entryDescription: ZipEntryDescription?,
|
||||
) : VirtualFile() {
|
||||
private val myParent: VirtualFile? = parent
|
||||
private var myChildren = EMPTY_ARRAY
|
||||
fun setChildren(children: Array<VirtualFile>) {
|
||||
myChildren = children
|
||||
|
||||
private var myChildrenArray = EMPTY_ARRAY
|
||||
private val myChildrenList: MutableList<VirtualFile> = mutableListOf()
|
||||
|
||||
init {
|
||||
parent?.myChildrenList?.add(this)
|
||||
}
|
||||
|
||||
fun initChildrenArrayFromList() {
|
||||
myChildrenArray = myChildrenList.toTypedArray()
|
||||
myChildrenList.clear()
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return myName.toString()
|
||||
return name.toString()
|
||||
}
|
||||
|
||||
override fun getNameSequence(): CharSequence {
|
||||
return myName
|
||||
return name
|
||||
}
|
||||
|
||||
override fun getFileSystem(): VirtualFileSystem {
|
||||
return myHandler.fileSystem
|
||||
return handler.fileSystem
|
||||
}
|
||||
|
||||
override fun getPath(): String {
|
||||
if (myParent == null) {
|
||||
return FileUtil.toSystemIndependentName(myHandler.file.path) + "!/"
|
||||
if (parent == null) {
|
||||
return FileUtil.toSystemIndependentName(handler.file.path) + "!/"
|
||||
}
|
||||
val parentPath = myParent.path
|
||||
val answer = StringBuilder(parentPath.length + 1 + myName.length)
|
||||
val parentPath = parent.path
|
||||
val answer = StringBuilder(parentPath.length + 1 + name.length)
|
||||
answer.append(parentPath)
|
||||
if (answer[answer.length - 1] != '/') {
|
||||
answer.append('/')
|
||||
}
|
||||
answer.append(myName)
|
||||
answer.append(name)
|
||||
return answer.toString()
|
||||
}
|
||||
|
||||
@@ -57,7 +63,7 @@ internal class FastJarVirtualFile(
|
||||
}
|
||||
|
||||
override fun isDirectory(): Boolean {
|
||||
return myLength < 0
|
||||
return length < 0
|
||||
}
|
||||
|
||||
override fun isValid(): Boolean {
|
||||
@@ -65,11 +71,11 @@ internal class FastJarVirtualFile(
|
||||
}
|
||||
|
||||
override fun getParent(): VirtualFile? {
|
||||
return myParent
|
||||
return parent
|
||||
}
|
||||
|
||||
override fun getChildren(): Array<VirtualFile> {
|
||||
return myChildren
|
||||
return myChildrenArray
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -79,21 +85,16 @@ internal class FastJarVirtualFile(
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun contentsToByteArray(): ByteArray {
|
||||
val pair: Couple<String> = FastJarFileSystem.splitPath(
|
||||
path
|
||||
)
|
||||
return myHandler.contentsToByteArray(pair.second)
|
||||
if (entryDescription == null) return EMPTY_BYTE_ARRAY
|
||||
return handler.contentsToByteArray(entryDescription)
|
||||
}
|
||||
|
||||
override fun getTimeStamp(): Long {
|
||||
return myTimestamp
|
||||
}
|
||||
override fun getTimeStamp(): Long = 0
|
||||
|
||||
override fun getLength(): Long {
|
||||
return myLength
|
||||
}
|
||||
override fun getLength(): Long = length.toLong()
|
||||
|
||||
override fun refresh(asynchronous: Boolean, recursive: Boolean, postRunnable: Runnable?) {}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun getInputStream(): InputStream {
|
||||
return BufferExposingByteArrayInputStream(contentsToByteArray())
|
||||
@@ -103,3 +104,5 @@ internal class FastJarVirtualFile(
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
private val EMPTY_BYTE_ARRAY = ByteArray(0)
|
||||
|
||||
@@ -12,12 +12,12 @@ import java.util.zip.Inflater
|
||||
|
||||
|
||||
class ZipEntryDescription(
|
||||
val relativePath: String,
|
||||
val relativePath: CharSequence,
|
||||
val compressedSize: Int,
|
||||
val uncompressedSize: Int,
|
||||
val offsetInFile: Int,
|
||||
val compressionKind: CompressionKind,
|
||||
val fileNameSize: Int
|
||||
val fileNameSize: Int,
|
||||
) {
|
||||
|
||||
enum class CompressionKind {
|
||||
@@ -62,9 +62,11 @@ fun MappedByteBuffer.contentsToByteArray(
|
||||
fun MappedByteBuffer.parseCentralDirectory(): List<ZipEntryDescription> {
|
||||
order(ByteOrder.LITTLE_ENDIAN)
|
||||
|
||||
val endOfCentralDirectoryOffset = (capacity() - END_OF_CENTRAL_DIR_SIZE downTo 0).first { offset ->
|
||||
var endOfCentralDirectoryOffset = capacity() - END_OF_CENTRAL_DIR_SIZE
|
||||
while (endOfCentralDirectoryOffset >= 0) {
|
||||
// header of "End of central directory"
|
||||
getInt(offset) == 0x06054b50
|
||||
if (getInt(endOfCentralDirectoryOffset) == 0x06054b50) break
|
||||
endOfCentralDirectoryOffset--
|
||||
}
|
||||
|
||||
val entriesNumber = getUnsignedShort(endOfCentralDirectoryOffset + 10)
|
||||
@@ -97,7 +99,11 @@ fun MappedByteBuffer.parseCentralDirectory(): List<ZipEntryDescription> {
|
||||
position(currentOffset + 46)
|
||||
get(bytesForName)
|
||||
|
||||
val name = String(bytesForName)
|
||||
val name =
|
||||
if (bytesForName.all { it >= 0 })
|
||||
ByteArrayCharSequence(bytesForName)
|
||||
else
|
||||
String(bytesForName, Charsets.UTF_8)
|
||||
|
||||
currentOffset += 46 + fileNameLength + extraLength + fileCommentLength
|
||||
|
||||
|
||||
@@ -254,6 +254,9 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
|
||||
|
||||
put(JVMConfigurationKeys.SERIALIZE_IR, arguments.serializeIr)
|
||||
|
||||
put(JVMConfigurationKeys.VALIDATE_IR, arguments.validateIr)
|
||||
put(JVMConfigurationKeys.VALIDATE_BYTECODE, arguments.validateBytecode)
|
||||
|
||||
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
|
||||
messageCollector.report(
|
||||
ERROR,
|
||||
|
||||
@@ -157,5 +157,11 @@ public class JVMConfigurationKeys {
|
||||
CompilerConfigurationKey.create("Don't automatically include kotlin-reflect.jar into the output if the output is a jar");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> SERIALIZE_IR =
|
||||
CompilerConfigurationKey.create("serialize IR to class metadata");
|
||||
CompilerConfigurationKey.create("Serialize IR to class metadata");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> VALIDATE_IR =
|
||||
CompilerConfigurationKey.create("Validate IR");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> VALIDATE_BYTECODE =
|
||||
CompilerConfigurationKey.create("Validate generated JVM bytecode");
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ enum class JvmTarget(
|
||||
JVM_14("14", Opcodes.V12 + 2),
|
||||
JVM_15("15", Opcodes.V12 + 3),
|
||||
JVM_16("16", Opcodes.V12 + 4),
|
||||
JVM_17("17", Opcodes.V12 + 5),
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -49,7 +49,7 @@ dependencies {
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||
kotlinOptions {
|
||||
apiVersion = "1.3"
|
||||
apiVersion = "1.4"
|
||||
freeCompilerArgs += "-Xsuppress-version-warnings"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ dependencies {
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||
kotlinOptions {
|
||||
// This module is being run from within Gradle, older versions of which only have kotlin-stdlib 1.3 in the runtime classpath.
|
||||
apiVersion = "1.3"
|
||||
// This module is being run from within Gradle, older versions of which only have older kotlin-stdlib in the runtime classpath.
|
||||
apiVersion = "1.4"
|
||||
freeCompilerArgs += "-Xsuppress-version-warnings"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationOnDeclarationWithDifferentArguments.kt")
|
||||
public void testAnnotationOnDeclarationWithDifferentArguments() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
|
||||
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt");
|
||||
@@ -616,6 +621,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClassInAnnotationArgument.kt")
|
||||
public void testNestedClassInAnnotationArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noParameterForName.kt")
|
||||
public void testNoParameterForName() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/noParameterForName.kt");
|
||||
@@ -2580,6 +2590,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("implicitInAnonymous.kt")
|
||||
public void testImplicitInAnonymous() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/implicitInAnonymous.kt");
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
FILE: annotationOnDeclarationWithDifferentArguments.kt
|
||||
public final enum class SomeEnum : R|kotlin/Enum<SomeEnum>| {
|
||||
private constructor(): R|SomeEnum| {
|
||||
super<R|kotlin/Enum<SomeEnum>|>()
|
||||
}
|
||||
|
||||
public final static enum entry A: R|SomeEnum|
|
||||
public final static enum entry B: R|SomeEnum|
|
||||
public final static fun values(): R|kotlin/Array<SomeEnum>| {
|
||||
}
|
||||
|
||||
public final static fun valueOf(value: R|kotlin/String|): R|SomeEnum| {
|
||||
}
|
||||
|
||||
}
|
||||
public final annotation class MyAnnotation : R|kotlin/Annotation| {
|
||||
public constructor(intValue: R|kotlin/Int|, stringValue: R|kotlin/String|, enumValue: R|SomeEnum|, kClasses: R|kotlin/Array<out kotlin/reflect/KClass<*>>|, annotation: R|MyOtherAnnotation|): R|MyAnnotation| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val intValue: R|kotlin/Int| = R|<local>/intValue|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val stringValue: R|kotlin/String| = R|<local>/stringValue|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final val enumValue: R|SomeEnum| = R|<local>/enumValue|
|
||||
public get(): R|SomeEnum|
|
||||
|
||||
public final val kClasses: R|kotlin/Array<out kotlin/reflect/KClass<*>>| = R|<local>/kClasses|
|
||||
public get(): R|kotlin/Array<out kotlin/reflect/KClass<*>>|
|
||||
|
||||
public final val annotation: R|MyOtherAnnotation| = R|<local>/annotation|
|
||||
public get(): R|MyOtherAnnotation|
|
||||
|
||||
}
|
||||
public final annotation class MyOtherAnnotation : R|kotlin/Annotation| {
|
||||
public constructor(intValue: R|kotlin/Int|, stringValue: R|kotlin/String|): R|MyOtherAnnotation| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val intValue: R|kotlin/Int| = R|<local>/intValue|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val stringValue: R|kotlin/String| = R|<local>/stringValue|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
public final const val constInt: R|kotlin/Int| = Int(10)
|
||||
public get(): R|kotlin/Int|
|
||||
public final const val constString: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
@R|MyAnnotation|(intValue = Int(10), stringValue = R|/constString|, enumValue = Q|SomeEnum|.R|/SomeEnum.A|, kClasses = <implicitArrayOf>(<getClass>(Q|kotlin/String|), <getClass>(R|/constString|)), annotation = R|/MyOtherAnnotation.MyOtherAnnotation|(intValue = R|/constInt|, stringValue = String(hello))) public final fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
30
compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.kt
vendored
Normal file
30
compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.kt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
annotation class MyAnnotation(
|
||||
val intValue: Int,
|
||||
val stringValue: String,
|
||||
val enumValue: SomeEnum,
|
||||
val kClasses: Array<out KClass<*>>,
|
||||
val annotation: MyOtherAnnotation
|
||||
)
|
||||
annotation class MyOtherAnnotation(val intValue: Int, val stringValue: String)
|
||||
|
||||
const val constInt = 10
|
||||
const val constString = ""
|
||||
|
||||
@MyAnnotation(
|
||||
intValue = 10,
|
||||
stringValue = constString,
|
||||
enumValue = SomeEnum.A,
|
||||
kClasses = [String::class, <!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>constString::class<!>],
|
||||
|
||||
annotation = MyOtherAnnotation(
|
||||
intValue = constInt,
|
||||
stringValue = "hello"
|
||||
)
|
||||
)
|
||||
fun foo() {}
|
||||
26
compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.fir.txt
vendored
Normal file
26
compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.fir.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
FILE: nestedClassInAnnotationArgument.kt
|
||||
public final annotation class Ann : R|kotlin/Annotation| {
|
||||
public constructor(kClass: R|kotlin/reflect/KClass<*>|): R|Ann| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val kClass: R|kotlin/reflect/KClass<*>| = R|<local>/kClass|
|
||||
public get(): R|kotlin/reflect/KClass<*>|
|
||||
|
||||
}
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@R|Ann|(<getClass>(Q|A.EmptyList|)) public final fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final object EmptyList : R|kotlin/Any| {
|
||||
private constructor(): R|A.EmptyList| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
11
compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.kt
vendored
Normal file
11
compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// WITH_STDLIB
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
annotation class Ann(val kClass: KClass<*>)
|
||||
|
||||
class A {
|
||||
@Ann(EmptyList::class)
|
||||
fun foo() {}
|
||||
|
||||
object EmptyList
|
||||
}
|
||||
@@ -13,12 +13,12 @@ FILE: cast.kt
|
||||
}
|
||||
|
||||
public get(): R|() -> kotlin/Unit|
|
||||
public final val h: R|(kotlin/String) -> kotlin/Boolean| = fun <anonymous>(_: R|kotlin/String|): R|kotlin/Boolean| <inline=Unknown> {
|
||||
public final val h: R|(kotlin/String) -> kotlin/Boolean| = fun <anonymous>(<unused var>: R|kotlin/String|): R|kotlin/Boolean| <inline=Unknown> {
|
||||
^ Boolean(false)
|
||||
}
|
||||
|
||||
public get(): R|(kotlin/String) -> kotlin/Boolean|
|
||||
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(_: <ERROR TYPE REF: No type for parameter>): R|kotlin/Boolean| <inline=Unknown> {
|
||||
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(<unused var>: <ERROR TYPE REF: No type for parameter>): R|kotlin/Boolean| <inline=Unknown> {
|
||||
^ Boolean(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// !DUMP_CFG
|
||||
inline fun foo(vararg x: Any) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo(vararg x: Any) {}
|
||||
|
||||
fun test(a: Any, b: Any, c: Any) {
|
||||
foo(a, { "" }, b)
|
||||
|
||||
@@ -20,7 +20,7 @@ abstract class K {
|
||||
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> val i2: Int
|
||||
}
|
||||
|
||||
private open <!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class L<!> : K()
|
||||
private open <!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_ERROR!>class L<!> : K()
|
||||
private abstract class M : K()
|
||||
|
||||
class X {
|
||||
|
||||
@@ -66,3 +66,9 @@ class Test8<S8 : Test7<S8, <!UPPER_BOUND_VIOLATED!>in Any<!>>>
|
||||
class Class<V : Any>
|
||||
typealias Alias <V1> = (Class<V1>) -> Boolean
|
||||
|
||||
/* TODO: Should not be errors. Uncomment after fixing of https://youtrack.jetbrains.com/issue/KT-48044
|
||||
abstract class Base<T : Base<T>> {}
|
||||
class DerivedOut<out O : Base<out O>> {}
|
||||
class DerivedIn<in I : Base<in I>> {}*/
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ fun f() {
|
||||
LocalClass().foo = 1
|
||||
}
|
||||
|
||||
internal inline fun internal() {
|
||||
internal <!NOTHING_TO_INLINE!>inline<!> fun internal() {
|
||||
f()
|
||||
}
|
||||
|
||||
|
||||
27
compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.fir.txt
vendored
Normal file
27
compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.fir.txt
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
FILE: anonymousInAnonymous.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval base: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun bar(): R|<anonymous>| {
|
||||
^bar object : R|kotlin/Any| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun buz(): R|kotlin/String| {
|
||||
^buz this@R|/<anonymous>|.R|/<anonymous>.foobar|
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final val foobar: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
8
compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt
vendored
Normal file
8
compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
val base = object {
|
||||
fun bar() = object {
|
||||
fun buz() = foobar
|
||||
}
|
||||
val foobar = ""
|
||||
}
|
||||
}
|
||||
@@ -1413,4 +1413,59 @@ digraph nullability_kt {
|
||||
534 -> {535};
|
||||
535 -> {536};
|
||||
|
||||
subgraph cluster_107 {
|
||||
color=red
|
||||
537 [label="Enter function test_14" style="filled" fillcolor=red];
|
||||
subgraph cluster_108 {
|
||||
color=blue
|
||||
538 [label="Enter block"];
|
||||
subgraph cluster_109 {
|
||||
color=blue
|
||||
539 [label="Enter when"];
|
||||
subgraph cluster_110 {
|
||||
color=blue
|
||||
540 [label="Enter when branch condition "];
|
||||
541 [label="Access variable R|<local>/q|"];
|
||||
542 [label="Access variable R|/Q.data|"];
|
||||
543 [label="Const: Null(null)"];
|
||||
544 [label="Equality operator =="];
|
||||
545 [label="Exit when branch condition"];
|
||||
}
|
||||
546 [label="Synthetic else branch"];
|
||||
547 [label="Enter when branch result"];
|
||||
subgraph cluster_111 {
|
||||
color=blue
|
||||
548 [label="Enter block"];
|
||||
549 [label="Access variable R|<local>/q|"];
|
||||
550 [label="Access variable R|/Q.data|"];
|
||||
551 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
552 [label="Exit block"];
|
||||
}
|
||||
553 [label="Exit when branch result"];
|
||||
554 [label="Exit when"];
|
||||
}
|
||||
555 [label="Exit block"];
|
||||
}
|
||||
556 [label="Exit function test_14" style="filled" fillcolor=red];
|
||||
}
|
||||
537 -> {538};
|
||||
538 -> {539};
|
||||
539 -> {540};
|
||||
540 -> {541};
|
||||
541 -> {542};
|
||||
542 -> {543};
|
||||
543 -> {544};
|
||||
544 -> {545};
|
||||
545 -> {547 546};
|
||||
546 -> {554};
|
||||
547 -> {548};
|
||||
548 -> {549};
|
||||
549 -> {550};
|
||||
550 -> {551};
|
||||
551 -> {552};
|
||||
552 -> {553};
|
||||
553 -> {554};
|
||||
554 -> {555};
|
||||
555 -> {556};
|
||||
|
||||
}
|
||||
|
||||
@@ -232,3 +232,11 @@ FILE: nullability.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_14(q: R|Q|): R|kotlin/Unit| {
|
||||
when () {
|
||||
==(R|<local>/q|.R|/Q.data|, Null(null)) -> {
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -175,3 +175,10 @@ fun test_13(q: QImplMutable?) {
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
|
||||
}
|
||||
}
|
||||
|
||||
fun test_14(q: Q) {
|
||||
// `q.data` is a property that has an open getter
|
||||
if (q.data == null) {
|
||||
q.data<!UNSAFE_CALL!>.<!>s // should be UNSAFE_CALL and NOT SMARTCAST_IMPOSSIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ FILE: delegateTypeMismatch.kt
|
||||
public get(): R|kotlin/Boolean|
|
||||
|
||||
private final fun <T> property(initialValue: R|T|): R|kotlin/properties/ReadWriteProperty<A, T>| {
|
||||
^property Q|kotlin/properties/Delegates|.R|kotlin/properties/Delegates.vetoable|<R|T|>(R|<local>/initialValue|, <L> = vetoable@fun <anonymous>(_: R|@R|kotlin/ParameterName|(name = String(property)) kotlin/reflect/KProperty<*>|, _: R|T|, _: R|T|): R|kotlin/Boolean| <inline=CrossInline, kind=UNKNOWN> {
|
||||
^property Q|kotlin/properties/Delegates|.R|kotlin/properties/Delegates.vetoable|<R|T|>(R|<local>/initialValue|, <L> = vetoable@fun <anonymous>(<unused var>: R|@R|kotlin/ParameterName|(name = String(property)) kotlin/reflect/KProperty<*>|, <unused var>: R|T|, <unused var>: R|T|): R|kotlin/Boolean| <inline=CrossInline, kind=UNKNOWN> {
|
||||
^ when () {
|
||||
this@R|/A|.R|/A.isLocked| -> {
|
||||
throw R|java/lang/IllegalStateException.IllegalStateException|(String(Cannot modify readonly DescriptorRendererOptions))
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
FILE: DailyAggregatedDoubleFactor.kt
|
||||
public abstract interface DailyAggregatedDoubleFactor : R|kotlin/Any| {
|
||||
}
|
||||
private final fun R|DailyAggregatedDoubleFactor|.aggregateBy(reduce: R|(kotlin/Double, kotlin/Double) -> kotlin/Double|): R|kotlin/collections/Map<kotlin/String, kotlin/Double>| {
|
||||
^aggregateBy R|kotlin/collections/mutableMapOf|<R|kotlin/String|, R|kotlin/Double|>()
|
||||
}
|
||||
public final fun R|DailyAggregatedDoubleFactor|.aggregateMin(): R|kotlin/collections/Map<kotlin/String, kotlin/Double>| {
|
||||
^aggregateMin this@R|/aggregateMin|.R|/aggregateBy|(::R|kotlin/comparisons/minOf|)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
interface DailyAggregatedDoubleFactor
|
||||
|
||||
private fun DailyAggregatedDoubleFactor.aggregateBy(reduce: (Double, Double) -> Double): Map<String, Double> {
|
||||
return mutableMapOf<String, Double>()
|
||||
}
|
||||
|
||||
fun DailyAggregatedDoubleFactor.aggregateMin(): Map<String, Double> = aggregateBy(::minOf)
|
||||
3
compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.fir.txt
vendored
Normal file
3
compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.fir.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
FILE: jvm.kt
|
||||
@R|some/Nls|(R|some/Nls.Capitalization.Title|) public final fun f(): R|kotlin/Unit| {
|
||||
}
|
||||
17
compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.kt
vendored
Normal file
17
compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.kt
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// FILE: some/Nls.java
|
||||
package some
|
||||
public @interface Nls {
|
||||
Capitalization capitalization() default Capitalization.NotSpecified;
|
||||
|
||||
enum Capitalization { NotSpecified, Title, Sentence }
|
||||
}
|
||||
|
||||
|
||||
// FILE: jvm.kt
|
||||
import some.Nls.Capitalization.*
|
||||
import some.Nls
|
||||
|
||||
@Nls(Title)
|
||||
fun f() {
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
FILE: MapCompute.kt
|
||||
public final fun <D> R|kotlin/collections/MutableMap<kotlin/String, kotlin/collections/MutableSet<D>>|.initAndAdd(key: R|kotlin/String|, value: R|D|): R|kotlin/Unit| {
|
||||
this@R|/initAndAdd|.R|SubstitutionOverride<kotlin/collections/MutableMap.compute: R|kotlin/collections/MutableSet<D>?|>|(R|<local>/key|, <L> = compute@fun <anonymous>(_: R|ft<kotlin/String, kotlin/String?>|, maybeValues: R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>|): R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>| <inline=NoInline> {
|
||||
this@R|/initAndAdd|.R|SubstitutionOverride<kotlin/collections/MutableMap.compute: R|kotlin/collections/MutableSet<D>?|>|(R|<local>/key|, <L> = compute@fun <anonymous>(<unused var>: R|ft<kotlin/String, kotlin/String?>|, maybeValues: R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>|): R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>| <inline=NoInline> {
|
||||
lval setOfValues: R|kotlin/collections/MutableSet<D>| = R|<local>/maybeValues| ?: R|kotlin/collections/mutableSetOf|<R|D|>()
|
||||
R|<local>/setOfValues|.R|SubstitutionOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(R|<local>/value|)
|
||||
^ R|<local>/setOfValues|
|
||||
|
||||
@@ -26,6 +26,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationOnDeclarationWithDifferentArguments.kt")
|
||||
public void testAnnotationOnDeclarationWithDifferentArguments() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
|
||||
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
|
||||
@@ -725,6 +731,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassInAnnotationArgument.kt")
|
||||
public void testNestedClassInAnnotationArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("noParameterForName.kt")
|
||||
public void testNoParameterForName() throws Exception {
|
||||
@@ -2925,6 +2937,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("implicitInAnonymous.kt")
|
||||
public void testImplicitInAnonymous() throws Exception {
|
||||
@@ -4994,6 +5012,22 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Intellij {
|
||||
@Test
|
||||
public void testAllFilesPresentInIntellij() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DailyAggregatedDoubleFactor.kt")
|
||||
public void testDailyAggregatedDoubleFactor() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -5003,6 +5037,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationWithEnum.kt")
|
||||
public void testAnnotationWithEnum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("BasicWithAnnotatedJava.kt")
|
||||
public void testBasicWithAnnotatedJava() throws Exception {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationOnDeclarationWithDifferentArguments.kt")
|
||||
public void testAnnotationOnDeclarationWithDifferentArguments() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
|
||||
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
|
||||
@@ -725,6 +731,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassInAnnotationArgument.kt")
|
||||
public void testNestedClassInAnnotationArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/nestedClassInAnnotationArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("noParameterForName.kt")
|
||||
public void testNoParameterForName() throws Exception {
|
||||
@@ -2925,6 +2937,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/localClasses"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("anonymousInAnonymous.kt")
|
||||
public void testAnonymousInAnonymous() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/localClasses/anonymousInAnonymous.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("implicitInAnonymous.kt")
|
||||
public void testImplicitInAnonymous() throws Exception {
|
||||
@@ -4994,6 +5012,22 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Intellij {
|
||||
@Test
|
||||
public void testAllFilesPresentInIntellij() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DailyAggregatedDoubleFactor.kt")
|
||||
public void testDailyAggregatedDoubleFactor() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@@ -5003,6 +5037,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationWithEnum.kt")
|
||||
public void testAnnotationWithEnum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/AnnotationWithEnum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("BasicWithAnnotatedJava.kt")
|
||||
public void testBasicWithAnnotatedJava() throws Exception {
|
||||
|
||||
@@ -680,6 +680,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/SafeCallNonNullReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SafeCallNonNullReceiver2.kt")
|
||||
public void testSafeCallNonNullReceiver2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/SafeCallNonNullReceiver2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SafeCallNonNullReceiverReturnNull.kt")
|
||||
public void testSafeCallNonNullReceiverReturnNull() throws Exception {
|
||||
@@ -1133,12 +1139,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedRepeatable.kt")
|
||||
public void testDeprecatedRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt")
|
||||
public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception {
|
||||
@@ -2095,21 +2095,99 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable.kt")
|
||||
public void testJavaRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt");
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable.kt")
|
||||
public void testJavaUnrepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt");
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable.kt")
|
||||
public void testKotlinRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt");
|
||||
@TestMetadata("containerArguments_1_5.kt")
|
||||
public void testContainerArguments_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerArguments_1_6.kt")
|
||||
public void testContainerArguments_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerRetention_1_5.kt")
|
||||
public void testContainerRetention_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerRetention_1_6.kt")
|
||||
public void testContainerRetention_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerTarget_1_6.kt")
|
||||
public void testContainerTarget_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatableJvmTarget6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable_1_5.kt")
|
||||
public void testJavaRepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable_1_6.kt")
|
||||
public void testJavaRepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable_1_5.kt")
|
||||
public void testJavaUnrepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable_1_6.kt")
|
||||
public void testJavaUnrepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable_1_5.kt")
|
||||
public void testKotlinRepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable_1_6.kt")
|
||||
public void testKotlinRepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassContainer_1_5.kt")
|
||||
public void testNestedClassContainer_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassContainer_1_6.kt")
|
||||
public void testNestedClassContainer_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15156,6 +15234,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt47941.kt")
|
||||
public void testKt47941() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt47941.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt702.kt")
|
||||
public void testKt702() throws Exception {
|
||||
@@ -29808,38 +29892,48 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/jvmRecord/supertypesCheck.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class TestsWithJava17 {
|
||||
@Test
|
||||
public void testAllFilesPresentInTestsWithJava17() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses")
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SealedClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInSealedClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaSealedClassExhaustiveness.kt")
|
||||
public void testJavaSealedClassExhaustiveness() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/javaSealedClassExhaustiveness.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/javaSealedClassExhaustiveness.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaSealedInterfaceExhaustiveness.kt")
|
||||
public void testJavaSealedInterfaceExhaustiveness() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/javaSealedInterfaceExhaustiveness.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/javaSealedInterfaceExhaustiveness.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinInheritsJavaClass.kt")
|
||||
public void testKotlinInheritsJavaClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/kotlinInheritsJavaClass.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/kotlinInheritsJavaClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinInheritsJavaInterface.kt")
|
||||
public void testKotlinInheritsJavaInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/kotlinInheritsJavaInterface.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/kotlinInheritsJavaInterface.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31827,6 +31921,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/when/kt4434.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt47922.kt")
|
||||
public void testKt47922() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/kt47922.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9929.kt")
|
||||
public void testKt9929() throws Exception {
|
||||
|
||||
@@ -680,6 +680,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/SafeCallNonNullReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SafeCallNonNullReceiver2.kt")
|
||||
public void testSafeCallNonNullReceiver2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/SafeCallNonNullReceiver2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SafeCallNonNullReceiverReturnNull.kt")
|
||||
public void testSafeCallNonNullReceiverReturnNull() throws Exception {
|
||||
@@ -1133,12 +1139,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedRepeatable.kt")
|
||||
public void testDeprecatedRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt")
|
||||
public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception {
|
||||
@@ -2095,21 +2095,99 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable.kt")
|
||||
public void testJavaRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt");
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable.kt")
|
||||
public void testJavaUnrepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt");
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable.kt")
|
||||
public void testKotlinRepeatable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt");
|
||||
@TestMetadata("containerArguments_1_5.kt")
|
||||
public void testContainerArguments_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerArguments_1_6.kt")
|
||||
public void testContainerArguments_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerRetention_1_5.kt")
|
||||
public void testContainerRetention_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerRetention_1_6.kt")
|
||||
public void testContainerRetention_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerTarget_1_6.kt")
|
||||
public void testContainerTarget_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatableJvmTarget6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable_1_5.kt")
|
||||
public void testJavaRepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatable_1_6.kt")
|
||||
public void testJavaRepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable_1_5.kt")
|
||||
public void testJavaUnrepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaUnrepeatable_1_6.kt")
|
||||
public void testJavaUnrepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable_1_5.kt")
|
||||
public void testKotlinRepeatable_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinRepeatable_1_6.kt")
|
||||
public void testKotlinRepeatable_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassContainer_1_5.kt")
|
||||
public void testNestedClassContainer_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassContainer_1_6.kt")
|
||||
public void testNestedClassContainer_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15156,6 +15234,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt47941.kt")
|
||||
public void testKt47941() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt47941.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt702.kt")
|
||||
public void testKt702() throws Exception {
|
||||
@@ -29808,38 +29892,48 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/jvmRecord/supertypesCheck.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class TestsWithJava17 {
|
||||
@Test
|
||||
public void testAllFilesPresentInTestsWithJava17() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses")
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SealedClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInSealedClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaSealedClassExhaustiveness.kt")
|
||||
public void testJavaSealedClassExhaustiveness() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/javaSealedClassExhaustiveness.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/javaSealedClassExhaustiveness.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaSealedInterfaceExhaustiveness.kt")
|
||||
public void testJavaSealedInterfaceExhaustiveness() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/javaSealedInterfaceExhaustiveness.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/javaSealedInterfaceExhaustiveness.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinInheritsJavaClass.kt")
|
||||
public void testKotlinInheritsJavaClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/kotlinInheritsJavaClass.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/kotlinInheritsJavaClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinInheritsJavaInterface.kt")
|
||||
public void testKotlinInheritsJavaInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava15/sealedClasses/kotlinInheritsJavaInterface.kt");
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/kotlinInheritsJavaInterface.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31827,6 +31921,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/when/kt4434.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt47922.kt")
|
||||
public void testKt47922() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/kt47922.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9929.kt")
|
||||
public void testKt9929() throws Exception {
|
||||
|
||||
@@ -14,9 +14,10 @@ import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -229,8 +230,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val DEPRECATED_SINCE_KOTLIN_WITH_DEPRECATED_LEVEL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
|
||||
val ANNOTATION_ON_SUPERCLASS by error<KtAnnotationEntry>()
|
||||
val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by error<PsiElement>()
|
||||
val ANNOTATION_ON_SUPERCLASS by deprecationError<KtAnnotationEntry>(LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes)
|
||||
val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by deprecationError<PsiElement>(LanguageFeature.RestrictRetentionForExpressionAnnotations)
|
||||
val WRONG_ANNOTATION_TARGET by error<KtAnnotationEntry> {
|
||||
parameter<String>("actualTarget")
|
||||
}
|
||||
@@ -443,7 +444,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val RECURSION_IN_IMPLICIT_TYPES by error<PsiElement>()
|
||||
val INFERENCE_ERROR by error<PsiElement>()
|
||||
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error<PsiElement>()
|
||||
val UPPER_BOUND_VIOLATED by error<PsiElement> {
|
||||
val UPPER_BOUND_VIOLATED by warning<PsiElement> {
|
||||
parameter<ConeKotlinType>("expectedUpperBound")
|
||||
parameter<ConeKotlinType>("actualUpperBound")
|
||||
}
|
||||
@@ -491,11 +492,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by error<PsiElement> {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING by warning<PsiElement> {
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by deprecationError<PsiElement>(LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments) {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
@@ -556,7 +553,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<ConeKotlinType>("typeB")
|
||||
}
|
||||
|
||||
val TYPE_VARIANCE_CONFLICT by error<PsiElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
val TYPE_VARIANCE_CONFLICT by warning<PsiElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
parameter<Variance>("typeParameterVariance")
|
||||
parameter<Variance>("variance")
|
||||
@@ -664,11 +661,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirClassSymbol<*>>("classOrObject")
|
||||
parameter<FirCallableSymbol<*>>("missingDeclaration")
|
||||
}
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClassSymbol<*>>("classOrObject")
|
||||
parameter<FirCallableSymbol<*>>("invisibleDeclaration")
|
||||
}
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING by warning<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by deprecationError<KtClassOrObject>(
|
||||
LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses,
|
||||
PositioningStrategy.DECLARATION_NAME
|
||||
) {
|
||||
parameter<FirClassSymbol<*>>("classOrObject")
|
||||
parameter<FirCallableSymbol<*>>("invisibleDeclaration")
|
||||
}
|
||||
@@ -922,10 +918,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val VAL_REASSIGNMENT by error<KtExpression> {
|
||||
parameter<FirVariableSymbol<*>>("variable")
|
||||
}
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by warning<KtExpression> {
|
||||
parameter<FirBackingFieldSymbol>("property")
|
||||
}
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR by error<KtExpression> {
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError<KtExpression>(LanguageFeature.RestrictionOfValReassignmentViaBackingField) {
|
||||
parameter<FirBackingFieldSymbol>("property")
|
||||
}
|
||||
val CAPTURED_VAL_INITIALIZATION by error<KtExpression> {
|
||||
@@ -951,6 +944,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val INITIALIZATION_BEFORE_DECLARATION by error<KtExpression>() {
|
||||
parameter<Symbol>("property")
|
||||
}
|
||||
|
||||
val UNREACHABLE_CODE by warning<KtElement>(PositioningStrategy.UNREACHABLE_CODE) {
|
||||
parameter<Set<FirSourceElement>>("reachable")
|
||||
parameter<Set<FirSourceElement>>("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
val NULLABILITY by object : DiagnosticGroup("Nullability") {
|
||||
@@ -1062,8 +1060,15 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<ConeKotlinType>("actualType")
|
||||
}
|
||||
|
||||
val UNDERSCORE_IS_RESERVED by error<KtElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<KtElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_IS_RESERVED by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||
val RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER by warning<KtNameReferenceExpression>()
|
||||
val INVALID_CHARACTERS by error<KtNamedDeclaration>(PositioningStrategy.NAME_IDENTIFIER) {
|
||||
parameter<String>("message")
|
||||
}
|
||||
val DANGEROUS_CHARACTERS by warning<KtNamedDeclaration>(PositioningStrategy.NAME_IDENTIFIER) {
|
||||
parameter<String>("characters")
|
||||
}
|
||||
|
||||
val EQUALITY_NOT_APPLICABLE by error<KtBinaryExpression> {
|
||||
parameter<String>("operator")
|
||||
@@ -1125,6 +1130,17 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Symbol>("parameter")
|
||||
}
|
||||
|
||||
val NOT_YET_SUPPORTED_IN_INLINE by error<KtDeclaration>(PositioningStrategy.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT) {
|
||||
parameter<String>("message")
|
||||
}
|
||||
|
||||
val NOTHING_TO_INLINE by warning<KtDeclaration>(PositioningStrategy.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
|
||||
|
||||
val NULLABLE_INLINE_PARAMETER by error<KtDeclaration>() {
|
||||
parameter<FirValueParameterSymbol>("parameter")
|
||||
parameter<Symbol>("function")
|
||||
}
|
||||
|
||||
val RECURSION_IN_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("symbol")
|
||||
}
|
||||
@@ -1157,6 +1173,27 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val SUPER_CALL_FROM_PUBLIC_INLINE by warning<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<Symbol>("symbol")
|
||||
}
|
||||
|
||||
val DECLARATION_CANT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
|
||||
val OVERRIDE_BY_INLINE by warning<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
|
||||
val NON_INTERNAL_PUBLISHED_API by error<KtElement>()
|
||||
|
||||
val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error<KtElement>() {
|
||||
parameter<FirExpression>("defaultValue")
|
||||
parameter<FirValueParameterSymbol>("parameter")
|
||||
}
|
||||
|
||||
val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error<KtElement>(PositioningStrategy.REIFIED_MODIFIER)
|
||||
|
||||
val INLINE_PROPERTY_WITH_BACKING_FIELD by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
|
||||
val ILLEGAL_INLINE_PARAMETER_MODIFIER by error<KtElement>(PositioningStrategy.INLINE_PARAMETER_MODIFIER)
|
||||
|
||||
val INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED by error<KtParameter>()
|
||||
|
||||
val REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE by warning<KtElement>(PositioningStrategy.SUSPEND_MODIFIER)
|
||||
}
|
||||
|
||||
val IMPORTS by object : DiagnosticGroup("Imports") {
|
||||
@@ -1176,6 +1213,20 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
|
||||
val OPERATOR_RENAMED_ON_IMPORT by error<KtImportDirective>(PositioningStrategy.IMPORT_LAST_NAME)
|
||||
}
|
||||
|
||||
val SUSPEND by object : DiagnosticGroup("Suspend errors") {
|
||||
val ILLEGAL_SUSPEND_FUNCTION_CALL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||
parameter<Symbol>("suspendCallable")
|
||||
}
|
||||
val ILLEGAL_SUSPEND_PROPERTY_ACCESS by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||
parameter<Symbol>("suspendCallable")
|
||||
}
|
||||
val NON_LOCAL_SUSPENSION_POINT by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val RETURN_FOR_BUILT_IN_SUSPEND by error<KtReturnExpression>()
|
||||
}
|
||||
}
|
||||
|
||||
private val exposedVisibilityDiagnosticInit: DiagnosticBuilder.() -> Unit = {
|
||||
@@ -1186,13 +1237,13 @@ private val exposedVisibilityDiagnosticInit: DiagnosticBuilder.() -> Unit = {
|
||||
|
||||
private inline fun <reified P : PsiElement> AbstractDiagnosticGroup.exposedVisibilityError(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT
|
||||
): PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DiagnosticData>> {
|
||||
): PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, RegularDiagnosticData>> {
|
||||
return error<P>(positioningStrategy, exposedVisibilityDiagnosticInit)
|
||||
}
|
||||
|
||||
private inline fun <reified P : PsiElement> AbstractDiagnosticGroup.exposedVisibilityWarning(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT
|
||||
): PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DiagnosticData>> {
|
||||
): PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, RegularDiagnosticData>> {
|
||||
return warning<P>(positioningStrategy, exposedVisibilityDiagnosticInit)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
@@ -24,24 +25,31 @@ abstract class AbstractDiagnosticGroup @PrivateForInline constructor(val name: S
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> error(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = diagnosticDelegateProvider<P>(Severity.ERROR, positioningStrategy, init)
|
||||
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> warning(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = diagnosticDelegateProvider<P>(Severity.WARNING, positioningStrategy, init)
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> deprecationError(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.Deprecation.() -> Unit = {}
|
||||
) = deprecationDiagnosticDelegateProvider<P>(featureForError, positioningStrategy, init)
|
||||
|
||||
@PrivateForInline
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal inline fun <reified P : PsiElement> diagnosticDelegateProvider(
|
||||
severity: Severity,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder(
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, RegularDiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder.Regular(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name = property.name,
|
||||
@@ -52,6 +60,24 @@ abstract class AbstractDiagnosticGroup @PrivateForInline constructor(val name: S
|
||||
ReadOnlyProperty { _, _ -> diagnostic }
|
||||
}
|
||||
|
||||
@PrivateForInline
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal inline fun <reified P : PsiElement> deprecationDiagnosticDelegateProvider(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
crossinline init: DiagnosticBuilder.Deprecation.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DeprecationDiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder.Deprecation(
|
||||
containingObjectName,
|
||||
featureForError,
|
||||
name = property.name,
|
||||
psiType = typeOf<P>(),
|
||||
positioningStrategy,
|
||||
).apply(init).build()
|
||||
_diagnostics += diagnostic
|
||||
ReadOnlyProperty { _, _ -> diagnostic }
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
operator fun plus(other: AbstractDiagnosticGroup): AbstractDiagnosticGroup {
|
||||
require(name == other.name)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
@@ -65,13 +66,52 @@ abstract class DiagnosticList(internal val objectName: String) {
|
||||
abstract inner class DiagnosticGroup(name: String) : AbstractDiagnosticGroup(name, objectName)
|
||||
}
|
||||
|
||||
class DiagnosticBuilder(
|
||||
private val containingObjectName: String,
|
||||
private val severity: Severity,
|
||||
private val name: String,
|
||||
private val psiType: KType,
|
||||
private val positioningStrategy: PositioningStrategy,
|
||||
sealed class DiagnosticBuilder(
|
||||
protected val containingObjectName: String,
|
||||
protected val name: String,
|
||||
protected val psiType: KType,
|
||||
protected val positioningStrategy: PositioningStrategy,
|
||||
) {
|
||||
class Regular(
|
||||
containingObjectName: String,
|
||||
private val severity: Severity,
|
||||
name: String,
|
||||
psiType: KType,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticBuilder(containingObjectName, name, psiType, positioningStrategy) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun build(): RegularDiagnosticData {
|
||||
return RegularDiagnosticData(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class Deprecation(
|
||||
containingObjectName: String,
|
||||
private val featureForError: LanguageFeature,
|
||||
name: String,
|
||||
psiType: KType,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticBuilder(containingObjectName, name, psiType, positioningStrategy) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun build(): DeprecationDiagnosticData {
|
||||
return DeprecationDiagnosticData(
|
||||
containingObjectName,
|
||||
featureForError,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PrivateForInline
|
||||
val parameters = mutableListOf<DiagnosticParameter>()
|
||||
|
||||
@@ -86,15 +126,7 @@ class DiagnosticBuilder(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun build() = DiagnosticData(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
abstract fun build(): DiagnosticData
|
||||
|
||||
companion object {
|
||||
const val MAX_DIAGNOSTIC_PARAMETER_COUNT = 4
|
||||
|
||||
@@ -55,16 +55,21 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
|
||||
private fun SmartPrinter.printDiagnostic(diagnostic: DiagnosticData) {
|
||||
print("val ${diagnostic.name} by ${diagnostic.getFactoryFunction()}")
|
||||
printTypeArguments(diagnostic.getAllTypeArguments())
|
||||
printPositioningStrategy(diagnostic)
|
||||
printPositioningStrategyAndLanguageFeature(diagnostic)
|
||||
println()
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printPositioningStrategy(diagnostic: DiagnosticData) {
|
||||
print("(")
|
||||
if (!diagnostic.hasDefaultPositioningStrategy()) {
|
||||
print(diagnostic.positioningStrategy.expressionToCreate)
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun SmartPrinter.printPositioningStrategyAndLanguageFeature(diagnostic: DiagnosticData) {
|
||||
val argumentsList = buildList {
|
||||
if (diagnostic is DeprecationDiagnosticData) {
|
||||
add(diagnostic.featureForError.name)
|
||||
}
|
||||
if (!diagnostic.hasDefaultPositioningStrategy()) {
|
||||
add(diagnostic.positioningStrategy.expressionToCreate)
|
||||
}
|
||||
}
|
||||
print(")")
|
||||
print(argumentsList.joinToString(", ", prefix = "(", postfix = ")"))
|
||||
}
|
||||
|
||||
|
||||
@@ -124,14 +129,19 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
|
||||
add(PositioningStrategy.importToAdd)
|
||||
}
|
||||
}
|
||||
for (deprecationDiagnostic in diagnosticList.allDiagnostics.filterIsInstance<DeprecationDiagnosticData>()) {
|
||||
add("org.jetbrains.kotlin.config.LanguageFeature.${deprecationDiagnostic.featureForError.name}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val KType.kClass: KClass<*>
|
||||
get() = classifier as KClass<*>
|
||||
|
||||
private fun DiagnosticData.getFactoryFunction(): String =
|
||||
severity.name.lowercase() + parameters.size
|
||||
private fun DiagnosticData.getFactoryFunction(): String = when (this) {
|
||||
is RegularDiagnosticData -> severity.name.lowercase()
|
||||
is DeprecationDiagnosticData -> "deprecationError"
|
||||
} + parameters.size
|
||||
}
|
||||
|
||||
private inline fun <T> SmartPrinter.printSeparatedWithComma(list: List<T>, printItem: (T) -> Unit) {
|
||||
|
||||
@@ -5,17 +5,35 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import kotlin.reflect.KType
|
||||
|
||||
data class DiagnosticData(
|
||||
val containingObjectName: String,
|
||||
sealed class DiagnosticData {
|
||||
abstract val containingObjectName: String
|
||||
abstract val name: String
|
||||
abstract val psiType: KType
|
||||
abstract val parameters: List<DiagnosticParameter>
|
||||
abstract val positioningStrategy: PositioningStrategy
|
||||
}
|
||||
|
||||
data class RegularDiagnosticData(
|
||||
override val containingObjectName: String,
|
||||
val severity: Severity,
|
||||
val name: String,
|
||||
val psiType: KType,
|
||||
val parameters: List<DiagnosticParameter>,
|
||||
val positioningStrategy: PositioningStrategy,
|
||||
)
|
||||
override val name: String,
|
||||
override val psiType: KType,
|
||||
override val parameters: List<DiagnosticParameter>,
|
||||
override val positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticData()
|
||||
|
||||
data class DeprecationDiagnosticData(
|
||||
override val containingObjectName: String,
|
||||
val featureForError: LanguageFeature,
|
||||
override val name: String,
|
||||
override val psiType: KType,
|
||||
override val parameters: List<DiagnosticParameter>,
|
||||
override val positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticData()
|
||||
|
||||
data class DiagnosticParameter(
|
||||
val name: String,
|
||||
@@ -69,7 +87,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
FUN_MODIFIER,
|
||||
SUSPEND_MODIFIER,
|
||||
FUN_INTERFACE,
|
||||
RESERVED_UNDERSCORE,
|
||||
NAME_IDENTIFIER,
|
||||
QUESTION_MARK_BY_TYPE,
|
||||
ANNOTATION_USE_SITE,
|
||||
ASSIGNMENT_LHS,
|
||||
@@ -77,8 +95,11 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
DATA_MODIFIER,
|
||||
SPREAD_OPERATOR,
|
||||
DECLARATION_WITH_BODY,
|
||||
NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT,
|
||||
INCOMPATIBLE_DECLARATION,
|
||||
ACTUAL_DECLARATION_NAME,
|
||||
UNREACHABLE_CODE,
|
||||
INLINE_PARAMETER_MODIFIER,
|
||||
|
||||
;
|
||||
|
||||
@@ -8,12 +8,18 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.RestrictRetentionForExpressionAnnotations
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.RestrictionOfValReassignmentViaBackingField
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
@@ -56,6 +62,7 @@ import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
@@ -206,8 +213,8 @@ object FirErrors {
|
||||
val DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val DEPRECATED_SINCE_KOTLIN_WITH_DEPRECATED_LEVEL by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val ANNOTATION_ON_SUPERCLASS by error0<KtAnnotationEntry>()
|
||||
val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by error0<PsiElement>()
|
||||
val ANNOTATION_ON_SUPERCLASS by deprecationError0<KtAnnotationEntry>(ProhibitUseSiteTargetAnnotationsOnSuperTypes)
|
||||
val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by deprecationError0<PsiElement>(RestrictRetentionForExpressionAnnotations)
|
||||
val WRONG_ANNOTATION_TARGET by error1<KtAnnotationEntry, String>()
|
||||
val WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET by error2<KtAnnotationEntry, String, String>()
|
||||
val INAPPLICABLE_TARGET_ON_PROPERTY by error1<KtAnnotationEntry, String>()
|
||||
@@ -303,7 +310,7 @@ object FirErrors {
|
||||
val RECURSION_IN_IMPLICIT_TYPES by error0<PsiElement>()
|
||||
val INFERENCE_ERROR by error0<PsiElement>()
|
||||
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0<PsiElement>()
|
||||
val UPPER_BOUND_VIOLATED by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
|
||||
val UPPER_BOUND_VIOLATED by warning2<PsiElement, ConeKotlinType, ConeKotlinType>()
|
||||
val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
|
||||
val TYPE_ARGUMENTS_NOT_ALLOWED by error0<PsiElement>()
|
||||
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2<PsiElement, Int, FirRegularClassSymbol>()
|
||||
@@ -323,8 +330,7 @@ object FirErrors {
|
||||
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0<KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE by error1<KtNamedDeclaration, FirTypeParameterSymbol>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val TYPE_PARAMETER_AS_REIFIED by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING by warning1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by deprecationError1<PsiElement, FirTypeParameterSymbol>(ProhibitNonReifiedArraysAsReifiedTypeArguments)
|
||||
val REIFIED_TYPE_FORBIDDEN_SUBSTITUTION by error1<PsiElement, ConeKotlinType>()
|
||||
val FINAL_UPPER_BOUND by warning1<KtTypeReference, ConeKotlinType>()
|
||||
val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error0<KtTypeReference>()
|
||||
@@ -344,7 +350,7 @@ object FirErrors {
|
||||
val DYNAMIC_UPPER_BOUND by error0<KtTypeReference>()
|
||||
val INCOMPATIBLE_TYPES by error2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val INCOMPATIBLE_TYPES_WARNING by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val TYPE_VARIANCE_CONFLICT by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val TYPE_VARIANCE_CONFLICT by warning4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val SMARTCAST_IMPOSSIBLE by error3<KtExpression, ConeKotlinType, FirExpression, String>()
|
||||
|
||||
@@ -372,8 +378,7 @@ object FirErrors {
|
||||
val CONFLICTING_INHERITED_MEMBERS by error1<KtClassOrObject, List<FirCallableSymbol<*>>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING by warning2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by deprecationError2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(ProhibitInvisibleAbstractMethodsInSuperclasses, SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClassSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val OVERRIDING_FINAL_MEMBER_BY_DELEGATION by error2<KtClassOrObject, FirCallableSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
@@ -492,8 +497,7 @@ object FirErrors {
|
||||
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirEnumEntrySymbol>()
|
||||
val UNINITIALIZED_ENUM_COMPANION by error1<KtSimpleNameExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>()
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by warning1<KtExpression, FirBackingFieldSymbol>()
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR by error1<KtExpression, FirBackingFieldSymbol>()
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField)
|
||||
val CAPTURED_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
|
||||
val CAPTURED_MEMBER_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
|
||||
val SETTER_PROJECTED_OUT by error1<KtBinaryExpression, FirPropertySymbol>(SourceElementPositioningStrategies.ASSIGNMENT_LHS)
|
||||
@@ -502,6 +506,7 @@ object FirErrors {
|
||||
val WRONG_IMPLIES_CONDITION by warning0<PsiElement>()
|
||||
val VARIABLE_WITH_NO_TYPE_NO_INITIALIZER by error0<KtVariableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INITIALIZATION_BEFORE_DECLARATION by error1<KtExpression, FirBasedSymbol<*>>()
|
||||
val UNREACHABLE_CODE by warning2<KtElement, Set<FirSourceElement>, Set<FirSourceElement>>(SourceElementPositioningStrategies.UNREACHABLE_CODE)
|
||||
|
||||
// Nullability
|
||||
val UNSAFE_CALL by error2<PsiElement, ConeKotlinType, FirExpression?>(SourceElementPositioningStrategies.DOT_BY_QUALIFIED)
|
||||
@@ -552,8 +557,11 @@ object FirErrors {
|
||||
val DELEGATE_SPECIAL_FUNCTION_AMBIGUITY by error2<KtExpression, String, Collection<FirBasedSymbol<*>>>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE by error2<KtExpression, String, Collection<FirBasedSymbol<*>>>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH by error3<KtExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val UNDERSCORE_IS_RESERVED by error0<KtElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<KtElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_IS_RESERVED by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER by warning0<KtNameReferenceExpression>()
|
||||
val INVALID_CHARACTERS by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val DANGEROUS_CHARACTERS by warning1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val EQUALITY_NOT_APPLICABLE by error3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val EQUALITY_NOT_APPLICABLE_WARNING by warning3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val INCOMPATIBLE_ENUM_COMPARISON_ERROR by error2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
@@ -590,6 +598,9 @@ object FirErrors {
|
||||
// Inline
|
||||
val USAGE_IS_NOT_INLINABLE by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val NON_LOCAL_RETURN_NOT_ALLOWED by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val NOT_YET_SUPPORTED_IN_INLINE by error1<KtDeclaration, String>(SourceElementPositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
|
||||
val NOTHING_TO_INLINE by warning0<KtDeclaration>(SourceElementPositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
|
||||
val NULLABLE_INLINE_PARAMETER by error2<KtDeclaration, FirValueParameterSymbol, FirBasedSymbol<*>>()
|
||||
val RECURSION_IN_INLINE by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
@@ -597,6 +608,15 @@ object FirErrors {
|
||||
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val SUPER_CALL_FROM_PUBLIC_INLINE by warning1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val DECLARATION_CANT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val OVERRIDE_BY_INLINE by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val NON_INTERNAL_PUBLISHED_API by error0<KtElement>()
|
||||
val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2<KtElement, FirExpression, FirValueParameterSymbol>()
|
||||
val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error0<KtElement>(SourceElementPositioningStrategies.REIFIED_MODIFIER)
|
||||
val INLINE_PROPERTY_WITH_BACKING_FIELD by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val ILLEGAL_INLINE_PARAMETER_MODIFIER by error0<KtElement>(SourceElementPositioningStrategies.INLINE_PARAMETER_MODIFIER)
|
||||
val INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED by error0<KtParameter>()
|
||||
val REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE by warning0<KtElement>(SourceElementPositioningStrategies.SUSPEND_MODIFIER)
|
||||
|
||||
// Imports
|
||||
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
|
||||
@@ -605,4 +625,13 @@ object FirErrors {
|
||||
val CONFLICTING_IMPORT by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
|
||||
val OPERATOR_RENAMED_ON_IMPORT by error0<KtImportDirective>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
|
||||
|
||||
// Suspend errors
|
||||
val ILLEGAL_SUSPEND_FUNCTION_CALL by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val ILLEGAL_SUSPEND_PROPERTY_ACCESS by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val NON_LOCAL_SUSPENSION_POINT by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val RETURN_FOR_BUILT_IN_SUSPEND by error0<KtReturnExpression>()
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnonymousFunctionParametersChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirReservedUnderscoreDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirAnonymousFunctionSyntaxChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDelegationInInterfaceSyntaxChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirFunctionTypeParametersSyntaxChecker
|
||||
@@ -30,7 +29,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirInfixFunctionDeclarationChecker,
|
||||
FirExposedVisibilityDeclarationChecker,
|
||||
FirCyclicTypeBoundsChecker,
|
||||
FirExpectActualDeclarationChecker
|
||||
FirExpectActualDeclarationChecker,
|
||||
FirInvalidAndDangerousCharactersChecker
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
@@ -56,6 +56,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirPropertyTypeParametersChecker,
|
||||
FirInitializerTypeMismatchChecker,
|
||||
FirDelegatedPropertyChecker,
|
||||
FirInlinePropertyChecker,
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker>
|
||||
@@ -129,6 +130,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
|
||||
get() = setOf(
|
||||
FirAnnotationChecker,
|
||||
FirPublishedApiChecker,
|
||||
)
|
||||
|
||||
override val typeAliasCheckers: Set<FirTypeAliasChecker>
|
||||
|
||||
@@ -16,7 +16,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
|
||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||
get() = setOf(
|
||||
FirReservedUnderscoreExpressionChecker,
|
||||
FirUnderscoreChecker,
|
||||
FirExpressionAnnotationChecker,
|
||||
FirDeprecationChecker
|
||||
)
|
||||
@@ -41,7 +41,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirSealedClassConstructorCallChecker,
|
||||
FirUninitializedEnumChecker,
|
||||
FirFunInterfaceConstructorReferenceChecker,
|
||||
FirReifiedChecker
|
||||
FirReifiedChecker,
|
||||
FirSuspendCallChecker,
|
||||
)
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||
|
||||
@@ -30,6 +30,7 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() {
|
||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
||||
get() = setOf(
|
||||
UnusedChecker,
|
||||
UnreachableCodeChecker,
|
||||
)
|
||||
|
||||
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
|
||||
fun checkUnderscoreDiagnostics(
|
||||
source: FirSourceElement?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isExpression: Boolean
|
||||
) {
|
||||
if (source != null && source.kind !is FirFakeSourceElementKind) {
|
||||
with(SourceNavigator.forSource(source)) {
|
||||
if (source.getRawIdentifier()?.isUnderscore == true) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val CharSequence.isUnderscore: Boolean
|
||||
get() = all { it == '_' }
|
||||
@@ -6,15 +6,22 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.getAncestors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.nameIdentifier
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtTypeProjectionElementType
|
||||
|
||||
/**
|
||||
* Service to answer source-related questions in generic fashion.
|
||||
@@ -26,17 +33,27 @@ interface SourceNavigator {
|
||||
|
||||
fun FirTypeRef.isInTypeConstraint(): Boolean
|
||||
|
||||
fun FirSourceElement.getRawIdentifier(): String?
|
||||
|
||||
fun FirDeclaration.getRawName(): String?
|
||||
|
||||
fun FirValueParameterSymbol.isCatchElementParameter(): Boolean
|
||||
|
||||
companion object {
|
||||
|
||||
private val lightTreeInstance = LightTreeSourceNavigator()
|
||||
|
||||
fun forElement(e: FirElement): SourceNavigator = when (e.source) {
|
||||
fun forElement(e: FirElement): SourceNavigator = forSource(e.source)
|
||||
|
||||
fun forSource(e: FirSourceElement?): SourceNavigator = when (e) {
|
||||
is FirLightSourceElement -> lightTreeInstance
|
||||
is FirPsiSourceElement -> PsiSourceNavigator
|
||||
null -> lightTreeInstance //shouldn't matter
|
||||
}
|
||||
|
||||
inline fun <R> FirElement.withNavigator(block: SourceNavigator.() -> R): R = with(forElement(this), block)
|
||||
inline fun <R> FirElement.withNavigator(block: SourceNavigator.() -> R): R = with(forSource(this.source), block)
|
||||
|
||||
inline fun <R> FirSourceElement.withNavigator(block: SourceNavigator.() -> R): R = with(forSource(this), block)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,16 +72,61 @@ open class LightTreeSourceNavigator : SourceNavigator {
|
||||
.find { it.tokenType == KtNodeTypes.TYPE_CONSTRAINT || it.tokenType == KtNodeTypes.TYPE_PARAMETER }
|
||||
?.tokenType == KtNodeTypes.TYPE_CONSTRAINT
|
||||
}
|
||||
|
||||
override fun FirSourceElement.getRawIdentifier(): String? {
|
||||
val tokenType = elementType
|
||||
return if (tokenType is KtNameReferenceExpressionElementType || tokenType == KtTokens.IDENTIFIER) {
|
||||
lighterASTNode.toString()
|
||||
} else if (tokenType is KtTypeProjectionElementType) {
|
||||
lighterASTNode.getChildren(treeStructure).last().toString()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun FirDeclaration.getRawName(): String? {
|
||||
return source?.let { it.treeStructure.nameIdentifier(it.lighterASTNode)?.toString() }
|
||||
}
|
||||
|
||||
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||
val localSource = source ?: return false
|
||||
var parent = localSource.treeStructure.getParent(localSource.lighterASTNode)
|
||||
parent?.let { parent = localSource.treeStructure.getParent(it) }
|
||||
return parent?.tokenType == KtNodeTypes.CATCH
|
||||
}
|
||||
}
|
||||
|
||||
//by default psi tree can reuse light tree manipulations
|
||||
object PsiSourceNavigator : LightTreeSourceNavigator() {
|
||||
|
||||
//Swallows incorrect casts!!!
|
||||
private inline fun <reified P : PsiElement> FirElement.psi(): P? {
|
||||
val psi = (source as? FirPsiSourceElement)?.psi
|
||||
private inline fun <reified P : PsiElement> FirElement.psi(): P? = source?.psi()
|
||||
|
||||
private inline fun <reified P : PsiElement> FirSourceElement.psi(): P? {
|
||||
val psi = (this as? FirPsiSourceElement)?.psi
|
||||
return psi as? P
|
||||
}
|
||||
|
||||
override fun FirTypeRef.isInConstructorCallee(): Boolean = psi<KtTypeReference>()?.parent is KtConstructorCalleeExpression
|
||||
|
||||
override fun FirSourceElement.getRawIdentifier(): String? {
|
||||
val psi = psi<PsiElement>()
|
||||
return if (psi is KtNameReferenceExpression) {
|
||||
psi.getReferencedNameElement().node.text
|
||||
} else if (psi is KtTypeProjection) {
|
||||
psi.typeReference?.typeElement?.text
|
||||
} else if (psi is LeafPsiElement && psi.elementType == KtTokens.IDENTIFIER) {
|
||||
psi.text
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun FirDeclaration.getRawName(): String? {
|
||||
return (this.psi() as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||
}
|
||||
|
||||
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||
return source?.psi<PsiElement>()?.parent?.parent is KtCatchClause
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,15 @@ abstract class CheckerContext {
|
||||
|
||||
abstract fun dropDeclaration()
|
||||
|
||||
fun <T> withDeclaration(declaration: FirDeclaration, f: (CheckerContext) -> T): T {
|
||||
val newContext = addDeclaration(declaration)
|
||||
try {
|
||||
return f(newContext)
|
||||
} finally {
|
||||
newContext.dropDeclaration()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): CheckerContext
|
||||
|
||||
abstract fun dropQualifiedAccessOrAnnotationCall()
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.containingClassAttr
|
||||
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
@@ -207,7 +207,7 @@ internal fun FirRegularClassSymbol.isInlineOrValueClass(): Boolean {
|
||||
internal val FirDeclaration.isEnumEntryInitializer: Boolean
|
||||
get() {
|
||||
if (this !is FirConstructor || !this.isPrimary) return false
|
||||
return (containingClassAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.classKind == ClassKind.ENUM_ENTRY
|
||||
return (containingClassForStaticMemberAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.classKind == ClassKind.ENUM_ENTRY
|
||||
}
|
||||
|
||||
// contract: returns(true) implies (this is FirMemberDeclaration<*>)
|
||||
|
||||
@@ -10,38 +10,50 @@ import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isInlineOnly
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.util.checkChildrenWithCustomVisitor
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembers
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isMarkedNullable
|
||||
import org.jetbrains.kotlin.fir.types.isNullable
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.isInline) return
|
||||
if (!declaration.isInline) {
|
||||
checkParametersInNotInline(declaration, context, reporter)
|
||||
return
|
||||
}
|
||||
// local inline functions are prohibited
|
||||
if (declaration.isLocalMember) return
|
||||
if (declaration.isLocalMember) {
|
||||
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context)
|
||||
return
|
||||
}
|
||||
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
|
||||
|
||||
val effectiveVisibility = declaration.effectiveVisibility
|
||||
checkInlineFunctionBody(declaration, effectiveVisibility, context, reporter)
|
||||
withSuppressedDiagnostics(declaration, context) { ctx ->
|
||||
checkInlineFunctionBody(declaration, effectiveVisibility, ctx, reporter)
|
||||
checkCallableDeclaration(declaration, ctx, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkInlineFunctionBody(
|
||||
@@ -64,7 +76,9 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
context.session,
|
||||
reporter
|
||||
)
|
||||
body.checkChildrenWithCustomVisitor(context, visitor)
|
||||
context.withDeclaration(function) {
|
||||
body.checkChildrenWithCustomVisitor(it, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor(
|
||||
@@ -102,6 +116,22 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
checkQualifiedAccess(variableAssignment, setterSymbol, data)
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
||||
if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) {
|
||||
reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data)
|
||||
} else {
|
||||
super.visitRegularClass(regularClass, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) {
|
||||
if (data.containingDeclarations.lastOrNull() === inlineFunction) {
|
||||
reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data)
|
||||
} else {
|
||||
super.visitSimpleFunction(simpleFunction, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReceiversOfQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
targetSymbol: FirBasedSymbol<*>?,
|
||||
@@ -310,4 +340,157 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
return containingClassVisibility == Visibilities.Private || containingClassVisibility == Visibilities.PrivateToThis
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkParameters(
|
||||
function: FirSimpleFunction,
|
||||
overriddenSymbols: List<FirCallableSymbol<out FirCallableDeclaration>>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
for (param in function.valueParameters) {
|
||||
val coneType = param.returnTypeRef.coneType
|
||||
val isFunctionalType = coneType.isFunctionalType(context.session)
|
||||
val isSuspendFunctionalType = coneType.isSuspendFunctionType(context.session)
|
||||
val defaultValue = param.defaultValue
|
||||
|
||||
if (!(isFunctionalType || isSuspendFunctionalType) && (param.isNoinline || param.isCrossinline)) {
|
||||
reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context)
|
||||
}
|
||||
|
||||
if (param.isNoinline) continue
|
||||
|
||||
if (function.isSuspend && defaultValue != null && isSuspendFunctionalType) {
|
||||
reporter.reportOn(
|
||||
param.source,
|
||||
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
|
||||
"Suspend functional parameters with default values",
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
if (isSuspendFunctionalType && !param.isCrossinline) {
|
||||
if (function.isSuspend) {
|
||||
reporter.reportOn(param.returnTypeRef.source, FirErrors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, context)
|
||||
} else {
|
||||
reporter.reportOn(param.source, FirErrors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (coneType.isNullable && isFunctionalType) {
|
||||
reporter.reportOn(
|
||||
param.source,
|
||||
FirErrors.NULLABLE_INLINE_PARAMETER,
|
||||
param.symbol,
|
||||
function.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
if (isFunctionalType && defaultValue != null && !isInlinableDefaultValue(defaultValue)) {
|
||||
reporter.reportOn(
|
||||
defaultValue.source,
|
||||
FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE,
|
||||
defaultValue,
|
||||
param.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (overriddenSymbols.isNotEmpty()) {
|
||||
for (param in function.typeParameters) {
|
||||
if (param.isReified) {
|
||||
reporter.reportOn(param.source, FirErrors.REIFIED_TYPE_PARAMETER_IN_OVERRIDE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for inherited default values
|
||||
val paramsWithDefaults = overriddenSymbols.flatMap {
|
||||
if (it !is FirFunctionSymbol<*>) return@flatMap emptyList<Int>()
|
||||
it.valueParameterSymbols.mapIndexedNotNull { idx, param ->
|
||||
idx.takeIf { param.hasDefaultValue }
|
||||
}
|
||||
}.toSet()
|
||||
function.valueParameters.forEachIndexed { idx, param ->
|
||||
if (param.defaultValue == null && paramsWithDefaults.contains(idx)) {
|
||||
reporter.reportOn(
|
||||
param.source,
|
||||
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
|
||||
"Functional parameters with inherited default values",
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (param in function.valueParameters) {
|
||||
if (param.isNoinline || param.isCrossinline) {
|
||||
reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCallableDeclaration.getOverriddenSymbols(context: CheckerContext): List<FirCallableSymbol<out FirCallableDeclaration>> {
|
||||
if (!this.isOverride) return emptyList()
|
||||
val classSymbol = this.containingClass()?.toSymbol(context.session) as? FirClassSymbol<*> ?: return emptyList()
|
||||
val scope = classSymbol.unsubstitutedScope(context)
|
||||
//this call is needed because AbstractFirUseSiteMemberScope collect overrides in it only,
|
||||
//and not in processDirectOverriddenFunctionsWithBaseScope
|
||||
scope.processFunctionsByName(this.symbol.name) { }
|
||||
return scope.getDirectOverriddenMembers(this.symbol, true)
|
||||
}
|
||||
|
||||
private fun checkNothingToInline(function: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (function.isExpect || function.isSuspend) return
|
||||
if (function.typeParameters.any { it.symbol.isReified }) return
|
||||
val hasInlinableParameters =
|
||||
function.valueParameters.any { param ->
|
||||
val type = param.returnTypeRef.coneType
|
||||
!param.isNoinline && !type.isNullable
|
||||
&& (type.isFunctionalType(context.session) || type.isSuspendFunctionType(context.session))
|
||||
}
|
||||
if (hasInlinableParameters) return
|
||||
if (function.isInlineOnly()) return
|
||||
|
||||
reporter.reportOn(function.source, FirErrors.NOTHING_TO_INLINE, context)
|
||||
}
|
||||
|
||||
private fun checkCanBeInlined(
|
||||
declaration: FirCallableDeclaration,
|
||||
effectiveVisibility: EffectiveVisibility,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
): Boolean {
|
||||
if (declaration.containingClass() == null) return true
|
||||
if (effectiveVisibility == EffectiveVisibility.PrivateInClass) return true
|
||||
|
||||
if (!declaration.isFinal) {
|
||||
reporter.reportOn(declaration.source, FirErrors.DECLARATION_CANT_BE_INLINED, context)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isInlinableDefaultValue(expression: FirExpression): Boolean =
|
||||
expression is FirCallableReferenceAccess ||
|
||||
expression is FirFunctionCall ||
|
||||
expression is FirLambdaArgumentExpression ||
|
||||
expression is FirAnonymousFunctionExpression ||
|
||||
(expression is FirConstExpression<*> && expression.value == null) //this will be reported separately
|
||||
|
||||
internal fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirPropertyAccessor) return
|
||||
val overriddenSymbols = declaration.getOverriddenSymbols(context)
|
||||
if (declaration is FirSimpleFunction) {
|
||||
checkParameters(declaration, overriddenSymbols, context, reporter)
|
||||
checkNothingToInline(declaration, context, reporter)
|
||||
}
|
||||
val canBeInlined = checkCanBeInlined(declaration, declaration.effectiveVisibility, context, reporter)
|
||||
|
||||
if (canBeInlined && overriddenSymbols.isNotEmpty()) {
|
||||
reporter.reportOn(declaration.source, FirErrors.OVERRIDE_BY_INLINE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
|
||||
object FirInlinePropertyChecker : FirPropertyChecker() {
|
||||
|
||||
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration.getter?.isInline != true && declaration.setter?.isInline != true) return
|
||||
|
||||
FirInlineDeclarationChecker.checkCallableDeclaration(declaration, context, reporter)
|
||||
|
||||
if (declaration.hasBackingField || declaration.delegate != null) {
|
||||
reporter.reportOn(declaration.source, FirErrors.INLINE_PROPERTY_WITH_BACKING_FIELD, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object FirInvalidAndDangerousCharactersChecker : FirBasicDeclarationChecker() {
|
||||
// See The Java Virtual Machine Specification, section 4.7.9.1 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.9.1
|
||||
private val INVALID_CHARS = setOf('.', ';', '[', ']', '/', '<', '>', ':', '\\')
|
||||
|
||||
// These characters can cause problems on Windows. '?*"|' are not allowed in file names, and % leads to unexpected env var expansion.
|
||||
private val DANGEROUS_CHARS = setOf('?', '*', '"', '|', '%')
|
||||
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = declaration.source
|
||||
when (declaration) {
|
||||
is FirRegularClass -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
is FirSimpleFunction -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
is FirTypeParameter -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
is FirProperty -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
is FirTypeAlias -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
is FirValueParameter -> checkNameAndReport(declaration.name, source, context, reporter)
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkNameAndReport(name: Name, source: FirSourceElement?, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (source != null &&
|
||||
source.kind !is FirFakeSourceElementKind &&
|
||||
!name.isSpecial
|
||||
) {
|
||||
val nameString = name.asString()
|
||||
if (nameString.any { it in INVALID_CHARS }) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.INVALID_CHARACTERS,
|
||||
"contains illegal characters: ${INVALID_CHARS.intersect(nameString.toSet()).joinToString("")}",
|
||||
context
|
||||
)
|
||||
} else if (nameString.any { it in DANGEROUS_CHARS }) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.DANGEROUS_CHARACTERS,
|
||||
DANGEROUS_CHARS.intersect(nameString.toSet()).joinToString(""),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_ME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
@@ -25,7 +24,6 @@ import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembers
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||
@@ -112,11 +110,7 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
}
|
||||
if (!canHaveAbstractDeclarations && invisibleSymbols.isNotEmpty()) {
|
||||
val invisible = invisibleSymbols.first()
|
||||
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses)) {
|
||||
reporter.reportOn(source, INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER, classSymbol, invisible, context)
|
||||
} else {
|
||||
reporter.reportOn(source, INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING, classSymbol, invisible, context)
|
||||
}
|
||||
reporter.reportOn(source, INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER, classSymbol, invisible, context)
|
||||
}
|
||||
|
||||
manyImplementationsDelegationSymbols.firstOrNull()?.let {
|
||||
|
||||
@@ -51,7 +51,7 @@ private fun checkOuterClassArgumentsRequired(
|
||||
for (index in typeArguments.size until typeParameters.size) {
|
||||
val typeParameter = typeParameters[index]
|
||||
if (!isValidTypeParameterFromOuterClass(typeParameter, declaration, context.session)) {
|
||||
val outerClass = typeParameter.containingDeclarationSymbol as FirRegularClassSymbol
|
||||
val outerClass = typeParameter.containingDeclarationSymbol as? FirRegularClassSymbol ?: break
|
||||
reporter.reportOn(typeRef.source, FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED, outerClass, context)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ object FirOverrideChecker : FirClassChecker() {
|
||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
if (overriddenSymbols.isEmpty()) return
|
||||
val visibilities = overriddenSymbols.map {
|
||||
it to it.visibility
|
||||
}.sortedBy { pair ->
|
||||
@@ -124,17 +125,33 @@ object FirOverrideChecker : FirClassChecker() {
|
||||
Visibilities.compare(visibility, pair.second) ?: Int.MIN_VALUE
|
||||
}
|
||||
|
||||
for ((overridden, overriddenVisibility) in visibilities) {
|
||||
val compare = Visibilities.compare(visibility, overriddenVisibility)
|
||||
if (compare == null) {
|
||||
reporter.reportCannotChangeAccessPrivilege(this, overridden, context)
|
||||
return
|
||||
} else if (compare < 0) {
|
||||
reporter.reportCannotWeakenAccessPrivilege(this, overridden, context)
|
||||
return
|
||||
if (this is FirPropertySymbol) {
|
||||
getterSymbol?.checkVisibility(
|
||||
containingClass,
|
||||
reporter,
|
||||
overriddenSymbols.map { (it as FirPropertySymbol).getterSymbol ?: it },
|
||||
context
|
||||
)
|
||||
setterSymbol?.checkVisibility(
|
||||
containingClass,
|
||||
reporter,
|
||||
overriddenSymbols.mapNotNull { (it as FirPropertySymbol).setterSymbol },
|
||||
context
|
||||
)
|
||||
} else {
|
||||
for ((overridden, overriddenVisibility) in visibilities) {
|
||||
val compare = Visibilities.compare(visibility, overriddenVisibility)
|
||||
if (compare == null) {
|
||||
reporter.reportCannotChangeAccessPrivilege(this, overridden, context)
|
||||
break
|
||||
} else if (compare < 0) {
|
||||
reporter.reportCannotWeakenAccessPrivilege(this, overridden, context)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this is FirPropertyAccessorSymbol) return
|
||||
val file = context.findClosest<FirFile>() ?: return
|
||||
val containingDeclarations = context.containingDeclarations + containingClass
|
||||
val visibilityChecker = context.session.visibilityChecker
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
|
||||
object FirPublishedApiChecker : FirAnnotatedDeclarationChecker() {
|
||||
override fun check(declaration: FirAnnotatedDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration !is FirMemberDeclaration) return
|
||||
if (declaration.visibility == Visibilities.Internal) return
|
||||
val annotation = declaration.getAnnotationByFqName(StandardNames.FqNames.publishedApi) ?: return
|
||||
reporter.reportOn(annotation.source, FirErrors.NON_INTERNAL_PUBLISHED_API, context)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkUnderscoreDiagnostics
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isUnderscore
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||
|
||||
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (
|
||||
declaration is FirRegularClass ||
|
||||
declaration is FirTypeParameter ||
|
||||
declaration is FirProperty ||
|
||||
declaration is FirTypeAlias
|
||||
) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
} else if (declaration is FirFunction) {
|
||||
if (declaration is FirSimpleFunction) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
}
|
||||
|
||||
val isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
|
||||
for (parameter in declaration.valueParameters) {
|
||||
reportIfUnderscore(
|
||||
parameter,
|
||||
context,
|
||||
reporter,
|
||||
isSingleUnderscoreAllowed = isSingleUnderscoreAllowed
|
||||
)
|
||||
}
|
||||
} else if (declaration is FirFile) {
|
||||
for (import in declaration.imports) {
|
||||
checkUnderscoreDiagnostics(import.aliasSource, context, reporter, isExpression = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
declaration: FirDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false
|
||||
) {
|
||||
val declarationSource = declaration.source
|
||||
if (declarationSource != null && declarationSource.kind !is FirFakeSourceElementKind) {
|
||||
with(SourceNavigator.forElement(declaration)) {
|
||||
val rawName = declaration.getRawName()
|
||||
if (rawName?.isUnderscore == true && !(isSingleUnderscoreAllowed && rawName == "_")) {
|
||||
reporter.reportOn(
|
||||
declarationSource,
|
||||
FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val returnOrReceiverTypeRef = when (declaration) {
|
||||
is FirValueParameter -> declaration.returnTypeRef
|
||||
is FirFunction -> declaration.receiverTypeRef
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (returnOrReceiverTypeRef is FirResolvedTypeRef) {
|
||||
val delegatedTypeRef = returnOrReceiverTypeRef.delegatedTypeRef
|
||||
if (delegatedTypeRef is FirUserTypeRef) {
|
||||
for (qualifierPart in delegatedTypeRef.qualifier) {
|
||||
checkUnderscoreDiagnostics(qualifierPart.source, context, reporter, isExpression = true)
|
||||
|
||||
for (typeArgument in qualifierPart.typeArgumentList.typeArguments) {
|
||||
checkUnderscoreDiagnostics(typeArgument.source, context, reporter, isExpression = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory1
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -62,9 +57,7 @@ object FirReifiedChecker : FirQualifiedAccessExpressionChecker() {
|
||||
lateinit var symbol: FirTypeParameterSymbol
|
||||
if (typeArgument is ConeTypeParameterType) {
|
||||
factory = if (isArray) {
|
||||
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments))
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY else
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY.chooseFactory(context)
|
||||
} else {
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
}
|
||||
@@ -82,4 +75,4 @@ object FirReifiedChecker : FirQualifiedAccessExpressionChecker() {
|
||||
private fun ConeKotlinType.cannotBeReified(): Boolean {
|
||||
return this.isNothing || this.isNullableNothing || this is ConeCapturedType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.text
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtDotQualifiedExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
|
||||
|
||||
object FirReservedUnderscoreExpressionChecker : FirBasicExpressionChecker() {
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = expression.source
|
||||
|
||||
if (expression is FirFunctionCall) {
|
||||
val calleeReferenceSource = expression.calleeReference.source
|
||||
if (calleeReferenceSource is FirLightSourceElement && calleeReferenceSource.lighterASTNode.tokenType == KtNodeTypes.OPERATION_REFERENCE) {
|
||||
return
|
||||
}
|
||||
|
||||
reportIfUnderscore(
|
||||
expression.calleeReference.source.text, expression.calleeReference.source, context, reporter,
|
||||
isExpression = true
|
||||
)
|
||||
} else if (expression is FirQualifiedAccess) {
|
||||
if (source is FirPsiSourceElement) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
} else if (source is FirLightSourceElement) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
}
|
||||
} else if (expression is FirGetClassCall) {
|
||||
for (argument in expression.argumentList.arguments) {
|
||||
reportIfUnderscore(argument.source.text, expression.source, context, reporter, isExpression = true)
|
||||
}
|
||||
} else if (expression is FirReturnExpression) {
|
||||
var labelName: String? = null
|
||||
if (source is FirPsiSourceElement) {
|
||||
labelName = (source.psi.parent as? KtLabeledExpression)?.getLabelName()
|
||||
} else if (source is FirLightSourceElement) {
|
||||
val parent = source.treeStructure.getParent(source.lighterASTNode)
|
||||
if (parent != null && parent.tokenType == KtNodeTypes.LABELED_EXPRESSION) {
|
||||
labelName = source.treeStructure.findDescendantByType(parent, KtNodeTypes.LABEL).toString()
|
||||
labelName = labelName.substring(0, labelName.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
reportIfUnderscore(labelName, expression.source, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirPsiSourceElement,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(psi: PsiElement?) {
|
||||
if (psi is KtNameReferenceExpression) {
|
||||
reportIfUnderscore(psi.text, expression.source, context, reporter, isExpression = true)
|
||||
} else if (psi is KtDotQualifiedExpression || psi is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi.firstChild)
|
||||
processQualifiedAccess(psi.lastChild)
|
||||
}
|
||||
}
|
||||
|
||||
val psi = source.psi
|
||||
if (psi.parent !is KtDotQualifiedExpression && psi.parent !is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirLightSourceElement,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(lightSourceElement: LighterASTNode?) {
|
||||
val tokenType = lightSourceElement?.tokenType
|
||||
if (tokenType is KtNameReferenceExpressionElementType) {
|
||||
reportIfUnderscore(lightSourceElement.toString(), expression.source, context, reporter, isExpression = true)
|
||||
} else if (lightSourceElement != null && (tokenType is KtDotQualifiedExpressionElementType || tokenType == KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION)) {
|
||||
val children = lightSourceElement.getChildren(source.treeStructure)
|
||||
processQualifiedAccess(children.first())
|
||||
processQualifiedAccess(children.last())
|
||||
}
|
||||
}
|
||||
|
||||
val astNode = source.lighterASTNode
|
||||
val parent = source.treeStructure.getParent(astNode)
|
||||
if (parent?.tokenType !is KtDotQualifiedExpressionElementType && parent?.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION) {
|
||||
processQualifiedAccess(astNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (
|
||||
declaration is FirClass ||
|
||||
declaration is FirFunction ||
|
||||
declaration is FirTypeParameter ||
|
||||
declaration is FirProperty ||
|
||||
declaration is FirTypeAlias
|
||||
) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
|
||||
if (declaration is FirFunction) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
reportIfUnderscore(
|
||||
parameter,
|
||||
context,
|
||||
reporter,
|
||||
isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (declaration is FirFile) {
|
||||
for (import in declaration.imports) {
|
||||
reportIfUnderscore(import.aliasName?.asString(), import.source, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
declaration: FirDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false
|
||||
) {
|
||||
val source = declaration.source
|
||||
val rawIdentifier = when (source) {
|
||||
is FirPsiSourceElement ->
|
||||
(source.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||
is FirLightSourceElement ->
|
||||
source.treeStructure.nameIdentifier(source.lighterASTNode)?.toString()
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
reportIfUnderscore(rawIdentifier, source, context, reporter, isSingleUnderscoreAllowed)
|
||||
|
||||
val returnOrReceiverTypeRef = when (declaration) {
|
||||
is FirValueParameter -> declaration.returnTypeRef.source
|
||||
is FirFunction -> declaration.receiverTypeRef?.source
|
||||
else -> null
|
||||
}
|
||||
|
||||
val isReportUnderscoreInReturnOrReceiverTypeRef = when (returnOrReceiverTypeRef) {
|
||||
is FirPsiSourceElement -> {
|
||||
val psi = returnOrReceiverTypeRef.psi
|
||||
psi is KtTypeReference && psi.anyDescendantOfType<LeafPsiElement> { isUnderscore(it.text) }
|
||||
}
|
||||
is FirLightSourceElement -> {
|
||||
val lighterASTNode = returnOrReceiverTypeRef.lighterASTNode
|
||||
lighterASTNode.tokenType == KtNodeTypes.TYPE_REFERENCE &&
|
||||
source?.treeStructure?.findFirstDescendant(lighterASTNode)
|
||||
{ it.tokenType == KtNodeTypes.REFERENCE_EXPRESSION && isUnderscore(it.toString()) } != null
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
if (isReportUnderscoreInReturnOrReceiverTypeRef) {
|
||||
reporter.reportOn(returnOrReceiverTypeRef, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
text: CharSequence?,
|
||||
source: FirSourceElement?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false,
|
||||
isExpression: Boolean = false
|
||||
) {
|
||||
if (text == null || isSingleUnderscoreAllowed && text == "_") {
|
||||
return
|
||||
}
|
||||
|
||||
if (isUnderscore(text)) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUnderscore(text: CharSequence) = text.all { it == '_' }
|
||||
@@ -6,14 +6,18 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
|
||||
object FirReturnAllowedChecker : FirReturnExpressionChecker() {
|
||||
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -26,6 +30,25 @@ object FirReturnAllowedChecker : FirReturnExpressionChecker() {
|
||||
reporter.reportOn(source, FirErrors.RETURN_NOT_ALLOWED, context)
|
||||
}
|
||||
|
||||
if (targetSymbol is FirAnonymousFunctionSymbol) {
|
||||
val label = targetSymbol.label
|
||||
if (label?.source?.kind !is FirRealSourceElementKind) {
|
||||
val functionCall = context.qualifiedAccessOrAnnotationCalls.asReversed().find {
|
||||
it is FirFunctionCall &&
|
||||
((it.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId ==
|
||||
FirSuspendCallChecker.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID
|
||||
}
|
||||
if (functionCall is FirFunctionCall &&
|
||||
functionCall.arguments.any {
|
||||
it is FirLambdaArgumentExpression &&
|
||||
(it.expression as? FirAnonymousFunctionExpression)?.anonymousFunction?.symbol == targetSymbol
|
||||
}
|
||||
) {
|
||||
reporter.reportOn(source, FirErrors.RETURN_FOR_BUILT_IN_SUSPEND, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val containingDeclaration = context.containingDeclarations.last()
|
||||
if (containingDeclaration is FirFunction && containingDeclaration.body is FirSingleExpressionBlock) {
|
||||
reporter.reportOn(source, FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY, context)
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_3_FQ_NAME
|
||||
import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
|
||||
|
||||
object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
|
||||
private val RESTRICTS_SUSPENSION_CLASS_ID =
|
||||
ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, Name.identifier("RestrictsSuspension"))
|
||||
|
||||
private val BUILTIN_SUSPEND_NAME = KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME.shortName()
|
||||
|
||||
internal val KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID = CallableId(StandardClassIds.BASE_KOTLIN_PACKAGE, BUILTIN_SUSPEND_NAME)
|
||||
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
|
||||
val symbol = reference.resolvedSymbol as? FirCallableSymbol ?: return
|
||||
if (reference.name == BUILTIN_SUSPEND_NAME ||
|
||||
symbol is FirNamedFunctionSymbol && symbol.name == BUILTIN_SUSPEND_NAME
|
||||
) {
|
||||
checkSuspendModifierForm(expression, reference, symbol, context, reporter)
|
||||
}
|
||||
if (reference is FirResolvedCallableReference) return
|
||||
when (symbol) {
|
||||
is FirNamedFunctionSymbol -> if (!symbol.isSuspend) return
|
||||
is FirPropertySymbol -> if (symbol.callableId.asSingleFqName() != COROUTINE_CONTEXT_1_3_FQ_NAME) return
|
||||
else -> return
|
||||
}
|
||||
val enclosingSuspendFunction = findEnclosingSuspendFunction(context)
|
||||
if (enclosingSuspendFunction == null) {
|
||||
when (symbol) {
|
||||
is FirNamedFunctionSymbol -> reporter.reportOn(expression.source, FirErrors.ILLEGAL_SUSPEND_FUNCTION_CALL, symbol, context)
|
||||
is FirPropertySymbol -> reporter.reportOn(expression.source, FirErrors.ILLEGAL_SUSPEND_PROPERTY_ACCESS, symbol, context)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!checkNonLocalReturnUsage(enclosingSuspendFunction, context)) {
|
||||
reporter.reportOn(expression.source, FirErrors.NON_LOCAL_SUSPENSION_POINT, context)
|
||||
}
|
||||
if (!checkRestrictsSuspension(expression, enclosingSuspendFunction, symbol, context)) {
|
||||
reporter.reportOn(expression.source, FirErrors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSuspendModifierForm(
|
||||
expression: FirQualifiedAccessExpression,
|
||||
reference: FirResolvedNamedReference,
|
||||
symbol: FirCallableSymbol<*>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
if (symbol.callableId == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID) {
|
||||
if (reference.name != BUILTIN_SUSPEND_NAME ||
|
||||
expression.explicitReceiver != null ||
|
||||
!expression.hasFormOfSuspendModifierForLambda()
|
||||
) {
|
||||
reporter.reportOn(expression.source, FirErrors.NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND, context)
|
||||
}
|
||||
} else {
|
||||
if (reference.name == BUILTIN_SUSPEND_NAME && expression.hasFormOfSuspendModifierForLambda()) {
|
||||
reporter.reportOn(expression.source, FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirQualifiedAccessExpression.hasFormOfSuspendModifierForLambda(): Boolean {
|
||||
if (this !is FirFunctionCall) return false
|
||||
val reference = this.calleeReference
|
||||
if (reference is FirResolvedCallableReference) return false
|
||||
if (typeArguments.any { it.source != null }) return false
|
||||
if (arguments.singleOrNull() is FirLambdaArgumentExpression) {
|
||||
// No brackets should be in a selector call
|
||||
val callExpressionSource =
|
||||
if (explicitReceiver == null) source
|
||||
else source?.getChild(KtNodeTypes.CALL_EXPRESSION, index = 1, depth = 1)
|
||||
if (callExpressionSource?.getChild(KtNodeTypes.VALUE_ARGUMENT_LIST, depth = 1) == null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (origin == FirFunctionCallOrigin.Infix) {
|
||||
val lastArgument = arguments.lastOrNull()
|
||||
if (lastArgument is FirAnonymousFunctionExpression && source?.getChild(KtNodeTypes.PARENTHESIZED, depth = 1) == null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun findEnclosingSuspendFunction(context: CheckerContext): FirFunction? {
|
||||
return context.containingDeclarations.lastOrNull {
|
||||
when (it) {
|
||||
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendFunctionType(context.session)
|
||||
is FirSimpleFunction -> it.isSuspend
|
||||
else -> false
|
||||
}
|
||||
} as? FirFunction
|
||||
}
|
||||
|
||||
private fun checkNonLocalReturnUsage(enclosingSuspendFunction: FirFunction, context: CheckerContext): Boolean {
|
||||
val containingFunction = context.containingDeclarations.lastIsInstanceOrNull<FirFunction>() ?: return false
|
||||
return if (containingFunction is FirAnonymousFunction && enclosingSuspendFunction !== containingFunction) {
|
||||
containingFunction.inlineStatus.returnAllowed
|
||||
} else {
|
||||
enclosingSuspendFunction === containingFunction
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRestrictsSuspension(
|
||||
expression: FirQualifiedAccessExpression,
|
||||
enclosingSuspendFunction: FirFunction,
|
||||
calledDeclarationSymbol: FirCallableSymbol<*>,
|
||||
context: CheckerContext
|
||||
): Boolean {
|
||||
val session = context.session
|
||||
val enclosingSuspendFunctionDispatchReceiverOwner =
|
||||
(enclosingSuspendFunction.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.toFirRegularClass(session)
|
||||
val enclosingSuspendFunctionExtensionReceiverOwner = enclosingSuspendFunction.takeIf { it.receiverTypeRef != null }
|
||||
val dispatchReceiverExpression = expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }
|
||||
val extensionReceiverExpression = expression.extensionReceiver.takeIf { it !is FirNoReceiverExpression }
|
||||
for (receiverExpression in listOfNotNull(dispatchReceiverExpression, extensionReceiverExpression)) {
|
||||
if (!receiverExpression.typeRef.coneType.isRestrictSuspensionReceiver(session)) continue
|
||||
if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionDispatchReceiverOwner)) continue
|
||||
if (sameInstanceOfReceiver(receiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) continue
|
||||
|
||||
return false
|
||||
}
|
||||
if (enclosingSuspendFunctionExtensionReceiverOwner?.receiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) != true) {
|
||||
return true
|
||||
}
|
||||
if (sameInstanceOfReceiver(dispatchReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) {
|
||||
return true
|
||||
}
|
||||
if (sameInstanceOfReceiver(extensionReceiverExpression, enclosingSuspendFunctionExtensionReceiverOwner)) {
|
||||
if (calledDeclarationSymbol.resolvedReceiverTypeRef?.coneType?.isRestrictSuspensionReceiver(session) == true) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isRestrictSuspensionReceiver(session: FirSession): Boolean {
|
||||
when (this) {
|
||||
is ConeClassLikeType -> {
|
||||
val regularClass = fullyExpandedType(session).lookupTag.toFirRegularClass(session) ?: return false
|
||||
if (regularClass.hasAnnotation(RESTRICTS_SUSPENSION_CLASS_ID)) {
|
||||
return true
|
||||
}
|
||||
return regularClass.superTypeRefs.any { it.coneType.isRestrictSuspensionReceiver(session) }
|
||||
}
|
||||
is ConeTypeParameterType -> {
|
||||
return lookupTag.typeParameterSymbol.resolvedBounds.any { it.coneType.isRestrictSuspensionReceiver(session) }
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun sameInstanceOfReceiver(useSiteReceiverExpression: FirExpression?, declarationSiteReceiverOwner: FirDeclaration?): Boolean {
|
||||
if (declarationSiteReceiverOwner == null || useSiteReceiverExpression == null) return false
|
||||
if (useSiteReceiverExpression is FirThisReceiverExpression) {
|
||||
return useSiteReceiverExpression.calleeReference.boundSymbol == declarationSiteReceiverOwner.symbol
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkUnderscoreDiagnostics
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreUsageWithoutBackticks
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
|
||||
|
||||
object FirUnderscoreChecker : FirBasicExpressionChecker() {
|
||||
private val singleUnderscore: Name = Name.identifier("_")
|
||||
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
when (expression) {
|
||||
is FirResolvable -> {
|
||||
checkUnderscoreDiagnostics(expression.calleeReference.source, context, reporter, true)
|
||||
checkResolvedToUnderscoreNamedCatchParameter(expression, context, reporter)
|
||||
}
|
||||
is FirResolvedQualifier -> {
|
||||
for (reservedUnderscoreDiagnostic in expression.nonFatalDiagnostics.filterIsInstance<ConeUnderscoreUsageWithoutBackticks>()) {
|
||||
reporter.reportOn(reservedUnderscoreDiagnostic.source, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkResolvedToUnderscoreNamedCatchParameter(
|
||||
expression: FirResolvable,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val calleeReference = expression.calleeReference
|
||||
val symbol = calleeReference.toResolvedCallableSymbol()
|
||||
with(SourceNavigator.forElement(expression)) {
|
||||
if (symbol is FirValueParameterSymbol && symbol.isCatchElementParameter() && symbol.name == singleUnderscore) {
|
||||
reporter.reportOn(
|
||||
calleeReference.source,
|
||||
FirErrors.RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,13 +35,7 @@ object FirValReassignmentChecker : FirVariableAssignmentChecker() {
|
||||
val closestGetter = context.findClosest<FirPropertyAccessor> { it.isGetter }?.symbol ?: return
|
||||
if (propertySymbol.getterSymbol != closestGetter) return
|
||||
|
||||
backingFieldReference.source?.let {
|
||||
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfValReassignmentViaBackingField)) {
|
||||
reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, propertySymbol, context)
|
||||
} else {
|
||||
reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD, propertySymbol, context)
|
||||
}
|
||||
}
|
||||
reporter.reportOn(backingFieldReference.source, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD, propertySymbol, context)
|
||||
}
|
||||
|
||||
private fun checkValReassignmentOnValueParameter(
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
|
||||
object UnreachableCodeChecker : FirControlFlowChecker() {
|
||||
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||
val nodes = graph.allNodes()
|
||||
val (unreachableNodes, reachableNodes) = nodes.filterNot { it.skipNode() }.partition { it.isDead }
|
||||
if (unreachableNodes.isEmpty()) return
|
||||
val unreachableSources = unreachableNodes.mapNotNull { it.fir.source }.toSet()
|
||||
val reachableSources = reachableNodes.mapNotNull { it.fir.source }.toSet()
|
||||
val unreachableElements = unreachableNodes.map { it.fir }
|
||||
val innerNodes = mutableSetOf<FirElement>()
|
||||
unreachableElements.forEach { it.collectInnerNodes(innerNodes) }
|
||||
//todo cfg is broken in catch and finally blocks, so exclude reporting anything
|
||||
nodes.mapNotNull { it.fir as? FirTryExpression }.distinct().forEach { tryNode ->
|
||||
tryNode.finallyBlock?.collectInnerNodes(innerNodes)
|
||||
tryNode.catches.forEach { it.collectInnerNodes(innerNodes) }
|
||||
}
|
||||
unreachableElements.distinctBy { it.source }.forEach { element ->
|
||||
if (element !in innerNodes) {
|
||||
reporter.reportOn(element.source, FirErrors.UNREACHABLE_CODE, reachableSources, unreachableSources, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ControlFlowGraph.allNodes(acc: MutableList<CFGNode<*>> = mutableListOf()): List<CFGNode<*>> {
|
||||
acc.addAll(this.nodes)
|
||||
subGraphs.forEach { it.allNodes(acc) }
|
||||
return acc
|
||||
}
|
||||
|
||||
private val sourceKindsToSkip = setOf(
|
||||
FirFakeSourceElementKind.ImplicitReturn,
|
||||
FirFakeSourceElementKind.DesugaredForLoop
|
||||
)
|
||||
|
||||
private fun CFGNode<*>.skipNode(): Boolean {
|
||||
val skipType = this is ExitNodeMarker ||
|
||||
this is EnterNodeMarker ||
|
||||
this is StubNode ||
|
||||
this is BinaryOrExitLeftOperandNode ||
|
||||
this is BinaryOrEnterRightOperandNode ||
|
||||
this is BinaryAndExitLeftOperandNode ||
|
||||
this is BinaryAndEnterRightOperandNode ||
|
||||
this is WhenSyntheticElseBranchNode ||
|
||||
this is WhenBranchResultEnterNode ||
|
||||
this is WhenBranchResultExitNode
|
||||
val allowType = this is LoopEnterNode ||
|
||||
this is LoopBlockEnterNode ||
|
||||
this is TryExpressionEnterNode
|
||||
return !allowType && (skipType || sourceKindsToSkip.contains(this.fir.source?.kind))
|
||||
}
|
||||
|
||||
|
||||
private fun FirElement.collectInnerNodes(nodes: MutableSet<FirElement>) {
|
||||
acceptChildren(CollectNodesVisitor(nodes))
|
||||
}
|
||||
|
||||
private class CollectNodesVisitor(private val nodes: MutableSet<FirElement>) : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
nodes.add(element)
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,7 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
|
||||
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
|
||||
val variableSymbol = node.fir.symbol
|
||||
if (node.fir.source == null) return
|
||||
if (variableSymbol.isLoopIterator) return
|
||||
val dataPerNode = data[node] ?: return
|
||||
for (dataPerLabel in dataPerNode.values) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
|
||||
abstract class DiagnosticReporter {
|
||||
abstract fun report(diagnostic: FirDiagnostic?, context: CheckerContext)
|
||||
@@ -75,6 +76,74 @@ fun <A : Any, B : Any, C : Any, D : Any> DiagnosticReporter.reportOn(
|
||||
source?.let { report(factory.on(it, a, b, c, d, positioningStrategy), context) }
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation0,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation1<A>,
|
||||
a: A,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation2<A, B>,
|
||||
a: A,
|
||||
b: B,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any, C : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation3<A, B, C>,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, c, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any, C : Any, D : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation4<A, B, C, D>,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, c, d, context, positioningStrategy)
|
||||
}
|
||||
|
||||
fun <F : AbstractFirDiagnosticFactory> FirDiagnosticFactoryForDeprecation<F>.chooseFactory(context: CheckerContext): F {
|
||||
return if (context.session.languageVersionSettings.supportsFeature(deprecatingFeature)) {
|
||||
errorFactory
|
||||
} else {
|
||||
warningFactory
|
||||
}
|
||||
}
|
||||
|
||||
inline fun withSuppressedDiagnostics(
|
||||
element: FirElement,
|
||||
context: CheckerContext,
|
||||
|
||||
@@ -107,10 +107,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_INHERITANCE_HIERARCHY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DANGEROUS_CHARACTERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_CONFLICT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DECLARATION_CANT_BE_INLINED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERTY_INSIDE_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERTY_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
|
||||
@@ -188,8 +190,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SELECTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_FUNCTION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_PROPERTY_ACCESS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
|
||||
@@ -220,10 +226,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_CLASS_CONS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_CLASS_NOT_FINAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_CLASS_NOT_TOP_LEVEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_PROPERTY_WITH_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_INSIDE_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_CHARACTERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_REFERENCE
|
||||
@@ -242,6 +252,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_LAMBDA_EXPRE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
@@ -256,12 +267,16 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNC
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_EXHAUSTIVE_WHEN_STATEMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_INTERNAL_PUBLISHED_API
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_LOCAL_SUSPENSION_POINT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||
@@ -270,6 +285,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTIO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_FOR_EXPECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_YET_SUPPORTED_IN_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD
|
||||
@@ -278,6 +294,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RETURN_IN_FUNC
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_VALUE_FOR_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_INLINE_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
|
||||
@@ -286,6 +303,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDE_BY_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_CANNOT_BE_IMPORTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
|
||||
@@ -315,6 +333,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_ANNOTATION_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_EXPLICIT_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_OPEN_IN_INTERFACE
|
||||
@@ -325,12 +344,15 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_VISIBILITY_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_IN_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESOLUTION_TO_CLASSIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESULT_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_FOR_BUILT_IN_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH
|
||||
@@ -371,13 +393,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_I
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_VARIANCE_CONFLICT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNDERSCORE_IS_RESERVED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY
|
||||
@@ -386,6 +409,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VAR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_SAFE_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNREACHABLE_CODE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_CALL
|
||||
@@ -414,7 +438,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_LOO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_REASSIGNMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_WITH_SETTER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARARG_OUTSIDE_PARENTHESES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_EXPECTED
|
||||
@@ -806,11 +829,6 @@ class FirDefaultErrorMessages {
|
||||
"Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING,
|
||||
"Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
REIFIED_TYPE_FORBIDDEN_SUBSTITUTION,
|
||||
"Cannot use ''{0}'' as reified type parameter",
|
||||
@@ -919,6 +937,17 @@ class FirDefaultErrorMessages {
|
||||
map.put(INLINE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Inline class cannot implement an interface by delegation")
|
||||
map.put(INLINE_CLASS_CANNOT_EXTEND_CLASSES, "Inline class cannot extend classes")
|
||||
map.put(INLINE_CLASS_CANNOT_BE_RECURSIVE, "Inline class cannot be recursive")
|
||||
map.put(DECLARATION_CANT_BE_INLINED, "'inline' modifier is not allowed on virtual members. Only private or final members can be inlined")
|
||||
map.put(OVERRIDE_BY_INLINE, "Override by an inline function")
|
||||
map.put(REIFIED_TYPE_PARAMETER_IN_OVERRIDE, "Override by a function with reified type parameter")
|
||||
map.put(INLINE_PROPERTY_WITH_BACKING_FIELD, "Inline property cannot have backing field")
|
||||
map.put(NON_INTERNAL_PUBLISHED_API, "@PublishedApi annotation is only applicable for internal declaration")
|
||||
map.put(
|
||||
INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE,
|
||||
"Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported",
|
||||
FIR,
|
||||
DECLARATION_NAME
|
||||
)
|
||||
map.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", TO_STRING)
|
||||
map.put(
|
||||
SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS,
|
||||
@@ -1253,8 +1282,7 @@ class FirDefaultErrorMessages {
|
||||
map.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", VARIABLE_NAME)
|
||||
map.put(UNINITIALIZED_ENUM_COMPANION, "Companion object of enum class ''{0}'' is uninitialized here", SYMBOL)
|
||||
map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME)
|
||||
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Reassignment of read-only property via backing field is deprecated", VARIABLE_NAME)
|
||||
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, "Reassignment of read-only property via backing field", VARIABLE_NAME)
|
||||
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Reassignment of read-only property via backing field", VARIABLE_NAME)
|
||||
map.put(
|
||||
CAPTURED_VAL_INITIALIZATION,
|
||||
"Captured values initialization is forbidden due to possible reassignment",
|
||||
@@ -1279,6 +1307,7 @@ class FirDefaultErrorMessages {
|
||||
)
|
||||
map.put(LEAKED_IN_PLACE_LAMBDA, "Leaked in-place lambda: {2}", SYMBOL)
|
||||
map.put(FirErrors.WRONG_IMPLIES_CONDITION, "Wrong implies condition")
|
||||
map.put(UNREACHABLE_CODE, "Unreachable code", NOT_RENDERED, NOT_RENDERED)
|
||||
|
||||
// Nullability
|
||||
map.put(
|
||||
@@ -1378,6 +1407,28 @@ class FirDefaultErrorMessages {
|
||||
RENDER_TYPE,
|
||||
RENDER_TYPE,
|
||||
)
|
||||
map.put(
|
||||
UNDERSCORE_IS_RESERVED,
|
||||
"Names _, __, ___, ..., are reserved in Kotlin"
|
||||
)
|
||||
map.put(
|
||||
UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
|
||||
"Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
||||
)
|
||||
map.put(
|
||||
RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER,
|
||||
"Referencing to an underscore-named parameter is deprecated. It will be an error in a future release."
|
||||
)
|
||||
map.put(
|
||||
INVALID_CHARACTERS,
|
||||
"Name {0}",
|
||||
STRING
|
||||
)
|
||||
map.put(
|
||||
DANGEROUS_CHARACTERS,
|
||||
"Name contains characters which can cause problems on Windows: {0}",
|
||||
STRING
|
||||
)
|
||||
map.put(
|
||||
EQUALITY_NOT_APPLICABLE,
|
||||
"Operator ''{0}'' cannot be applied to ''{1}'' and ''{2}''",
|
||||
@@ -1453,8 +1504,32 @@ class FirDefaultErrorMessages {
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(NOT_YET_SUPPORTED_IN_INLINE, "{0} are not yet supported in inline functions", STRING)
|
||||
map.put(
|
||||
NOTHING_TO_INLINE,
|
||||
"Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types"
|
||||
)
|
||||
map.put(
|
||||
NULLABLE_INLINE_PARAMETER,
|
||||
"Inline-parameter ''{0}'' of ''{1}'' must not be nullable. Add ''noinline'' modifier to the parameter declaration or make its type not nullable",
|
||||
SYMBOL,
|
||||
SYMBOL
|
||||
)
|
||||
|
||||
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
|
||||
|
||||
map.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier is allowed only for function parameters of an inline function")
|
||||
|
||||
map.put(
|
||||
INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED,
|
||||
"Suspend inline lambda parameters of non-suspend function type are not supported. Add 'noinline' or 'crossinline' modifier."
|
||||
)
|
||||
|
||||
map.put(
|
||||
REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE,
|
||||
"Redundant 'suspend' modifier: lambda parameters of suspend function type uses existing continuation."
|
||||
)
|
||||
|
||||
//imports
|
||||
map.put(
|
||||
CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON,
|
||||
@@ -1474,6 +1549,32 @@ class FirDefaultErrorMessages {
|
||||
)
|
||||
map.put(OPERATOR_RENAMED_ON_IMPORT, "Operator renamed to a different operator on import")
|
||||
|
||||
// Suspend
|
||||
map.put(
|
||||
ILLEGAL_SUSPEND_FUNCTION_CALL,
|
||||
"Suspend function ''{0}'' should be called only from a coroutine or another suspend function",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
ILLEGAL_SUSPEND_PROPERTY_ACCESS,
|
||||
"Suspend property ''{0}'' should be accessed only from a coroutine or suspend function",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(NON_LOCAL_SUSPENSION_POINT, "Suspension functions can be called only within coroutine body")
|
||||
map.put(
|
||||
ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL,
|
||||
"Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope"
|
||||
)
|
||||
map.put(
|
||||
NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND,
|
||||
"''suspend'' function can only be called in a form of modifier of a lambda: suspend { ... }"
|
||||
)
|
||||
map.put(
|
||||
MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND,
|
||||
"Calls having a form of ''suspend {}'' are deprecated because ''suspend'' in the context will have a meaning of a modifier. Add empty argument list to the call: ''suspend() { ... }''"
|
||||
)
|
||||
map.put(RETURN_FOR_BUILT_IN_SUSPEND, "Using implicit label for this lambda is prohibited")
|
||||
|
||||
// Extended checkers group
|
||||
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
|
||||
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
@@ -200,3 +201,41 @@ class FirDiagnosticFactory4<A, B, C, D>(
|
||||
private fun incorrectElement(element: FirSourceElement): Nothing {
|
||||
throw IllegalArgumentException("Unknown element type: ${element::class}")
|
||||
}
|
||||
|
||||
// ------------------------------ factories for deprecation ------------------------------
|
||||
|
||||
sealed class FirDiagnosticFactoryForDeprecation<F : AbstractFirDiagnosticFactory>(
|
||||
val deprecatingFeature: LanguageFeature,
|
||||
val warningFactory: F,
|
||||
val errorFactory: F
|
||||
)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation0(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory0,
|
||||
errorFactory: FirDiagnosticFactory0
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory0>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation1<A>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory1<A>,
|
||||
errorFactory: FirDiagnosticFactory1<A>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory1<A>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation2<A, B>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory2<A, B>,
|
||||
errorFactory: FirDiagnosticFactory2<A, B>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory2<A, B>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation3<A, B, C>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory3<A, B, C>,
|
||||
errorFactory: FirDiagnosticFactory3<A, B, C>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory3<A, B, C>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation4<A, B, C, D>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory4<A, B, C, D>,
|
||||
errorFactory: FirDiagnosticFactory4<A, B, C, D>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory4<A, B, C, D>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KClass
|
||||
@@ -35,6 +36,12 @@ inline fun <reified P : PsiElement, A, B, C> warning3(
|
||||
return DiagnosticFactory3DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B, C, D> warning4(
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DiagnosticFactory4DelegateProvider<A, B, C, D> {
|
||||
return DiagnosticFactory4DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement> error0(
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DiagnosticFactory0DelegateProvider {
|
||||
@@ -65,6 +72,41 @@ inline fun <reified P : PsiElement, A, B, C, D> error4(
|
||||
return DiagnosticFactory4DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement> deprecationError0(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory0DelegateProvider {
|
||||
return DeprecationDiagnosticFactory0DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A> deprecationError1(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory1DelegateProvider<A> {
|
||||
return DeprecationDiagnosticFactory1DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B> deprecationError2(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory2DelegateProvider<A, B> {
|
||||
return DeprecationDiagnosticFactory2DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B, C> deprecationError3(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory3DelegateProvider<A, B, C> {
|
||||
return DeprecationDiagnosticFactory3DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B, C, D> deprecationError4(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D> {
|
||||
return DeprecationDiagnosticFactory4DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
// ------------------------------ Providers ------------------------------
|
||||
|
||||
class DiagnosticFactory0DelegateProvider(
|
||||
@@ -117,6 +159,69 @@ class DiagnosticFactory4DelegateProvider<A, B, C, D>(
|
||||
}
|
||||
}
|
||||
|
||||
private const val WARNING = "_WARNING"
|
||||
private const val ERROR = "_ERROR"
|
||||
|
||||
class DeprecationDiagnosticFactory0DelegateProvider(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation0> {
|
||||
val errorFactory = FirDiagnosticFactory0("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory0("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation0(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory1DelegateProvider<A>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation1<A>> {
|
||||
val errorFactory = FirDiagnosticFactory1<A>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory1<A>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation1(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory2DelegateProvider<A, B>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation2<A, B>> {
|
||||
val errorFactory = FirDiagnosticFactory2<A, B>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory2<A, B>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation2(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory3DelegateProvider<A, B, C>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation3<A, B, C>> {
|
||||
val errorFactory = FirDiagnosticFactory3<A, B, C>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory3<A, B, C>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation3(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation4<A, B, C, D>> {
|
||||
val errorFactory = FirDiagnosticFactory4<A, B, C, D>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory4<A, B, C, D>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation4(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class DummyDelegate<T>(val value: T) : ReadOnlyProperty<Any?, T> {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
|
||||
@@ -54,7 +54,68 @@ class FirDiagnosticFactoryToRendererMap(val name: String) {
|
||||
put(factory, FirDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
|
||||
}
|
||||
|
||||
fun put(factory: FirDiagnosticFactoryForDeprecation0, message: String) {
|
||||
put(factory.errorFactory, SimpleFirDiagnosticRenderer(message))
|
||||
put(factory.warningFactory, SimpleFirDiagnosticRenderer(factory.warningMessage(message)))
|
||||
}
|
||||
|
||||
fun <A> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation1<A>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters1Renderer(message, rendererA))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters1Renderer(factory.warningMessage(message), rendererA))
|
||||
}
|
||||
|
||||
fun <A, B> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation2<A, B>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters2Renderer(message, rendererA, rendererB))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters2Renderer(factory.warningMessage(message), rendererA, rendererB))
|
||||
}
|
||||
|
||||
fun <A, B, C> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation3<A, B, C>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?,
|
||||
rendererC: DiagnosticParameterRenderer<C>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters3Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC))
|
||||
}
|
||||
|
||||
fun <A, B, C, D> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation4<A, B, C, D>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?,
|
||||
rendererC: DiagnosticParameterRenderer<C>?,
|
||||
rendererD: DiagnosticParameterRenderer<D>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters4Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC, rendererD))
|
||||
}
|
||||
|
||||
private fun put(factory: AbstractFirDiagnosticFactory, renderer: FirDiagnosticRenderer) {
|
||||
renderersMap[factory] = renderer
|
||||
}
|
||||
|
||||
private fun FirDiagnosticFactoryForDeprecation<*>.warningMessage(errorMessage: String): String {
|
||||
return buildString {
|
||||
append(errorMessage)
|
||||
append(". This will become an error")
|
||||
val sinceVersion = deprecatingFeature.sinceVersion
|
||||
if (sinceVersion != null) {
|
||||
append(" in Kotlin ")
|
||||
append(sinceVersion.versionString)
|
||||
} else {
|
||||
append(" in a future release")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.cfg.UnreachableCode
|
||||
import org.jetbrains.kotlin.diagnostics.PositioningStrategy
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
abstract class FirPsiPositioningStrategy<in E : PsiElement> : PositioningStrategy<E>(),
|
||||
FirDiagnosticPositioningStrategy<FirPsiSourceElement>
|
||||
|
||||
object FirPsiPositioningStrategies {
|
||||
|
||||
val UNREACHABLE_CODE = object : FirPsiPositioningStrategy<PsiElement>() {
|
||||
|
||||
override fun markFirDiagnostic(element: FirPsiSourceElement, diagnostic: FirDiagnostic): List<TextRange> {
|
||||
//todo it is better to implement arguments extraction in FirDiagnosticFactory, but kotlin struggle with checking types in it atm
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val typed = diagnostic as FirDiagnosticWithParameters2<Set<FirSourceElement>, Set<FirSourceElement>>
|
||||
return UnreachableCode.getUnreachableTextRanges(
|
||||
element.psi as KtElement,
|
||||
typed.a.mapNotNull { it.psi as? KtElement }.toSet(),
|
||||
typed.b.mapNotNull { it.psi as? KtElement }.toSet()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -358,6 +358,9 @@ object LightTreePositioningStrategies {
|
||||
val DATA_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.DATA_KEYWORD))
|
||||
|
||||
val INLINE_PARAMETER_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD))
|
||||
|
||||
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
@@ -708,27 +711,20 @@ object LightTreePositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
val RESERVED_UNDERSCORE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
val NAME_IDENTIFIER: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
if (node.tokenType == KtNodeTypes.RETURN) {
|
||||
val parent = tree.getParent(node)
|
||||
if (parent != null) {
|
||||
val label = tree.findDescendantByType(parent, KtNodeTypes.LABEL)
|
||||
if (label != null) {
|
||||
return markElement(label, startOffset, endOffset - 1, tree, node)
|
||||
}
|
||||
}
|
||||
val nameIdentifier = tree.nameIdentifier(node)
|
||||
if (nameIdentifier != null) {
|
||||
return markElement(nameIdentifier, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType == KtNodeTypes.LABEL_QUALIFIER) {
|
||||
return super.mark(node, startOffset, endOffset - 1, tree)
|
||||
}
|
||||
|
||||
val descendants =
|
||||
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } }
|
||||
if (descendants.isNotEmpty())
|
||||
return descendants.map { markSingleElement(it, it, startOffset, endOffset, tree, node) }
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
@@ -840,6 +836,53 @@ object LightTreePositioningStrategies {
|
||||
private fun lastSymbol(range: TextRange): TextRange =
|
||||
if (range.isEmpty) range else TextRange.create(range.endOffset - 1, range.endOffset)
|
||||
}
|
||||
|
||||
val UNREACHABLE_CODE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun markFirDiagnostic(element: FirSourceElement, diagnostic: FirDiagnostic): List<TextRange> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val typed = diagnostic as FirDiagnosticWithParameters2<Set<FirSourceElement>, Set<FirSourceElement>>
|
||||
with(UnreachableCodeLightTreeHelper(element.treeStructure)) {
|
||||
val reachable = typed.a.map { it.lighterASTNode }.toSet()
|
||||
val unreachable = typed.b.map { it.lighterASTNode }.toSet()
|
||||
if (!element.lighterASTNode.hasChildrenInSet(reachable)) {
|
||||
return super.markFirDiagnostic(element, diagnostic)
|
||||
}
|
||||
|
||||
val nodesToMark = element.lighterASTNode.getLeavesOrReachableChildren(reachable, unreachable)
|
||||
.removeReachableElementsWithMeaninglessSiblings(reachable)
|
||||
|
||||
if (nodesToMark.isEmpty()) {
|
||||
return super.markFirDiagnostic(element, diagnostic)
|
||||
}
|
||||
|
||||
val ranges = nodesToMark.flatMap {
|
||||
markElement(it, element.startOffset, element.endOffset, element.treeStructure, element.lighterASTNode)
|
||||
}
|
||||
|
||||
return ranges.mergeAdjacentTextRanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
val nodeToMark = when (node.tokenType) {
|
||||
KtNodeTypes.CLASS ->
|
||||
tree.findChildByType(node, KtTokens.CLASS_KEYWORD)
|
||||
KtNodeTypes.OBJECT_DECLARATION ->
|
||||
tree.findChildByType(node, KtTokens.OBJECT_KEYWORD)
|
||||
KtNodeTypes.FUN ->
|
||||
tree.inlineModifier(node) ?: tree.findChildByType(node, KtTokens.FUN_KEYWORD)
|
||||
else -> node
|
||||
}
|
||||
return markElement(nodeToMark ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||
@@ -962,6 +1005,9 @@ internal fun FlyweightCapableTreeStructure<LighterASTNode>.modalityModifier(decl
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.overrideModifier(declaration: LighterASTNode): LighterASTNode? =
|
||||
modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) }
|
||||
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.inlineModifier(declaration: LighterASTNode): LighterASTNode? =
|
||||
modifierList(declaration)?.let { findChildByType(it, KtTokens.INLINE_KEYWORD) }
|
||||
|
||||
internal fun FlyweightCapableTreeStructure<LighterASTNode>.typeParametersList(declaration: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(declaration, KtNodeTypes.TYPE_PARAMETER_LIST)
|
||||
|
||||
@@ -1107,6 +1153,29 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.collectDescendantsOfType(
|
||||
return result
|
||||
}
|
||||
|
||||
fun FlyweightCapableTreeStructure<LighterASTNode>.traverseDescendants(
|
||||
node: LighterASTNode,
|
||||
acceptor: (LighterASTNode) -> Boolean
|
||||
) {
|
||||
fun FlyweightCapableTreeStructure<LighterASTNode>.traverse(node: LighterASTNode) {
|
||||
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||
getChildren(node, childrenRef)
|
||||
|
||||
val childrenRefGet = childrenRef.get()
|
||||
if (childrenRefGet != null) {
|
||||
for (child in childrenRefGet) {
|
||||
if (child != null) {
|
||||
if (acceptor(child)) {
|
||||
traverse(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node)
|
||||
}
|
||||
|
||||
fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: TokenSet): LighterASTNode? {
|
||||
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||
getChildren(node, childrenRef)
|
||||
|
||||
@@ -10,12 +10,22 @@ import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.WHITE_SPACE
|
||||
|
||||
open class LightTreePositioningStrategy {
|
||||
interface FirDiagnosticPositioningStrategy<E : FirSourceElement> {
|
||||
fun markFirDiagnostic(element: E, diagnostic: FirDiagnostic): List<TextRange>
|
||||
}
|
||||
|
||||
open class LightTreePositioningStrategy : FirDiagnosticPositioningStrategy<FirSourceElement> {
|
||||
|
||||
override fun markFirDiagnostic(element: FirSourceElement, diagnostic: FirDiagnostic): List<TextRange> {
|
||||
return mark(element.lighterASTNode, element.startOffset, element.endOffset, element.treeStructure)
|
||||
}
|
||||
|
||||
open fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
@@ -78,11 +88,12 @@ private val FILLER_TOKENS = setOf(
|
||||
)
|
||||
|
||||
private fun LighterASTNode.nonFillerFirstChildOrSelf(tree: FlyweightCapableTreeStructure<LighterASTNode>): LighterASTNode =
|
||||
getChildren(tree).firstOrNull { it != null && it.tokenType !in FILLER_TOKENS } ?: this
|
||||
getChildren(tree).firstOrNull { it != null && !it.isFiller() } ?: this
|
||||
|
||||
internal fun LighterASTNode.nonFillerLastChildOrSelf(tree: FlyweightCapableTreeStructure<LighterASTNode>): LighterASTNode =
|
||||
getChildren(tree).lastOrNull { it != null && it.tokenType !in FILLER_TOKENS } ?: this
|
||||
getChildren(tree).lastOrNull { it != null && !it.isFiller() } ?: this
|
||||
|
||||
internal fun LighterASTNode.isFiller() = tokenType in FILLER_TOKENS
|
||||
|
||||
private fun hasSyntaxErrors(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
|
||||
if (node.tokenType == TokenType.ERROR_ELEMENT) return true
|
||||
|
||||
@@ -238,9 +238,9 @@ object SourceElementPositioningStrategies {
|
||||
PositioningStrategies.TYPE_PARAMETERS_LIST
|
||||
)
|
||||
|
||||
val RESERVED_UNDERSCORE = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.RESERVED_UNDERSCORE,
|
||||
PositioningStrategies.RESERVED_UNDERSCORE
|
||||
val NAME_IDENTIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.NAME_IDENTIFIER,
|
||||
PositioningStrategies.NAME_IDENTIFIER
|
||||
)
|
||||
|
||||
val QUESTION_MARK_BY_TYPE = SourceElementPositioningStrategy(
|
||||
@@ -273,7 +273,22 @@ object SourceElementPositioningStrategies {
|
||||
PositioningStrategies.DECLARATION_WITH_BODY
|
||||
)
|
||||
|
||||
val UNREACHABLE_CODE = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.UNREACHABLE_CODE,
|
||||
FirPsiPositioningStrategies.UNREACHABLE_CODE
|
||||
)
|
||||
|
||||
// TODO
|
||||
val ACTUAL_DECLARATION_NAME = DEFAULT
|
||||
val INCOMPATIBLE_DECLARATION = DEFAULT
|
||||
|
||||
val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT,
|
||||
PositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT
|
||||
)
|
||||
|
||||
val INLINE_PARAMETER_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.INLINE_PARAMETER_MODIFIER,
|
||||
PositioningStrategies.INLINE_PARAMETER_MODIFIER
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@ class SourceElementPositioningStrategy(
|
||||
fun markDiagnostic(diagnostic: FirDiagnostic): List<TextRange> {
|
||||
val element = diagnostic.element
|
||||
if (element is FirPsiSourceElement) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return psiStrategy.hackyMark(element.psi)
|
||||
return if (psiStrategy is FirPsiPositioningStrategy<*>) {
|
||||
psiStrategy.markFirDiagnostic(element, diagnostic)
|
||||
} else {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
psiStrategy.hackyMark(element.psi)
|
||||
}
|
||||
}
|
||||
return lightTreeStrategy.mark(element.lighterASTNode, element.startOffset, element.endOffset, element.treeStructure)
|
||||
return lightTreeStrategy.markFirDiagnostic(element, diagnostic)
|
||||
}
|
||||
|
||||
fun isValid(element: FirSourceElement): Boolean {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user