[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" />
</profile>
</component>
<component name="GithubSharedProjectSettings">
<option name="branchProtectionPatterns">
<list>
<option value="master" />
</list>
</option>
</component>
<component name="IssueNavigationConfiguration">
<option name="links">
<list>
+1
View File
@@ -18,6 +18,7 @@ Some handy links:
* [Issue Tracker](https://youtrack.jetbrains.com/issues/KT)
* [Forum](https://discuss.kotlinlang.org/)
* [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)
* [Public Slack channel](https://slack.kotlinlang.org/)
* [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 isGradleEnabled: 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 {
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 GRADLE_LOG = "gradle-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 matchedName = when {
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
isGradleEnabled && GRADLE_LOG in files -> GRADLE_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))
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
if (annotationDataEncoded != null) {
ByteArrayInputStream(BitEncoding.decodeBytes(annotationDataEncoded)).use {
input ->
when (classHeader.kind) {
KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
ByteArrayInputStream(BitEncoding.decodeBytes(classHeader.data!!)).use { 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)}")
if (!classHeader.metadataVersion.isCompatible()) {
error("Incompatible class ($classHeader): $classFile")
}
when (classHeader.kind) {
KotlinClassHeader.Kind.FILE_FACADE ->
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()
when (classHeader.kind) {
KotlinClassHeader.Kind.FILE_FACADE ->
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 -> error(classHeader.kind)
}
}
}
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()
+6 -7
View File
@@ -74,7 +74,7 @@ val kotlinVersion by extra(
} ?: buildNumber
)
val kotlinLanguageVersion by extra("1.4")
val kotlinLanguageVersion by extra("1.5")
allprojects {
group = "org.jetbrains.kotlin"
@@ -166,13 +166,12 @@ extra["versions.jansi"] = "1.16"
extra["versions.jline"] = "3.3.1"
extra["versions.junit"] = "4.12"
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.kotlinx-coroutines-core"] = "1.3.8"
extra["versions.kotlinx-coroutines-jdk8"] = "1.3.8"
extra["versions.json"] = "20160807"
extra["versions.native-platform"] = "0.14"
extra["versions.ant-launcher"] = "1.8.0"
extra["versions.robolectric"] = "4.0"
extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0"
@@ -326,11 +325,13 @@ extra["tasksWithWarnings"] = listOf(
":kotlin-stdlib:compileTestKotlin",
":kotlin-stdlib-jdk7:compileTestKotlin",
":kotlin-stdlib-jdk8:compileTestKotlin",
":compiler:cli:compileKotlin",
":compiler:frontend:compileKotlin",
":compiler:fir:tree:compileKotlin",
":compiler:fir:resolve:compileKotlin",
":compiler:fir:checkers:compileKotlin",
":compiler:fir:java:compileKotlin",
":kotlin-scripting-compiler:compileKotlin",
":plugins:uast-kotlin:compileKotlin",
":plugins:uast-kotlin:compileTestKotlin",
":plugins:uast-kotlin-idea:compileKotlin"
@@ -351,8 +352,7 @@ val coreLibProjects = listOfNotNull(
":kotlin-test:kotlin-test-junit5",
":kotlin-test:kotlin-test-testng",
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
":kotlin-reflect",
":kotlin-coroutines-experimental-compat"
":kotlin-reflect"
)
val gradlePluginProjects = listOf(
@@ -977,8 +977,7 @@ tasks {
":kotlin-reflect:publish",
":kotlin-main-kts:publish",
":kotlin-stdlib-js:publish",
":kotlin-test:kotlin-test-js:publish",
":kotlin-coroutines-experimental-compat:publish"
":kotlin-test:kotlin-test-js:publish"
)
}
}
@@ -1,14 +1,11 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
ext {
isD8Enabled = project.findProperty('android.enableD8').toBoolean()
}
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:4.1.1'
}
}
apply plugin: 'com.android.application'
@@ -20,7 +17,7 @@ repositories {
android {
compileSdkVersion 26
buildToolsVersion "28.0.3"
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "org.jetbrains.kotlin.android.tests"
@@ -60,11 +57,9 @@ android {
resultsDir = "build/test/results"
}
if (isD8Enabled) {
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
flavorDimensions "box"
@@ -86,15 +81,12 @@ android {
dimension "box"
}
jvm80 {
dimension "box"
}
if (isD8Enabled) {
jvm80 {
dimension "box"
}
reflectjvm80 {
dimension "box"
}
reflectjvm80 {
dimension "box"
}
}
@@ -1,3 +1,2 @@
#don't try to download android specific tools within gradle: licence acceptance will be required
android.builder.sdkDownload=false
android.enableD8=true
android.builder.sdkDownload=false
@@ -25,7 +25,7 @@ import org.junit.runners.AllTests;
import java.io.File;
//@RunWith(AllTests.class)
@RunWith(AllTests.class)
public class AndroidRunner {
private static PathManager pathManager;
@@ -321,8 +321,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
companion object {
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change
const val GRADLE_SHA_256 = "1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d"
const val GRADLE_VERSION = "6.8.1" // update GRADLE_SHA_256 on change
const val GRADLE_SHA_256 = "fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd"
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
const val testClassName = "CodegenTestCaseOnAndroid"
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 {
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) {
e.printStackTrace()
throw e
@@ -81,16 +71,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
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) {
val reportFolder = File(flavorFolder())
try {
@@ -121,8 +121,11 @@ public class Emulator {
public void startEmulator() {
startServer();
System.out.println("Starting emulator...");
RunUtils.executeOnSeparateThread(new RunUtils.RunSettings(getStartCommand(), null, false, "START: ", true));
System.out.println("Starting emulator with ANDROID_HOME/ANDROID_SDK_ROOT: " + pathManager.getAndroidSdkRoot());
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();
}
@@ -144,6 +147,7 @@ public class Emulator {
bootCheckCommand.addParameter("shell");
bootCheckCommand.addParameter("getprop");
bootCheckCommand.addParameter("sys.boot_completed");
int counter = 0;
RunResult execute = RunUtils.execute(bootCheckCommand);
while (counter < 20) {
@@ -264,7 +264,7 @@ public class ClassFileFactory implements OutputFileCollection {
return new MultifileClassCodegenImpl(state, files, facadeFqName);
}
private void registerSourceFiles(Collection<KtFile> files) {
public void registerSourceFiles(@NotNull Collection<KtFile> files) {
sourceFiles.addAll(toIoFilesIgnoringNonPhysical(files));
}
@@ -272,6 +272,7 @@ public class ClassFileFactory implements OutputFileCollection {
private static List<File> toIoFilesIgnoringNonPhysical(@NotNull Collection<? extends PsiFile> psiFiles) {
List<File> result = new ArrayList<>(psiFiles.size());
for (PsiFile psiFile : psiFiles) {
if (psiFile == null) continue;
VirtualFile virtualFile = psiFile.getVirtualFile();
// 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
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
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.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
@@ -118,8 +117,9 @@ public class ConstructorCodegen {
}
private void registerAccessorForHiddenConstructorIfNeeded(ClassConstructorDescriptor descriptor) {
if (!InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) return;
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
if (DescriptorAsmUtil.isHiddenConstructor(descriptor)) {
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
}
}
public void generateSecondaryConstructor(
@@ -371,11 +371,13 @@ public class ConstructorCodegen {
JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
if (delegatingKind == 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;
}
assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind :
"Constructors of the same class should have the same set of implicit arguments";
if (index >= parameters.size() || parameters.get(index).getKind() != delegatingKind) {
throw new AssertionError(
"Constructors of the same class should have the same set of implicit arguments: " + delegatingConstructor);
}
JvmMethodParameterSignature parameter = parameters.get(index);
iv.load(offset, parameter.getAsmType());
@@ -383,7 +385,7 @@ public class ConstructorCodegen {
}
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(),
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.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
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.types.TypeUtils.isNullableType;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -368,6 +369,18 @@ public class DescriptorAsmUtil {
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)) {
return ACC_PRIVATE;
}
@@ -893,4 +906,19 @@ public class DescriptorAsmUtil {
//Trait always should have this descriptor
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
return descriptor;
}
else if (InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor.getOriginal())) {
// Constructors with inline class type value parameters should always be called using an accessor.
// 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 if (shouldForceAccessorForConstructor(descriptor.getOriginal())) {
return createAccessorForHiddenConstructor(resolvedCall, descriptor);
}
else {
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
public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver);
@@ -207,6 +207,14 @@ class GenerationState private constructor(
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: 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 classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
val bindingTrace: BindingTrace = DelegatingBindingTrace(
@@ -375,13 +375,27 @@ class KotlinTypeMapper @JvmOverloads constructor(
kind: OwnerKind? = null,
resolvedCall: ResolvedCall<*>? = null
): 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
if (descriptor is ConstructorDescriptor && kind != OwnerKind.ERASED_INLINE_CLASS) {
val method = mapSignatureSkipGeneric(descriptor.original)
val owner = mapOwner(descriptor)
val originalDescriptor = descriptor.original
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,
boxInlineClassBeforeInvoke = false
)
@@ -557,7 +571,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
return CallableMethod(
owner, ownerForDefaultImpl,
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)) },
mapDefaultCallback(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)),
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType,
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
@@ -33,6 +33,13 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
)
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)
@Argument(value = "-source-map", description = "Generate source map")
var sourceMap: Boolean by FreezableVar(false)
@@ -362,6 +362,15 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
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(
value = "-Xklib",
valueDescription = "<path>",
@@ -134,7 +134,7 @@ fun main(args: Array<String>) {
}
val resolvedLibraries = jsResolveLibraries(
dependencies, messageCollectorLogger(MessageCollector.NONE)
dependencies, emptyList(), messageCollectorLogger(MessageCollector.NONE)
)
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.declarations.persistent.PersistentIrFactory
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.name.FqName
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 friendLibraries: List<String> = configureLibraries(arguments.friendModules)
val repositories: List<String> = configureLibraries(arguments.repositries)
configuration.put(JSConfigurationKeys.LIBRARIES, libraries)
configuration.put(JSConfigurationKeys.TRANSITIVE_LIBRARIES, libraries)
configuration.put(JSConfigurationKeys.REPOSITORIES, repositories)
val commonSourcesArray = arguments.commonSources
val commonSources = commonSourcesArray?.toSet() ?: emptySet()
@@ -175,6 +178,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val resolvedLibraries = jsResolveLibraries(
libraries,
configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList(),
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) {
val outputKlibPath =
if (arguments.irProduceKlibDir)
File(outputFilePath).parent
else
outputFilePath
if (arguments.irProduceKlibFile) {
require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" }
}
try {
generateKLib(
@@ -199,7 +201,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
irFactory = PersistentIrFactory,
outputKlibPath = outputKlibPath,
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir
)
} catch (e: JsIrCompilationError) {
@@ -59,8 +59,28 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
} else {
messageCollector.report(
ERROR, "Unknown -Xstring-concat mode: ${arguments.jvmTarget}\n" +
"Supported versions: ${JvmStringConcat.values().joinToString { it.description }}"
ERROR, "Unknown `-Xstring-concat` mode: ${arguments.stringConcat}\n" +
"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
// as "pre-release" and will not be loaded by release versions of the compiler.
// 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";
@@ -114,6 +114,9 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<JvmStringConcat> STRING_CONCAT =
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 =
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 {
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")
@@ -12,7 +12,7 @@ public sealed class Sealed : R|kotlin/Any| {
public final val z: 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 <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|.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 test_3(): R|kotlin/Unit| {
@@ -20,7 +20,7 @@ fun test_2(n: Int) {
fun Int.bar(): Int {}
fun Int.baz(): Int
fun Int.baz(): Int {}
fun Byte.baz(): Byte {}
fun test_3() {
+1 -1
View File
@@ -15,7 +15,7 @@ fun test_2(x: Int?) {
} else {
x
}
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!>
y<!UNSAFE_CALL!>.<!>inc()
}
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 constructor(): R|mest| {
super<R|kotlin/Any|>()
@@ -59,7 +59,7 @@ class L {
fun B.foo() {}
}
fun mest()
fun 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?) {
val bar = x?.bar
if (bar != null) {
x.bar.<!INAPPLICABLE_CANDIDATE!>length<!>
x.bar<!UNSAFE_CALL!>.<!>length
}
}
@@ -5,7 +5,7 @@ interface B
class Clazz1 : 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())
@@ -14,7 +14,7 @@ package a.d
import b.d.*
fun foo(arg: Other): Another
<!NON_MEMBER_FUNCTION_NO_BODY!>fun foo(arg: Other): Another<!>
fun bar() {
baz()
@@ -26,7 +26,7 @@ fun test_3(a: A?, b: Boolean) {
if (b && a!!.foo()) {
a.foo() // OK
}
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!> // Bad
a<!UNSAFE_CALL!>.<!>foo() // Bad
}
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) {
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) {
@@ -8,13 +8,13 @@ fun test_1(b: Boolean?) {
if ((b == true) == true) {
b.not() // OK
} else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
}
}
fun test_2(b: Boolean?) {
if ((b == true) != true) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
} else {
b.not() // OK
}
@@ -22,7 +22,7 @@ fun test_2(b: Boolean?) {
fun test_3(b: Boolean?) {
if ((b == true) == false) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
} else {
b.not() // OK
}
@@ -32,13 +32,13 @@ fun test_4(b: Boolean?) {
if ((b == true) != false) {
b.not() // OK
} else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
}
}
fun test_5(b: Boolean?) {
if ((b != true) == true) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
} else {
b.not() // OK
}
@@ -48,7 +48,7 @@ fun test_6(b: Boolean?) {
if ((b != true) != true) {
b.not() // OK
} 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) {
b.not() // OK
} else {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
}
}
fun test_8(b: Boolean?) {
if ((b != true) != false) {
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>not<!>()<!> // Bad
b<!UNSAFE_CALL!>.<!>not() // Bad
} else {
b.not() // OK
}
@@ -34,24 +34,24 @@ fun test_4(a: A?) {
fun test_5(a: A?) {
a == null || throw Exception()
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
a<!UNSAFE_CALL!>.<!>foo()
}
fun teat_6(a: A?) {
a != null && throw Exception()
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
a<!UNSAFE_CALL!>.<!>foo()
}
fun test_7(a: A?) {
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?) {
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) {
x.length // OK
y.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad
y<!UNSAFE_CALL!>.<!>length // Bad
z.length // OK
}
if (y != null) {
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad
x<!UNSAFE_CALL!>.<!>length // Bad
y.length // OK
z.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad
z<!UNSAFE_CALL!>.<!>length // Bad
}
if (z != null) {
x.length // OK
y.<!INAPPLICABLE_CANDIDATE!>length<!> // Bad
y<!UNSAFE_CALL!>.<!>length // Bad
z.length // OK
}
}
@@ -16,12 +16,12 @@ fun test_1(x: A, y: A?) {
fun test_2(x: A?, y: A?) {
if (x == y) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
x<!UNSAFE_CALL!>.<!>foo()
y<!UNSAFE_CALL!>.<!>foo()
}
if (x === y) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
y.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
x<!UNSAFE_CALL!>.<!>foo()
y<!UNSAFE_CALL!>.<!>foo()
}
}
@@ -39,18 +39,18 @@ fun test_1(x: A?) {
if (x != null) {
x.foo()
} 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?) {
if (x == null) {
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
x<!UNSAFE_CALL!>.<!>foo()
} else {
x.foo()
}
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
x<!UNSAFE_CALL!>.<!>foo()
}
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.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad
q.data<!UNSAFE_CALL!>.<!>s // 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?.s?.inc() ?: return
q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad
q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
}
fun test_7(q: Q?) {
if (q?.fdata()?.fs()?.inc() != null) {
q.fdata() // good
q.fdata().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>fs<!>()<!> // bad
q.fdata().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>fs<!>()<!>.inc() // bad
q.fdata()<!UNSAFE_CALL!>.<!>fs() // bad
q.fdata()<!UNSAFE_CALL!>.<!>fs().inc() // bad
}
}
@@ -98,44 +98,44 @@ fun test_9(a: Int, b: Int?) {
if (a == b) {
b.inc()
}
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!>
b<!UNSAFE_CALL!>.<!>inc()
if (a === b) {
b.inc()
}
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!>
b<!UNSAFE_CALL!>.<!>inc()
if (b == a) {
b.inc()
}
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!>
b<!UNSAFE_CALL!>.<!>inc()
if (b === a) {
b.inc()
}
b.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>inc<!>()<!>
b<!UNSAFE_CALL!>.<!>inc()
}
fun test_10(a: Int?, b: Int?) {
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) {
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) {
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) {
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) {
@@ -148,8 +148,8 @@ fun test_11(q: QImpl?, q2: QImpl) {
// Smartcasting of `q.data` should have no effect on `q2.data`.
// Issue: Smartcasting of QImpl.data affects all instances
q2.data
q2.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad
q2.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad
q2.data<!UNSAFE_CALL!>.<!>s // should be bad
q2.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
if (q2.data != null) {
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.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad
q.data<!UNSAFE_CALL!>.<!>s // 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.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data.<!INAPPLICABLE_CANDIDATE!>s<!> // should be bad
q.data.<!INAPPLICABLE_CANDIDATE!>s<!>.inc() // should be bad
q.data<!UNSAFE_CALL!>.<!>s // 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) {
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) {
s.length // Should be OK
} 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) {
s.length // Should be OK
} else {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad
s<!UNSAFE_CALL!>.<!>length // Should be bad
}
}
fun test_3(s: String?) {
if (s?.check() != true) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad
s<!UNSAFE_CALL!>.<!>length // Should be bad
} else {
s.length // Should be OK
}
@@ -27,7 +27,7 @@ fun test_3(s: String?) {
fun test_4(s: String?) {
if (s?.check() != false) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad
s<!UNSAFE_CALL!>.<!>length // Should be bad
} else {
s.length // Should be OK
}
@@ -5,7 +5,7 @@ fun String.let(block: () -> Unit) {}
fun test(x: String?) {
x?.foo(x.length == 1)
x.<!INAPPLICABLE_CANDIDATE!>length<!>
x<!UNSAFE_CALL!>.<!>length
}
interface A {
@@ -27,12 +27,12 @@ fun test_3(x: Any) {
fun test_4(x: A?) {
x?.id()?.bool()
x.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>id<!>()<!>
x<!UNSAFE_CALL!>.<!>id()
}
fun Any?.boo(b: Boolean) {}
fun test_5(x: A?) {
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 {
a = null
}
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
a<!UNSAFE_CALL!>.<!>foo()
}
@@ -18,5 +18,5 @@ fun test_3() {
x = ""
x.length
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{LT}!><!CONFLICTING_OVERLOADS!>fun bar(x: String): Double<!> = 1<!>
<!CONFLICTING_OVERLOADS!>fun bar(x: String): Int<!> = 1
<!CONFLICTING_OVERLOADS!>fun bar(x: String): Double<!> = 1
fun baz(x: String): Int = 1
fun <T, R> foobaz(x: T): R = TODO()
@@ -31,16 +31,16 @@ fun main() {
foo1(KotlinClass::baz)
foo2(KotlinClass::baz)
// Ambiguity (companion/class)
<!AMBIGUITY!>foo3<!>(KotlinClass::baz)
<!AMBIGUITY{LT}!><!AMBIGUITY{PSI}!>foo3<!>(KotlinClass::baz)<!>
// Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo1<!>(<!UNRESOLVED_REFERENCE!>KotlinClass::bar<!>)
<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo1<!>(<!UNRESOLVED_REFERENCE!>KotlinClass::bar<!>)<!>
foo2(KotlinClass::bar)
foo3(KotlinClass::bar)
foo1(KotlinClass2::bar)
// Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo2<!>(<!UNRESOLVED_REFERENCE!>KotlinClass2::bar<!>)
<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo2<!>(<!UNRESOLVED_REFERENCE!>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 test(a: A, b: B) {
<!INAPPLICABLE_CANDIDATE!>baz<!>(a, <!UNRESOLVED_REFERENCE!>::fooB<!>)
<!INAPPLICABLE_CANDIDATE!>bar<!>(<!UNRESOLVED_REFERENCE!>::fooB<!>, a)
<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>(a, <!UNRESOLVED_REFERENCE!>::fooB<!>)<!>
<!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 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()
@@ -16,5 +16,5 @@ fun foo3(x: (String) -> Int) {}
fun main() {
foo1(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 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?) {
// contracts related
if (s.isNullOrEmpty()) {
s.<!INAPPLICABLE_CANDIDATE!>length<!> // Should be bad
s<!UNSAFE_CALL!>.<!>length // Should be bad
} else {
s.length // Should be OK
}
@@ -59,8 +59,8 @@ fun test_2(x: Any) {
fun test_3(x: Any) {
myRequireOr(x is B, x is C)
x.foo() // OK
x.<!UNRESOLVED_REFERENCE!>bar<!>() // Error
x.<!UNRESOLVED_REFERENCE!>baz<!>() // Error
x.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>bar<!>()<!> // Error
x.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>baz<!>()<!> // Error
}
fun test_4(x: Any) {
@@ -21,7 +21,7 @@ fun test_1(x: String?) {
if (checkNotNull(x)) {
x.length // OK
} else {
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Error
x<!UNSAFE_CALL!>.<!>length // Error
}
}
@@ -27,7 +27,7 @@ fun test_3(x: A?) {
with(x) {
myRequireNotNull()
}
x.<!INAPPLICABLE_CANDIDATE!>foo<!>()
x<!UNSAFE_CALL!>.<!>foo()
}
fun test_4(x: A?) {
@@ -27,8 +27,8 @@ class A {
val p3 = JavaProtected().<!HIDDEN!>javaPProtectedPackage<!>
fun test() {
JavaProtected.<!HIDDEN!>javaMProtectedStatic<!>()
JavaPackageLocal.<!HIDDEN!>javaMPackage<!>()
JavaProtected.<!HIDDEN{LT}!><!HIDDEN{PSI}!>javaMProtectedStatic<!>()<!>
JavaPackageLocal.<!HIDDEN{LT}!><!HIDDEN{PSI}!>javaMPackage<!>()<!>
}
}
@@ -39,7 +39,7 @@ class B : JavaProtected() {
fun test() {
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)
// 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().<!INAPPLICABLE_CANDIDATE!>nested<!>(1)
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>nested<!>(1)<!>
}
// FILE: J1.java
@@ -9,5 +9,5 @@ public class JavaClass {
// FILE: K2.kt
fun main() {
JavaClass.baz(KotlinClass())
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>("")
JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>("")<!>
}
@@ -10,6 +10,6 @@ public class JavaClass {
fun main() {
JavaClass.baz(KotlinClass())
JavaClass.baz(KotlinClass<Int>())
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>(KotlinClass<String>())
JavaClass.<!INAPPLICABLE_CANDIDATE!>baz<!>("")
JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>(KotlinClass<String>())<!>
JavaClass.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>baz<!>("")<!>
}
@@ -1,6 +1,6 @@
fun List<String>.modify() {
<!VARIABLE_EXPECTED!>this<!> += "Alpha"
<!VARIABLE_EXPECTED!>this<!> += "Omega"
<!VARIABLE_EXPECTED{PSI}!>this<!> += "Alpha"
<!VARIABLE_EXPECTED{PSI}!>this<!> += "Omega"
}
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<!>
fun foo(): Int<!> = 1<!>
fun foo(): Int<!> = 1
<!CONFLICTING_OVERLOADS{LT}!><!CONFLICTING_OVERLOADS!>fun foo(): String<!> = ""<!>
<!CONFLICTING_OVERLOADS!>fun foo(): String<!> = ""
fun test() {
val s = foo()
@@ -2,11 +2,11 @@
class K2: J1() {
class Q : <!UNRESOLVED_REFERENCE!>Nested<!>()
fun bar() {
<!UNRESOLVED_REFERENCE!>foo<!>()
<!UNRESOLVED_REFERENCE!>baz<!>()
<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>foo<!>()<!>
<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>baz<!>()<!>
<!UNRESOLVED_REFERENCE!>superClass<!>()
<!UNRESOLVED_REFERENCE!>superI<!>()
<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>superClass<!>()<!>
<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>superI<!>()<!>
}
}
@@ -1424,6 +1424,22 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
public void testValOnAnnotationParameter() throws Exception {
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
@@ -1457,6 +1457,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testParenthesizedAnnotations() throws Exception {
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
@@ -14002,6 +14008,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("kt702.kt")
public void testKt702() throws Exception {
@@ -14189,6 +14201,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testSubstitutionIntoInnerClass() throws Exception {
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
@@ -14305,6 +14323,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
@@ -20201,6 +20225,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("rawOverrides.kt")
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);
}
@Test
@TestMetadata("buildFlexibleEnhancement.kt")
public void testBuildFlexibleEnhancement() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/buildFlexibleEnhancement.kt");
}
@Test
@TestMetadata("overriddenExtensions.kt")
public void testOverriddenExtensions() throws Exception {
@@ -24391,12 +24427,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("NeverObject.kt")
public void testNeverObject() throws Exception {
@@ -27231,12 +27261,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion")
@TestDataPath("$PROJECT_ROOT")
@@ -4906,12 +4906,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
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
@TestMetadata("selfcreate.kt")
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);
}
@Test
@TestMetadata("ConstValAccess.kt")
public void testConstValAccess() throws Exception {
runTest("compiler/testData/codegen/box/fir/ConstValAccess.kt");
}
@Test
@TestMetadata("ExtensionAlias.kt")
public void testExtensionAlias() throws Exception {
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
@TestMetadata("SuspendExtension.kt")
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
@TestMetadata("compiler/testData/codegen/box/ir")
@TestDataPath("$PROJECT_ROOT")
@@ -19264,6 +19544,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
@TestMetadata("compiler/testData/codegen/box/jvm8/defaults")
@TestDataPath("$PROJECT_ROOT")
public class Defaults extends AbstractFirBlackBoxCodegenTest {
@Test
@TestMetadata("26360.kt")
public void test26360() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/26360.kt");
}
@Test
@TestMetadata("accessor.kt")
public void testAccessor() throws Exception {
@@ -33290,6 +33576,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
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
@TestMetadata("arrayLengthNPE.kt")
public void testArrayLengthNPE() throws Exception {
@@ -34224,12 +34516,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
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
@TestMetadata("castFromAny.kt")
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);
}
@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
@TestMetadata("multipleFiles_enabled.kt")
public void testMultipleFiles_enabled() throws Exception {
@@ -34506,6 +34804,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
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
@TestMetadata("simple.kt")
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);
}
@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
@TestMetadata("falseSmartCast.kt")
public void testFalseSmartCast() throws Exception {
@@ -2140,12 +2140,24 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
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
@TestMetadata("kt43342.kt")
public void testKt43342() throws Exception {
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
@TestMetadata("MultiList.kt")
public void testMultiList() throws Exception {
@@ -5,10 +5,120 @@
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.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.isExpect
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.*
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*.
internal fun isInsideExpectClass(containingDeclaration: FirRegularClass, context: CheckerContext): Boolean =
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.FirErrors
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.FirVariable
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.FirResolvedNamedReference
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.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() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -65,8 +70,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
val originalDestructuringDeclarationOrInitializerSource = originalDestructuringDeclarationOrInitializer.source ?: return
val originalDestructuringDeclarationType =
when (originalDestructuringDeclarationOrInitializer) {
is FirVariable<*> -> originalDestructuringDeclarationOrInitializer.returnTypeRef
is FirExpression -> originalDestructuringDeclarationOrInitializer.typeRef
is FirVariable<*> -> originalDestructuringDeclarationOrInitializer.returnTypeRef.coneTypeSafe<ConeKotlinType>()
is FirExpression -> originalDestructuringDeclarationOrInitializer.typeRef.coneTypeSafe<ConeKotlinType>()
else -> null
} ?: 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
}
}
@@ -60,6 +60,8 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
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
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.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.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.lexer.KtTokens
// See old FE's [DeclarationsChecker]
@@ -34,6 +34,8 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
context: CheckerContext,
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`.
// So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = with(FirModifierList) { property.source.getModifierList() }
@@ -56,18 +58,14 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
return
}
}
if (property.delegate != null) {
property.delegate!!.source?.let {
if (containingDeclaration.isInterface) {
reporter.report(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE)
} else {
reporter.report(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY)
}
}
property.initializer?.source?.let {
reporter.report(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER)
}
property.delegate?.source?.let {
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)
}
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
if (hasOpenModifier &&
@@ -100,28 +98,8 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
}
}
}
}
private fun checkPropertyInitializer(
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)
}
}
}
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
}
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.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.diagnostics.*
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.FirErrorResolvedQualifier
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.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -62,7 +61,10 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
// Will be handled by [FirDestructuringDeclarationChecker]
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.
if (diagnostic is ConeUnresolvedNameError || diagnostic is ConeAmbiguityError) {
if (diagnostic is ConeUnresolvedNameError ||
diagnostic is ConeAmbiguityError ||
diagnostic is ConeInapplicableCandidateError
) {
return
}
}
@@ -72,7 +74,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.classId.asString())
is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, diagnostic.name.asString())
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) {
FirErrors.NONE_APPLICABLE.on(source, diagnostic.candidates)
} else {
@@ -98,6 +100,37 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
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, *> {
@Suppress("UNCHECKED_CAST")
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.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.*
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
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) {
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.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.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.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
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.COMPONENT_FUNCTION_AMBIGUITY
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_PROJECTION
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.ENUM_AS_SUPERTYPE
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.EXPOSED_FUNCTION_RETURN_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.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_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_SEALED
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.UNRESOLVED_LABEL
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.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_INITIALIZER_IS_REDUNDANT
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(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(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(
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
map.put(
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_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
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
map.put(
@@ -398,6 +420,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
TO_STRING,
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
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(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
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility 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.FirClassLikeSymbol
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 {
val NULLABLE_STRING = Renderer<String?> { it ?: "null" }
@@ -58,9 +59,9 @@ object FirDiagnosticRenderers {
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.
typeRef.render()
t.render()
}
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 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 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)
// 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
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 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_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 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_SETTER by error0<FirSourceElement, KtPropertyAccessor>()
val PRIVATE_SETTER_FOR_ABSTRACT_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
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, KtDestructuringDeclaration>()
val COMPONENT_FUNCTION_MISSING by error2<FirSourceElement, PsiElement, Name, FirTypeRef>()
val COMPONENT_FUNCTION_AMBIGUITY by error2<FirSourceElement, PsiElement, Name, Collection<AbstractFirBasedSymbol<*>>>()
// TODO: val COMPONENT_FUNCTION_ON_NULLABLE by ...
val COMPONENT_FUNCTION_MISSING by error2<FirSourceElement, KtExpression, Name, ConeKotlinType>()
val COMPONENT_FUNCTION_AMBIGUITY by error2<FirSourceElement, KtExpression, Name, Collection<AbstractFirBasedSymbol<*>>>()
val COMPONENT_FUNCTION_ON_NULLABLE by error1<FirSourceElement, KtExpression, Name>()
// TODO: val COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH by ...
// Control flow diagnostics
@@ -188,6 +208,13 @@ object FirErrors {
val LEAKED_IN_PLACE_LAMBDA by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>()
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
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_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)
}
}
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 =
@@ -261,6 +305,9 @@ fun FirSourceElement.hasPrimaryConstructor(): Boolean =
private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? =
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? =
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? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
@@ -52,4 +52,19 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.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,
)
override val fileCheckers: Set<FirFileChecker> = setOf(
FirTopLevelFunctionChecker,
FirTopLevelPropertyChecker,
)
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
FirCallsEffectAnalyzer,
FirReturnsImpliesAnalyzer,
@@ -8,6 +8,10 @@ package org.jetbrains.kotlin.fir.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
object CommonExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker> = setOf(
FirAnonymousFunctionChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
FirSuperNotAvailableChecker,
FirNotASupertypeChecker,
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.session
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.*
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.FirPredicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
@@ -40,6 +42,12 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(InferenceComponents::class, InferenceComponents(this))
}
@OptIn(SessionConfiguration::class)
fun FirSession.registerThreadUnsafeCaches() {
register(FirCachesFactory::class, FirThreadUnsafeCachesFactory)
}
// -------------------------- 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.checkersComponent
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.extensions.BunchOfRegisteredExtensions
import org.jetbrains.kotlin.fir.extensions.extensionService
@@ -68,6 +70,7 @@ object FirSessionFactory {
init: FirSessionConfigurator.() -> Unit = {}
): FirJavaModuleBasedSession {
return FirJavaModuleBasedSession(moduleInfo, sessionProvider).apply {
registerThreadUnsafeCaches()
registerCommonComponents(languageVersionSettings)
registerResolveComponents()
registerJavaSpecificResolveComponents()
@@ -113,6 +116,7 @@ object FirSessionFactory {
val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(scope)
return FirLibrarySession(moduleInfo, sessionProvider).apply {
registerThreadUnsafeCaches()
registerCommonComponents(languageVersionSettings)
val javaSymbolProvider = JavaSymbolProvider(this, project, scope)
@@ -714,11 +714,12 @@ class FirElementSerializer private constructor(
private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int {
// [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations,
// user-contributed visibility, and modifiers, such as `external` or `inline`.
val nonSourceAnnotations = accessor.nonSourceAnnotations(session)
val isDefault = accessor is FirDefaultPropertyAccessor &&
accessor.annotations.isEmpty() && accessor.visibility == property.visibility &&
nonSourceAnnotations.isEmpty() && accessor.visibility == property.visibility &&
!accessor.isExternal && !accessor.isInline
return Flags.getAccessorFlags(
accessor.nonSourceAnnotations(session).isNotEmpty(),
nonSourceAnnotations.isNotEmpty(),
ProtoEnumFlags.visibility(normalizeVisibility(accessor)),
ProtoEnumFlags.modality(accessor.modality!!),
!isDefault,
@@ -232,7 +232,19 @@ internal tailrec fun FirCallableSymbol<*>.unwrapCallRepresentative(root: FirCall
val originalForTypeAlias = fir.originalConstructorIfTypeAlias
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 {
it.containingClass() == root.containingClass()
@@ -1026,7 +1026,7 @@ class Fir2IrDeclarationStorage(
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) {
val isFakeOverride =
firFunctionSymbol is FirNamedFunctionSymbol && fir.isSubstitutionOverride &&
firFunctionSymbol is FirNamedFunctionSymbol && fir.isSubstitutionOrIntersectionOverride &&
firFunctionSymbol.dispatchReceiverClassOrNull() !=
firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazySimpleFunction(
@@ -1065,7 +1065,7 @@ class Fir2IrDeclarationStorage(
val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareProperty(signature, { symbol }) {
val isFakeOverride =
fir.isSubstitutionOverride &&
fir.isSubstitutionOrIntersectionOverride &&
firPropertySymbol.dispatchReceiverClassOrNull() !=
firPropertySymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazyProperty(
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.fir.backend
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.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.expressions.*
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.FirResolvedNamedReference
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.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
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.withHasQuestionMark
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker
class Fir2IrImplicitCastInserter(
private val components: Fir2IrComponents,
@@ -285,58 +281,29 @@ class Fir2IrImplicitCastInserter(
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
}
internal fun convertToImplicitCastExpression(
expressionWithSmartcast: FirExpressionWithSmartcast, calleeReference: FirReference
internal fun implicitCastFromDispatchReceiver(
original: IrExpression,
originalTypeRef: FirTypeRef,
calleeReference: FirReference,
): IrExpression {
val originalExpression = expressionWithSmartcast.originalExpression
val value = visitor.convertToIrExpression(originalExpression)
val castTypeRef = expressionWithSmartcast.typeRef
if (calleeReference !is FirResolvedNamedReference) {
return implicitCastOrExpression(value, castTypeRef)
}
val referencedSymbol = calleeReference.resolvedSymbol
if (referencedSymbol !is FirPropertySymbol && referencedSymbol !is FirFunctionSymbol) {
return implicitCastOrExpression(value, castTypeRef)
}
val referencedDeclaration =
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirCallableSymbol<*>)?.unwrapCallRepresentative()
?.fir as? FirCallableMemberDeclaration<*>
val originalTypeRef = expressionWithSmartcast.originalType
if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) {
val castType = castTypeRef.type
if (castType is ConeIntersectionType) {
val unwrappedSymbol = (referencedSymbol as? FirCallableSymbol)?.baseForIntersectionOverride ?: referencedSymbol
castType.intersectedTypes.forEach {
if (it.doesContainReferencedSymbolInScope(unwrappedSymbol, calleeReference.name)) {
return implicitCastOrExpression(value, it)
}
}
val dispatchReceiverType =
referencedDeclaration?.dispatchReceiverType as? ConeClassLikeType
?: return implicitCastOrExpression(original, originalTypeRef)
val starProjectedDispatchReceiver = dispatchReceiverType.replaceArgumentsWithStarProjections()
val castType = originalTypeRef.coneTypeSafe<ConeIntersectionType>()
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(
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
return implicitCastOrExpression(original, originalTypeRef)
}
private fun implicitCastOrExpression(original: IrExpression, castType: ConeKotlinType): IrExpression {
@@ -348,7 +315,8 @@ class Fir2IrImplicitCastInserter(
}
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 {
@@ -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.references.FirReference
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.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -470,16 +471,16 @@ class Fir2IrVisitor(
}
}
private fun convertToIrReceiverExpression(
internal fun convertToIrReceiverExpression(
expression: FirExpression?,
calleeReference: FirReference,
callableReferenceAccess: FirCallableReferenceAccess? = null
): IrExpression? {
return when (expression) {
null -> null
null -> return null
is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess)
is FirExpressionWithSmartcast -> implicitCastInserter.convertToImplicitCastExpression(expression, calleeReference)
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression)
is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess, is FirExpressionWithSmartcast ->
convertToIrExpression(expression)
else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) {
val variableAsFunctionMode = calleeReference is FirResolvedNamedReference &&
calleeReference.name != OperatorNameConventions.INVOKE &&
@@ -491,6 +492,10 @@ class Fir2IrVisitor(
} else {
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) {
return explicitReceiverExpression
}
if (firReceiver is FirResolvedQualifier) {
return convertToGetObject(firReceiver, this as? FirCallableReferenceAccess)
}
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
return firReceiver.takeIf { it !is FirNoReceiverExpression }
?.let { visitor.convertToIrReceiverExpression(it, calleeReference, this as? FirCallableReferenceAccess) }
?: explicitReceiverExpression
?: run {
if (this is FirCallableReferenceAccess) return null
@@ -192,8 +192,10 @@ class FakeOverrideGenerator(
): List<S> {
if (symbol.fir.origin != FirDeclarationOrigin.IntersectionOverride) return listOf(basedSymbol)
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 {
it.fir.isSubstitutionOverride && it.dispatchReceiverClassOrNull() == containingClass ->
it.fir.isSubstitutionOverride ->
it.originalForSubstitutionOverride!!
it.fir.origin == FirDeclarationOrigin.Delegated ->
it.fir.delegatedWrapperData?.wrapped?.symbol!! as S
@@ -127,6 +127,7 @@ class Fir2IrLazyProperty(
}
override var getter: IrSimpleFunction? by lazyVar {
if (fir.isConst) return@lazyVar null
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
when {

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