[MERGE] KT: build-1.5.20-dev-7 KT/N: eecc10f9a OLD: e9501e82c
This commit is contained in:
Generated
-7
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
+25
-19
@@ -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
@@ -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;
|
||||
|
||||
+2
-2
@@ -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"
|
||||
|
||||
-20
@@ -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 {
|
||||
|
||||
+6
-2
@@ -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,
|
||||
|
||||
+7
@@ -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)
|
||||
|
||||
+9
@@ -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 }}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 }
|
||||
}
|
||||
}
|
||||
+18
@@ -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")
|
||||
|
||||
+1
-1
@@ -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|
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ public sealed class SealedClass : R|kotlin/Any| {
|
||||
|
||||
}
|
||||
|
||||
private constructor(): R|test/SealedClass|
|
||||
internal constructor(): R|test/SealedClass|
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -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|))
|
||||
}
|
||||
|
||||
+2
-1
@@ -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| {
|
||||
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
@@ -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?) {
|
||||
|
||||
+2
-1
@@ -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|>()
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ class L {
|
||||
fun B.foo() {}
|
||||
}
|
||||
|
||||
fun mest()
|
||||
fun mest() {}
|
||||
|
||||
class mest
|
||||
|
||||
|
||||
Vendored
+45
@@ -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| {
|
||||
}
|
||||
)
|
||||
}
|
||||
Vendored
+16
@@ -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<!>) {})
|
||||
}
|
||||
+1
-1
@@ -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
-8
@@ -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
|
||||
}
|
||||
|
||||
+6
-6
@@ -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()
|
||||
}
|
||||
|
||||
compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt
Vendored
+4
-4
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
-4
@@ -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
|
||||
}
|
||||
|
||||
+3
-3
@@ -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()
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,5 +11,5 @@ fun test(b: Boolean) {
|
||||
} else {
|
||||
a = null
|
||||
}
|
||||
a.<!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>foo<!>()<!>
|
||||
a<!UNSAFE_CALL!>.<!>foo()
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -18,5 +18,5 @@ fun test_3() {
|
||||
x = ""
|
||||
x.length
|
||||
x = null
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
+2
-2
@@ -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()
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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)<!>
|
||||
}
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+1
-1
@@ -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)<!>
|
||||
}
|
||||
|
||||
+1
-1
@@ -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<!>)<!>
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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?) {
|
||||
|
||||
+3
-3
@@ -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<!>()<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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<!>("")<!>
|
||||
}
|
||||
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
+3
-3
@@ -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()
|
||||
|
||||
Vendored
+4
-4
@@ -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<!>()<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -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
|
||||
|
||||
+2132
-2617
File diff suppressed because it is too large
Load Diff
+4617
-3161
File diff suppressed because it is too large
Load Diff
+36
-12
@@ -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")
|
||||
|
||||
+328
-12
@@ -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 {
|
||||
|
||||
+1059
-495
File diff suppressed because it is too large
Load Diff
+12
@@ -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 {
|
||||
|
||||
+112
-2
@@ -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)
|
||||
|
||||
+17
-3
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -60,6 +60,8 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
|
||||
reporter.report(FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(source, function))
|
||||
}
|
||||
}
|
||||
|
||||
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-34
@@ -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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+40
@@ -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)
|
||||
}
|
||||
}
|
||||
+32
@@ -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)
|
||||
}
|
||||
}
|
||||
+30
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
-6
@@ -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) {
|
||||
|
||||
+5
@@ -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)
|
||||
}
|
||||
|
||||
+39
@@ -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")
|
||||
|
||||
+4
-3
@@ -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<*>> ->
|
||||
|
||||
+31
-4
@@ -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)
|
||||
|
||||
+60
@@ -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)
|
||||
|
||||
+15
@@ -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
|
||||
)
|
||||
}
|
||||
+5
@@ -59,6 +59,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirConstructorAllowedChecker,
|
||||
)
|
||||
|
||||
override val fileCheckers: Set<FirFileChecker> = setOf(
|
||||
FirTopLevelFunctionChecker,
|
||||
FirTopLevelPropertyChecker,
|
||||
)
|
||||
|
||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
|
||||
FirCallsEffectAnalyzer,
|
||||
FirReturnsImpliesAnalyzer,
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+3
-2
@@ -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()
|
||||
|
||||
+2
-2
@@ -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(
|
||||
|
||||
+24
-56
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -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
|
||||
|
||||
+3
-1
@@ -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
Reference in New Issue
Block a user