[MERGE] KT: build-1.5.20-dev-7 KT/N: eecc10f9a OLD: e9501e82c

This commit is contained in:
Vasily Levchenko
2021-02-01 16:54:30 +01:00
1477 changed files with 34391 additions and 17631 deletions
Generated
-7
View File
@@ -8,13 +8,6 @@
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
</profile> </profile>
</component> </component>
<component name="GithubSharedProjectSettings">
<option name="branchProtectionPatterns">
<list>
<option value="master" />
</list>
</option>
</component>
<component name="IssueNavigationConfiguration"> <component name="IssueNavigationConfiguration">
<option name="links"> <option name="links">
<list> <list>
+1
View File
@@ -18,6 +18,7 @@ Some handy links:
* [Issue Tracker](https://youtrack.jetbrains.com/issues/KT) * [Issue Tracker](https://youtrack.jetbrains.com/issues/KT)
* [Forum](https://discuss.kotlinlang.org/) * [Forum](https://discuss.kotlinlang.org/)
* [Kotlin Blog](https://blog.jetbrains.com/kotlin/) * [Kotlin Blog](https://blog.jetbrains.com/kotlin/)
* [Subscribe to Kotlin YouTube channel](https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw)
* [Follow Kotlin on Twitter](https://twitter.com/kotlin) * [Follow Kotlin on Twitter](https://twitter.com/kotlin)
* [Public Slack channel](https://slack.kotlinlang.org/) * [Public Slack channel](https://slack.kotlinlang.org/)
* [TeamCity CI build](https://teamcity.jetbrains.com/project.html?tab=projectOverview&projectId=Kotlin) * [TeamCity CI build](https://teamcity.jetbrains.com/project.html?tab=projectOverview&projectId=Kotlin)
@@ -22,12 +22,12 @@ data class BuildLogFinder(
private val isDataContainerBuildLogEnabled: Boolean = false, private val isDataContainerBuildLogEnabled: Boolean = false,
private val isGradleEnabled: Boolean = false, private val isGradleEnabled: Boolean = false,
private val isJsEnabled: Boolean = false, private val isJsEnabled: Boolean = false,
private val isJsIrEnabled: Boolean = false, // TODO rename as it is used for metadata-only test private val isScopeExpansionEnabled: Boolean = false,
private val isScopeExpansionEnabled: Boolean = false private val isKlibEnabled: Boolean = false
) { ) {
companion object { companion object {
private const val JS_LOG = "js-build.log" private const val JS_LOG = "js-build.log"
private const val JS_IR_LOG = "js-ir-build.log" private const val KLIB_LOG = "klib-build.log"
private const val SCOPE_EXPANDING_LOG = "build-with-scope-expansion.log" private const val SCOPE_EXPANDING_LOG = "build-with-scope-expansion.log"
private const val GRADLE_LOG = "gradle-build.log" private const val GRADLE_LOG = "gradle-build.log"
private const val DATA_CONTAINER_LOG = "data-container-version-build.log" private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
@@ -43,7 +43,7 @@ data class BuildLogFinder(
val files = names.filter { File(dir, it).isFile }.toSet() val files = names.filter { File(dir, it).isFile }.toSet()
val matchedName = when { val matchedName = when {
isScopeExpansionEnabled && SCOPE_EXPANDING_LOG in files -> SCOPE_EXPANDING_LOG isScopeExpansionEnabled && SCOPE_EXPANDING_LOG in files -> SCOPE_EXPANDING_LOG
isJsIrEnabled && JS_IR_LOG in files -> JS_IR_LOG isKlibEnabled && KLIB_LOG in files -> KLIB_LOG
isJsEnabled && JS_LOG in files -> JS_LOG isJsEnabled && JS_LOG in files -> JS_LOG
isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG
isJsEnabled && JS_JPS_LOG in files -> JS_JPS_LOG isJsEnabled && JS_JPS_LOG in files -> JS_JPS_LOG
@@ -151,29 +151,35 @@ private fun classFileToString(classFile: File): String {
val traceVisitor = TraceClassVisitor(PrintWriter(out)) val traceVisitor = TraceClassVisitor(PrintWriter(out))
ClassReader(classFile.readBytes()).accept(traceVisitor, 0) ClassReader(classFile.readBytes()).accept(traceVisitor, 0)
val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader ?: return ""
if (!classHeader.metadataVersion.isCompatible()) {
error("Incompatible class ($classHeader): $classFile")
}
val annotationDataEncoded = classHeader?.data when (classHeader.kind) {
if (annotationDataEncoded != null) { KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
ByteArrayInputStream(BitEncoding.decodeBytes(annotationDataEncoded)).use { ByteArrayInputStream(BitEncoding.decodeBytes(classHeader.data!!)).use { input ->
input -> out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}")
out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}") when (classHeader.kind) {
KotlinClassHeader.Kind.FILE_FACADE ->
if (!classHeader.metadataVersion.isCompatible()) { out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
error("Incompatible class ($classHeader): $classFile") KotlinClassHeader.Kind.CLASS ->
} out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ->
when (classHeader.kind) { out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
KotlinClassHeader.Kind.FILE_FACADE -> else -> error(classHeader.kind)
out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}") }
KotlinClassHeader.Kind.CLASS ->
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ->
out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
else -> throw IllegalStateException()
} }
} }
KotlinClassHeader.Kind.MULTIFILE_CLASS -> {
out.write("\n------ multi-file facade data -----\n")
out.write(classHeader.data!!.joinToString("\n"))
}
KotlinClassHeader.Kind.SYNTHETIC_CLASS -> {
// Synthetic class has no metadata, thus there can be no differences in it.
}
KotlinClassHeader.Kind.UNKNOWN -> error("Should not meet unknown classes here: $classFile")
} }
return out.toString() return out.toString()
+6 -7
View File
@@ -74,7 +74,7 @@ val kotlinVersion by extra(
} ?: buildNumber } ?: buildNumber
) )
val kotlinLanguageVersion by extra("1.4") val kotlinLanguageVersion by extra("1.5")
allprojects { allprojects {
group = "org.jetbrains.kotlin" group = "org.jetbrains.kotlin"
@@ -166,13 +166,12 @@ extra["versions.jansi"] = "1.16"
extra["versions.jline"] = "3.3.1" extra["versions.jline"] = "3.3.1"
extra["versions.junit"] = "4.12" extra["versions.junit"] = "4.12"
extra["versions.javaslang"] = "2.0.6" extra["versions.javaslang"] = "2.0.6"
extra["versions.ant"] = "1.8.2" extra["versions.ant"] = "1.10.7"
extra["versions.android"] = "2.3.1" extra["versions.android"] = "2.3.1"
extra["versions.kotlinx-coroutines-core"] = "1.3.8" extra["versions.kotlinx-coroutines-core"] = "1.3.8"
extra["versions.kotlinx-coroutines-jdk8"] = "1.3.8" extra["versions.kotlinx-coroutines-jdk8"] = "1.3.8"
extra["versions.json"] = "20160807" extra["versions.json"] = "20160807"
extra["versions.native-platform"] = "0.14" extra["versions.native-platform"] = "0.14"
extra["versions.ant-launcher"] = "1.8.0"
extra["versions.robolectric"] = "4.0" extra["versions.robolectric"] = "4.0"
extra["versions.org.springframework"] = "4.2.0.RELEASE" extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0" extra["versions.jflex"] = "1.7.0"
@@ -326,11 +325,13 @@ extra["tasksWithWarnings"] = listOf(
":kotlin-stdlib:compileTestKotlin", ":kotlin-stdlib:compileTestKotlin",
":kotlin-stdlib-jdk7:compileTestKotlin", ":kotlin-stdlib-jdk7:compileTestKotlin",
":kotlin-stdlib-jdk8:compileTestKotlin", ":kotlin-stdlib-jdk8:compileTestKotlin",
":compiler:cli:compileKotlin",
":compiler:frontend:compileKotlin", ":compiler:frontend:compileKotlin",
":compiler:fir:tree:compileKotlin", ":compiler:fir:tree:compileKotlin",
":compiler:fir:resolve:compileKotlin", ":compiler:fir:resolve:compileKotlin",
":compiler:fir:checkers:compileKotlin", ":compiler:fir:checkers:compileKotlin",
":compiler:fir:java:compileKotlin", ":compiler:fir:java:compileKotlin",
":kotlin-scripting-compiler:compileKotlin",
":plugins:uast-kotlin:compileKotlin", ":plugins:uast-kotlin:compileKotlin",
":plugins:uast-kotlin:compileTestKotlin", ":plugins:uast-kotlin:compileTestKotlin",
":plugins:uast-kotlin-idea:compileKotlin" ":plugins:uast-kotlin-idea:compileKotlin"
@@ -351,8 +352,7 @@ val coreLibProjects = listOfNotNull(
":kotlin-test:kotlin-test-junit5", ":kotlin-test:kotlin-test-junit5",
":kotlin-test:kotlin-test-testng", ":kotlin-test:kotlin-test-testng",
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync }, ":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
":kotlin-reflect", ":kotlin-reflect"
":kotlin-coroutines-experimental-compat"
) )
val gradlePluginProjects = listOf( val gradlePluginProjects = listOf(
@@ -977,8 +977,7 @@ tasks {
":kotlin-reflect:publish", ":kotlin-reflect:publish",
":kotlin-main-kts:publish", ":kotlin-main-kts:publish",
":kotlin-stdlib-js:publish", ":kotlin-stdlib-js:publish",
":kotlin-test:kotlin-test-js:publish", ":kotlin-test:kotlin-test-js:publish"
":kotlin-coroutines-experimental-compat:publish"
) )
} }
} }
@@ -1,14 +1,11 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
ext {
isD8Enabled = project.findProperty('android.enableD8').toBoolean()
}
buildscript { buildscript {
repositories { repositories {
google() google()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.3' classpath 'com.android.tools.build:gradle:4.1.1'
} }
} }
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
@@ -20,7 +17,7 @@ repositories {
android { android {
compileSdkVersion 26 compileSdkVersion 26
buildToolsVersion "28.0.3" buildToolsVersion "29.0.3"
defaultConfig { defaultConfig {
applicationId "org.jetbrains.kotlin.android.tests" applicationId "org.jetbrains.kotlin.android.tests"
@@ -60,11 +57,9 @@ android {
resultsDir = "build/test/results" resultsDir = "build/test/results"
} }
if (isD8Enabled) { compileOptions {
compileOptions { sourceCompatibility = 1.8
sourceCompatibility = 1.8 targetCompatibility = 1.8
targetCompatibility = 1.8
}
} }
flavorDimensions "box" flavorDimensions "box"
@@ -86,15 +81,12 @@ android {
dimension "box" dimension "box"
} }
jvm80 {
dimension "box"
}
if (isD8Enabled) { reflectjvm80 {
jvm80 { dimension "box"
dimension "box"
}
reflectjvm80 {
dimension "box"
}
} }
} }
@@ -1,3 +1,2 @@
#don't try to download android specific tools within gradle: licence acceptance will be required #don't try to download android specific tools within gradle: licence acceptance will be required
android.builder.sdkDownload=false android.builder.sdkDownload=false
android.enableD8=true
@@ -25,7 +25,7 @@ import org.junit.runners.AllTests;
import java.io.File; import java.io.File;
//@RunWith(AllTests.class) @RunWith(AllTests.class)
public class AndroidRunner { public class AndroidRunner {
private static PathManager pathManager; private static PathManager pathManager;
@@ -321,8 +321,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM) CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
companion object { companion object {
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change const val GRADLE_VERSION = "6.8.1" // update GRADLE_SHA_256 on change
const val GRADLE_SHA_256 = "1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d" const val GRADLE_SHA_256 = "fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd"
const val testClassPackage = "org.jetbrains.kotlin.android.tests" const val testClassPackage = "org.jetbrains.kotlin.android.tests"
const val testClassName = "CodegenTestCaseOnAndroid" const val testClassName = "CodegenTestCaseOnAndroid"
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests" const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
@@ -55,16 +55,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply { runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply {
rootSuite.addTest(this) rootSuite.addTest(this)
} }
renameFlavorFolder()
enableD8(false)
runTestsOnEmulator(gradleRunner, TestSuite("DX")).apply {
(0 until this.countTestCases()).forEach {
val testCase = testAt(it) as TestCase
testCase.name += "_DX"
}
rootSuite.addTest(this)
}
} catch (e: RuntimeException) { } catch (e: RuntimeException) {
e.printStackTrace() e.printStackTrace()
throw e throw e
@@ -81,16 +71,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
return rootSuite return rootSuite
} }
private fun enableD8(enable: Boolean) {
val file = File(pathManager.androidTmpFolder, "gradle.properties")
val lines = file.readLines().map {
if (it.startsWith("android.enableD8=")) {
"android.enableD8=$enable"
} else it
}
file.writeText(lines.joinToString("\n"))
}
private fun processReport(suite: TestSuite, resultOutput: String) { private fun processReport(suite: TestSuite, resultOutput: String) {
val reportFolder = File(flavorFolder()) val reportFolder = File(flavorFolder())
try { try {
@@ -121,8 +121,11 @@ public class Emulator {
public void startEmulator() { public void startEmulator() {
startServer(); startServer();
System.out.println("Starting emulator..."); System.out.println("Starting emulator with ANDROID_HOME/ANDROID_SDK_ROOT: " + pathManager.getAndroidSdkRoot());
RunUtils.executeOnSeparateThread(new RunUtils.RunSettings(getStartCommand(), null, false, "START: ", true)); GeneralCommandLine startCommand = getStartCommand();
startCommand.withEnvironment("ANDROID_SDK_ROOT", pathManager.getAndroidSdkRoot());
startCommand.withEnvironment("ANDROID_HOME", pathManager.getAndroidSdkRoot());
RunUtils.executeOnSeparateThread(new RunUtils.RunSettings(startCommand, null, false, "START: ", true));
printLog(); printLog();
} }
@@ -144,6 +147,7 @@ public class Emulator {
bootCheckCommand.addParameter("shell"); bootCheckCommand.addParameter("shell");
bootCheckCommand.addParameter("getprop"); bootCheckCommand.addParameter("getprop");
bootCheckCommand.addParameter("sys.boot_completed"); bootCheckCommand.addParameter("sys.boot_completed");
int counter = 0; int counter = 0;
RunResult execute = RunUtils.execute(bootCheckCommand); RunResult execute = RunUtils.execute(bootCheckCommand);
while (counter < 20) { while (counter < 20) {
@@ -264,7 +264,7 @@ public class ClassFileFactory implements OutputFileCollection {
return new MultifileClassCodegenImpl(state, files, facadeFqName); return new MultifileClassCodegenImpl(state, files, facadeFqName);
} }
private void registerSourceFiles(Collection<KtFile> files) { public void registerSourceFiles(@NotNull Collection<KtFile> files) {
sourceFiles.addAll(toIoFilesIgnoringNonPhysical(files)); sourceFiles.addAll(toIoFilesIgnoringNonPhysical(files));
} }
@@ -272,6 +272,7 @@ public class ClassFileFactory implements OutputFileCollection {
private static List<File> toIoFilesIgnoringNonPhysical(@NotNull Collection<? extends PsiFile> psiFiles) { private static List<File> toIoFilesIgnoringNonPhysical(@NotNull Collection<? extends PsiFile> psiFiles) {
List<File> result = new ArrayList<>(psiFiles.size()); List<File> result = new ArrayList<>(psiFiles.size());
for (PsiFile psiFile : psiFiles) { for (PsiFile psiFile : psiFiles) {
if (psiFile == null) continue;
VirtualFile virtualFile = psiFile.getVirtualFile(); VirtualFile virtualFile = psiFile.getVirtualFile();
// We ignore non-physical files here, because this code is needed to tell the make what inputs affect which outputs // We ignore non-physical files here, because this code is needed to tell the make what inputs affect which outputs
// a non-physical file cannot be processed by make // a non-physical file cannot be processed by make
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt; import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.jvm.InlineClassManglingRulesKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
@@ -118,8 +117,9 @@ public class ConstructorCodegen {
} }
private void registerAccessorForHiddenConstructorIfNeeded(ClassConstructorDescriptor descriptor) { private void registerAccessorForHiddenConstructorIfNeeded(ClassConstructorDescriptor descriptor) {
if (!InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) return; if (DescriptorAsmUtil.isHiddenConstructor(descriptor)) {
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null); context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
}
} }
public void generateSecondaryConstructor( public void generateSecondaryConstructor(
@@ -371,11 +371,13 @@ public class ConstructorCodegen {
JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind(); JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
if (delegatingKind == JvmMethodParameterKind.VALUE) { if (delegatingKind == JvmMethodParameterKind.VALUE) {
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE: assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE:
"Delegating constructor has not enough implicit parameters"; "Delegating constructor has not enough implicit parameters: " + delegatingConstructor;
break; break;
} }
assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind : if (index >= parameters.size() || parameters.get(index).getKind() != delegatingKind) {
"Constructors of the same class should have the same set of implicit arguments"; throw new AssertionError(
"Constructors of the same class should have the same set of implicit arguments: " + delegatingConstructor);
}
JvmMethodParameterSignature parameter = parameters.get(index); JvmMethodParameterSignature parameter = parameters.get(index);
iv.load(offset, parameter.getAsmType()); iv.load(offset, parameter.getAsmType());
@@ -383,7 +385,7 @@ public class ConstructorCodegen {
} }
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE : assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE :
"Delegating constructor has not enough parameters"; "Delegating constructor has not enough parameters: " + delegatingConstructor;
return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(), return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(),
delegatingCallable.getValueParameterTypes()); delegatingCallable.getValueParameterTypes());
@@ -61,7 +61,8 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode; import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineWithReified; import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineWithReified;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation; import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType; import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -368,6 +369,18 @@ public class DescriptorAsmUtil {
return ACC_PRIVATE; return ACC_PRIVATE;
} }
// Sealed class constructors should be ACC_PRIVATE.
// In 1.4 and before, sealed class constructors had PRIVATE visibility, and were represented as private methods in bytecode.
// In 1.5 (+AllowSealedInheritorsInDifferentFilesOfSamePackage), sealed class constructors became INTERNAL,
// but still should be represented as private methods in bytecode in order to prevent inheriting from sealed classes on JVM.
if (memberDescriptor instanceof ConstructorDescriptor &&
!(memberDescriptor instanceof AccessorForConstructorDescriptor) &&
isSealedClass(((ConstructorDescriptor) memberDescriptor).getConstructedClass()) &&
memberDescriptor.getVisibility() != DescriptorVisibilities.PUBLIC
) {
return ACC_PRIVATE;
}
if (isInlineOnlyPrivateInBytecode(memberDescriptor)) { if (isInlineOnlyPrivateInBytecode(memberDescriptor)) {
return ACC_PRIVATE; return ACC_PRIVATE;
} }
@@ -893,4 +906,19 @@ public class DescriptorAsmUtil {
//Trait always should have this descriptor //Trait always should have this descriptor
return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1; return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1;
} }
public static boolean isHiddenConstructor(FunctionDescriptor descriptor) {
if (!(descriptor instanceof ClassConstructorDescriptor)) return false;
ClassConstructorDescriptor classConstructorDescriptor = (ClassConstructorDescriptor) descriptor;
if (InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) {
return true;
}
if (isSealedClass(classConstructorDescriptor.getConstructedClass()) &&
classConstructorDescriptor.getVisibility() != DescriptorVisibilities.PUBLIC
) {
return true;
}
return false;
}
} }
@@ -2523,21 +2523,39 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// $default method is not private, so you need no accessor to call it // $default method is not private, so you need no accessor to call it
return descriptor; return descriptor;
} }
else if (InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor.getOriginal())) { else if (shouldForceAccessorForConstructor(descriptor.getOriginal())) {
// Constructors with inline class type value parameters should always be called using an accessor. return createAccessorForHiddenConstructor(resolvedCall, descriptor);
// NB this will require accessors even if the constructor itself is in a different module.
return new AccessorForConstructorDescriptor(
(ClassConstructorDescriptor) descriptor.getOriginal(),
descriptor.getContainingDeclaration(),
getSuperCallTarget(resolvedCall.getCall()),
AccessorKind.NORMAL
);
} }
else { else {
return context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall())); return context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall()));
} }
} }
private boolean shouldForceAccessorForConstructor(FunctionDescriptor descriptor) {
// Force using accessors on hidden constructors only
if (!isHiddenConstructor(descriptor)) {
return false;
}
// Don't use accessor when calling hidden constructor from the same class.
if (descriptor.getContainingDeclaration() == context.getContextDescriptor().getContainingDeclaration()) {
return false;
}
return true;
}
@NotNull
private AccessorForConstructorDescriptor createAccessorForHiddenConstructor(
@NotNull ResolvedCall<?> resolvedCall,
FunctionDescriptor descriptor
) {
return new AccessorForConstructorDescriptor(
(ClassConstructorDescriptor) descriptor.getOriginal(),
descriptor.getContainingDeclaration(),
getSuperCallTarget(resolvedCall.getCall()),
AccessorKind.NORMAL
);
}
@NotNull @NotNull
public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) { public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver); return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver);
@@ -207,6 +207,14 @@ class GenerationState private constructor(
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
else JvmStringConcat.INLINE else JvmStringConcat.INLINE
val samConversionsScheme = run {
val fromConfig = configuration.get(JVMConfigurationKeys.SAM_CONVERSIONS) ?: JvmSamConversions.DEFAULT
if (target >= fromConfig.minJvmTarget)
fromConfig
else
JvmSamConversions.DEFAULT
}
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module) val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
val bindingTrace: BindingTrace = DelegatingBindingTrace( val bindingTrace: BindingTrace = DelegatingBindingTrace(
@@ -375,13 +375,27 @@ class KotlinTypeMapper @JvmOverloads constructor(
kind: OwnerKind? = null, kind: OwnerKind? = null,
resolvedCall: ResolvedCall<*>? = null resolvedCall: ResolvedCall<*>? = null
): CallableMethod { ): CallableMethod {
fun mapDefaultCallback(descriptor: FunctionDescriptor, kind: OwnerKind): () -> Method {
if (useOldManglingRulesForFunctionAcceptingInlineClass && !useOldInlineClassesManglingScheme) {
return {
val prevManglingState = useOldManglingRulesForFunctionAcceptingInlineClass
useOldManglingRulesForFunctionAcceptingInlineClass = true
mapDefaultMethod(descriptor, kind).also {
useOldManglingRulesForFunctionAcceptingInlineClass = prevManglingState
}
}
} else {
return { mapDefaultMethod(descriptor, kind) }
}
}
// we generate constructors of inline classes as usual functions // we generate constructors of inline classes as usual functions
if (descriptor is ConstructorDescriptor && kind != OwnerKind.ERASED_INLINE_CLASS) { if (descriptor is ConstructorDescriptor && kind != OwnerKind.ERASED_INLINE_CLASS) {
val method = mapSignatureSkipGeneric(descriptor.original) val method = mapSignatureSkipGeneric(descriptor.original)
val owner = mapOwner(descriptor) val owner = mapOwner(descriptor)
val originalDescriptor = descriptor.original val originalDescriptor = descriptor.original
return CallableMethod( return CallableMethod(
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL, owner, owner, mapDefaultCallback(originalDescriptor, OwnerKind.IMPLEMENTATION), method, INVOKESPECIAL,
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false, null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false,
boxInlineClassBeforeInvoke = false boxInlineClassBeforeInvoke = false
) )
@@ -557,7 +571,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
return CallableMethod( return CallableMethod(
owner, ownerForDefaultImpl, owner, ownerForDefaultImpl,
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)) }, mapDefaultCallback(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)),
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType, calleeType, returnKotlinType,
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE, if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
@@ -33,6 +33,13 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
) )
var libraries: String? by NullableStringFreezableVar(null) var libraries: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xrepositories",
valueDescription = "<path>",
description = "Paths to additional places where libraries could be found"
)
var repositries: String? by NullableStringFreezableVar(null)
@GradleOption(DefaultValues.BooleanFalseDefault::class) @GradleOption(DefaultValues.BooleanFalseDefault::class)
@Argument(value = "-source-map", description = "Generate source map") @Argument(value = "-source-map", description = "Generate source map")
var sourceMap: Boolean by FreezableVar(false) var sourceMap: Boolean by FreezableVar(false)
@@ -362,6 +362,15 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description) var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)
@Argument(
value = "-Xsam-conversions",
valueDescription = "{class|indy}",
description = """Select code generation scheme for SAM conversions.
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 8` or greater.
-Xsam-conversions=class Generate SAM conversions as explicit classes"""
)
var samConversions: String? by NullableStringFreezableVar(JvmSamConversions.CLASS.description)
@Argument( @Argument(
value = "-Xklib", value = "-Xklib",
valueDescription = "<path>", valueDescription = "<path>",
@@ -134,7 +134,7 @@ fun main(args: Array<String>) {
} }
val resolvedLibraries = jsResolveLibraries( val resolvedLibraries = jsResolveLibraries(
dependencies, messageCollectorLogger(MessageCollector.NONE) dependencies, emptyList(), messageCollectorLogger(MessageCollector.NONE)
) )
buildKLib(moduleName, listOfKtFilesFrom(inputFiles), outputPath, resolvedLibraries, listOfKtFilesFrom(commonSources)) buildKLib(moduleName, listOfKtFilesFrom(inputFiles), outputPath, resolvedLibraries, listOfKtFilesFrom(commonSources))
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
import org.jetbrains.kotlin.js.config.* import org.jetbrains.kotlin.js.config.*
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -113,9 +114,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val libraries: List<String> = configureLibraries(arguments.libraries) + listOfNotNull(arguments.includes) val libraries: List<String> = configureLibraries(arguments.libraries) + listOfNotNull(arguments.includes)
val friendLibraries: List<String> = configureLibraries(arguments.friendModules) val friendLibraries: List<String> = configureLibraries(arguments.friendModules)
val repositories: List<String> = configureLibraries(arguments.repositries)
configuration.put(JSConfigurationKeys.LIBRARIES, libraries) configuration.put(JSConfigurationKeys.LIBRARIES, libraries)
configuration.put(JSConfigurationKeys.TRANSITIVE_LIBRARIES, libraries) configuration.put(JSConfigurationKeys.TRANSITIVE_LIBRARIES, libraries)
configuration.put(JSConfigurationKeys.REPOSITORIES, repositories)
val commonSourcesArray = arguments.commonSources val commonSourcesArray = arguments.commonSources
val commonSources = commonSourcesArray?.toSet() ?: emptySet() val commonSources = commonSourcesArray?.toSet() ?: emptySet()
@@ -175,6 +178,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val resolvedLibraries = jsResolveLibraries( val resolvedLibraries = jsResolveLibraries(
libraries, libraries,
configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList(),
messageCollectorLogger(configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] ?: error("Could not find message collector")) messageCollectorLogger(configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] ?: error("Could not find message collector"))
) )
@@ -184,11 +188,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
} }
if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) { if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) {
val outputKlibPath = if (arguments.irProduceKlibFile) {
if (arguments.irProduceKlibDir) require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" }
File(outputFilePath).parent }
else
outputFilePath
try { try {
generateKLib( generateKLib(
@@ -199,7 +201,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
allDependencies = resolvedLibraries, allDependencies = resolvedLibraries,
friendDependencies = friendDependencies, friendDependencies = friendDependencies,
irFactory = PersistentIrFactory, irFactory = PersistentIrFactory,
outputKlibPath = outputKlibPath, outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir nopack = arguments.irProduceKlibDir
) )
} catch (e: JsIrCompilationError) { } catch (e: JsIrCompilationError) {
@@ -59,8 +59,28 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
} }
} else { } else {
messageCollector.report( messageCollector.report(
ERROR, "Unknown -Xstring-concat mode: ${arguments.jvmTarget}\n" + ERROR, "Unknown `-Xstring-concat` mode: ${arguments.stringConcat}\n" +
"Supported versions: ${JvmStringConcat.values().joinToString { it.description }}" "Supported modes: ${JvmStringConcat.values().joinToString { it.description }}"
)
}
}
if (arguments.samConversions != null) {
val samConversions = JvmSamConversions.fromString(arguments.samConversions)
if (samConversions != null) {
put(JVMConfigurationKeys.SAM_CONVERSIONS, samConversions)
if (jvmTarget < samConversions.minJvmTarget) {
messageCollector.report(
WARNING,
"`-Xsam-conversions=${arguments.samConversions}` requires JVM target at least " +
"${samConversions.minJvmTarget.description} and is ignored."
)
}
} else {
messageCollector.report(
ERROR,
"Unknown `-Xsam-conversions` argument: ${arguments.samConversions}\n" +
"Supported arguments: ${JvmSamConversions.values().joinToString { it.description }}"
) )
} }
} }
@@ -19,7 +19,7 @@ public class KotlinCompilerVersion {
// Binaries produced by this compiler with that language version (or any future language version) are going to be marked // Binaries produced by this compiler with that language version (or any future language version) are going to be marked
// as "pre-release" and will not be loaded by release versions of the compiler. // as "pre-release" and will not be loaded by release versions of the compiler.
// Change this value before and after every major release // Change this value before and after every major release
private static final boolean IS_PRE_RELEASE = false; private static final boolean IS_PRE_RELEASE = true;
public static final String TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY = "kotlin.test.is.pre.release"; public static final String TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY = "kotlin.test.is.pre.release";
@@ -114,6 +114,9 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<JvmStringConcat> STRING_CONCAT = public static final CompilerConfigurationKey<JvmStringConcat> STRING_CONCAT =
CompilerConfigurationKey.create("Specifies string concatenation scheme"); CompilerConfigurationKey.create("Specifies string concatenation scheme");
public static final CompilerConfigurationKey<JvmSamConversions> SAM_CONVERSIONS =
CompilerConfigurationKey.create("SAM conversions code generation scheme");
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS = public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries"); CompilerConfigurationKey.create("Paths to .klib libraries");
@@ -0,0 +1,23 @@
/*
* 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.config
enum class JvmSamConversions(
val description: String,
val minJvmTarget: JvmTarget
) {
CLASS("class", JvmTarget.JVM_1_6),
INDY("indy", JvmTarget.JVM_1_8),
;
companion object {
val DEFAULT = CLASS
@JvmStatic
fun fromString(string: String?) =
values().find { it.description == string }
}
}
@@ -1231,6 +1231,24 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
public void testValOnAnnotationParameter() throws Exception { public void testValOnAnnotationParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/valOnAnnotationParameter.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/valOnAnnotationParameter.kt");
} }
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionAsExpression extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFunctionAsExpression() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("Parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression/Parameters.kt");
}
}
} }
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
@@ -12,7 +12,7 @@ public sealed class Sealed : R|kotlin/Any| {
public final val z: R|test/Z| public final val z: R|test/Z|
public get(): R|test/Z| public get(): R|test/Z|
@R|test/Ann|() private constructor(@R|test/Ann|() z: R|test/Z|): R|test/Sealed| @R|test/Ann|() internal constructor(@R|test/Ann|() z: R|test/Z|): R|test/Sealed|
} }
@@ -14,7 +14,7 @@ public sealed class SealedClass : R|kotlin/Any| {
} }
private constructor(): R|test/SealedClass| internal constructor(): R|test/SealedClass|
} }
@@ -7,5 +7,5 @@ FILE: definetelyNotNullForTypeParameter.kt
public final fun <F : R|kotlin/Any|> foo(computable: R|Out<F?>|): R|kotlin/Unit| { public final fun <F : R|kotlin/Any|> foo(computable: R|Out<F?>|): R|kotlin/Unit| {
} }
public final fun <T : R|kotlin/Any|> bar(computable: R|Out<T?>|): R|kotlin/Unit| { public final fun <T : R|kotlin/Any|> bar(computable: R|Out<T?>|): R|kotlin/Unit| {
R|/foo|<R|T?!!|>(R|/id|<R|T?|>(R|<local>/computable|)) R|/foo|<R|T|>(R|/id|<R|T?|>(R|<local>/computable|))
} }
@@ -19,7 +19,8 @@ FILE: operatorsOverLiterals.kt
} }
public final fun R|kotlin/Int|.bar(): R|kotlin/Int| { public final fun R|kotlin/Int|.bar(): R|kotlin/Int| {
} }
public final fun R|kotlin/Int|.baz(): R|kotlin/Int| public final fun R|kotlin/Int|.baz(): R|kotlin/Int| {
}
public final fun R|kotlin/Byte|.baz(): R|kotlin/Byte| { public final fun R|kotlin/Byte|.baz(): R|kotlin/Byte| {
} }
public final fun test_3(): R|kotlin/Unit| { public final fun test_3(): R|kotlin/Unit| {
@@ -20,7 +20,7 @@ fun test_2(n: Int) {
fun Int.bar(): Int {} fun Int.bar(): Int {}
fun Int.baz(): Int fun Int.baz(): Int {}
fun Byte.baz(): Byte {} fun Byte.baz(): Byte {}
fun test_3() { fun test_3() {
+1 -1
View File
@@ -15,7 +15,7 @@ fun test_2(x: Int?) {
} else { } else {
x x
} }
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> y<!UNSAFE_CALL!>.<!>inc()
} }
fun test_3(x: Int?) { fun test_3(x: Int?) {
@@ -111,7 +111,8 @@ FILE: conflictingOverloads.kt
} }
} }
public final fun mest(): R|kotlin/Unit| public final fun mest(): R|kotlin/Unit| {
}
public final class mest : R|kotlin/Any| { public final class mest : R|kotlin/Any| {
public constructor(): R|mest| { public constructor(): R|mest| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
@@ -59,7 +59,7 @@ class L {
fun B.foo() {} fun B.foo() {}
} }
fun mest() fun mest() {}
class mest class mest
@@ -0,0 +1,45 @@
FILE: Parameters.kt
public final val bar: R|(kotlin/Int) -> kotlin/Unit| = fun <anonymous>(p: R|kotlin/Int| = Int(3)): R|kotlin/Unit| {
}
public get(): R|(kotlin/Int) -> kotlin/Unit|
public final val bas: R|(kotlin/Int) -> kotlin/Unit| = fun <anonymous>(vararg p: R|kotlin/Int|): R|kotlin/Unit| {
}
public get(): R|(kotlin/Int) -> kotlin/Unit|
public final fun gar(): R|(kotlin/Int) -> kotlin/Unit| {
^gar fun <anonymous>(p: R|kotlin/Int| = Int(3)): R|kotlin/Unit| {
}
}
public final fun gas(): R|(kotlin/Int) -> kotlin/Unit| {
^gas fun <anonymous>(vararg p: R|kotlin/Int|): R|kotlin/Unit| {
}
}
public final fun outer(b: R|kotlin/Any?|): R|kotlin/Unit| {
lval bar: R|(kotlin/Int) -> kotlin/Unit| = fun <anonymous>(p: R|kotlin/Int| = Int(3)): R|kotlin/Unit| {
}
lval bas: R|(kotlin/Int) -> kotlin/Unit| = fun <anonymous>(vararg p: R|kotlin/Int|): R|kotlin/Unit| {
}
local final fun gar(): R|(kotlin/Int) -> kotlin/Unit| {
^gar fun <anonymous>(p: R|kotlin/Int| = Int(3)): R|kotlin/Unit| {
}
}
local final fun gas(): R|(kotlin/Int) -> kotlin/Unit| {
^gas fun <anonymous>(vararg p: R|kotlin/Int|): R|kotlin/Unit| {
}
}
R|/outer|(fun <anonymous>(p: R|kotlin/Int| = Int(3)): R|kotlin/Unit| {
}
)
R|/outer|(fun <anonymous>(vararg p: R|kotlin/Int|): R|kotlin/Unit| {
}
)
}
@@ -0,0 +1,16 @@
val bar = fun(p: Int = <!ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE!>3<!>) {}
val bas = fun(<!USELESS_VARARG_ON_PARAMETER!>vararg p: Int<!>) {}
fun gar() = fun(p: Int = <!ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE!>3<!>) {}
fun gas() = fun(<!USELESS_VARARG_ON_PARAMETER!>vararg p: Int<!>) {}
fun outer(b: Any?) {
val bar = fun(p: Int = <!ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE!>3<!>) {}
val bas = fun(<!USELESS_VARARG_ON_PARAMETER!>vararg p: Int<!>) {}
fun gar() = fun(p: Int = <!ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE!>3<!>) {}
fun gas() = fun(<!USELESS_VARARG_ON_PARAMETER!>vararg p: Int<!>) {}
outer(fun(p: Int = <!ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE!>3<!>) {})
outer(fun(<!USELESS_VARARG_ON_PARAMETER!>vararg p: Int<!>) {})
}
@@ -34,7 +34,7 @@ fun test3(x: AnotherClass?) {
fun test4(x: SomeClass?) { fun test4(x: SomeClass?) {
val bar = x?.bar val bar = x?.bar
if (bar != null) { if (bar != null) {
x.bar.<!INAPPLICABLE_CANDIDATE!>length<!> x.bar<!UNSAFE_CALL!>.<!>length
} }
} }
@@ -5,7 +5,7 @@ interface B
class Clazz1 : A, B class Clazz1 : A, B
class Clazz2 : A, B class Clazz2 : A, B
fun <K> select(x: K, y: K): K <!NON_MEMBER_FUNCTION_NO_BODY!>fun <K> select(x: K, y: K): K<!>
fun test() = select(Clazz1(), Clazz2()) fun test() = select(Clazz1(), Clazz2())
@@ -14,7 +14,7 @@ package a.d
import b.d.* import b.d.*
fun foo(arg: Other): Another <!NON_MEMBER_FUNCTION_NO_BODY!>fun foo(arg: Other): Another<!>
fun bar() { fun bar() {
baz() baz()
@@ -26,7 +26,7 @@ fun test_3(a: A?, b: Boolean) {
if (b && a!!.foo()) { if (b && a!!.foo()) {
a.foo() // OK a.foo() // OK
} }
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> // Bad a<!UNSAFE_CALL!>.<!>foo() // Bad
} }
fun test_4(a: A?, b: Boolean) { fun test_4(a: A?, b: Boolean) {
@@ -38,9 +38,9 @@ fun test_4(a: A?, b: Boolean) {
fun test_5(a: A?, b: Boolean) { fun test_5(a: A?, b: Boolean) {
if (b || a!!.foo()) { if (b || a!!.foo()) {
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
fun <X : A?> test_6(x: X) { fun <X : A?> test_6(x: X) {
@@ -8,13 +8,13 @@ fun test_1(b: Boolean?) {
if ((b == true) == true) { if ((b == true) == true) {
b.not() // OK b.not() // OK
} else { } else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} }
} }
fun test_2(b: Boolean?) { fun test_2(b: Boolean?) {
if ((b == true) != true) { if ((b == true) != true) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} else { } else {
b.not() // OK b.not() // OK
} }
@@ -22,7 +22,7 @@ fun test_2(b: Boolean?) {
fun test_3(b: Boolean?) { fun test_3(b: Boolean?) {
if ((b == true) == false) { if ((b == true) == false) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} else { } else {
b.not() // OK b.not() // OK
} }
@@ -32,13 +32,13 @@ fun test_4(b: Boolean?) {
if ((b == true) != false) { if ((b == true) != false) {
b.not() // OK b.not() // OK
} else { } else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} }
} }
fun test_5(b: Boolean?) { fun test_5(b: Boolean?) {
if ((b != true) == true) { if ((b != true) == true) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} else { } else {
b.not() // OK b.not() // OK
} }
@@ -48,7 +48,7 @@ fun test_6(b: Boolean?) {
if ((b != true) != true) { if ((b != true) != true) {
b.not() // OK b.not() // OK
} else { } else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} }
} }
@@ -56,13 +56,13 @@ fun test_7(b: Boolean?) {
if ((b != true) == false) { if ((b != true) == false) {
b.not() // OK b.not() // OK
} else { } else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} }
} }
fun test_8(b: Boolean?) { fun test_8(b: Boolean?) {
if ((b != true) != false) { if ((b != true) != false) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad b<!UNSAFE_CALL!>.<!>not() // Bad
} else { } else {
b.not() // OK b.not() // OK
} }
@@ -34,24 +34,24 @@ fun test_4(a: A?) {
fun test_5(a: A?) { fun test_5(a: A?) {
a == null || throw Exception() a == null || throw Exception()
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
fun teat_6(a: A?) { fun teat_6(a: A?) {
a != null && throw Exception() a != null && throw Exception()
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
fun test_7(a: A?) { fun test_7(a: A?) {
if (a == null || throw Exception()) { if (a == null || throw Exception()) {
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
fun test_8(a: A?) { fun test_8(a: A?) {
if (a != null && throw Exception()) { if (a != null && throw Exception()) {
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
@@ -104,18 +104,18 @@ fun test_7() {
if (x != null) { if (x != null) {
x.length // OK x.length // OK
y.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad y<!UNSAFE_CALL!>.<!>length // Bad
z.length // OK z.length // OK
} }
if (y != null) { if (y != null) {
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad x<!UNSAFE_CALL!>.<!>length // Bad
y.length // OK y.length // OK
z.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad z<!UNSAFE_CALL!>.<!>length // Bad
} }
if (z != null) { if (z != null) {
x.length // OK x.length // OK
y.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad y<!UNSAFE_CALL!>.<!>length // Bad
z.length // OK z.length // OK
} }
} }
@@ -16,12 +16,12 @@ fun test_1(x: A, y: A?) {
fun test_2(x: A?, y: A?) { fun test_2(x: A?, y: A?) {
if (x == y) { if (x == y) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> y<!UNSAFE_CALL!>.<!>foo()
} }
if (x === y) { if (x === y) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> y<!UNSAFE_CALL!>.<!>foo()
} }
} }
@@ -39,18 +39,18 @@ fun test_1(x: A?) {
if (x != null) { if (x != null) {
x.foo() x.foo()
} else { } else {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
} }
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
} }
fun test_2(x: A?) { fun test_2(x: A?) {
if (x == null) { if (x == null) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
} else { } else {
x.foo() x.foo()
} }
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> x<!UNSAFE_CALL!>.<!>foo()
} }
fun test_3(x: A?) { fun test_3(x: A?) {
@@ -67,8 +67,8 @@ fun test_5(q: Q?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData. // `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) { if (q?.data?.s?.inc() != null) {
q.data // good q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
} }
} }
@@ -76,15 +76,15 @@ fun test_6(q: Q?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData. // `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
q?.data?.s?.inc() ?: return q?.data?.s?.inc() ?: return
q.data // good q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
} }
fun test_7(q: Q?) { fun test_7(q: Q?) {
if (q?.fdata()?.fs()?.inc() != null) { if (q?.fdata()?.fs()?.inc() != null) {
q.fdata() // good q.fdata() // good
q.fdata().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>fs<!>()<!> // bad q.fdata()<!UNSAFE_CALL!>.<!>fs() // bad
q.fdata().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>fs<!>()<!>.inc() // bad q.fdata()<!UNSAFE_CALL!>.<!>fs().inc() // bad
} }
} }
@@ -98,44 +98,44 @@ fun test_9(a: Int, b: Int?) {
if (a == b) { if (a == b) {
b.inc() b.inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (a === b) { if (a === b) {
b.inc() b.inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (b == a) { if (b == a) {
b.inc() b.inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (b === a) { if (b === a) {
b.inc() b.inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
fun test_10(a: Int?, b: Int?) { fun test_10(a: Int?, b: Int?) {
if (a == b) { if (a == b) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (a === b) { if (a === b) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (b == a) { if (b == a) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
if (b === a) { if (b === a) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!> b<!UNSAFE_CALL!>.<!>inc()
} }
fun test_11(q: QImpl?, q2: QImpl) { fun test_11(q: QImpl?, q2: QImpl) {
@@ -148,8 +148,8 @@ fun test_11(q: QImpl?, q2: QImpl) {
// Smartcasting of `q.data` should have no effect on `q2.data`. // Smartcasting of `q.data` should have no effect on `q2.data`.
// Issue: Smartcasting of QImpl.data affects all instances // Issue: Smartcasting of QImpl.data affects all instances
q2.data q2.data
q2.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad q2.data<!UNSAFE_CALL!>.<!>s // should be bad
q2.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad q2.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
if (q2.data != null) { if (q2.data != null) {
q2.data.s q2.data.s
@@ -162,8 +162,8 @@ fun test_12(q: QImplWithCustomGetter?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData. // `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) { if (q?.data?.s?.inc() != null) {
q.data // good q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
} }
} }
@@ -171,7 +171,7 @@ fun test_13(q: QImplMutable?) {
// `q.data` is a property that is mutable, so we can NOT smartcast it to non-nullable MyData. // `q.data` is a property that is mutable, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) { if (q?.data?.s?.inc() != null) {
q.data // good q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
} }
} }
@@ -22,6 +22,6 @@ fun test_3(a: Any?, b: Boolean) {
fun test_4(a: Any?, b: Boolean) { fun test_4(a: Any?, b: Boolean) {
if (a is String || b) { if (a is String || b) {
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> // Should be Bad a<!UNSAFE_CALL!>.<!>foo() // Should be Bad
} }
} }
@@ -5,7 +5,7 @@ fun test_1(s: String?) {
if (s?.check() == true) { if (s?.check() == true) {
s.length // Should be OK s.length // Should be OK
} else { } else {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad s<!UNSAFE_CALL!>.<!>length // Should be bad
} }
} }
@@ -13,13 +13,13 @@ fun test_2(s: String?) {
if (s?.check() == false) { if (s?.check() == false) {
s.length // Should be OK s.length // Should be OK
} else { } else {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad s<!UNSAFE_CALL!>.<!>length // Should be bad
} }
} }
fun test_3(s: String?) { fun test_3(s: String?) {
if (s?.check() != true) { if (s?.check() != true) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad s<!UNSAFE_CALL!>.<!>length // Should be bad
} else { } else {
s.length // Should be OK s.length // Should be OK
} }
@@ -27,7 +27,7 @@ fun test_3(s: String?) {
fun test_4(s: String?) { fun test_4(s: String?) {
if (s?.check() != false) { if (s?.check() != false) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad s<!UNSAFE_CALL!>.<!>length // Should be bad
} else { } else {
s.length // Should be OK s.length // Should be OK
} }
@@ -5,7 +5,7 @@ fun String.let(block: () -> Unit) {}
fun test(x: String?) { fun test(x: String?) {
x?.foo(x.length == 1) x?.foo(x.length == 1)
x.<!INAPPLICABLE_CANDIDATE!>length<!> x<!UNSAFE_CALL!>.<!>length
} }
interface A { interface A {
@@ -27,12 +27,12 @@ fun test_3(x: Any) {
fun test_4(x: A?) { fun test_4(x: A?) {
x?.id()?.bool() x?.id()?.bool()
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>id<!>()<!> x<!UNSAFE_CALL!>.<!>id()
} }
fun Any?.boo(b: Boolean) {} fun Any?.boo(b: Boolean) {}
fun test_5(x: A?) { fun test_5(x: A?) {
x?.let { return }?.boo(x.bool()) x?.let { return }?.boo(x.bool())
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>id<!>()<!> x<!UNSAFE_CALL!>.<!>id()
} }
@@ -11,5 +11,5 @@ fun test(b: Boolean) {
} else { } else {
a = null a = null
} }
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> a<!UNSAFE_CALL!>.<!>foo()
} }
@@ -18,5 +18,5 @@ fun test_3() {
x = "" x = ""
x.length x.length
x = null x = null
x.<!INAPPLICABLE_CANDIDATE!>length<!> x<!UNSAFE_CALL!>.<!>length
} }
@@ -1,5 +1,5 @@
<!CONFLICTING_OVERLOADS{LT}!><!CONFLICTING_OVERLOADS!>fun bar(x: String): Int<!> = 1<!> <!CONFLICTING_OVERLOADS!>fun bar(x: String): Int<!> = 1
<!CONFLICTING_OVERLOADS{LT}!><!CONFLICTING_OVERLOADS!>fun bar(x: String): Double<!> = 1<!> <!CONFLICTING_OVERLOADS!>fun bar(x: String): Double<!> = 1
fun baz(x: String): Int = 1 fun baz(x: String): Int = 1
fun <T, R> foobaz(x: T): R = TODO() fun <T, R> foobaz(x: T): R = TODO()
@@ -31,16 +31,16 @@ fun main() {
foo1(KotlinClass::baz) foo1(KotlinClass::baz)
foo2(KotlinClass::baz) foo2(KotlinClass::baz)
// Ambiguity (companion/class) // Ambiguity (companion/class)
<!AMBIGUITY!>foo3<!>(KotlinClass::baz) <!AMBIGUITY{LT}!><!AMBIGUITY{PSI}!>foo3<!>(KotlinClass::baz)<!>
// Type mismatch // Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo1<!>(<!UNRESOLVED_REFERENCE!>KotlinClass::bar<!>) <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo1<!>(<!UNRESOLVED_REFERENCE!>KotlinClass::bar<!>)<!>
foo2(KotlinClass::bar) foo2(KotlinClass::bar)
foo3(KotlinClass::bar) foo3(KotlinClass::bar)
foo1(KotlinClass2::bar) foo1(KotlinClass2::bar)
// Type mismatch // Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo2<!>(<!UNRESOLVED_REFERENCE!>KotlinClass2::bar<!>) <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo2<!>(<!UNRESOLVED_REFERENCE!>KotlinClass2::bar<!>)<!>
foo3(KotlinClass2::bar) foo3(KotlinClass2::bar)
} }
@@ -7,6 +7,6 @@ fun <T> bar(f: (T) -> Unit, e: T) {}
fun <T> baz(e: T, f: (T) -> Unit) {} fun <T> baz(e: T, f: (T) -> Unit) {}
fun test(a: A, b: B) { fun test(a: A, b: B) {
<!INAPPLICABLE_CANDIDATE!>baz<!>(a, <!UNRESOLVED_REFERENCE!>::fooB<!>) <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>(a, <!UNRESOLVED_REFERENCE!>::fooB<!>)<!>
<!INAPPLICABLE_CANDIDATE!>bar<!>(<!UNRESOLVED_REFERENCE!>::fooB<!>, a) <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>bar<!>(<!UNRESOLVED_REFERENCE!>::fooB<!>, a)<!>
} }
@@ -3,5 +3,5 @@ fun <T, R> use(x: (T) -> R): (T) -> R = x
fun foo() = use(::bar) fun foo() = use(::bar)
fun bar(x: String) = 1 fun bar(x: String) = 1
fun loop1() = <!INAPPLICABLE_CANDIDATE!>use<!>(<!UNRESOLVED_REFERENCE!>::loop2<!>) fun loop1() = <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>use<!>(<!UNRESOLVED_REFERENCE!>::loop2<!>)<!>
fun loop2() = loop1() fun loop2() = loop1()
@@ -16,5 +16,5 @@ fun foo3(x: (String) -> Int) {}
fun main() { fun main() {
foo1(JavaClass::bar) foo1(JavaClass::bar)
foo2(JavaClass::bar) foo2(JavaClass::bar)
<!AMBIGUITY!>foo3<!>(JavaClass::bar) <!AMBIGUITY{LT}!><!AMBIGUITY{PSI}!>foo3<!>(JavaClass::bar)<!>
} }
@@ -6,5 +6,5 @@ fun bar(): Int = 1
fun bar(x: String): Int = 1 fun bar(x: String): Int = 1
fun main() { fun main() {
<!AMBIGUITY!>foo<!>(<!UNRESOLVED_REFERENCE!>::bar<!>) <!AMBIGUITY{LT}!><!AMBIGUITY{PSI}!>foo<!>(<!UNRESOLVED_REFERENCE!>::bar<!>)<!>
} }
@@ -7,7 +7,7 @@ fun test_1(s: String?) {
fun test_2(s: String?) { fun test_2(s: String?) {
// contracts related // contracts related
if (s.isNullOrEmpty()) { if (s.isNullOrEmpty()) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad s<!UNSAFE_CALL!>.<!>length // Should be bad
} else { } else {
s.length // Should be OK s.length // Should be OK
} }
@@ -59,8 +59,8 @@ fun test_2(x: Any) {
fun test_3(x: Any) { fun test_3(x: Any) {
myRequireOr(x is B, x is C) myRequireOr(x is B, x is C)
x.foo() // OK x.foo() // OK
x.<!UNRESOLVED_REFERENCE!>bar<!>() // Error x.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>bar<!>()<!> // Error
x.<!UNRESOLVED_REFERENCE!>baz<!>() // Error x.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>baz<!>()<!> // Error
} }
fun test_4(x: Any) { fun test_4(x: Any) {
@@ -21,7 +21,7 @@ fun test_1(x: String?) {
if (checkNotNull(x)) { if (checkNotNull(x)) {
x.length // OK x.length // OK
} else { } else {
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Error x<!UNSAFE_CALL!>.<!>length // Error
} }
} }
@@ -27,7 +27,7 @@ fun test_3(x: A?) {
with(x) { with(x) {
myRequireNotNull() myRequireNotNull()
} }
x.<!INAPPLICABLE_CANDIDATE!>foo<!>() x<!UNSAFE_CALL!>.<!>foo()
} }
fun test_4(x: A?) { fun test_4(x: A?) {
@@ -27,8 +27,8 @@ class A {
val p3 = JavaProtected().<!HIDDEN!>javaPProtectedPackage<!> val p3 = JavaProtected().<!HIDDEN!>javaPProtectedPackage<!>
fun test() { fun test() {
JavaProtected.<!HIDDEN!>javaMProtectedStatic<!>() JavaProtected.<!HIDDEN{LT}!><!HIDDEN{PSI}!>javaMProtectedStatic<!>()<!>
JavaPackageLocal.<!HIDDEN!>javaMPackage<!>() JavaPackageLocal.<!HIDDEN{LT}!><!HIDDEN{PSI}!>javaMPackage<!>()<!>
} }
} }
@@ -39,7 +39,7 @@ class B : JavaProtected() {
fun test() { fun test() {
JavaProtected.javaMProtectedStatic() JavaProtected.javaMProtectedStatic()
JavaPackageLocal.<!HIDDEN!>javaMPackage<!>() JavaPackageLocal.<!HIDDEN{LT}!><!HIDDEN{PSI}!>javaMPackage<!>()<!>
} }
} }
@@ -5,9 +5,9 @@ fun main(k: KSub, vString: SuperClass<String>.NestedInSuperClass, vInt: SuperCla
k.getImpl().nestedI(vString) k.getImpl().nestedI(vString)
// TODO: Support parametrisized inner classes // TODO: Support parametrisized inner classes
k.getImpl().<!INAPPLICABLE_CANDIDATE!>nestedI<!>(vInt) k.getImpl().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>nestedI<!>(vInt)<!>
k.getNestedSubClass().nested("") k.getNestedSubClass().nested("")
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>(1) k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>nested<!>(1)<!>
} }
// FILE: J1.java // FILE: J1.java
@@ -9,5 +9,5 @@ public class JavaClass {
// FILE: K2.kt // FILE: K2.kt
fun main() { fun main() {
JavaClass.baz(KotlinClass()) JavaClass.baz(KotlinClass())
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>("") JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>("")<!>
} }
@@ -10,6 +10,6 @@ public class JavaClass {
fun main() { fun main() {
JavaClass.baz(KotlinClass()) JavaClass.baz(KotlinClass())
JavaClass.baz(KotlinClass<Int>()) JavaClass.baz(KotlinClass<Int>())
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>(KotlinClass<String>()) JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>(KotlinClass<String>())<!>
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>("") JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>("")<!>
} }
@@ -1,6 +1,6 @@
fun List<String>.modify() { fun List<String>.modify() {
<!VARIABLE_EXPECTED!>this<!> += "Alpha" <!VARIABLE_EXPECTED{PSI}!>this<!> += "Alpha"
<!VARIABLE_EXPECTED!>this<!> += "Omega" <!VARIABLE_EXPECTED{PSI}!>this<!> += "Omega"
} }
fun Any.modify() { fun Any.modify() {
@@ -1,8 +1,8 @@
<!CONFLICTING_OVERLOADS{LT}!><!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") <!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
<!HIDDEN!>@kotlin.internal.LowPriorityInOverloadResolution<!> <!HIDDEN!>@kotlin.internal.LowPriorityInOverloadResolution<!>
fun foo(): Int<!> = 1<!> fun foo(): Int<!> = 1
<!CONFLICTING_OVERLOADS{LT}!><!CONFLICTING_OVERLOADS!>fun foo(): String<!> = ""<!> <!CONFLICTING_OVERLOADS!>fun foo(): String<!> = ""
fun test() { fun test() {
val s = foo() val s = foo()
@@ -2,11 +2,11 @@
class K2: J1() { class K2: J1() {
class Q : <!UNRESOLVED_REFERENCE!>Nested<!>() class Q : <!UNRESOLVED_REFERENCE!>Nested<!>()
fun bar() { fun bar() {
<!UNRESOLVED_REFERENCE!>foo<!>() <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>foo<!>()<!>
<!UNRESOLVED_REFERENCE!>baz<!>() <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>baz<!>()<!>
<!UNRESOLVED_REFERENCE!>superClass<!>() <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>superClass<!>()<!>
<!UNRESOLVED_REFERENCE!>superI<!>() <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>superI<!>()<!>
} }
} }
@@ -1424,6 +1424,22 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
public void testValOnAnnotationParameter() throws Exception { public void testValOnAnnotationParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/valOnAnnotationParameter.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/valOnAnnotationParameter.kt");
} }
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression")
@TestDataPath("$PROJECT_ROOT")
public class FunctionAsExpression extends AbstractFirDiagnosticTest {
@Test
public void testAllFilesPresentInFunctionAsExpression() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("Parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/functionAsExpression/Parameters.kt");
}
}
} }
@Nested @Nested
@@ -1457,6 +1457,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testParenthesizedAnnotations() throws Exception { public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt"); runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
} }
@Test
@TestMetadata("propagteAnyAnnotations.kt")
public void testPropagteAnyAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/propagteAnyAnnotations.kt");
}
} }
@Nested @Nested
@@ -14002,6 +14008,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt"); runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
} }
@Test
@TestMetadata("kt44440.kt")
public void testKt44440() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt");
}
@Test @Test
@TestMetadata("kt702.kt") @TestMetadata("kt702.kt")
public void testKt702() throws Exception { public void testKt702() throws Exception {
@@ -14189,6 +14201,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testSubstitutionIntoInnerClass() throws Exception { public void testSubstitutionIntoInnerClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt"); runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt");
} }
@Test
@TestMetadata("substitutionOfTypeEnhancement.kt")
public void testSubstitutionOfTypeEnhancement() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt");
}
} }
@Nested @Nested
@@ -14305,6 +14323,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inline/anonymousObjects.kt"); runTest("compiler/testData/diagnostics/tests/inline/anonymousObjects.kt");
} }
@Test
@TestMetadata("approximateReturnedAnonymousObjects.kt")
public void testApproximateReturnedAnonymousObjects() throws Exception {
runTest("compiler/testData/diagnostics/tests/inline/approximateReturnedAnonymousObjects.kt");
}
@Test @Test
@TestMetadata("assignment.kt") @TestMetadata("assignment.kt")
public void testAssignment() throws Exception { public void testAssignment() throws Exception {
@@ -20201,6 +20225,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/override.kt"); runTest("compiler/testData/diagnostics/tests/platformTypes/override.kt");
} }
@Test
@TestMetadata("propagateFlexibilityFromOtherConstraints.kt")
public void testPropagateFlexibilityFromOtherConstraints() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/propagateFlexibilityFromOtherConstraints.kt");
}
@Test @Test
@TestMetadata("rawOverrides.kt") @TestMetadata("rawOverrides.kt")
public void testRawOverrides() throws Exception { public void testRawOverrides() throws Exception {
@@ -20852,6 +20882,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
} }
@Test
@TestMetadata("buildFlexibleEnhancement.kt")
public void testBuildFlexibleEnhancement() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/buildFlexibleEnhancement.kt");
}
@Test @Test
@TestMetadata("overriddenExtensions.kt") @TestMetadata("overriddenExtensions.kt")
public void testOverriddenExtensions() throws Exception { public void testOverriddenExtensions() throws Exception {
@@ -24391,12 +24427,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/sealed/NeverFinal.kt"); runTest("compiler/testData/diagnostics/tests/sealed/NeverFinal.kt");
} }
@Test
@TestMetadata("NeverInterface.kt")
public void testNeverInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/NeverInterface.kt");
}
@Test @Test
@TestMetadata("NeverObject.kt") @TestMetadata("NeverObject.kt")
public void testNeverObject() throws Exception { public void testNeverObject() throws Exception {
@@ -27231,12 +27261,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt"); runTest("compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt");
} }
@Test
@TestMetadata("noTopLevelSealedInheritance.kt")
public void testNoTopLevelSealedInheritance() throws Exception {
runTest("compiler/testData/diagnostics/tests/sourceCompatibility/noTopLevelSealedInheritance.kt");
}
@Nested @Nested
@TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion") @TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -4906,12 +4906,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/classes/rightHandOverride.kt"); runTest("compiler/testData/codegen/box/classes/rightHandOverride.kt");
} }
@Test
@TestMetadata("sealedInSameFile.kt")
public void testSealedInSameFile() throws Exception {
runTest("compiler/testData/codegen/box/classes/sealedInSameFile.kt");
}
@Test @Test
@TestMetadata("selfcreate.kt") @TestMetadata("selfcreate.kt")
public void testSelfcreate() throws Exception { public void testSelfcreate() throws Exception {
@@ -13706,12 +13700,36 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/fir"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/fir"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
} }
@Test
@TestMetadata("ConstValAccess.kt")
public void testConstValAccess() throws Exception {
runTest("compiler/testData/codegen/box/fir/ConstValAccess.kt");
}
@Test @Test
@TestMetadata("ExtensionAlias.kt") @TestMetadata("ExtensionAlias.kt")
public void testExtensionAlias() throws Exception { public void testExtensionAlias() throws Exception {
runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt"); runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt");
} }
@Test
@TestMetadata("FakeOverrideBuilder.kt")
public void testFakeOverrideBuilder() throws Exception {
runTest("compiler/testData/codegen/box/fir/FakeOverrideBuilder.kt");
}
@Test
@TestMetadata("IrBuiltIns.kt")
public void testIrBuiltIns() throws Exception {
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
}
@Test
@TestMetadata("NameHighlighter.kt")
public void testNameHighlighter() throws Exception {
runTest("compiler/testData/codegen/box/fir/NameHighlighter.kt");
}
@Test @Test
@TestMetadata("SuspendExtension.kt") @TestMetadata("SuspendExtension.kt")
public void testSuspendExtension() throws Exception { public void testSuspendExtension() throws Exception {
@@ -18361,6 +18379,268 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
} }
} }
@Nested
@TestMetadata("compiler/testData/codegen/box/invokedynamic")
@TestDataPath("$PROJECT_ROOT")
public class Invokedynamic extends AbstractFirBlackBoxCodegenTest {
@Test
public void testAllFilesPresentInInvokedynamic() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
public class Sam extends AbstractFirBlackBoxCodegenTest {
@Test
public void testAllFilesPresentInSam() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("boundFunctionReferenceEquality.kt")
public void testBoundFunctionReferenceEquality() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundFunctionReferenceEquality.kt");
}
@Test
@TestMetadata("boundReference.kt")
public void testBoundReference() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundReference.kt");
}
@Test
@TestMetadata("builtinMemberReference.kt")
public void testBuiltinMemberReference() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/builtinMemberReference.kt");
}
@Test
@TestMetadata("capturedDispatchReceiver.kt")
public void testCapturedDispatchReceiver() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturedDispatchReceiver.kt");
}
@Test
@TestMetadata("capturedExtensionReceiver.kt")
public void testCapturedExtensionReceiver() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturedExtensionReceiver.kt");
}
@Test
@TestMetadata("capturingIndyFunInterface.kt")
public void testCapturingIndyFunInterface() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndyFunInterface.kt");
}
@Test
@TestMetadata("capturingIndySam.kt")
public void testCapturingIndySam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndySam.kt");
}
@Test
@TestMetadata("capturingVar.kt")
public void testCapturingVar() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingVar.kt");
}
@Test
@TestMetadata("constructorReference.kt")
public void testConstructorReference() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/constructorReference.kt");
}
@Test
@TestMetadata("genericFunInterface.kt")
public void testGenericFunInterface() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithPrimitive.kt")
public void testGenericFunInterfaceWithPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
}
@Test
@TestMetadata("possibleOverrideClash.kt")
public void testPossibleOverrideClash() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/possibleOverrideClash.kt");
}
@Test
@TestMetadata("primitiveVsWrapperInSam.kt")
public void testPrimitiveVsWrapperInSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
}
@Test
@TestMetadata("samConversionInsideSamConvertedLambda.kt")
public void testSamConversionInsideSamConvertedLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionInsideSamConvertedLambda.kt");
}
@Test
@TestMetadata("samConversionOnFunctionReference.kt")
public void testSamConversionOnFunctionReference() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
}
@Test
@TestMetadata("simpleIndyFunInterface.kt")
public void testSimpleIndyFunInterface() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndyFunInterface.kt");
}
@Test
@TestMetadata("simpleIndySam.kt")
public void testSimpleIndySam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@Test
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt");
}
@Test
@TestMetadata("streamApi2.kt")
public void testStreamApi2() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/streamApi2.kt");
}
@Test
@TestMetadata("suspendFunInterface.kt")
public void testSuspendFunInterface() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/suspendFunInterface.kt");
}
@Test
@TestMetadata("unboundFunctionReferenceEquality.kt")
public void testUnboundFunctionReferenceEquality() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/unboundFunctionReferenceEquality.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inline")
@TestDataPath("$PROJECT_ROOT")
public class Inline extends AbstractFirBlackBoxCodegenTest {
@Test
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("crossinlineLambda1.kt")
public void testCrossinlineLambda1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inline/crossinlineLambda1.kt");
}
@Test
@TestMetadata("crossinlineLambda2.kt")
public void testCrossinlineLambda2() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inline/crossinlineLambda2.kt");
}
@Test
@TestMetadata("inlineFunInDifferentPackage.kt")
public void testInlineFunInDifferentPackage() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inline/inlineFunInDifferentPackage.kt");
}
@Test
@TestMetadata("inlineLambda1.kt")
public void testInlineLambda1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inline/inlineLambda1.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
public class InlineClassInSignature extends AbstractFirBlackBoxCodegenTest {
@Test
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("funInterfaceWithInlineAny.kt")
public void testFunInterfaceWithInlineAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineAny.kt");
}
@Test
@TestMetadata("funInterfaceWithInlineInt.kt")
public void testFunInterfaceWithInlineInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineInt.kt");
}
@Test
@TestMetadata("funInterfaceWithInlineNAny.kt")
public void testFunInterfaceWithInlineNAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineNAny.kt");
}
@Test
@TestMetadata("funInterfaceWithInlineNInt.kt")
public void testFunInterfaceWithInlineNInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineNInt.kt");
}
@Test
@TestMetadata("funInterfaceWithInlineNString.kt")
public void testFunInterfaceWithInlineNString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineNString.kt");
}
@Test
@TestMetadata("funInterfaceWithInlineString.kt")
public void testFunInterfaceWithInlineString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/funInterfaceWithInlineString.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineAny.kt")
public void testGenericFunInterfaceWithInlineAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineAny.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineInt.kt")
public void testGenericFunInterfaceWithInlineInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineInt.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineNAny.kt")
public void testGenericFunInterfaceWithInlineNAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineNAny.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineNInt.kt")
public void testGenericFunInterfaceWithInlineNInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineNInt.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineNString.kt")
public void testGenericFunInterfaceWithInlineNString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineNString.kt");
}
@Test
@TestMetadata("genericFunInterfaceWithInlineString.kt")
public void testGenericFunInterfaceWithInlineString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature/genericFunInterfaceWithInlineString.kt");
}
}
}
}
@Nested @Nested
@TestMetadata("compiler/testData/codegen/box/ir") @TestMetadata("compiler/testData/codegen/box/ir")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -19264,6 +19544,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
@TestMetadata("compiler/testData/codegen/box/jvm8/defaults") @TestMetadata("compiler/testData/codegen/box/jvm8/defaults")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
public class Defaults extends AbstractFirBlackBoxCodegenTest { public class Defaults extends AbstractFirBlackBoxCodegenTest {
@Test
@TestMetadata("26360.kt")
public void test26360() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/26360.kt");
}
@Test @Test
@TestMetadata("accessor.kt") @TestMetadata("accessor.kt")
public void testAccessor() throws Exception { public void testAccessor() throws Exception {
@@ -33290,6 +33576,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/regressions/approximateIntersectionType.kt"); runTest("compiler/testData/codegen/box/regressions/approximateIntersectionType.kt");
} }
@Test
@TestMetadata("approximationForDefinitelyNotNull.kt")
public void testApproximationForDefinitelyNotNull() throws Exception {
runTest("compiler/testData/codegen/box/regressions/approximationForDefinitelyNotNull.kt");
}
@Test @Test
@TestMetadata("arrayLengthNPE.kt") @TestMetadata("arrayLengthNPE.kt")
public void testArrayLengthNPE() throws Exception { public void testArrayLengthNPE() throws Exception {
@@ -34224,12 +34516,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt"); runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
} }
@Test
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
}
@Test @Test
@TestMetadata("castFromAny.kt") @TestMetadata("castFromAny.kt")
public void testCastFromAny() throws Exception { public void testCastFromAny() throws Exception {
@@ -34494,6 +34780,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sealed"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sealed"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
} }
@Test
@TestMetadata("constructorAnnotations.kt")
public void testConstructorAnnotations() throws Exception {
runTest("compiler/testData/codegen/box/sealed/constructorAnnotations.kt");
}
@Test
@TestMetadata("delegatingConstructor.kt")
public void testDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/sealed/delegatingConstructor.kt");
}
@Test @Test
@TestMetadata("multipleFiles_enabled.kt") @TestMetadata("multipleFiles_enabled.kt")
public void testMultipleFiles_enabled() throws Exception { public void testMultipleFiles_enabled() throws Exception {
@@ -34506,6 +34804,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/sealed/objects.kt"); runTest("compiler/testData/codegen/box/sealed/objects.kt");
} }
@Test
@TestMetadata("sealedInSameFile.kt")
public void testSealedInSameFile() throws Exception {
runTest("compiler/testData/codegen/box/sealed/sealedInSameFile.kt");
}
@Test @Test
@TestMetadata("simple.kt") @TestMetadata("simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
@@ -34858,6 +35162,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/smartCasts"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
} }
@Test
@TestMetadata("complexExplicitReceiver.kt")
public void testComplexExplicitReceiver() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/complexExplicitReceiver.kt");
}
@Test
@TestMetadata("complexImplicitReceiver.kt")
public void testComplexImplicitReceiver() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/complexImplicitReceiver.kt");
}
@Test @Test
@TestMetadata("falseSmartCast.kt") @TestMetadata("falseSmartCast.kt")
public void testFalseSmartCast() throws Exception { public void testFalseSmartCast() throws Exception {
@@ -2140,12 +2140,24 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt"); runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt");
} }
@Test
@TestMetadata("JCTree.kt")
public void testJCTree() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/JCTree.kt");
}
@Test @Test
@TestMetadata("kt43342.kt") @TestMetadata("kt43342.kt")
public void testKt43342() throws Exception { public void testKt43342() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/kt43342.kt"); runTest("compiler/testData/ir/irText/firProblems/kt43342.kt");
} }
@Test
@TestMetadata("Modality.kt")
public void testModality() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/Modality.kt");
}
@Test @Test
@TestMetadata("MultiList.kt") @TestMetadata("MultiList.kt")
public void testMultiList() throws Exception { public void testMultiList() throws Exception {
@@ -5,10 +5,120 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
import org.jetbrains.kotlin.fir.declarations.isExpect import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.lexer.KtTokens
// Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*. // Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*.
internal fun isInsideExpectClass(containingDeclaration: FirRegularClass, context: CheckerContext): Boolean = internal fun isInsideExpectClass(containingDeclaration: FirRegularClass, context: CheckerContext): Boolean =
containingDeclaration.isExpect || context.containingDeclarations.asReversed().any { it is FirRegularClass && it.isExpect } containingDeclaration.isExpect || context.containingDeclarations.asReversed().any { it is FirRegularClass && it.isExpect }
// TODO: check class too
internal fun checkExpectDeclarationVisibilityAndBody(
declaration: FirMemberDeclaration,
source: FirSourceElement,
modifierList: FirModifierList?,
reporter: DiagnosticReporter
) {
if (declaration.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true) {
if (Visibilities.isPrivate(declaration.visibility)) {
reporter.report(source, FirErrors.EXPECTED_PRIVATE_DECLARATION)
}
if (declaration is FirSimpleFunction && declaration.hasBody) {
reporter.report(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY)
}
}
}
internal fun checkPropertyInitializer(
containingClass: FirRegularClass?,
property: FirProperty,
reporter: DiagnosticReporter
) {
val inInterface = containingClass?.isInterface == true
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
// So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = with(FirModifierList) { property.source.getModifierList() }
val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true
val isAbstract = property.isAbstract || hasAbstractModifier
if (isAbstract) {
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
property.source?.let {
reporter.report(it, FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER)
}
}
return
}
// TODO: not exactly...
val backingFieldRequired = property.hasBackingField
if (inInterface && backingFieldRequired && property.hasAccessorImplementation) {
property.source?.let {
// reporter.report(it, FirErrors.BACKING_FIELD_IN_INTERFACE)
}
}
val isExpect = property.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
when {
property.initializer != null -> {
property.initializer?.source?.let {
when {
inInterface -> {
reporter.report(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE)
}
isExpect -> {
reporter.report(it, FirErrors.EXPECTED_PROPERTY_INITIALIZER)
}
!backingFieldRequired -> {
// reporter.report(it, FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD)
}
property.receiverTypeRef != null -> {
// reporter.report(it, FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD)
}
}
}
}
property.delegate != null -> {
property.delegate?.source?.let {
when {
inInterface -> {
reporter.report(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE)
}
isExpect -> {
reporter.report(it, FirErrors.EXPECTED_DELEGATED_PROPERTY)
}
}
}
}
else -> {
val isExternal = property.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true
// TODO: need to analyze class anonymous initializer to see if the property is initialized there.
val isUninitialized = false
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && isUninitialized && !isExternal) {
property.source?.let {
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
// reporter.report(it, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT)
} else {
if (containingClass != null || property.hasAccessorImplementation) {
// reporter.report(it, FirErrors.MUST_BE_INITIALIZED)
} else {
// reporter.report(it, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT)
}
}
}
}
}
}
}
private val FirProperty.hasAccessorImplementation: Boolean
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
@@ -20,8 +21,12 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.isNullable
object FirDestructuringDeclarationChecker : FirPropertyChecker() { object FirDestructuringDeclarationChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -65,8 +70,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
val originalDestructuringDeclarationOrInitializerSource = originalDestructuringDeclarationOrInitializer.source ?: return val originalDestructuringDeclarationOrInitializerSource = originalDestructuringDeclarationOrInitializer.source ?: return
val originalDestructuringDeclarationType = val originalDestructuringDeclarationType =
when (originalDestructuringDeclarationOrInitializer) { when (originalDestructuringDeclarationOrInitializer) {
is FirVariable<*> -> originalDestructuringDeclarationOrInitializer.returnTypeRef is FirVariable<*> -> originalDestructuringDeclarationOrInitializer.returnTypeRef.coneTypeSafe<ConeKotlinType>()
is FirExpression -> originalDestructuringDeclarationOrInitializer.typeRef is FirExpression -> originalDestructuringDeclarationOrInitializer.typeRef.coneTypeSafe<ConeKotlinType>()
else -> null else -> null
} ?: return } ?: return
@@ -89,7 +94,16 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
) )
) )
} }
// TODO: COMPONENT_FUNCTION_ON_NULLABLE is ConeInapplicableCandidateError -> {
if (originalDestructuringDeclarationType.isNullable) {
reporter.report(
FirErrors.COMPONENT_FUNCTION_ON_NULLABLE.on(
originalDestructuringDeclarationOrInitializerSource,
(diagnostic.candidateSymbol.fir as FirSimpleFunction).name
)
)
}
}
// TODO: COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH // TODO: COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH
} }
} }
@@ -60,6 +60,8 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
reporter.report(FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(source, function)) reporter.report(FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(source, function))
} }
} }
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter)
} }
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extended.report import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
@@ -15,7 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
// See old FE's [DeclarationsChecker] // See old FE's [DeclarationsChecker]
@@ -34,6 +34,8 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
context: CheckerContext, context: CheckerContext,
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
val source = property.source ?: return
if (source.kind is FirFakeSourceElementKind) return
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
// So, our source of truth should be the full modifier list retrieved from the source. // So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = with(FirModifierList) { property.source.getModifierList() } val modifierList = with(FirModifierList) { property.source.getModifierList() }
@@ -56,18 +58,14 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
return return
} }
} }
property.initializer?.source?.let {
if (property.delegate != null) { reporter.report(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER)
property.delegate!!.source?.let { }
if (containingDeclaration.isInterface) { property.delegate?.source?.let {
reporter.report(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE) reporter.report(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY)
} else {
reporter.report(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY)
}
}
} }
checkAccessor(property.getter, property.delegate) { src, symbol -> checkAccessor(property.getter, property.delegate) { src, _ ->
reporter.report(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER) reporter.report(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER)
} }
checkAccessor(property.setter, property.delegate) { src, symbol -> checkAccessor(property.setter, property.delegate) { src, symbol ->
@@ -79,7 +77,7 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
} }
} }
checkPropertyInitializer(containingDeclaration, property, isAbstract, reporter) checkPropertyInitializer(containingDeclaration, property, reporter)
val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true
if (hasOpenModifier && if (hasOpenModifier &&
@@ -100,28 +98,8 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
} }
} }
} }
}
private fun checkPropertyInitializer( checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
containingDeclaration: FirRegularClass,
property: FirProperty,
propertyIsAbstract: Boolean,
reporter: DiagnosticReporter
) {
property.initializer?.source?.let {
if (propertyIsAbstract) {
reporter.report(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER)
} else if (containingDeclaration.isInterface) {
reporter.report(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE)
}
}
if (propertyIsAbstract) {
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
property.source?.let {
reporter.report(it, FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER)
}
}
}
} }
private fun checkAccessor( private fun checkAccessor(
@@ -135,5 +113,4 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
} }
} }
} }
} }
@@ -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.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
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.declarations.*
import org.jetbrains.kotlin.lexer.KtTokens
// See old FE's [DeclarationsChecker]
object FirTopLevelFunctionChecker : FirFileChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
for (topLevelDeclaration in declaration.declarations) {
if (topLevelDeclaration is FirSimpleFunction) {
checkFunction(topLevelDeclaration, reporter)
}
}
}
private fun checkFunction(function: FirSimpleFunction, reporter: DiagnosticReporter) {
val source = function.source ?: return
if (source.kind is FirFakeSourceElementKind) return
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
// So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = with(FirModifierList) { source.getModifierList() }
if (modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true) return
if (function.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true) return
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
if (!function.hasBody && !isExpect) {
reporter.report(FirErrors.NON_MEMBER_FUNCTION_NO_BODY.on(source, function))
}
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter)
}
}
@@ -0,0 +1,32 @@
/*
* 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.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty
// See old FE's [DeclarationsChecker]
object FirTopLevelPropertyChecker : FirFileChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
for (topLevelDeclaration in declaration.declarations) {
if (topLevelDeclaration is FirProperty) {
checkProperty(topLevelDeclaration, reporter)
}
}
}
private fun checkProperty(property: FirProperty, reporter: DiagnosticReporter) {
val source = property.source ?: return
if (source.kind is FirFakeSourceElementKind) return
val modifierList = with(FirModifierList) { source.getModifierList() }
checkPropertyInitializer(null, property, reporter)
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
}
}
@@ -0,0 +1,30 @@
/*
* 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.extended.report
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.FirStatement
object FirAnonymousFunctionChecker : FirExpressionChecker<FirStatement>() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
if (expression !is FirAnonymousFunction) {
return
}
for (valueParameter in expression.valueParameters) {
val source = valueParameter.source ?: continue
if (valueParameter.defaultValue != null) {
reporter.report(source, FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE)
}
if (valueParameter.isVararg) {
reporter.report(source, FirErrors.USELESS_VARARG_ON_PARAMETER)
}
}
}
}
@@ -10,9 +10,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.* import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.*
@@ -20,8 +18,9 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableWrongReceiver
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -62,7 +61,10 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
// Will be handled by [FirDestructuringDeclarationChecker] // Will be handled by [FirDestructuringDeclarationChecker]
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) { if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) {
// TODO: if all diagnostics are supported, we don't need the following check, and will bail out based on element type. // TODO: if all diagnostics are supported, we don't need the following check, and will bail out based on element type.
if (diagnostic is ConeUnresolvedNameError || diagnostic is ConeAmbiguityError) { if (diagnostic is ConeUnresolvedNameError ||
diagnostic is ConeAmbiguityError ||
diagnostic is ConeInapplicableCandidateError
) {
return return
} }
} }
@@ -72,7 +74,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.classId.asString()) is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.classId.asString())
is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.name.asString()) is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.name.asString())
is ConeHiddenCandidateError -> FirErrors.HIDDEN.on(source, diagnostic.candidateSymbol) is ConeHiddenCandidateError -> FirErrors.HIDDEN.on(source, diagnostic.candidateSymbol)
is ConeInapplicableCandidateError -> FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidateSymbol) is ConeInapplicableCandidateError -> mapInapplicableCandidateError(diagnostic, source)
is ConeAmbiguityError -> if (!diagnostic.applicability.isSuccess) { is ConeAmbiguityError -> if (!diagnostic.applicability.isSuccess) {
FirErrors.NONE_APPLICABLE.on(source, diagnostic.candidates) FirErrors.NONE_APPLICABLE.on(source, diagnostic.candidates)
} else { } else {
@@ -98,6 +100,37 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
reporter.report(coneDiagnostic) reporter.report(coneDiagnostic)
} }
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
return when (this) {
is ConeClassLikeType -> !isMarkedNullable
is ConeTypeParameterType -> !isMarkedNullable && lookupTag.typeParameterSymbol.fir.bounds.any {
it.coneTypeSafe<ConeKotlinType>()?.isEffectivelyNotNull() == true
}
else -> false
}
}
private fun mapInapplicableCandidateError(
diagnostic: ConeInapplicableCandidateError,
source: FirSourceElement,
): FirDiagnostic<*> {
// TODO: Need to distinguish SMARTCAST_IMPOSSIBLE
// TODO: handle other UNSAFE_* variants: invoke, infix, operator
val rootCause = diagnostic.diagnostics.find { it.applicability == diagnostic.applicability }
if (rootCause != null &&
rootCause is InapplicableWrongReceiver &&
rootCause.actualType?.isNullable == true &&
(rootCause.expectedType == null || !rootCause.expectedType!!.isMarkedNullable)
) {
val expectedType = rootCause.expectedType
if (expectedType == null || expectedType.isEffectivelyNotNull()) {
return FirErrors.UNSAFE_CALL.on(source, rootCause.actualType!!)
}
}
return FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidateSymbol)
}
private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceElement, *> { private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceElement, *> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return when (kind) { return when (kind) {
@@ -10,11 +10,16 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecke
import org.jetbrains.kotlin.fir.analysis.checkersComponent import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) { class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
private val checkers = session.checkersComponent.expressionCheckers private val checkers = session.checkersComponent.expressionCheckers
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
checkers.basicExpressionCheckers.check(anonymousFunction, data, reporter)
}
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) { override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) {
checkers.basicExpressionCheckers.check(typeOperatorCall, data, reporter) checkers.basicExpressionCheckers.check(typeOperatorCall, data, reporter)
} }
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANY_METHOD_IMPLEMENTED_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANY_METHOD_IMPLEMENTED_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGNED_VALUE_IS_NEVER_READ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGNED_VALUE_IS_NEVER_READ
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_MISSING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_MISSING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_ON_NULLABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE
@@ -49,6 +51,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_E
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DECLARATION_WITH_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DELEGATED_PROPERTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PRIVATE_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PROPERTY_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_FUNCTION_RETURN_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_FUNCTION_RETURN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PARAMETER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PARAMETER_TYPE
@@ -79,6 +85,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
@@ -131,8 +138,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL 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.UNRESOLVED_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_EXPECTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_NEVER_READ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_NEVER_READ
@@ -357,9 +366,16 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(ABSTRACT_FUNCTION_WITH_BODY, "A function ''{0}'' with body cannot be abstract", DECLARATION_NAME) map.put(ABSTRACT_FUNCTION_WITH_BODY, "A function ''{0}'' with body cannot be abstract", DECLARATION_NAME)
map.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without a body must be abstract", DECLARATION_NAME) map.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without a body must be abstract", DECLARATION_NAME)
map.put(PRIVATE_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be private", DECLARATION_NAME) map.put(PRIVATE_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be private", DECLARATION_NAME)
map.put(NON_MEMBER_FUNCTION_NO_BODY, "Function ''{0}'' must have a body", DECLARATION_NAME)
map.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name") map.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name")
map.put(
ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE,
"An anonymous function is not allowed to specify default values for its parameters"
)
map.put(USELESS_VARARG_ON_PARAMETER, "Vararg on this parameter is useless")
// Properties & accessors // Properties & accessors
map.put( map.put(
ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS,
@@ -384,6 +400,12 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, "Private setters are not allowed for abstract properties") map.put(PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, "Private setters are not allowed for abstract properties")
map.put(PRIVATE_SETTER_FOR_OPEN_PROPERTY, "Private setters are not allowed for open properties") map.put(PRIVATE_SETTER_FOR_OPEN_PROPERTY, "Private setters are not allowed for open properties")
// Multi-platform projects
map.put(EXPECTED_DECLARATION_WITH_BODY, "Expected declaration must not have a body")
map.put(EXPECTED_PROPERTY_INITIALIZER, "Expected property cannot have an initializer")
map.put(EXPECTED_DELEGATED_PROPERTY, "Expected property cannot be delegated")
map.put(EXPECTED_PRIVATE_DECLARATION, "Expected declaration cannot be private")
// Destructuring declaration // Destructuring declaration
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration") map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
map.put( map.put(
@@ -398,6 +420,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
TO_STRING, TO_STRING,
AMBIGUOUS_CALLS AMBIGUOUS_CALLS
) )
map.put(
COMPONENT_FUNCTION_ON_NULLABLE,
"Not nullable value required to call ''{0}()'' function of destructuring declaration initializer",
TO_STRING
)
// Control flow diagnostics // Control flow diagnostics
map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", PROPERTY_NAME) map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", PROPERTY_NAME)
@@ -411,6 +438,18 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(LEAKED_IN_PLACE_LAMBDA, "Leaked in-place lambda: {2}", SYMBOL) map.put(LEAKED_IN_PLACE_LAMBDA, "Leaked in-place lambda: {2}", SYMBOL)
map.put(FirErrors.WRONG_IMPLIES_CONDITION, "Wrong implies condition") map.put(FirErrors.WRONG_IMPLIES_CONDITION, "Wrong implies condition")
// Nullability
map.put(
UNSAFE_CALL,
"Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type {0}",
RENDER_TYPE
)
//map.put(
// UNSAFE_IMPLICIT_INVOKE_CALL,
// "Reference has a nullable type ''{0}'', use explicit \"?.invoke\" to make a function-like call instead.",
// RENDER_TYPE
//)
// Extended checkers group // Extended checkers group
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier") map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier") map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.render
object FirDiagnosticRenderers { object FirDiagnosticRenderers {
val NULLABLE_STRING = Renderer<String?> { it ?: "null" } val NULLABLE_STRING = Renderer<String?> { it ?: "null" }
@@ -58,9 +59,9 @@ object FirDiagnosticRenderers {
name.asString() name.asString()
} }
val RENDER_TYPE = Renderer { typeRef: FirTypeRef -> val RENDER_TYPE = Renderer { t: ConeKotlinType ->
// TODO: need a way to tune granuality, e.g., without parameter names in functional types. // TODO: need a way to tune granuality, e.g., without parameter names in functional types.
typeRef.render() t.render()
} }
val AMBIGUOUS_CALLS = Renderer { candidates: Collection<AbstractFirBasedSymbol<*>> -> val AMBIGUOUS_CALLS = Renderer { candidates: Collection<AbstractFirBasedSymbol<*>> ->
@@ -155,31 +155,51 @@ object FirErrors {
val ABSTRACT_FUNCTION_WITH_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER) val ABSTRACT_FUNCTION_WITH_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
val NON_ABSTRACT_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val NON_ABSTRACT_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val PRIVATE_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val PRIVATE_FUNCTION_WITH_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val NON_MEMBER_FUNCTION_NO_BODY by error1<FirSourceElement, KtFunction, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val FUNCTION_DECLARATION_WITH_NO_NAME by error0<FirSourceElement, KtFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val FUNCTION_DECLARATION_WITH_NO_NAME by error0<FirSourceElement, KtFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// TODO: val ANONYMOUS_FUNCTION_WITH_NAME by error1<FirSourceElement, PsiElement, Name>(SourceElementPositioningStrategies.DECLARATION_NAME)
val ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE by error0<FirSourceElement, KtParameter>(SourceElementPositioningStrategies.PARAMETER_DEFAULT_VALUE)
val USELESS_VARARG_ON_PARAMETER by warning0<FirSourceElement, KtParameter>()
// Properties & accessors // Properties & accessors
val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error2<FirSourceElement, KtModifierListOwner, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER) val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error2<FirSourceElement, KtModifierListOwner, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
val PRIVATE_PROPERTY_IN_INTERFACE by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val PRIVATE_PROPERTY_IN_INTERFACE by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val ABSTRACT_PROPERTY_WITH_INITIALIZER by error0<FirSourceElement, KtExpression>() val ABSTRACT_PROPERTY_WITH_INITIALIZER by error0<FirSourceElement, KtExpression>()
// TODO: val MUST_BE_INITIALIZED by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// TODO: val MUST_BE_INITIALIZED_OR_BE_ABSTRACT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// TODO: val EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// TODO: val EXTENSION_PROPERTY_WITH_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
// TODO: val PROPERTY_INITIALIZER_NO_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
val PROPERTY_INITIALIZER_IN_INTERFACE by error0<FirSourceElement, KtExpression>() val PROPERTY_INITIALIZER_IN_INTERFACE by error0<FirSourceElement, KtExpression>()
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
// TODO: val BACKING_FIELD_IN_INTERFACE by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val ABSTRACT_DELEGATED_PROPERTY by error0<FirSourceElement, KtPropertyDelegate>() val ABSTRACT_DELEGATED_PROPERTY by error0<FirSourceElement, KtPropertyDelegate>()
val DELEGATED_PROPERTY_IN_INTERFACE by error0<FirSourceElement, KtPropertyDelegate>() val DELEGATED_PROPERTY_IN_INTERFACE by error0<FirSourceElement, KtPropertyDelegate>()
// TODO: val ACCESSOR_FOR_DELEGATED_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>() // TODO: val ACCESSOR_FOR_DELEGATED_PROPERTY by error1<FirSourceElement, KtPropertyAccessor, FirPropertyAccessorSymbol>()
val ABSTRACT_PROPERTY_WITH_GETTER by error0<FirSourceElement, KtPropertyAccessor>() val ABSTRACT_PROPERTY_WITH_GETTER by error0<FirSourceElement, KtPropertyAccessor>()
val ABSTRACT_PROPERTY_WITH_SETTER by error0<FirSourceElement, KtPropertyAccessor>() val ABSTRACT_PROPERTY_WITH_SETTER by error0<FirSourceElement, KtPropertyAccessor>()
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error0<FirSourceElement, PsiElement>() val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error0<FirSourceElement, PsiElement>()
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error0<FirSourceElement, PsiElement>() val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error0<FirSourceElement, PsiElement>()
// Multi-platform projects
val EXPECTED_DECLARATION_WITH_BODY by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val EXPECTED_PROPERTY_INITIALIZER by error0<FirSourceElement, KtExpression>()
// TODO: need to cover `by` as well as delegate expression
val EXPECTED_DELEGATED_PROPERTY by error0<FirSourceElement, KtPropertyDelegate>()
val EXPECTED_PRIVATE_DECLARATION by error0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
// Destructuring declaration // Destructuring declaration
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, KtDestructuringDeclaration>() val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, KtDestructuringDeclaration>()
val COMPONENT_FUNCTION_MISSING by error2<FirSourceElement, PsiElement, Name, FirTypeRef>() val COMPONENT_FUNCTION_MISSING by error2<FirSourceElement, KtExpression, Name, ConeKotlinType>()
val COMPONENT_FUNCTION_AMBIGUITY by error2<FirSourceElement, PsiElement, Name, Collection<AbstractFirBasedSymbol<*>>>() val COMPONENT_FUNCTION_AMBIGUITY by error2<FirSourceElement, KtExpression, Name, Collection<AbstractFirBasedSymbol<*>>>()
// TODO: val COMPONENT_FUNCTION_ON_NULLABLE by ... val COMPONENT_FUNCTION_ON_NULLABLE by error1<FirSourceElement, KtExpression, Name>()
// TODO: val COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH by ... // TODO: val COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH by ...
// Control flow diagnostics // Control flow diagnostics
@@ -188,6 +208,13 @@ object FirErrors {
val LEAKED_IN_PLACE_LAMBDA by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>() val LEAKED_IN_PLACE_LAMBDA by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>()
val WRONG_IMPLIES_CONDITION by warning0<FirSourceElement, PsiElement>() val WRONG_IMPLIES_CONDITION by warning0<FirSourceElement, PsiElement>()
// Nullability
val UNSAFE_CALL by error1<FirSourceElement, PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.DOT_BY_SELECTOR)
// TODO: val UNSAFE_IMPLICIT_INVOKE_CALL by error1<FirSourceElement, PsiElement, ConeKotlinType>()
// TODO: val UNSAFE_INFIX_CALL by ...
// TODO: val UNSAFE_OPERATOR_CALL by ...
// TODO: val UNEXPECTED_SAFE_CALL by ...
// Extended checkers group // Extended checkers group
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER) val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
@@ -247,6 +247,50 @@ object LightTreePositioningStrategies {
return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node) return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node)
} }
} }
val PARAMETER_DEFAULT_VALUE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
val defaultValueElement = tree.defaultValue(node) ?: node
return markElement(defaultValueElement, startOffset, endOffset, tree, node)
}
}
val PARAMETER_VARARG_MODIFIER: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
val modifier = tree.modifierList(node)?.let { modifierList -> tree.findChildByType(modifierList, KtTokens.VARARG_KEYWORD) }
return markElement(modifier ?: node, startOffset, endOffset, tree, node)
}
}
val DOT_BY_SELECTOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
if (node.tokenType != KtNodeTypes.REFERENCE_EXPRESSION && node.tokenType != KtNodeTypes.CALL_EXPRESSION) {
// TODO: normally CALL_EXPRESSION should not be here. In PSI we have REFERENCE_EXPRESSION even for x.bar() case
// Remove CALL_EXPRESSION from here and repeat code below twice (see PSI counterpart) when fixed
return super.mark(node, startOffset, endOffset, tree)
}
val parentNode = tree.getParent(node) ?: return super.mark(node, startOffset, endOffset, tree)
if (parentNode.tokenType == KtNodeTypes.DOT_QUALIFIED_EXPRESSION) {
return markElement(tree.dotOperator(parentNode) ?: node, startOffset, endOffset, tree, node)
}
return super.mark(node, startOffset, endOffset, tree)
}
}
} }
fun FirSourceElement.hasValOrVar(): Boolean = fun FirSourceElement.hasValOrVar(): Boolean =
@@ -261,6 +305,9 @@ fun FirSourceElement.hasPrimaryConstructor(): Boolean =
private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? = private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.CONSTRUCTOR_KEYWORD) findChildByType(node, KtTokens.CONSTRUCTOR_KEYWORD)
private fun FlyweightCapableTreeStructure<LighterASTNode>.dotOperator(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.DOT)
private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: LighterASTNode): LighterASTNode? = private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.INIT_KEYWORD) findChildByType(node, KtTokens.INIT_KEYWORD)
@@ -317,6 +364,19 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.receiverTypeReference(
} }
} }
private fun FlyweightCapableTreeStructure<LighterASTNode>.defaultValue(node: LighterASTNode): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
// p : T = v
val children = childrenRef.get()?.reversed() ?: return null
for (child in children) {
if (child == null || child.tokenType == KtTokens.WHITE_SPACE) continue
if (child.tokenType == KtNodeTypes.TYPE_REFERENCE || child.tokenType == KtTokens.COLON) return null
return child
}
return null
}
fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: IElementType): LighterASTNode? { fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: IElementType): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>() val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef) getChildren(node, childrenRef)
@@ -52,4 +52,19 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.OPERATOR, LightTreePositioningStrategies.OPERATOR,
PositioningStrategies.OPERATOR PositioningStrategies.OPERATOR
) )
val PARAMETER_DEFAULT_VALUE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PARAMETER_DEFAULT_VALUE,
PositioningStrategies.PARAMETER_DEFAULT_VALUE
)
val PARAMETER_VARARG_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PARAMETER_VARARG_MODIFIER,
PositioningStrategies.PARAMETER_VARARG_MODIFIER
)
val DOT_BY_SELECTOR = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DOT_BY_SELECTOR,
PositioningStrategies.DOT_BY_SELECTOR
)
} }
@@ -59,6 +59,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirConstructorAllowedChecker, FirConstructorAllowedChecker,
) )
override val fileCheckers: Set<FirFileChecker> = setOf(
FirTopLevelFunctionChecker,
FirTopLevelPropertyChecker,
)
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf( override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
FirCallsEffectAnalyzer, FirCallsEffectAnalyzer,
FirReturnsImpliesAnalyzer, FirReturnsImpliesAnalyzer,
@@ -8,6 +8,10 @@ package org.jetbrains.kotlin.fir.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.* import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
object CommonExpressionCheckers : ExpressionCheckers() { object CommonExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker> = setOf(
FirAnonymousFunctionChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf( override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
FirSuperNotAvailableChecker, FirSuperNotAvailableChecker,
FirNotASupertypeChecker, FirNotASupertypeChecker,
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.session
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.CheckersComponent import org.jetbrains.kotlin.fir.analysis.CheckersComponent
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
import org.jetbrains.kotlin.fir.extensions.FirExtensionService import org.jetbrains.kotlin.fir.extensions.FirExtensionService
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
@@ -40,6 +42,12 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(InferenceComponents::class, InferenceComponents(this)) register(InferenceComponents::class, InferenceComponents(this))
} }
@OptIn(SessionConfiguration::class)
fun FirSession.registerThreadUnsafeCaches() {
register(FirCachesFactory::class, FirThreadUnsafeCachesFactory)
}
// -------------------------- Resolve components -------------------------- // -------------------------- Resolve components --------------------------
/* /*
@@ -19,6 +19,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
@@ -68,6 +70,7 @@ object FirSessionFactory {
init: FirSessionConfigurator.() -> Unit = {} init: FirSessionConfigurator.() -> Unit = {}
): FirJavaModuleBasedSession { ): FirJavaModuleBasedSession {
return FirJavaModuleBasedSession(moduleInfo, sessionProvider).apply { return FirJavaModuleBasedSession(moduleInfo, sessionProvider).apply {
registerThreadUnsafeCaches()
registerCommonComponents(languageVersionSettings) registerCommonComponents(languageVersionSettings)
registerResolveComponents() registerResolveComponents()
registerJavaSpecificResolveComponents() registerJavaSpecificResolveComponents()
@@ -113,6 +116,7 @@ object FirSessionFactory {
val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(scope) val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(scope)
return FirLibrarySession(moduleInfo, sessionProvider).apply { return FirLibrarySession(moduleInfo, sessionProvider).apply {
registerThreadUnsafeCaches()
registerCommonComponents(languageVersionSettings) registerCommonComponents(languageVersionSettings)
val javaSymbolProvider = JavaSymbolProvider(this, project, scope) val javaSymbolProvider = JavaSymbolProvider(this, project, scope)
@@ -714,11 +714,12 @@ class FirElementSerializer private constructor(
private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int { private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int {
// [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations, // [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations,
// user-contributed visibility, and modifiers, such as `external` or `inline`. // user-contributed visibility, and modifiers, such as `external` or `inline`.
val nonSourceAnnotations = accessor.nonSourceAnnotations(session)
val isDefault = accessor is FirDefaultPropertyAccessor && val isDefault = accessor is FirDefaultPropertyAccessor &&
accessor.annotations.isEmpty() && accessor.visibility == property.visibility && nonSourceAnnotations.isEmpty() && accessor.visibility == property.visibility &&
!accessor.isExternal && !accessor.isInline !accessor.isExternal && !accessor.isInline
return Flags.getAccessorFlags( return Flags.getAccessorFlags(
accessor.nonSourceAnnotations(session).isNotEmpty(), nonSourceAnnotations.isNotEmpty(),
ProtoEnumFlags.visibility(normalizeVisibility(accessor)), ProtoEnumFlags.visibility(normalizeVisibility(accessor)),
ProtoEnumFlags.modality(accessor.modality!!), ProtoEnumFlags.modality(accessor.modality!!),
!isDefault, !isDefault,
@@ -232,7 +232,19 @@ internal tailrec fun FirCallableSymbol<*>.unwrapCallRepresentative(root: FirCall
val originalForTypeAlias = fir.originalConstructorIfTypeAlias val originalForTypeAlias = fir.originalConstructorIfTypeAlias
if (originalForTypeAlias != null) return originalForTypeAlias.symbol.unwrapCallRepresentative(this) if (originalForTypeAlias != null) return originalForTypeAlias.symbol.unwrapCallRepresentative(this)
} }
if (fir.isIntersectionOverride) return this
if (fir.isIntersectionOverride) {
// We've got IR declarations (fake overrides) for intersection overrides in classes, but not for intersection types
// interface A { fun foo() }
// interface B { fun foo() }
// interface C : A, B // for C.foo we've got an IR fake override
// for {A & B} we don't have such an IR declaration, so we're unwrapping it
if (fir is FirCallableMemberDeclaration && fir.dispatchReceiverType is ConeIntersectionType) {
return fir.baseForIntersectionOverride!!.symbol.unwrapCallRepresentative(this)
}
return this
}
val overriddenSymbol = fir.originalForSubstitutionOverride?.takeIf { val overriddenSymbol = fir.originalForSubstitutionOverride?.takeIf {
it.containingClass() == root.containingClass() it.containingClass() == root.containingClass()
@@ -1026,7 +1026,7 @@ class Fir2IrDeclarationStorage(
val irFunction = fir.convertWithOffsets { startOffset, endOffset -> val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) { symbolTable.declareSimpleFunction(signature, { symbol }) {
val isFakeOverride = val isFakeOverride =
firFunctionSymbol is FirNamedFunctionSymbol && fir.isSubstitutionOverride && firFunctionSymbol is FirNamedFunctionSymbol && fir.isSubstitutionOrIntersectionOverride &&
firFunctionSymbol.dispatchReceiverClassOrNull() != firFunctionSymbol.dispatchReceiverClassOrNull() !=
firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull() firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazySimpleFunction( Fir2IrLazySimpleFunction(
@@ -1065,7 +1065,7 @@ class Fir2IrDeclarationStorage(
val irProperty = fir.convertWithOffsets { startOffset, endOffset -> val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareProperty(signature, { symbol }) { symbolTable.declareProperty(signature, { symbol }) {
val isFakeOverride = val isFakeOverride =
fir.isSubstitutionOverride && fir.isSubstitutionOrIntersectionOverride &&
firPropertySymbol.dispatchReceiverClassOrNull() != firPropertySymbol.dispatchReceiverClassOrNull() !=
firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull() firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazyProperty( Fir2IrLazyProperty(
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.baseForIntersectionOverride
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement
@@ -16,25 +16,21 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.removeAnnotations import org.jetbrains.kotlin.ir.types.removeAnnotations
import org.jetbrains.kotlin.ir.types.withHasQuestionMark import org.jetbrains.kotlin.ir.types.withHasQuestionMark
import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.AbstractTypeChecker
class Fir2IrImplicitCastInserter( class Fir2IrImplicitCastInserter(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
@@ -285,58 +281,29 @@ class Fir2IrImplicitCastInserter(
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef) return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
} }
internal fun convertToImplicitCastExpression( internal fun implicitCastFromDispatchReceiver(
expressionWithSmartcast: FirExpressionWithSmartcast, calleeReference: FirReference original: IrExpression,
originalTypeRef: FirTypeRef,
calleeReference: FirReference,
): IrExpression { ): IrExpression {
val originalExpression = expressionWithSmartcast.originalExpression val referencedDeclaration =
val value = visitor.convertToIrExpression(originalExpression) ((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirCallableSymbol<*>)?.unwrapCallRepresentative()
val castTypeRef = expressionWithSmartcast.typeRef ?.fir as? FirCallableMemberDeclaration<*>
if (calleeReference !is FirResolvedNamedReference) {
return implicitCastOrExpression(value, castTypeRef)
}
val referencedSymbol = calleeReference.resolvedSymbol
if (referencedSymbol !is FirPropertySymbol && referencedSymbol !is FirFunctionSymbol) {
return implicitCastOrExpression(value, castTypeRef)
}
val originalTypeRef = expressionWithSmartcast.originalType val dispatchReceiverType =
if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) { referencedDeclaration?.dispatchReceiverType as? ConeClassLikeType
val castType = castTypeRef.type ?: return implicitCastOrExpression(original, originalTypeRef)
if (castType is ConeIntersectionType) {
val unwrappedSymbol = (referencedSymbol as? FirCallableSymbol)?.baseForIntersectionOverride ?: referencedSymbol val starProjectedDispatchReceiver = dispatchReceiverType.replaceArgumentsWithStarProjections()
castType.intersectedTypes.forEach {
if (it.doesContainReferencedSymbolInScope(unwrappedSymbol, calleeReference.name)) { val castType = originalTypeRef.coneTypeSafe<ConeIntersectionType>()
return implicitCastOrExpression(value, it) castType?.intersectedTypes?.forEach { componentType ->
} if (AbstractTypeChecker.isSubtypeOf(session.typeContext, componentType, starProjectedDispatchReceiver)) {
} return implicitCastOrExpression(original, componentType)
} }
} }
return if (originalExpression is FirThisReceiverExpression &&
originalExpression.calleeReference.boundSymbol is FirAnonymousFunctionSymbol
) {
// If the original is a "this" in a local function and original.type is the same as castType,
// we still want to keep the cast. See kt-42517
implicitCast(value, castTypeRef.toIrType())
} else {
implicitCastOrExpression(value, castTypeRef.toIrType())
}
}
private fun ConeKotlinType.doesContainReferencedSymbolInScope( return implicitCastOrExpression(original, originalTypeRef)
referencedSymbol: AbstractFirBasedSymbol<*>, name: Name
): Boolean {
val scope = scope(session, components.scopeSession, FakeOverrideTypeCalculator.Forced) ?: return false
var result = false
val processor = { it: FirCallableSymbol<*> ->
if (!result && it == referencedSymbol) {
result = true
}
}
when (referencedSymbol) {
is FirPropertySymbol -> scope.processPropertiesByName(name, processor)
is FirFunctionSymbol -> scope.processFunctionsByName(name, processor)
}
return result
} }
private fun implicitCastOrExpression(original: IrExpression, castType: ConeKotlinType): IrExpression { private fun implicitCastOrExpression(original: IrExpression, castType: ConeKotlinType): IrExpression {
@@ -348,7 +315,8 @@ class Fir2IrImplicitCastInserter(
} }
internal fun implicitCastOrExpression(original: IrExpression, castType: IrType): IrExpression { internal fun implicitCastOrExpression(original: IrExpression, castType: IrType): IrExpression {
return original.takeIf { it.type == castType } ?: implicitCast(original, castType) if (original.type.makeNotNull() == castType.makeNotNull()) return original
return implicitCast(original, castType)
} }
private fun implicitCast(original: IrExpression, castType: IrType): IrExpression { private fun implicitCast(original: IrExpression, castType: IrType): IrExpression {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.isIteratorNext import org.jetbrains.kotlin.fir.resolve.isIteratorNext
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -470,16 +471,16 @@ class Fir2IrVisitor(
} }
} }
private fun convertToIrReceiverExpression( internal fun convertToIrReceiverExpression(
expression: FirExpression?, expression: FirExpression?,
calleeReference: FirReference, calleeReference: FirReference,
callableReferenceAccess: FirCallableReferenceAccess? = null callableReferenceAccess: FirCallableReferenceAccess? = null
): IrExpression? { ): IrExpression? {
return when (expression) { return when (expression) {
null -> null null -> return null
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess) is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess)
is FirExpressionWithSmartcast -> implicitCastInserter.convertToImplicitCastExpression(expression, calleeReference) is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess, is FirExpressionWithSmartcast ->
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression) convertToIrExpression(expression)
else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) { else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) {
val variableAsFunctionMode = calleeReference is FirResolvedNamedReference && val variableAsFunctionMode = calleeReference is FirResolvedNamedReference &&
calleeReference.name != OperatorNameConventions.INVOKE && calleeReference.name != OperatorNameConventions.INVOKE &&
@@ -491,6 +492,10 @@ class Fir2IrVisitor(
} else { } else {
convertToIrExpression(expression) convertToIrExpression(expression)
} }
}?.run {
if (expression is FirQualifiedAccessExpression && expression.calleeReference is FirSuperReference) return@run this
implicitCastInserter.implicitCastFromDispatchReceiver(this, expression.typeRef, calleeReference)
} }
} }
@@ -713,10 +713,9 @@ class CallAndReferenceGenerator(
if (firReceiver == explicitReceiver) { if (firReceiver == explicitReceiver) {
return explicitReceiverExpression return explicitReceiverExpression
} }
if (firReceiver is FirResolvedQualifier) {
return convertToGetObject(firReceiver, this as? FirCallableReferenceAccess) return firReceiver.takeIf { it !is FirNoReceiverExpression }
} ?.let { visitor.convertToIrReceiverExpression(it, calleeReference, this as? FirCallableReferenceAccess) }
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
?: explicitReceiverExpression ?: explicitReceiverExpression
?: run { ?: run {
if (this is FirCallableReferenceAccess) return null if (this is FirCallableReferenceAccess) return null
@@ -192,8 +192,10 @@ class FakeOverrideGenerator(
): List<S> { ): List<S> {
if (symbol.fir.origin != FirDeclarationOrigin.IntersectionOverride) return listOf(basedSymbol) if (symbol.fir.origin != FirDeclarationOrigin.IntersectionOverride) return listOf(basedSymbol)
return scope.directOverridden(symbol).map { return scope.directOverridden(symbol).map {
// Unwrapping should happen only for fake overrides members from the same class, not from supertypes
if (it.dispatchReceiverClassOrNull() != containingClass) return@map it
when { when {
it.fir.isSubstitutionOverride && it.dispatchReceiverClassOrNull() == containingClass -> it.fir.isSubstitutionOverride ->
it.originalForSubstitutionOverride!! it.originalForSubstitutionOverride!!
it.fir.origin == FirDeclarationOrigin.Delegated -> it.fir.origin == FirDeclarationOrigin.Delegated ->
it.fir.delegatedWrapperData?.wrapped?.symbol!! as S it.fir.delegatedWrapperData?.wrapped?.symbol!! as S
@@ -127,6 +127,7 @@ class Fir2IrLazyProperty(
} }
override var getter: IrSimpleFunction? by lazyVar { override var getter: IrSimpleFunction? by lazyVar {
if (fir.isConst) return@lazyVar null
Fir2IrLazyPropertyAccessor( Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset, components, startOffset, endOffset,
when { when {

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