mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 15:51:01 +00:00
Compare commits
104 Commits
rr/mitropo
...
v1.1-M04
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4773d54bb7 | ||
|
|
904f5ac0bc | ||
|
|
f6c82f34fc | ||
|
|
264409c399 | ||
|
|
407a39c46f | ||
|
|
7da0e66fdc | ||
|
|
b7cec10de4 | ||
|
|
378a11c898 | ||
|
|
46fb174831 | ||
|
|
83689dff92 | ||
|
|
aa7d69a81a | ||
|
|
a9d54a52a9 | ||
|
|
d72c1cda8e | ||
|
|
183f135505 | ||
|
|
df9cd57d24 | ||
|
|
c54f2b2966 | ||
|
|
212ff73488 | ||
|
|
2dc623a2c9 | ||
|
|
7cbc385193 | ||
|
|
f62d7a9593 | ||
|
|
5a04cbe94a | ||
|
|
5968e9e8c9 | ||
|
|
cccd5e8d22 | ||
|
|
2cb590df7f | ||
|
|
db293c8d10 | ||
|
|
7a6bce696e | ||
|
|
098c0662ca | ||
|
|
8d97034f1e | ||
|
|
4f2835481c | ||
|
|
44980733b8 | ||
|
|
541e389371 | ||
|
|
9ebefb2416 | ||
|
|
ef40daaaa0 | ||
|
|
be0ceaa17b | ||
|
|
4488f8b558 | ||
|
|
1e0a275974 | ||
|
|
fdd86c246d | ||
|
|
7a8e140908 | ||
|
|
7793d3fa10 | ||
|
|
9b8a45f754 | ||
|
|
876d540512 | ||
|
|
a13a307cb4 | ||
|
|
388fe0d353 | ||
|
|
360ec3ca25 | ||
|
|
2250038c67 | ||
|
|
cb089b31c8 | ||
|
|
e955124019 | ||
|
|
9bb390e208 | ||
|
|
7be97bb4b0 | ||
|
|
b6f0128153 | ||
|
|
2dc3262295 | ||
|
|
2a6fc323d3 | ||
|
|
87b151e94a | ||
|
|
4bfaa638b3 | ||
|
|
61c697e938 | ||
|
|
8b310ce329 | ||
|
|
0834a32151 | ||
|
|
ee75a95912 | ||
|
|
ec292c6cf9 | ||
|
|
ed29a60a8c | ||
|
|
d9401c4d71 | ||
|
|
a54127558f | ||
|
|
6e592110fa | ||
|
|
3d53348ea9 | ||
|
|
42b2c653cc | ||
|
|
a9ff441b67 | ||
|
|
d53bc2e358 | ||
|
|
61a650119b | ||
|
|
25b11e3068 | ||
|
|
8ceae7f4c4 | ||
|
|
06015e2770 | ||
|
|
f15d74c1e5 | ||
|
|
7aed4dfc1f | ||
|
|
6c6f1244c4 | ||
|
|
eea1b5fcc6 | ||
|
|
5af6db525a | ||
|
|
d3efabdb58 | ||
|
|
f41019e962 | ||
|
|
9a7a2f842a | ||
|
|
8e0708d891 | ||
|
|
7c5d8a85b9 | ||
|
|
d5c17e0509 | ||
|
|
4c061a93d4 | ||
|
|
b3142784ff | ||
|
|
6433145bad | ||
|
|
5b7968beca | ||
|
|
5878d9e00f | ||
|
|
4b2b86b32e | ||
|
|
f6c7ba69cc | ||
|
|
6b2982a681 | ||
|
|
17b3b6faf8 | ||
|
|
a9777fe706 | ||
|
|
9042e3a1af | ||
|
|
4201c63466 | ||
|
|
790115d1cf | ||
|
|
815377d726 | ||
|
|
c3629ddfad | ||
|
|
8e592706f6 | ||
|
|
0f52469dbc | ||
|
|
374b64350a | ||
|
|
99160027d6 | ||
|
|
9b1c63e542 | ||
|
|
1c694012c2 | ||
|
|
9d9f7d6315 |
1
.idea/artifacts/KotlinJpsPlugin.xml
generated
1
.idea/artifacts/KotlinJpsPlugin.xml
generated
@@ -25,6 +25,7 @@
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/native-platform-uberjar.jar" path-in-jar="/" />
|
||||
<element id="module-output" name="android-extensions-jps" />
|
||||
<element id="module-output" name="build-common" />
|
||||
<element id="module-output" name="compiler-runner" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -25,6 +25,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli.iml" filepath="$PROJECT_DIR$/compiler/cli/cli.iml" group="compiler/cli" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli-common/cli-common.iml" filepath="$PROJECT_DIR$/compiler/cli/cli-common/cli-common.iml" group="compiler/cli" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli-runner/cli-runner.iml" filepath="$PROJECT_DIR$/compiler/cli/cli-runner/cli-runner.iml" group="compiler/cli" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/compiler-runner/compiler-runner.iml" filepath="$PROJECT_DIR$/compiler/compiler-runner/compiler-runner.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/compiler/tests/compiler-tests.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/tests-java8/compiler-tests-java8.iml" filepath="$PROJECT_DIR$/compiler/tests-java8/compiler-tests-java8.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" filepath="$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" group="compiler" />
|
||||
@@ -55,6 +56,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea-runner/idea-runner.iml" filepath="$PROJECT_DIR$/idea-runner/idea-runner.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" filepath="$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/incremental-compilation-impl/incremental-compilation-impl.iml" filepath="$PROJECT_DIR$/compiler/incremental-compilation-impl/incremental-compilation-impl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" filepath="$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" group="compiler/cli" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.ir2cfg/ir.ir2cfg.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.ir2cfg/ir.ir2cfg.iml" group="compiler/ir" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" group="compiler/ir" />
|
||||
|
||||
1710
ChangeLog.md
1710
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import java.io.File
|
||||
|
||||
abstract class IncReporter {
|
||||
abstract class ICReporter {
|
||||
abstract fun report(message: ()->String)
|
||||
|
||||
// used in Gradle plugin
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
|
||||
@@ -70,8 +69,7 @@ fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToComp
|
||||
fun makeCompileServices(
|
||||
incrementalCaches: Map<TargetId, IncrementalCache>,
|
||||
lookupTracker: LookupTracker,
|
||||
compilationCanceledStatus: CompilationCanceledStatus?,
|
||||
sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? = null
|
||||
compilationCanceledStatus: CompilationCanceledStatus?
|
||||
): Services =
|
||||
with(Services.Builder()) {
|
||||
register(IncrementalCompilationComponents::class.java,
|
||||
@@ -79,9 +77,6 @@ fun makeCompileServices(
|
||||
compilationCanceledStatus?.let {
|
||||
register(CompilationCanceledStatus::class.java, it)
|
||||
}
|
||||
sourceRetentionAnnotationHandler?.let {
|
||||
register(SourceRetentionAnnotationHandler::class.java, it)
|
||||
}
|
||||
build()
|
||||
}
|
||||
|
||||
@@ -187,7 +182,7 @@ data class DirtyData(
|
||||
|
||||
fun <Target> CompilationResult.getDirtyData(
|
||||
caches: Iterable<IncrementalCacheImpl<Target>>,
|
||||
reporter: IncReporter
|
||||
reporter: ICReporter
|
||||
): DirtyData {
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
@@ -225,7 +220,7 @@ fun <Target> CompilationResult.getDirtyData(
|
||||
fun mapLookupSymbolsToFiles(
|
||||
lookupStorage: LookupStorage,
|
||||
lookupSymbols: Iterable<LookupSymbol>,
|
||||
reporter: IncReporter,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
): Set<File> {
|
||||
val dirtyFiles = HashSet<File>()
|
||||
@@ -242,7 +237,7 @@ fun mapLookupSymbolsToFiles(
|
||||
fun <Target> mapClassesFqNamesToFiles(
|
||||
caches: Iterable<IncrementalCacheImpl<Target>>,
|
||||
classesFqNames: Iterable<FqName>,
|
||||
reporter: IncReporter,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
): Set<File> {
|
||||
val dirtyFiles = HashSet<File>()
|
||||
@@ -260,8 +255,6 @@ fun <Target> mapClassesFqNamesToFiles(
|
||||
return dirtyFiles
|
||||
}
|
||||
|
||||
private fun File.isJavaFile() = extension.equals(JavaFileType.INSTANCE.defaultExtension, ignoreCase = true)
|
||||
|
||||
private fun findSrcDirRoot(file: File, roots: Iterable<File>): File? =
|
||||
roots.firstOrNull { FileUtil.isAncestor(it, file, false) }
|
||||
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
|
||||
import java.io.File
|
||||
|
||||
class SourceRetentionAnnotationHandlerImpl : SourceRetentionAnnotationHandler {
|
||||
private val mutableSourceRetentionAnnotations = mutableSetOf<String>()
|
||||
|
||||
val sourceRetentionAnnotations: Set<String>
|
||||
get() = mutableSourceRetentionAnnotations
|
||||
|
||||
override fun register(internalName: String) {
|
||||
mutableSourceRetentionAnnotations += internalName
|
||||
fun File.isJavaFile() =
|
||||
extension.equals("java", ignoreCase = true)
|
||||
|
||||
fun File.isKotlinFile(): Boolean =
|
||||
extension.let {
|
||||
"kt".equals(it, ignoreCase = true) ||
|
||||
"kts".equals(it, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun File.isClassFile(): Boolean =
|
||||
extension.equals("class", ignoreCase = true)
|
||||
64
build.xml
64
build.xml
@@ -107,6 +107,8 @@
|
||||
<include name="compiler/plugin-api/src"/>
|
||||
<include name="compiler/daemon/src"/>
|
||||
<include name="compiler/daemon/daemon-common/src"/>
|
||||
<include name="build-common/src"/>
|
||||
<include name="compiler/incremental-compilation-impl/src"/>
|
||||
<include name="compiler/serialization/src"/>
|
||||
<include name="compiler/util/src"/>
|
||||
<include name="js/js.dart-ast/src"/>
|
||||
@@ -139,6 +141,8 @@
|
||||
<include name="conditional-preprocessor/**"/>
|
||||
<include name="daemon/**"/>
|
||||
<include name="daemon-common/**"/>
|
||||
<include name="build-common/**"/>
|
||||
<include name="incremental-compilation-impl/**"/>
|
||||
<include name="util/**"/>
|
||||
<include name="util.runtime/**"/>
|
||||
<include name="light-classes/**"/>
|
||||
@@ -245,6 +249,8 @@
|
||||
<fileset dir="compiler/conditional-preprocessor/src"/>
|
||||
<fileset dir="compiler/daemon/src"/>
|
||||
<fileset dir="compiler/daemon/daemon-common/src"/>
|
||||
<fileset dir="build-common/src"/>
|
||||
<fileset dir="compiler/incremental-compilation-impl/src"/>
|
||||
<fileset dir="compiler/container/src"/>
|
||||
<fileset dir="compiler/frontend/src"/>
|
||||
<fileset dir="compiler/resolution/src"/>
|
||||
@@ -684,54 +690,6 @@
|
||||
<pack-compiler-for-maven/>
|
||||
</target>
|
||||
|
||||
<target name="kotlin-build-common">
|
||||
<cleandir dir="${output}/classes/kotlin-build-common"/>
|
||||
|
||||
<javac2 destdir="${output}/classes/kotlin-build-common" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false"
|
||||
source="${java.target}" target="${java.target}">
|
||||
<withKotlin modulename="kotlin-build-common">
|
||||
<compilerarg value="-version"/>
|
||||
</withKotlin>
|
||||
<skip pattern="kotlin/Metadata"/>
|
||||
<src>
|
||||
<pathelement path="build-common/src"/>
|
||||
</src>
|
||||
<classpath>
|
||||
<pathelement path="${bootstrap.runtime}"/>
|
||||
<pathelement path="${bootstrap.reflect}"/>
|
||||
<pathelement path="${bootstrap.script.runtime}"/>
|
||||
<pathelement path="${idea.sdk}/lib/util.jar"/>
|
||||
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-build-common.jar">
|
||||
<fileset dir="${output}/classes/kotlin-build-common"/>
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
|
||||
|
||||
<attribute name="Implementation-Vendor" value="${manifest.impl.vendor}"/>
|
||||
<attribute name="Implementation-Title" value="${manifest.impl.title.kotlin.build.common}"/>
|
||||
<attribute name="Implementation-Version" value="${build.number}"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
|
||||
<jar jarfile="${output}/kotlin-build-common-sources.jar">
|
||||
<fileset dir="build-common/src"/>
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
|
||||
|
||||
<attribute name="Implementation-Vendor" value="${manifest.impl.vendor}"/>
|
||||
<attribute name="Implementation-Title" value="${manifest.impl.title.kotlin.build.common.sources}"/>
|
||||
<attribute name="Implementation-Version" value="${build.number}"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="kotlin-build-common-test">
|
||||
<cleandir dir="${output}/classes/kotlin-build-common-test"/>
|
||||
|
||||
@@ -739,7 +697,10 @@
|
||||
source="${java.target}" target="${java.target}">
|
||||
<withKotlin modulename="kotlin-build-common"/>
|
||||
<skip pattern="kotlin/Metadata"/>
|
||||
<src path="build-common/test"/>
|
||||
<src>
|
||||
<pathelement path="build-common/test"/>
|
||||
<pathelement path="compiler/incremental-compilation-impl/test"/>
|
||||
</src>
|
||||
<classpath>
|
||||
<pathelement path="${bootstrap.runtime}"/>
|
||||
<pathelement path="${bootstrap.reflect}"/>
|
||||
@@ -747,7 +708,6 @@
|
||||
<pathelement path="${bootstrap.kotlin.test}"/>
|
||||
<pathelement path="${protobuf.jar}"/>
|
||||
<pathelement path="${idea.sdk}/lib/junit-4.12.jar"/>
|
||||
<pathelement path="${kotlin-home}/lib/kotlin-build-common.jar"/>
|
||||
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
@@ -902,7 +862,7 @@
|
||||
<fileset dir="${basedir}/plugins/sam-with-receiver/sam-with-receiver-cli/src" includes="META-INF/services/**"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="annotation-processing-under-jdk8">
|
||||
<property environment="env"/>
|
||||
|
||||
@@ -1313,7 +1273,7 @@
|
||||
depends="builtins,stdlib,kotlin-test,core,reflection,pack-runtime,pack-runtime-sources,script-runtime,mock-runtime-for-test"/>
|
||||
|
||||
<target name="dist"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,kotlin-build-common,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,annotation-processing-under-jdk8,daemon-client,kotlin-build-common-test"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,runtime,kotlin-js-stdlib,android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,annotation-processing-under-jdk8,daemon-client,kotlin-build-common-test"
|
||||
description="Builds redistributables from sources"/>
|
||||
|
||||
<target name="dist-quick"
|
||||
|
||||
@@ -65,6 +65,7 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
|
||||
@@ -306,10 +307,11 @@ public class AsmUtil {
|
||||
case ANNOTATION_CLASS:
|
||||
return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE;
|
||||
default:
|
||||
if (innerClass.getModality() == Modality.FINAL) {
|
||||
Modality modality = innerClass.getModality();
|
||||
if (modality == Modality.FINAL) {
|
||||
return ACC_FINAL;
|
||||
}
|
||||
else if (innerClass.getModality() == Modality.ABSTRACT) {
|
||||
else if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
|
||||
return ACC_ABSTRACT;
|
||||
}
|
||||
}
|
||||
@@ -342,7 +344,7 @@ public class AsmUtil {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||
|
||||
if (AnnotationUtilKt.isInlineOnlyOrReified(memberDescriptor)) return ACC_PRIVATE;
|
||||
if (isInlineOnlyOrReified(memberDescriptor)) return ACC_PRIVATE;
|
||||
|
||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
return ACC_PUBLIC;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ClassBuilderMode {
|
||||
}
|
||||
|
||||
public static ClassBuilderMode full(boolean generateSourceRetentionAnnotations) {
|
||||
return generateSourceRetentionAnnotations ? KAPT2 : FULL;
|
||||
return generateSourceRetentionAnnotations ? KAPT : FULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,15 +47,6 @@ public class ClassBuilderMode {
|
||||
/* sourceRetention = */ false,
|
||||
/* generateMultiFileFacadePartClasses = */ true);
|
||||
|
||||
/**
|
||||
* Full function bodies, write annotations with the "source" retention.
|
||||
*/
|
||||
private final static ClassBuilderMode KAPT2 = new ClassBuilderMode(
|
||||
/* bodies = */ true,
|
||||
/* metadata = */ true,
|
||||
/* sourceRetention = */ true,
|
||||
/* generateMultiFileFacadePartClasses = */ false);
|
||||
|
||||
/**
|
||||
* Generating light classes: Only function signatures
|
||||
*/
|
||||
|
||||
@@ -127,7 +127,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public final FrameMap myFrameMap;
|
||||
public final MethodContext context;
|
||||
private final Type returnType;
|
||||
private final Type boxedReturnTypeForCoroutine;
|
||||
|
||||
private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this);
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
@@ -161,14 +160,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
this.myFrameMap = frameMap;
|
||||
this.context = context;
|
||||
|
||||
FunctionDescriptor descriptorForCoroutine = getOriginalLambdaDescriptorForCoroutine(context);
|
||||
if (descriptorForCoroutine != null && descriptorForCoroutine.getReturnType() != null) {
|
||||
this.returnType = typeMapper.mapReturnType(descriptorForCoroutine);
|
||||
this.boxedReturnTypeForCoroutine = getBoxedReturnTypeForCoroutine(descriptorForCoroutine);
|
||||
FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context);
|
||||
if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) {
|
||||
this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor);
|
||||
}
|
||||
else {
|
||||
this.returnType = returnType;
|
||||
this.boxedReturnTypeForCoroutine = null;
|
||||
}
|
||||
|
||||
this.parentCodegen = parentCodegen;
|
||||
@@ -176,18 +173,31 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type getBoxedReturnTypeForCoroutine(FunctionDescriptor descriptorForCoroutine) {
|
||||
assert descriptorForCoroutine.getReturnType() != null : "Uninitialized coroutine return type";
|
||||
return AsmUtil.boxType(typeMapper.mapType(descriptorForCoroutine.getReturnType()));
|
||||
private Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) {
|
||||
assert descriptorForSuspend.getReturnType() != null : "Uninitialized suspend return type";
|
||||
return AsmUtil.boxType(typeMapper.mapType(descriptorForSuspend.getReturnType()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FunctionDescriptor getOriginalLambdaDescriptorForCoroutine(MethodContext context) {
|
||||
private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) {
|
||||
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
||||
if (originalCoroutineDescriptor != null) return originalCoroutineDescriptor;
|
||||
|
||||
if (context.getFunctionDescriptor().isSuspend()) {
|
||||
return (FunctionDescriptor) CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(context.getFunctionDescriptor());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FunctionDescriptor getOriginalCoroutineDescriptor(MethodContext context) {
|
||||
if ((context.getParentContext() instanceof ClosureContext) &&
|
||||
(context.getParentContext().closure != null) &&
|
||||
context.getParentContext().closure.isCoroutine()) {
|
||||
return ((ClosureContext) context.getParentContext()).getCoroutineDescriptor();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -351,7 +361,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
putStackValue(expr, type, value);
|
||||
}
|
||||
|
||||
private void putStackValue(KtElement expr, Type type, StackValue value) {
|
||||
private void putStackValue(@Nullable KtElement expr, @NotNull Type type, @NotNull StackValue value) {
|
||||
// for repl store the result of the last line into special field
|
||||
if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) {
|
||||
ScriptContext context = getScriptContext();
|
||||
@@ -944,14 +954,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange));
|
||||
@SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
|
||||
StackValue result = invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator));
|
||||
result.put(result.type, v);
|
||||
result.put(Type.BOOLEAN_TYPE, v);
|
||||
|
||||
FunctionDescriptor hasNext = hasNextCall.getResultingDescriptor();
|
||||
KotlinType type = hasNext.getReturnType();
|
||||
assert type != null && KotlinTypeChecker.DEFAULT.isSubtypeOf(type, DescriptorUtilsKt.getBuiltIns(hasNext).getBooleanType());
|
||||
|
||||
Type asmType = asmType(type);
|
||||
StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v);
|
||||
v.ifeq(loopExit);
|
||||
}
|
||||
|
||||
@@ -1775,7 +1779,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@NotNull
|
||||
private static CallableDescriptor unwrapOriginalLambdaDescriptorForCoroutine(@NotNull MethodContext context) {
|
||||
FunctionDescriptor coroutine = getOriginalLambdaDescriptorForCoroutine(context);
|
||||
FunctionDescriptor coroutine = getOriginalSuspendDescriptor(context);
|
||||
if (coroutine != null) return coroutine;
|
||||
return context.getFunctionDescriptor();
|
||||
}
|
||||
@@ -2159,26 +2163,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType;
|
||||
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : null;
|
||||
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
|
||||
|
||||
if (returnedExpression != null && valueToReturn != null) {
|
||||
putStackValue(returnedExpression, returnType, valueToReturn);
|
||||
}
|
||||
putStackValue(returnedExpression, returnType, valueToReturn);
|
||||
|
||||
Label afterReturnLabel = new Label();
|
||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
|
||||
|
||||
if (isNonLocalReturn) {
|
||||
if (nonLocalReturn.boxedCoroutineReturnType != null && !nonLocalReturn.boxedCoroutineReturnType.equals(returnType)) {
|
||||
StackValue.coerce(nonLocalReturn.returnType, nonLocalReturn.boxedCoroutineReturnType, v);
|
||||
returnType = nonLocalReturn.boxedCoroutineReturnType;
|
||||
}
|
||||
|
||||
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
|
||||
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
|
||||
}
|
||||
else {
|
||||
emitLocalReturnInsn();
|
||||
v.areturn(ExpressionCodegen.this.returnType);
|
||||
}
|
||||
|
||||
v.mark(afterReturnLabel);
|
||||
@@ -2213,7 +2210,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor containingFunction =
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL, null);
|
||||
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
|
||||
} else {
|
||||
//local
|
||||
return null;
|
||||
@@ -2225,49 +2222,49 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
||||
assert element != null : "Expression should be not null " + expression.getText();
|
||||
assert elementDescriptor != null : "Descriptor should be not null: " + element.getText();
|
||||
Type boxedCoroutineReturnType =
|
||||
elementDescriptor instanceof AnonymousFunctionDescriptor
|
||||
&& ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine()
|
||||
? getBoxedReturnTypeForCoroutine((FunctionDescriptor) elementDescriptor)
|
||||
: null;
|
||||
return new NonLocalReturnInfo(
|
||||
typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName(),
|
||||
boxedCoroutineReturnType
|
||||
);
|
||||
return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(elementDescriptor), expression.getLabelName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type getReturnTypeForNonLocalReturn(DeclarationDescriptor elementDescriptor) {
|
||||
return (elementDescriptor instanceof AnonymousFunctionDescriptor
|
||||
&& ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine())
|
||||
|| (elementDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) elementDescriptor).isSuspend())
|
||||
? getBoxedReturnTypeForSuspend((FunctionDescriptor) elementDescriptor)
|
||||
: typeMapper.mapReturnType((CallableDescriptor) elementDescriptor);
|
||||
}
|
||||
|
||||
public void returnExpression(KtExpression expr) {
|
||||
boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction;
|
||||
|
||||
// If generating body for named block-bodied function, generate it as sequence of statements
|
||||
gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType);
|
||||
FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context);
|
||||
boolean isVoidCoroutineLambda =
|
||||
originalCoroutineDescriptor != null && typeMapper.mapReturnType(originalCoroutineDescriptor).getSort() == Type.VOID;
|
||||
|
||||
// If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements
|
||||
Type typeForExpression =
|
||||
isBlockedNamedFunction || isVoidCoroutineLambda
|
||||
? Type.VOID_TYPE
|
||||
: returnType;
|
||||
|
||||
gen(expr, typeForExpression);
|
||||
|
||||
// If it does not end with return we should return something
|
||||
// because if we don't there can be VerifyError (specific cases with Nothing-typed expressions)
|
||||
if (!endsWithReturn(expr)) {
|
||||
markLineNumber(expr, true);
|
||||
|
||||
if (isLambdaVoidBody(expr, returnType)) {
|
||||
if (isLambdaVoidBody(expr, typeForExpression)) {
|
||||
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
|
||||
}
|
||||
|
||||
if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) {
|
||||
if (typeForExpression.getSort() == Type.VOID) {
|
||||
StackValue.none().put(returnType, v);
|
||||
}
|
||||
|
||||
emitLocalReturnInsn();
|
||||
}
|
||||
}
|
||||
|
||||
private void emitLocalReturnInsn() {
|
||||
if (boxedReturnTypeForCoroutine != null && !boxedReturnTypeForCoroutine.equals(returnType)) {
|
||||
StackValue.coerce(returnType, boxedReturnTypeForCoroutine, v);
|
||||
v.areturn(boxedReturnTypeForCoroutine);
|
||||
}
|
||||
else {
|
||||
v.areturn(returnType);
|
||||
}
|
||||
}
|
||||
@@ -2778,9 +2775,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
|
||||
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) {
|
||||
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
|
||||
return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
|
||||
if (bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall()) != null) {
|
||||
// Suspend function's calls inside another suspend function should behave like they leave values of correct type,
|
||||
// while real methods return java/lang/Object.
|
||||
// NB: They are always in return position at the moment.
|
||||
// If we didn't do this, StackValue.coerce would add proper CHECKCAST that would've failed in case of callee function
|
||||
// returning SUSPENDED marker, which is instance of java/lang/Object.
|
||||
return new OperationStackValue(returnType, ((OperationStackValue) result).getLambda());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2895,11 +2896,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (isSuspensionPoint) {
|
||||
v.tconst(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall));
|
||||
v.invokestatic(
|
||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
||||
"(Ljava/lang/Class;)V", false);
|
||||
"()V", false
|
||||
);
|
||||
}
|
||||
|
||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||
@@ -2918,23 +2919,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type getSuspensionBoxedReturnTypeByResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
|
||||
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
|
||||
|
||||
FunctionDescriptor initialSignature =
|
||||
((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor())
|
||||
.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION);
|
||||
|
||||
assert initialSignature != null : "Initial signature must be not null for suspension point";
|
||||
|
||||
KotlinType returnType = initialSignature.getReturnType();
|
||||
|
||||
assert returnType != null : "Return type of suspension point should not be null";
|
||||
return typeMapper.mapType(TypeUtils.makeNullable(returnType));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CallGenerator getOrCreateCallGenerator(
|
||||
@NotNull CallableDescriptor descriptor,
|
||||
@@ -4713,12 +4697,10 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
private final Type returnType;
|
||||
|
||||
private final String labelName;
|
||||
private final Type boxedCoroutineReturnType;
|
||||
|
||||
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name, @Nullable Type boxedCoroutineReturnType) {
|
||||
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name) {
|
||||
returnType = type;
|
||||
labelName = name;
|
||||
this.boxedCoroutineReturnType = boxedCoroutineReturnType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
@@ -83,6 +82,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
@@ -863,7 +863,7 @@ public class FunctionCodegen {
|
||||
// $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
|
||||
// $default methods are never protected to be accessible from subclass nested classes
|
||||
int visibilityFlag = Visibilities.isPrivate(functionDescriptor.getVisibility()) ||
|
||||
AnnotationUtilKt.isInlineOnlyOrReified(functionDescriptor) ?
|
||||
isInlineOnlyOrReified(functionDescriptor) ?
|
||||
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
|
||||
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
|
||||
if (!(functionDescriptor instanceof ConstructorDescriptor)) {
|
||||
|
||||
@@ -268,9 +268,7 @@ public class JvmCodegenUtil {
|
||||
|
||||
@NotNull
|
||||
public static CallableMemberDescriptor getDirectMember(@NotNull CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof PropertyAccessorDescriptor
|
||||
? ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()
|
||||
: descriptor;
|
||||
return DescriptorUtils.getDirectMember(descriptor);
|
||||
}
|
||||
|
||||
public static boolean isArgumentWhichWillBeInlined(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -39,6 +38,7 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
|
||||
@@ -638,7 +638,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
boolean withinInline,
|
||||
boolean isSuperCall
|
||||
) {
|
||||
if (AnnotationUtilKt.isInlineOnlyOrReified(unwrappedDescriptor)) return false;
|
||||
if (isInlineOnlyOrReified(unwrappedDescriptor)) return false;
|
||||
|
||||
return isSuperCall && withinInline ||
|
||||
(accessFlag & ACC_PRIVATE) != 0 ||
|
||||
|
||||
@@ -162,36 +162,12 @@ class CoroutineTransformerMethodVisitor(
|
||||
}
|
||||
|
||||
AFTER_SUSPENSION_POINT_MARKER_NAME -> {
|
||||
assert(beforeSuspensionPointMarkerStack.isNotEmpty()) { "Expected non-empty stack beforeSuspensionPointMarkerStack" }
|
||||
val beforeSuspensionPointMarker = beforeSuspensionPointMarkerStack.pop()
|
||||
assert(beforeSuspensionPointMarker.previous is LdcInsnNode) {
|
||||
"Instruction before BEFORE_SUSPENSION_POINT_MARKER_NAME should be LDC with expected return type, " +
|
||||
"but ${beforeSuspensionPointMarker.previous} was found"
|
||||
}
|
||||
|
||||
val fakeReturnValueInsns = mutableListOf<AbstractInsnNode>()
|
||||
|
||||
val suspensionPoint = SuspensionPoint(
|
||||
suspensionCallBegin = beforeSuspensionPointMarker,
|
||||
suspensionCallEnd = methodInsn,
|
||||
fakeReturnValueInsns = fakeReturnValueInsns,
|
||||
returnType = (beforeSuspensionPointMarker.previous as LdcInsnNode).cst as Type)
|
||||
suspensionPoints.add(suspensionPoint)
|
||||
|
||||
// Drop type info from marker
|
||||
methodNode.instructions.remove(beforeSuspensionPointMarker.previous)
|
||||
beforeSuspensionPointMarker.desc = "()V"
|
||||
|
||||
assert(suspensionPoint.returnType != Type.VOID_TYPE) { "Suspension point can't be VOID" }
|
||||
|
||||
// Checkcast only is needed to tell analyzer what type exactly should be returned from suspension point
|
||||
// This type is used when for restoring spilled variables into fields
|
||||
val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName)
|
||||
methodNode.instructions.insertBefore(
|
||||
suspensionPoint.suspensionCallEnd, checkCast
|
||||
suspensionPoints.add(
|
||||
SuspensionPoint(
|
||||
suspensionCallBegin = beforeSuspensionPointMarkerStack.pop(),
|
||||
suspensionCallEnd = methodInsn
|
||||
)
|
||||
)
|
||||
|
||||
fakeReturnValueInsns.add(checkCast)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +200,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
for (suspension in suspensionPoints) {
|
||||
val suspensionCallBegin = suspension.suspensionCallBegin
|
||||
val suspensionCallEnd = suspension.suspensionCallEnd
|
||||
assert(frames[suspensionCallEnd.next.index()]?.stackSize == (if (suspension.returnType.sort == Type.VOID) 0 else 1)) {
|
||||
assert(frames[suspensionCallEnd.next.index()]?.stackSize == 1) {
|
||||
"Stack should be spilled before suspension call"
|
||||
}
|
||||
|
||||
@@ -338,9 +314,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
)
|
||||
)
|
||||
|
||||
// Drop default value that purpose was to simulate returned value by suspension method
|
||||
suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) }
|
||||
|
||||
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
||||
dup()
|
||||
load(suspendMarkerVarIndex, AsmTypes.OBJECT_TYPE)
|
||||
@@ -371,7 +344,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
|
||||
visitLabel(continuationLabelAfterLoadedResult.label)
|
||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -500,9 +472,7 @@ private class SuspensionPoint(
|
||||
// INVOKESTATIC beforeSuspensionMarker
|
||||
val suspensionCallBegin: AbstractInsnNode,
|
||||
// INVOKESTATIC afterSuspensionMarker
|
||||
val suspensionCallEnd: AbstractInsnNode,
|
||||
val fakeReturnValueInsns: List<AbstractInsnNode>,
|
||||
val returnType: Type
|
||||
val suspensionCallEnd: AbstractInsnNode
|
||||
) {
|
||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
@@ -70,6 +69,7 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.hasInlineOnlyAnnotation;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||
|
||||
public class InlineCodegen extends CallGenerator {
|
||||
@@ -436,7 +436,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
||||
"Method inlining " + callElement.getText(),
|
||||
createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(),
|
||||
AnnotationUtilKt.hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
|
||||
hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
|
||||
); //with captured
|
||||
|
||||
LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
|
||||
|
||||
@@ -224,7 +224,7 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
CallableMemberDescriptor directMember = getDirectMember(descriptor);
|
||||
CallableMemberDescriptor directMember = DescriptorUtils.getDirectMember(descriptor);
|
||||
|
||||
if (directMember instanceof DeserializedCallableMemberDescriptor) {
|
||||
String facadeFqName = getPackageMemberOwnerInternalName((DeserializedCallableMemberDescriptor) directMember, publicFacade);
|
||||
@@ -946,7 +946,7 @@ public class KotlinTypeMapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
descriptor = getDirectMember(descriptor);
|
||||
descriptor = DescriptorUtils.getDirectMember(descriptor);
|
||||
assert descriptor instanceof DeserializedCallableMemberDescriptor :
|
||||
"Descriptor without sources should be instance of DeserializedCallableMemberDescriptor, but: " +
|
||||
descriptor;
|
||||
@@ -1039,7 +1039,7 @@ public class KotlinTypeMapper {
|
||||
writeVoidReturn(sw);
|
||||
}
|
||||
else {
|
||||
CallableMemberDescriptor directMember = getDirectMember(f);
|
||||
CallableMemberDescriptor directMember = DescriptorUtils.getDirectMember(f);
|
||||
KotlinType thisIfNeeded = null;
|
||||
if (OwnerKind.DEFAULT_IMPLS == kind) {
|
||||
ReceiverTypeAndTypeParameters receiverTypeAndTypeParameters = TypeMapperUtilsKt.patchTypeParametersForDefaultImplMethod(directMember);
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsSerializerExtension
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.METADATA_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.DOT_METADATA_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.DataOutputStream
|
||||
@@ -132,10 +132,10 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
|
||||
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
|
||||
packageFqName.asString().replace('.', '/') + "/" +
|
||||
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + METADATA_FILE_EXTENSION
|
||||
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + DOT_METADATA_FILE_EXTENSION
|
||||
|
||||
private fun getClassFilePath(classId: ClassId): String =
|
||||
classId.asSingleFqName().asString().replace('.', '/') + METADATA_FILE_EXTENSION
|
||||
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
|
||||
|
||||
protected inner class PackageSerializer(
|
||||
private val classes: Collection<DeclarationDescriptor>,
|
||||
|
||||
@@ -109,6 +109,9 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
languageVersionSettings: LanguageVersionSettings?,
|
||||
classpathJarRoots: List<VirtualFile>
|
||||
) {
|
||||
// TODO: write runtime version to Maven artifacts and enable these checks
|
||||
return
|
||||
|
||||
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
|
||||
if (runtimeJarsInfo.hasAnyJarsToCheck) {
|
||||
val languageVersion = languageVersionSettings?.let { MavenComparableVersion(it.languageVersion) } ?: CURRENT_COMPILER_VERSION
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
@@ -267,10 +266,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, components)
|
||||
}
|
||||
}
|
||||
|
||||
services.get(SourceRetentionAnnotationHandler::class.java)?.let { handler ->
|
||||
configuration.put(JVMConfigurationKeys.SOURCE_RETENTION_ANNOTATION_HANDLER, handler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,13 +39,13 @@ class JvmCliVirtualFileFinder(
|
||||
override fun findMetadata(classId: ClassId): InputStream? {
|
||||
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
|
||||
|
||||
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.METADATA_FILE_EXTENSION)?.inputStream
|
||||
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream
|
||||
}
|
||||
|
||||
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||
var found = false
|
||||
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
|
||||
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION.substring(1) }
|
||||
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION }
|
||||
!found
|
||||
})
|
||||
return found
|
||||
|
||||
@@ -313,7 +313,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.getProperties().setProperty("idea.plugins.compatible.build", "162.9999")
|
||||
setCompatibleBuild()
|
||||
}
|
||||
|
||||
private val APPLICATION_LOCK = Object()
|
||||
@@ -323,6 +323,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
@JvmStatic fun createForProduction(
|
||||
parentDisposable: Disposable, configuration: CompilerConfiguration, configFilePaths: List<String>
|
||||
): KotlinCoreEnvironment {
|
||||
setCompatibleBuild()
|
||||
val appEnv = getOrCreateApplicationEnvironmentForProduction(configuration, configFilePaths)
|
||||
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally
|
||||
// breaks a lot of tests, therefore it is disabled for production and enabled for tests
|
||||
@@ -345,6 +346,11 @@ class KotlinCoreEnvironment private constructor(
|
||||
return environment
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun setCompatibleBuild() {
|
||||
System.getProperties().setProperty("idea.plugins.compatible.build", "162.9999")
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@JvmStatic fun createForTests(
|
||||
parentDisposable: Disposable, configuration: CompilerConfiguration, extensionConfigs: List<String>
|
||||
|
||||
19
compiler/compiler-runner/compiler-runner.iml
Normal file
19
compiler/compiler-runner/compiler-runner.iml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="build-common" />
|
||||
<orderEntry type="module" module-name="cli-common" />
|
||||
<orderEntry type="module" module-name="daemon-client" />
|
||||
<orderEntry type="module" module-name="daemon-common" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="preloader" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
|
||||
open class CompilerEnvironment(
|
||||
val services: Services,
|
||||
val messageCollector: MessageCollector,
|
||||
open val outputItemsCollector: OutputItemsCollector
|
||||
)
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.util.containers.Stack
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
import org.xml.sax.Attributes
|
||||
import org.xml.sax.InputSource
|
||||
import org.xml.sax.SAXException
|
||||
import org.xml.sax.helpers.DefaultHandler
|
||||
|
||||
import javax.xml.parsers.SAXParser
|
||||
import javax.xml.parsers.SAXParserFactory
|
||||
import java.io.IOException
|
||||
import java.io.Reader
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.Companion.NO_LOCATION
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil.reportException
|
||||
|
||||
object CompilerOutputParser {
|
||||
fun parseCompilerMessagesFromReader(messageCollector: MessageCollector, reader: Reader, collector: OutputItemsCollector) {
|
||||
// Sometimes the compiler doesn't output valid XML.
|
||||
// Example: error in command line arguments passed to the compiler.
|
||||
// The compiler will print the usage and the SAX parser will break.
|
||||
// In this case, we want to read everything from this stream and report it as an IDE error.
|
||||
val stringBuilder = StringBuilder()
|
||||
val wrappingReader = object : Reader() {
|
||||
@Throws(IOException::class)
|
||||
override fun read(cbuf: CharArray, off: Int, len: Int): Int {
|
||||
val read = reader.read(cbuf, off, len)
|
||||
stringBuilder.append(cbuf, off, len)
|
||||
return read
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun close() {
|
||||
// Do nothing:
|
||||
// If the SAX parser sees a syntax error, it throws an exception
|
||||
// and calls close() on the reader.
|
||||
// We prevent hte reader from being closed here, and close it later,
|
||||
// when all the text is read from it
|
||||
}
|
||||
}
|
||||
try {
|
||||
val factory = SAXParserFactory.newInstance()
|
||||
val parser = factory.newSAXParser()
|
||||
parser.parse(InputSource(wrappingReader), CompilerOutputSAXHandler(messageCollector, collector))
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
// Load all the text into the stringBuilder
|
||||
try {
|
||||
// This will not close the reader (see the wrapper above)
|
||||
FileUtil.loadTextAndClose(wrappingReader)
|
||||
}
|
||||
catch (ioException: IOException) {
|
||||
reportException(messageCollector, ioException)
|
||||
}
|
||||
|
||||
val message = stringBuilder.toString()
|
||||
reportException(messageCollector, IllegalStateException(message, e))
|
||||
messageCollector.report(ERROR, message, NO_LOCATION)
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
reader.close()
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportException(messageCollector, e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class CompilerOutputSAXHandler(private val messageCollector: MessageCollector, private val collector: OutputItemsCollector) : DefaultHandler() {
|
||||
|
||||
private val message = StringBuilder()
|
||||
private val tags = Stack<String>()
|
||||
private var path: String? = null
|
||||
private var line: Int = 0
|
||||
private var column: Int = 0
|
||||
|
||||
@Throws(SAXException::class)
|
||||
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
||||
tags.push(qName)
|
||||
|
||||
message.setLength(0)
|
||||
|
||||
path = attributes.getValue("path")
|
||||
line = safeParseInt(attributes.getValue("line"), -1)
|
||||
column = safeParseInt(attributes.getValue("column"), -1)
|
||||
}
|
||||
|
||||
@Throws(SAXException::class)
|
||||
override fun characters(ch: CharArray?, start: Int, length: Int) {
|
||||
if (tags.size == 1) {
|
||||
// We're directly inside the root tag: <MESSAGES>
|
||||
val message = String(ch!!, start, length)
|
||||
if (!message.trim { it <= ' ' }.isEmpty()) {
|
||||
messageCollector.report(ERROR, "Unhandled compiler output: " + message, NO_LOCATION)
|
||||
}
|
||||
}
|
||||
else {
|
||||
message.append(ch, start, length)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(SAXException::class)
|
||||
override fun endElement(uri: String?, localName: String, qName: String) {
|
||||
if (tags.size == 1) {
|
||||
// We're directly inside the root tag: <MESSAGES>
|
||||
return
|
||||
}
|
||||
val qNameLowerCase = qName.toLowerCase()
|
||||
var category: CompilerMessageSeverity? = CATEGORIES[qNameLowerCase]
|
||||
if (category == null) {
|
||||
messageCollector.report(ERROR, "Unknown compiler message tag: " + qName, NO_LOCATION)
|
||||
category = INFO
|
||||
}
|
||||
val text = message.toString()
|
||||
|
||||
if (category == OUTPUT) {
|
||||
reportToCollector(text)
|
||||
}
|
||||
else {
|
||||
messageCollector.report(category, text, CompilerMessageLocation.create(path, line, column, null))
|
||||
}
|
||||
tags.pop()
|
||||
}
|
||||
|
||||
private fun reportToCollector(text: String) {
|
||||
val output = OutputMessageUtil.parseOutputMessage(text)
|
||||
if (output != null) {
|
||||
collector.add(output.sourceFiles, output.outputFile)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CATEGORIES = mapOf(
|
||||
"error" to ERROR,
|
||||
"warning" to WARNING,
|
||||
"logging" to LOGGING,
|
||||
"output" to OUTPUT,
|
||||
"exception" to EXCEPTION,
|
||||
"info" to INFO,
|
||||
"messages" to INFO)
|
||||
|
||||
private fun safeParseInt(value: String?, defaultValue: Int): Int {
|
||||
if (value == null) {
|
||||
return defaultValue
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(value.trim { it <= ' ' })
|
||||
}
|
||||
catch (e: NumberFormatException) {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
|
||||
import org.jetbrains.kotlin.daemon.client.CompilationServices
|
||||
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
|
||||
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
|
||||
import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import java.io.BufferedReader
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.StringReader
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
interface KotlinLogger {
|
||||
fun error(msg: String)
|
||||
fun warn(msg: String)
|
||||
fun info(msg: String)
|
||||
fun debug(msg: String)
|
||||
}
|
||||
|
||||
abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
|
||||
protected val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
|
||||
protected val K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler"
|
||||
protected val K2METADATA_COMPILER = "org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler"
|
||||
protected val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString()
|
||||
|
||||
protected abstract val log: KotlinLogger
|
||||
|
||||
class DaemonConnection(val daemon: CompileService?, val sessionId: Int = CompileService.NO_SESSION)
|
||||
|
||||
protected abstract fun getDaemonConnection(environment: Env): DaemonConnection
|
||||
|
||||
@Synchronized
|
||||
protected fun newDaemonConnection(compilerId: CompilerId, flagFile: File, environment: Env): DaemonConnection {
|
||||
val daemonOptions = configureDaemonOptions()
|
||||
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
|
||||
|
||||
val daemonReportMessages = ArrayList<DaemonReportMessage>()
|
||||
|
||||
val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler()
|
||||
|
||||
val connection = profiler.withMeasure(null) {
|
||||
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true)
|
||||
DaemonConnection(daemon, daemon?.leaseCompileSession(flagFile.absolutePath)?.get() ?: CompileService.NO_SESSION)
|
||||
}
|
||||
|
||||
for (msg in daemonReportMessages) {
|
||||
environment.messageCollector.report(CompilerMessageSeverity.INFO,
|
||||
(if (msg.category == DaemonReportCategory.EXCEPTION && connection.daemon == null) "Falling back to compilation without daemon due to error: " else "") + msg.message,
|
||||
CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
|
||||
fun reportTotalAndThreadPerf(message: String, daemonOptions: DaemonOptions, messageCollector: MessageCollector, profiler: Profiler) {
|
||||
if (daemonOptions.reportPerf) {
|
||||
fun Long.ms() = TimeUnit.NANOSECONDS.toMillis(this)
|
||||
val counters = profiler.getTotalCounters()
|
||||
messageCollector.report(CompilerMessageSeverity.INFO,
|
||||
"PERF: $message ${counters.time.ms()} ms, thread ${counters.threadTime.ms()}",
|
||||
CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
}
|
||||
|
||||
reportTotalAndThreadPerf("Daemon connect", daemonOptions, environment.messageCollector, profiler)
|
||||
return connection
|
||||
}
|
||||
|
||||
protected fun processCompilerOutput(
|
||||
environment: Env,
|
||||
stream: ByteArrayOutputStream,
|
||||
exitCode: ExitCode?
|
||||
) {
|
||||
val reader = BufferedReader(StringReader(stream.toString()))
|
||||
CompilerOutputParser.parseCompilerMessagesFromReader(environment.messageCollector, reader, environment.outputItemsCollector)
|
||||
|
||||
if (ExitCode.INTERNAL_ERROR == exitCode) {
|
||||
reportInternalCompilerError(environment.messageCollector)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun reportInternalCompilerError(messageCollector: MessageCollector): ExitCode {
|
||||
messageCollector.report(ERROR, "Compiler terminated with internal error", CompilerMessageLocation.NO_LOCATION)
|
||||
return ExitCode.INTERNAL_ERROR
|
||||
}
|
||||
|
||||
protected fun runCompiler(
|
||||
compilerClassName: String,
|
||||
arguments: CommonCompilerArguments,
|
||||
additionalArguments: String,
|
||||
environment: Env): ExitCode {
|
||||
return try {
|
||||
val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments)
|
||||
argumentsList.addAll(additionalArguments.split(" "))
|
||||
|
||||
val argsArray = argumentsList.toTypedArray()
|
||||
doRunCompiler(compilerClassName, argsArray, environment)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
MessageCollectorUtil.reportException(environment.messageCollector, e)
|
||||
reportInternalCompilerError(environment.messageCollector)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doRunCompiler(
|
||||
compilerClassName: String,
|
||||
argsArray: Array<String>,
|
||||
environment: Env
|
||||
): ExitCode
|
||||
|
||||
/**
|
||||
* Returns null if could not connect to daemon
|
||||
*/
|
||||
protected open fun compileWithDaemon(
|
||||
compilerClassName: String,
|
||||
argsArray: Array<String>,
|
||||
environment: Env
|
||||
): ExitCode? {
|
||||
val compilerOut = ByteArrayOutputStream()
|
||||
val daemonOut = ByteArrayOutputStream()
|
||||
val services = CompilationServices(
|
||||
incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java),
|
||||
compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java))
|
||||
val targetPlatform = when (compilerClassName) {
|
||||
K2JVM_COMPILER -> CompileService.TargetPlatform.JVM
|
||||
K2JS_COMPILER -> CompileService.TargetPlatform.JS
|
||||
K2METADATA_COMPILER -> CompileService.TargetPlatform.METADATA
|
||||
else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName")
|
||||
}
|
||||
|
||||
val res: Int = withDaemon(environment, retryOnConnectionError = true) { daemon, sessionId ->
|
||||
KotlinCompilerClient.incrementalCompile(daemon, sessionId, targetPlatform, argsArray, services, compilerOut, daemonOut)
|
||||
} ?: return null
|
||||
|
||||
val exitCode = exitCodeFromProcessExitCode(res)
|
||||
processCompilerOutput(environment, compilerOut, exitCode)
|
||||
BufferedReader(StringReader(daemonOut.toString())).forEachLine {
|
||||
environment.messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
return exitCode
|
||||
}
|
||||
|
||||
protected fun <T> withDaemon(environment: Env, retryOnConnectionError: Boolean, fn: (CompileService, sessionId: Int)->T): T? {
|
||||
fun retryOrFalse(e: Exception): T? {
|
||||
if (retryOnConnectionError) {
|
||||
log.debug("retrying once on daemon connection error: ${e.message}")
|
||||
return withDaemon(environment, retryOnConnectionError = false, fn = fn)
|
||||
}
|
||||
log.info("daemon connection error: ${e.message}")
|
||||
return null
|
||||
}
|
||||
|
||||
log.debug("Try to connect to daemon")
|
||||
val connection = getDaemonConnection(environment)
|
||||
|
||||
if (connection.daemon != null) {
|
||||
log.info("Connected to daemon")
|
||||
|
||||
try {
|
||||
return fn(connection.daemon, connection.sessionId)
|
||||
}
|
||||
catch (e: java.rmi.ConnectException) {
|
||||
return retryOrFalse(e)
|
||||
}
|
||||
catch (e: java.rmi.UnmarshalException) {
|
||||
return retryOrFalse(e)
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Daemon not found")
|
||||
return null
|
||||
}
|
||||
|
||||
protected fun exitCodeFromProcessExitCode(code: Int): ExitCode {
|
||||
val exitCode = ExitCode.values().find { it.code == code }
|
||||
if (exitCode != null) return exitCode
|
||||
|
||||
log.debug("Could not find exit code by value: $code")
|
||||
return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ interface CompileService : Remote {
|
||||
|
||||
enum class TargetPlatform : Serializable {
|
||||
JVM,
|
||||
JS
|
||||
JS,
|
||||
METADATA
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -125,6 +126,19 @@ interface CompileService : Remote {
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CallResult<Int>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun serverSideJvmIC(
|
||||
sessionId: Int,
|
||||
args: Array<out String>,
|
||||
servicesFacade: IncrementalCompilationServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CallResult<Int>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun clearJarCache()
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun leaseReplSession(
|
||||
aliveFlagPath: String?,
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.common
|
||||
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
import java.rmi.Remote
|
||||
import java.rmi.RemoteException
|
||||
|
||||
interface IncrementalCompilationServicesFacade : Remote {
|
||||
@Throws(RemoteException::class)
|
||||
fun areFileChangesKnown(): Boolean
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun modifiedFiles(): List<File>?
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun deletedFiles(): List<File>?
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun workingDir(): File
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun customCacheVersionFileName(): String
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun customCacheVersion(): Int
|
||||
|
||||
// ICReporter
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun shouldReportIC(): Boolean
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun reportIC(message: String)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun reportCompileIteration(files: Iterable<File>, exitCode: Int)
|
||||
|
||||
// AnnotationFileUpdater
|
||||
@Throws(RemoteException::class)
|
||||
fun hasAnnotationsFileUpdater(): Boolean
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun revert()
|
||||
|
||||
// ChangesRegistry
|
||||
@Throws(RemoteException::class)
|
||||
fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun unknownChanges(timestamp: Long)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getChanges(artifact: File, sinceTS: Long): Iterable<SimpleDirtyData>?
|
||||
}
|
||||
|
||||
class SimpleDirtyData(
|
||||
val dirtyLookupSymbols: List<String>,
|
||||
val dirtyClassesFqNames: List<String>
|
||||
) : Serializable
|
||||
@@ -12,5 +12,8 @@
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="incremental-compilation-impl" />
|
||||
<orderEntry type="module" module-name="build-common" />
|
||||
<orderEntry type="module" module-name="descriptor.loader.java" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -20,20 +20,34 @@ import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vfs.impl.ZipHandler
|
||||
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.incremental.*
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.rmi.NoSuchObjectException
|
||||
@@ -306,6 +320,63 @@ class CompileServiceImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun serverSideJvmIC(
|
||||
sessionId: Int,
|
||||
args: Array<out String>,
|
||||
servicesFacade: IncrementalCompilationServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CompileService.CallResult<Int> {
|
||||
return doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler ->
|
||||
val reporter = RemoteICReporter(servicesFacade)
|
||||
val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null
|
||||
|
||||
// these flags do not have any effect on the compiler (only on caches, incremental compilation logic, jps plugin)
|
||||
// so it's OK to just set them true
|
||||
IncrementalCompilation.setIsEnabled(true)
|
||||
IncrementalCompilation.setIsExperimental(true)
|
||||
|
||||
val k2jvmArgs = K2JVMCompilerArguments()
|
||||
(compiler[CompileService.TargetPlatform.JVM] as K2JVMCompiler).parseArguments(args, k2jvmArgs)
|
||||
|
||||
val moduleFile = k2jvmArgs.module?.let(::File)
|
||||
assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.module}" }
|
||||
val renderer = MessageRenderer.XML
|
||||
val messageCollector = PrintingMessageCollector(printStream, renderer, k2jvmArgs.verbose)
|
||||
val filteringMessageCollector = FilteringMessageCollector(messageCollector) { it == CompilerMessageSeverity.ERROR }
|
||||
|
||||
val parsedModule = ModuleXmlParser.parseModuleScript(k2jvmArgs.module, filteringMessageCollector)
|
||||
val javaSourceRoots = parsedModule.modules.flatMapTo(HashSet()) { it.getJavaSourceRoots().map { File(it.path) } }
|
||||
val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) }
|
||||
k2jvmArgs.friendPaths = parsedModule.modules.flatMap(Module::getFriendPaths).toTypedArray()
|
||||
|
||||
val changedFiles = if (servicesFacade.areFileChangesKnown()) {
|
||||
ChangedFiles.Known(servicesFacade.modifiedFiles()!!, servicesFacade.deletedFiles()!!)
|
||||
}
|
||||
else {
|
||||
ChangedFiles.Unknown()
|
||||
}
|
||||
|
||||
val artifactChanges = RemoteArtifactChangesProvider(servicesFacade)
|
||||
val changesRegistry = RemoteChangesRegostry(servicesFacade)
|
||||
|
||||
val workingDir = servicesFacade.workingDir()
|
||||
val versions = commonCacheVersions(workingDir) +
|
||||
customCacheVersion(servicesFacade.customCacheVersion(), servicesFacade.customCacheVersionFileName(), workingDir, forceEnable = true)
|
||||
|
||||
try {
|
||||
printStream.print(renderer.renderPreamble())
|
||||
IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater,
|
||||
artifactChanges, changesRegistry)
|
||||
.compile(allKotlinFiles, k2jvmArgs, messageCollector, { changedFiles })
|
||||
}
|
||||
finally {
|
||||
printStream.print(renderer.renderConclusion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun leaseReplSession(
|
||||
aliveFlagPath: String?,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -610,7 +681,7 @@ class CompileServiceImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearJarCache() {
|
||||
override fun clearJarCache() {
|
||||
ZipHandler.clearFileAccessorCache()
|
||||
(KotlinCoreEnvironment.applicationEnvironment?.jarFileSystem as? CoreJarFileSystem)?.clearHandlersCache()
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.daemon
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
@@ -125,9 +126,11 @@ object KotlinCompileDaemon {
|
||||
val compilerSelector = object : CompilerSelector {
|
||||
private val jvm by lazy { K2JVMCompiler() }
|
||||
private val js by lazy { K2JSCompiler() }
|
||||
private val metadata by lazy { K2MetadataCompiler() }
|
||||
override fun get(targetPlatform: CompileService.TargetPlatform): CLICompiler<*> = when (targetPlatform) {
|
||||
CompileService.TargetPlatform.JVM -> jvm
|
||||
CompileService.TargetPlatform.JS -> js
|
||||
CompileService.TargetPlatform.METADATA -> metadata
|
||||
}
|
||||
}
|
||||
// timer with a daemon thread, meaning it should not prevent JVM to exit normally
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
|
||||
import org.jetbrains.kotlin.daemon.common.DummyProfiler
|
||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler
|
||||
|
||||
|
||||
class RemoteIncrementalCompilationComponentsClient(val facade: CompilerCallbackServicesFacade, eventManger: EventManger, val profiler: Profiler = DummyProfiler()) : IncrementalCompilationComponents {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.ICReporter
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
|
||||
internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilationServicesFacade) : AnnotationFileUpdater {
|
||||
override fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>) {
|
||||
servicesFacade.updateAnnotations(outdatedClasses.map { it.internalName })
|
||||
}
|
||||
|
||||
override fun revert() {
|
||||
servicesFacade.revert()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import java.io.File
|
||||
|
||||
class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilationServicesFacade) : ArtifactChangesProvider {
|
||||
override fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>? =
|
||||
servicesFacade.getChanges(artifact, sinceTS)?.map { it.toDirtyData() }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
|
||||
internal class RemoteChangesRegostry(private val servicesFacade: IncrementalCompilationServicesFacade) : ChangesRegistry {
|
||||
override fun unknownChanges(timestamp: Long) {
|
||||
servicesFacade.unknownChanges(timestamp)
|
||||
}
|
||||
|
||||
override fun registerChanges(timestamp: Long, dirtyData: DirtyData) {
|
||||
servicesFacade.registerChanges(timestamp, dirtyData.toSimpleDirtyData())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.ICReporter
|
||||
import java.io.File
|
||||
|
||||
internal class RemoteICReporter(private val servicesFacade: IncrementalCompilationServicesFacade) : ICReporter() {
|
||||
override fun report(message: () -> String) {
|
||||
if (servicesFacade.shouldReportIC()) {
|
||||
servicesFacade.reportIC(message())
|
||||
}
|
||||
}
|
||||
|
||||
override fun reportCompileIteration(sourceFiles: Iterable<File>, exitCode: ExitCode) {
|
||||
if (servicesFacade.shouldReportIC()) {
|
||||
servicesFacade.reportCompileIteration(sourceFiles, exitCode.code)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.SimpleDirtyData
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import org.jetbrains.kotlin.incremental.LookupSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
fun SimpleDirtyData.toDirtyData(): DirtyData {
|
||||
val dirtyClassesFqNames = dirtyClassesFqNames.map(::FqName)
|
||||
val dirtyLookupSymbols = dirtyLookupSymbols.map {
|
||||
LookupSymbol(scope = it.substringBeforeLast("."), name = it.substringAfterLast("."))
|
||||
}
|
||||
return DirtyData(dirtyLookupSymbols, dirtyClassesFqNames)
|
||||
}
|
||||
|
||||
fun DirtyData.toSimpleDirtyData(): SimpleDirtyData {
|
||||
return SimpleDirtyData(dirtyClassesFqNames = dirtyClassesFqNames.map(FqName::asString),
|
||||
dirtyLookupSymbols = dirtyLookupSymbols.map { "${it.scope}.${it.name}" })
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.config;
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler;
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
|
||||
import org.jetbrains.kotlin.modules.Module;
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition;
|
||||
@@ -94,9 +93,6 @@ public class JVMConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<File> MODULE_XML_FILE =
|
||||
CompilerConfigurationKey.create("path to module.xml");
|
||||
|
||||
public static final CompilerConfigurationKey<SourceRetentionAnnotationHandler> SOURCE_RETENTION_ANNOTATION_HANDLER =
|
||||
CompilerConfigurationKey.create("source retention annotation handler");
|
||||
|
||||
public static final CompilerConfigurationKey<String> DECLARATIONS_JSON_PATH =
|
||||
CompilerConfigurationKey.create("path to declarations output");
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
val resolverForProject = createResolverForProject()
|
||||
|
||||
fun computeDependencyDescriptors(module: M): List<ModuleDescriptorImpl> {
|
||||
val orderedDependencies = LinkedHashSet(firstDependency.singletonOrEmptyList() + module.dependencies())
|
||||
val orderedDependencies = firstDependency.singletonOrEmptyList() + module.dependencies()
|
||||
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) {
|
||||
dependencyInfo ->
|
||||
resolverForProject.descriptorForModule(dependencyInfo as M)
|
||||
|
||||
@@ -234,6 +234,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtSuperTypeEntry> SUPERTYPE_NOT_INITIALIZED = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtTypeReference> DELEGATION_NOT_TO_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, List<CallableMemberDescriptor>> DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> SUPERTYPE_NOT_A_CLASS_OR_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> SUPERTYPE_IS_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -511,6 +512,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtParameter> HEADER_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtConstructorDelegationCall> HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtConstructor<?>> HEADER_ENUM_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtEnumEntry> HEADER_ENUM_ENTRY_WITH_BODY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> HEADER_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
@@ -265,6 +265,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(HEADER_DECLARATION_WITH_DEFAULT_PARAMETER, "Header declaration cannot have parameters with default values");
|
||||
MAP.put(HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of a header class is not allowed");
|
||||
MAP.put(HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Header class constructor cannot have a property parameter");
|
||||
MAP.put(HEADER_ENUM_CONSTRUCTOR, "Header enum class cannot have a constructor");
|
||||
MAP.put(HEADER_ENUM_ENTRY_WITH_BODY, "Header enum entry cannot have a body");
|
||||
MAP.put(HEADER_PROPERTY_INITIALIZER, "Header property cannot have an initializer");
|
||||
|
||||
MAP.put(IMPL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of 'impl' type alias should be a class, not another type alias");
|
||||
@@ -272,7 +274,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of 'impl' type alias cannot contain use-site variance or star projections");
|
||||
MAP.put(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of 'impl' type alias should be its type parameters in the same order, e.g. 'impl typealias Foo<A, B> = Bar<A, B>'");
|
||||
|
||||
MAP.put(HEADER_WITHOUT_IMPLEMENTATION, "Header declaration ''{0}'' has no implementation in module {1}{2}", NAME,
|
||||
MAP.put(HEADER_WITHOUT_IMPLEMENTATION, "Header declaration ''{0}'' has no implementation in module{1}{2}", NAME,
|
||||
PLATFORM, PlatformIncompatibilityDiagnosticRenderer.INSTANCE);
|
||||
MAP.put(IMPLEMENTATION_WITHOUT_HEADER, "Modifier 'impl' is only applicable to members that are initially declared in platform-independent code");
|
||||
|
||||
@@ -368,6 +370,7 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(DELEGATION_IN_INTERFACE, "Interfaces cannot use delegation");
|
||||
MAP.put(DELEGATION_NOT_TO_INTERFACE, "Only interfaces can be delegated to");
|
||||
MAP.put(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE, "Delegated member ''{0}'' hides supertype override: {1}. Please specify proper override explicitly", COMPACT, commaSeparated(SHORT_NAMES_IN_TYPES));
|
||||
MAP.put(NO_CONSTRUCTOR, "This class does not have a constructor");
|
||||
MAP.put(RESOLUTION_TO_CLASSIFIER, "{2}", NAME, TO_STRING, STRING);
|
||||
MAP.put(NOT_A_CLASS, "Not a class");
|
||||
|
||||
@@ -76,7 +76,7 @@ object Renderers {
|
||||
@JvmField val NAME = Renderer<Named> { it.name.asString() }
|
||||
|
||||
@JvmField val PLATFORM = Renderer<ModuleDescriptor> {
|
||||
if (it.platformKind == PlatformKind.DEFAULT) "" else "for " + it.platformKind.name
|
||||
if (it.platformKind == PlatformKind.DEFAULT) "" else " for " + it.platformKind.name
|
||||
}
|
||||
|
||||
@JvmField val VISIBILITY = Renderer<Visibility> {
|
||||
|
||||
@@ -41,19 +41,26 @@ interface AnnotationBasedExtension {
|
||||
|
||||
private fun AnnotationDescriptor.isASpecialAnnotation(
|
||||
modifierListOwner: KtModifierListOwner?,
|
||||
visitedAnnotations: MutableSet<String> = hashSetOf(),
|
||||
allowMetaAnnotations: Boolean = true
|
||||
): Boolean {
|
||||
val annotationType = type.constructor.declarationDescriptor ?: return false
|
||||
if (annotationType.fqNameSafe.asString() in getAnnotationFqNames(modifierListOwner)) return true
|
||||
val annotationFqName = annotationType.fqNameSafe.asString()
|
||||
if (annotationFqName in visitedAnnotations) return false // Prevent infinite recursion
|
||||
if (annotationFqName in getAnnotationFqNames(modifierListOwner)) return true
|
||||
|
||||
visitedAnnotations.add(annotationFqName)
|
||||
|
||||
if (allowMetaAnnotations) {
|
||||
for (metaAnnotation in annotationType.annotations) {
|
||||
if (metaAnnotation.isASpecialAnnotation(modifierListOwner, allowMetaAnnotations = false)) {
|
||||
if (metaAnnotation.isASpecialAnnotation(modifierListOwner, visitedAnnotations, allowMetaAnnotations = true)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitedAnnotations.remove(annotationFqName)
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,11 @@
|
||||
package org.jetbrains.kotlin.resolve.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ErrorValue
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
|
||||
private val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
|
||||
|
||||
@@ -54,17 +51,3 @@ fun AnnotationDescriptor.argumentValue(parameterName: String): Any? {
|
||||
|
||||
return constant.value
|
||||
}
|
||||
|
||||
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
|
||||
|
||||
fun MemberDescriptor.isInlineOnlyOrReified(): Boolean {
|
||||
if (this !is FunctionDescriptor) return false
|
||||
return typeParameters.any { it.isReified } || hasInlineOnlyAnnotation()
|
||||
}
|
||||
|
||||
fun MemberDescriptor.hasInlineOnlyAnnotation(): Boolean {
|
||||
if (this !is FunctionDescriptor) return false
|
||||
return annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) && InlineUtil.isInline(this).apply {
|
||||
assert(this) { "Function is not inline: ${this@hasInlineOnlyAnnotation}"; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
|
||||
@@ -274,6 +273,10 @@ class DeclarationsChecker(
|
||||
trace.report(HEADER_DECLARATION_WITH_BODY.on(declaration))
|
||||
}
|
||||
|
||||
if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) {
|
||||
trace.report(HEADER_ENUM_CONSTRUCTOR.on(declaration))
|
||||
}
|
||||
|
||||
if (declaration is KtPrimaryConstructor && !DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass)) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
if (parameter.hasValOrVar()) {
|
||||
@@ -895,15 +898,20 @@ class DeclarationsChecker(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkEnumEntry(enumEntry: KtEnumEntry, classDescriptor: ClassDescriptor) {
|
||||
val declaration = classDescriptor.containingDeclaration
|
||||
if (DescriptorUtils.isEnumClass(declaration)) {
|
||||
if (!enumEntry.hasInitializer() && !hasDefaultConstructor(declaration as ClassDescriptor)) {
|
||||
private fun checkEnumEntry(enumEntry: KtEnumEntry, enumEntryClass: ClassDescriptor) {
|
||||
val enumClass = enumEntryClass.containingDeclaration as ClassDescriptor
|
||||
if (DescriptorUtils.isEnumClass(enumClass)) {
|
||||
if (enumClass.isHeader) {
|
||||
if (enumEntry.getBody() != null) {
|
||||
trace.report(HEADER_ENUM_ENTRY_WITH_BODY.on(enumEntry))
|
||||
}
|
||||
}
|
||||
else if (!enumEntry.hasInitializer() && !hasDefaultConstructor(enumClass)) {
|
||||
trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry))
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(DescriptorUtils.isInterface(declaration)) { "Enum entry should be declared in enum class: " + classDescriptor }
|
||||
assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1141,7 +1141,7 @@ public class DescriptorResolver {
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false,
|
||||
/* isHeader = */ false,
|
||||
/* isImpl = */ false,
|
||||
/* isImpl = */ modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD),
|
||||
/* isExternal = */ false
|
||||
);
|
||||
propertyWrapper.setDescriptor(propertyDescriptor);
|
||||
|
||||
@@ -73,7 +73,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
InfixModifierChecker(),
|
||||
SinceKotlinAnnotationValueChecker,
|
||||
ReifiedTypeParameterAnnotationChecker(),
|
||||
DynamicReceiverChecker
|
||||
DynamicReceiverChecker,
|
||||
DelegationChecker()
|
||||
)
|
||||
|
||||
private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
@@ -51,13 +50,13 @@ import static org.jetbrains.kotlin.resolve.inline.InlineUtil.checkNonLocalReturn
|
||||
class InlineChecker implements CallChecker {
|
||||
private final FunctionDescriptor descriptor;
|
||||
private final Set<CallableDescriptor> inlinableParameters = new LinkedHashSet<CallableDescriptor>();
|
||||
private final boolean isEffectivelyPublicOrPublishedApiFunction;
|
||||
private final EffectiveVisibility inlineFunEffectiveVisibility;
|
||||
private final boolean isEffectivelyPrivateApiFunction;
|
||||
|
||||
public InlineChecker(@NotNull FunctionDescriptor descriptor) {
|
||||
assert InlineUtil.isInline(descriptor) : "This extension should be created only for inline functions: " + descriptor;
|
||||
this.descriptor = descriptor;
|
||||
this.isEffectivelyPublicOrPublishedApiFunction = isEffectivelyPublicOrPublishedApi(descriptor);
|
||||
this.inlineFunEffectiveVisibility = EffectiveVisibilityKt.effectiveVisibility(descriptor, descriptor.getVisibility(), true);
|
||||
this.isEffectivelyPrivateApiFunction = DescriptorUtilsKt.isEffectivelyPrivateApi(descriptor);
|
||||
for (ValueParameterDescriptor param : descriptor.getValueParameters()) {
|
||||
if (isInlinableParameter(param)) {
|
||||
@@ -239,31 +238,33 @@ class InlineChecker implements CallChecker {
|
||||
}
|
||||
|
||||
private void checkVisibilityAndAccess(
|
||||
@NotNull CallableDescriptor declarationDescriptor,
|
||||
@NotNull CallableDescriptor calledDescriptor,
|
||||
@NotNull KtElement expression,
|
||||
@NotNull CallCheckerContext context
|
||||
) {
|
||||
boolean declarationDescriptorIsPublicOrPublishedApi = isEffectivelyPublicOrPublishedApi(declarationDescriptor) ||
|
||||
isDefinedInInlineFunction(declarationDescriptor);
|
||||
if (isEffectivelyPublicOrPublishedApiFunction &&
|
||||
!declarationDescriptorIsPublicOrPublishedApi &&
|
||||
declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
|
||||
context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
EffectiveVisibility calledFunEffectiveVisibility =
|
||||
isDefinedInInlineFunction(calledDescriptor) ?
|
||||
EffectiveVisibility.Public.INSTANCE :
|
||||
EffectiveVisibilityKt.effectiveVisibility(calledDescriptor, calledDescriptor.getVisibility(), true);
|
||||
|
||||
boolean isCalledFunPublicOrPublishedApi = calledFunEffectiveVisibility.getPublicApi();
|
||||
boolean isInlineFunPublicOrPublishedApi = inlineFunEffectiveVisibility.getPublicApi();
|
||||
if (isInlineFunPublicOrPublishedApi &&
|
||||
!isCalledFunPublicOrPublishedApi &&
|
||||
calledDescriptor.getVisibility() != Visibilities.LOCAL) {
|
||||
context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor));
|
||||
}
|
||||
else {
|
||||
checkPrivateClassMemberAccess(declarationDescriptor, expression, context);
|
||||
checkPrivateClassMemberAccess(calledDescriptor, expression, context);
|
||||
}
|
||||
|
||||
if (isEffectivelyPublicOrPublishedApiFunction && declarationDescriptor.getVisibility() == Visibilities.PROTECTED) {
|
||||
context.getTrace().report(Errors.PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor));
|
||||
if (isInlineFunPublicOrPublishedApi &&
|
||||
inlineFunEffectiveVisibility.toVisibility() != Visibilities.PROTECTED &&
|
||||
calledFunEffectiveVisibility.toVisibility() == Visibilities.PROTECTED) {
|
||||
context.getTrace().report(Errors.PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEffectivelyPublicOrPublishedApi(@NotNull CallableDescriptor descriptor) {
|
||||
EffectiveVisibility visibility = EffectiveVisibilityKt.effectiveVisibility(descriptor, descriptor.getVisibility(), true);
|
||||
return visibility.getPublicApi();
|
||||
}
|
||||
|
||||
private void checkPrivateClassMemberAccess(
|
||||
@NotNull DeclarationDescriptor declarationDescriptor,
|
||||
@NotNull KtElement expression,
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspendExtensionsAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspensionAnnotation
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
@@ -67,7 +67,7 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
// Here we only record enclosing function mapping (for backends purposes)
|
||||
context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction)
|
||||
|
||||
checkRestrictsSuspendExtensions(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
||||
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
||||
}
|
||||
closestSuspensionLambdaDescriptor != null -> {
|
||||
val callElement = resolvedCall.call.callElement as KtExpression
|
||||
@@ -80,7 +80,7 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
BindingContext.ENCLOSING_SUSPEND_LAMBDA_FOR_SUSPENSION_POINT, resolvedCall.call, closestSuspensionLambdaDescriptor
|
||||
)
|
||||
|
||||
checkRestrictsSuspendExtensions(closestSuspensionLambdaDescriptor, resolvedCall, reportOn, context)
|
||||
checkRestrictsSuspension(closestSuspensionLambdaDescriptor, resolvedCall, reportOn, context)
|
||||
}
|
||||
else -> {
|
||||
context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn))
|
||||
@@ -110,7 +110,7 @@ fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, dia
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRestrictsSuspendExtensions(
|
||||
private fun checkRestrictsSuspension(
|
||||
enclosingCallableDescriptor: CallableDescriptor,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
reportOn: PsiElement,
|
||||
@@ -118,8 +118,8 @@ private fun checkRestrictsSuspendExtensions(
|
||||
) {
|
||||
val enclosingSuspendReceiverValue = enclosingCallableDescriptor.extensionReceiverParameter?.value ?: return
|
||||
|
||||
fun ReceiverValue.isRestrictsSuspendExtensionsReceiver() = (type.supertypes() + type).any {
|
||||
it.constructor.declarationDescriptor?.hasRestrictsSuspendExtensionsAnnotation() == true
|
||||
fun ReceiverValue.isRestrictsSuspensionReceiver() = (type.supertypes() + type).any {
|
||||
it.constructor.declarationDescriptor?.hasRestrictsSuspensionAnnotation() == true
|
||||
}
|
||||
|
||||
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
|
||||
@@ -134,13 +134,13 @@ private fun checkRestrictsSuspendExtensions(
|
||||
return this === (referenceTarget as? CallableDescriptor)?.extensionReceiverParameter?.value
|
||||
}
|
||||
|
||||
if (!enclosingSuspendReceiverValue.isRestrictsSuspendExtensionsReceiver()) return
|
||||
if (!enclosingSuspendReceiverValue.isRestrictsSuspensionReceiver()) return
|
||||
|
||||
// member of suspend receiver
|
||||
if (enclosingSuspendReceiverValue sameInstance resolvedCall.dispatchReceiver) return
|
||||
|
||||
if (enclosingSuspendReceiverValue sameInstance resolvedCall.extensionReceiver &&
|
||||
resolvedCall.candidateDescriptor.extensionReceiverParameter!!.value.isRestrictsSuspendExtensionsReceiver()) return
|
||||
resolvedCall.candidateDescriptor.extensionReceiverParameter!!.value.isRestrictsSuspensionReceiver()) return
|
||||
|
||||
context.trace.report(Errors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL.on(reportOn))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
||||
|
||||
class DelegationChecker : SimpleDeclarationChecker {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
if (declaration !is KtClassOrObject) return
|
||||
|
||||
val delegationDescriptors = descriptor.defaultType.memberScope.getContributedDescriptors().
|
||||
filterIsInstance<CallableMemberDescriptor>().filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }.sortedWith(MemberComparator.INSTANCE)
|
||||
|
||||
for (specifier in declaration.superTypeListEntries) {
|
||||
if (specifier is KtDelegatedSuperTypeEntry) {
|
||||
val superType = specifier.typeReference?.let { bindingContext.get(BindingContext.TYPE, it) } ?: continue
|
||||
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
||||
|
||||
val delegates = getDelegates(delegationDescriptors, superTypeDescriptor)
|
||||
delegates.forEach { (delegated, delegatedTo) ->
|
||||
checkDescriptor(declaration, delegated, delegatedTo, diagnosticHolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDescriptor(
|
||||
classDeclaration: KtDeclaration,
|
||||
delegatedDescriptor: CallableMemberDescriptor,
|
||||
delegatedToDescriptor: CallableMemberDescriptor,
|
||||
diagnosticHolder: DiagnosticSink
|
||||
) {
|
||||
val reachableFromDelegated = findAllReachableDeclarations(delegatedDescriptor)
|
||||
reachableFromDelegated.remove(delegatedDescriptor.original)
|
||||
val toRemove = linkedSetOf<CallableMemberDescriptor>()
|
||||
for (declaration in reachableFromDelegated) {
|
||||
val reachable = findAllReachableDeclarations(declaration.original)
|
||||
reachable.remove(declaration)
|
||||
toRemove.addAll(reachable)
|
||||
}
|
||||
reachableFromDelegated.removeAll(toRemove)
|
||||
reachableFromDelegated.remove(DescriptorUtils.unwrapFakeOverride(delegatedToDescriptor).original)
|
||||
|
||||
val nonAbstractReachable = reachableFromDelegated.filter { it.modality != Modality.ABSTRACT }
|
||||
|
||||
if (nonAbstractReachable.isNotEmpty()) {
|
||||
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
|
||||
diagnosticHolder.report(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(classDeclaration, delegatedDescriptor, nonAbstractReachable.toList()))
|
||||
}
|
||||
}
|
||||
|
||||
fun getDelegates(
|
||||
delegatedMethods: Iterable<CallableMemberDescriptor>,
|
||||
toInterface: ClassDescriptor
|
||||
): Map<CallableMemberDescriptor, CallableMemberDescriptor> {
|
||||
return delegatedMethods
|
||||
.keysToMapExceptNulls { delegatingMember ->
|
||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||
.filter { it.containingDeclaration == toInterface }
|
||||
.map { overriddenDescriptor ->
|
||||
val scope = toInterface.defaultType.memberScope
|
||||
val name = overriddenDescriptor.name
|
||||
|
||||
// this is the actual member of delegateExpressionType that we are delegating to
|
||||
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
||||
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) }
|
||||
}
|
||||
|
||||
actualDelegates.firstOrNull() as? CallableMemberDescriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findAllReachableDeclarations(memberDescriptor: CallableMemberDescriptor): MutableSet<CallableMemberDescriptor> {
|
||||
val collector = object : DFS.NodeHandlerWithListResult<CallableMemberDescriptor, CallableMemberDescriptor>() {
|
||||
override fun afterChildren(current: CallableMemberDescriptor) {
|
||||
if (current.kind.isReal) {
|
||||
result.add(current.original)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DFS.dfs(listOf(memberDescriptor), { it.overriddenDescriptors }, collector)
|
||||
return java.util.HashSet(collector.result())
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -28,9 +29,10 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Compatible
|
||||
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -55,11 +57,11 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
|
||||
if (descriptor !is MemberDescriptor) return
|
||||
|
||||
val checkImpl = !languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformDoNotCheckImpl)
|
||||
if (descriptor.isHeader && declaration.hasModifier(KtTokens.HEADER_KEYWORD)) {
|
||||
val checkImpl = !languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformDoNotCheckImpl)
|
||||
checkHeaderDeclarationHasImplementation(declaration, descriptor, diagnosticHolder, checkImpl)
|
||||
}
|
||||
else if (descriptor.isImpl && declaration.hasModifier(KtTokens.IMPL_KEYWORD)) {
|
||||
else if (checkImpl && descriptor.isImpl && declaration.hasModifier(KtTokens.IMPL_KEYWORD)) {
|
||||
checkImplementationHasHeaderDeclaration(declaration, descriptor, diagnosticHolder)
|
||||
}
|
||||
}
|
||||
@@ -100,7 +102,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
private fun checkImplementationHasHeaderDeclaration(
|
||||
reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink
|
||||
) {
|
||||
fun ClassifierDescriptor.findDeclarationForClass(): ClassDescriptor? =
|
||||
fun ClassifierDescriptorWithTypeParameters.findDeclarationForClass(): ClassDescriptor? =
|
||||
findClassifiersFromTheSameModule().firstOrNull { declaration ->
|
||||
this != declaration &&
|
||||
declaration is ClassDescriptor && declaration.isHeader &&
|
||||
@@ -121,7 +123,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
areCompatibleCallables(declaration, descriptor, checkImpl = false) == Compatible
|
||||
}
|
||||
}
|
||||
is ClassifierDescriptor -> descriptor.findDeclarationForClass() != null
|
||||
is ClassifierDescriptorWithTypeParameters -> descriptor.findDeclarationForClass() != null
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -140,17 +142,29 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
is FunctionDescriptor -> scope.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED)
|
||||
is PropertyDescriptor -> scope.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED)
|
||||
else -> throw AssertionError("Unsupported declaration: $this")
|
||||
}.filter {
|
||||
it.module == myModule // TODO: only obtain descriptors from our module to start with
|
||||
}
|
||||
} // TODO: only obtain descriptors from our module to start with
|
||||
}
|
||||
|
||||
fun ClassifierDescriptor.findClassifiersFromTheSameModule(): Collection<ClassifierDescriptor> {
|
||||
fun ClassifierDescriptorWithTypeParameters.findClassifiersFromTheSameModule(): Collection<ClassifierDescriptorWithTypeParameters> {
|
||||
val myModule = moduleToCheck ?: module
|
||||
// TODO: support nested classes
|
||||
return myModule.getPackage(fqNameSafe.parent()).memberScope
|
||||
.getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
|
||||
.filterIsInstance<ClassifierDescriptor>()
|
||||
val classId = classId ?: return emptyList()
|
||||
|
||||
fun MemberScope.getAllClassifiers(name: Name): Collection<ClassifierDescriptorWithTypeParameters> =
|
||||
getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name }
|
||||
.filterIsInstance<ClassifierDescriptorWithTypeParameters>()
|
||||
|
||||
val segments = classId.relativeClassName.pathSegments()
|
||||
var classifiers = myModule.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first())
|
||||
|
||||
for (name in segments.subList(1, segments.size)) {
|
||||
classifiers = classifiers.mapNotNull { classifier ->
|
||||
(classifier as? ClassDescriptor)?.unsubstitutedInnerClassesScope?.getContributedClassifier(
|
||||
name, NoLookupLocation.FOR_ALREADY_TRACKED
|
||||
) as? ClassifierDescriptorWithTypeParameters
|
||||
}
|
||||
}
|
||||
|
||||
return classifiers
|
||||
}
|
||||
|
||||
sealed class Compatibility {
|
||||
@@ -177,7 +191,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
|
||||
// Functions
|
||||
|
||||
object FunctionModifiers : Incompatible("modifiers are different (external, infix, inline, operator, suspend, tailrec)")
|
||||
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
|
||||
object FunctionModifiersNotSubset : Incompatible("some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec)")
|
||||
|
||||
// Properties
|
||||
|
||||
@@ -188,7 +203,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
|
||||
object ClassKind : Incompatible("class kinds are different (class, interface, object, enum, annotation)")
|
||||
|
||||
object ClassModifiers : Incompatible("modifiers are different (data)")
|
||||
object ClassModifiers : Incompatible("modifiers are different (companion, inner)")
|
||||
|
||||
object Supertypes : Incompatible("some supertypes are missing in the implementation")
|
||||
|
||||
@@ -196,6 +211,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
unimplemented: List<Pair<CallableMemberDescriptor, Map<Incompatible, Collection<CallableMemberDescriptor>>>>
|
||||
) : Incompatible("some members are not implemented", unimplemented)
|
||||
|
||||
object EnumEntries : Incompatible("some entries from header enum are missing in the impl enum")
|
||||
|
||||
// Common
|
||||
|
||||
object Modality : Incompatible("modality is different")
|
||||
@@ -260,7 +277,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
else -> throw AssertionError("Unsupported declarations: $a, $b")
|
||||
}
|
||||
|
||||
if (checkImpl && !b.isImpl) return Incompatible.NoImpl
|
||||
if (checkImpl && !b.isImpl && b.kind == CallableMemberDescriptor.Kind.DECLARATION) return Incompatible.NoImpl
|
||||
|
||||
return Compatible
|
||||
}
|
||||
@@ -274,9 +291,13 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
}
|
||||
|
||||
private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility {
|
||||
if (!equalBy(a, b) { f ->
|
||||
listOf(f.isExternal, f.isInfix, f.isInline, f.isOperator, f.isSuspend, f.isTailrec)
|
||||
}) return Incompatible.FunctionModifiers
|
||||
if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent
|
||||
|
||||
if (a.isExternal && !b.isExternal ||
|
||||
a.isInfix && !b.isInfix ||
|
||||
a.isInline && !b.isInline ||
|
||||
a.isOperator && !b.isOperator ||
|
||||
a.isTailrec && !b.isTailrec) return Incompatible.FunctionModifiersNotSubset
|
||||
|
||||
return Compatible
|
||||
}
|
||||
@@ -314,20 +335,25 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
|
||||
if (a.kind != b.kind) return Incompatible.ClassKind
|
||||
|
||||
if (!equalBy(a, b) { listOf(it.isCompanionObject, it.isInner) }) return Incompatible.ClassModifiers
|
||||
|
||||
val aTypeParams = a.declaredTypeParameters
|
||||
val bTypeParams = b.declaredTypeParameters
|
||||
if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount
|
||||
|
||||
val substitutor = Substitutor(aTypeParams, bTypeParams, parentSubstitutor)
|
||||
|
||||
if (a.modality != b.modality) return Incompatible.Modality
|
||||
if (a.modality != b.modality && !(a.modality == Modality.FINAL && b.modality == Modality.OPEN)) return Incompatible.Modality
|
||||
|
||||
if (a.visibility != b.visibility) return Incompatible.Visibility
|
||||
|
||||
areCompatibleTypeParameters(aTypeParams, bTypeParams, substitutor).let { if (it != Compatible) return it }
|
||||
|
||||
if (!equalBy(a, b) { it.isData }) return Incompatible.ClassModifiers
|
||||
|
||||
if (!b.typeConstructor.supertypes.containsAll(a.typeConstructor.supertypes.map(substitutor))) return Incompatible.Supertypes
|
||||
// Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified,
|
||||
// and not added if an explicit supertype _is_ specified
|
||||
val aSupertypes = a.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny)
|
||||
val bSupertypes = b.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny)
|
||||
if (!bSupertypes.containsAll(aSupertypes.map(substitutor))) return Incompatible.Supertypes
|
||||
|
||||
areCompatibleClassScopes(a, b, checkImpl && !implTypealias, substitutor).let { if (it != Compatible) return it }
|
||||
|
||||
@@ -365,7 +391,16 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
|
||||
unimplemented.add(aMember to incompatibilityMap)
|
||||
}
|
||||
|
||||
// TODO: check static scope, enum entries
|
||||
if (a.kind == ClassKind.ENUM_CLASS) {
|
||||
fun ClassDescriptor.enumEntries() =
|
||||
unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name }
|
||||
val aEntries = a.enumEntries()
|
||||
val bEntries = b.enumEntries()
|
||||
|
||||
if (!bEntries.containsAll(aEntries)) return Incompatible.EnumEntries
|
||||
}
|
||||
|
||||
// TODO: check static scope?
|
||||
|
||||
if (unimplemented.isEmpty()) return Compatible
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
package org.jetbrains.kotlin.resolve.inline
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnlyOrReified
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.AnalyzerExtensions
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.annotations.isInlineOnlyOrReified
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
|
||||
object InlineAnalyzerExtension : AnalyzerExtensions.AnalyzerExtension {
|
||||
|
||||
@@ -334,7 +334,13 @@ open class LazyClassMemberScope(
|
||||
val classOrObject = declarationProvider.correspondingClassOrObject ?: return null
|
||||
|
||||
val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor()
|
||||
if (DescriptorUtils.isInterface(thisDescriptor) && !hasPrimaryConstructor) return null
|
||||
if (!hasPrimaryConstructor) {
|
||||
when (thisDescriptor.kind) {
|
||||
ClassKind.INTERFACE -> return null
|
||||
ClassKind.OBJECT, ClassKind.ENUM_CLASS -> if (thisDescriptor.isHeader) return null
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
|
||||
val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
|
||||
@@ -343,11 +349,10 @@ open class LazyClassMemberScope(
|
||||
setDeferredReturnType(constructor)
|
||||
return constructor
|
||||
}
|
||||
else {
|
||||
val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace)
|
||||
setDeferredReturnType(constructor)
|
||||
return constructor
|
||||
}
|
||||
|
||||
val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace)
|
||||
setDeferredReturnType(constructor)
|
||||
return constructor
|
||||
}
|
||||
|
||||
private fun resolveSecondaryConstructors(): Collection<ClassConstructorDescriptor> {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testData" type="java-test-resource" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||
<orderEntry type="module" module-name="build-common" />
|
||||
<orderEntry type="module" module-name="cli" />
|
||||
<orderEntry type="module" module-name="descriptor.loader.java" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="library" name="junit-4.12" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.annotation
|
||||
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
|
||||
/**
|
||||
* Annotation file is generated by collecting annotated elements of generated files.
|
||||
* When compiling incrementally, the compiler generates only subset of all classes,
|
||||
* so after compilation annotation file contains only a subset of annotated elements,
|
||||
* which breaks the build.
|
||||
*
|
||||
* The workaround is to:
|
||||
* 1. backup old file before incremental compilation;
|
||||
* 2. after each iteration of IC:
|
||||
* 2.1 remove classes corresponding to dirty source files
|
||||
* 2.2 add annotations from newly generated annotations file
|
||||
*/
|
||||
interface AnnotationFileUpdater {
|
||||
fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>)
|
||||
fun revert()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import java.io.File
|
||||
|
||||
sealed class ChangedFiles {
|
||||
class Known(val modified: List<File>, val removed: List<File>) : ChangedFiles()
|
||||
class Unknown : ChangedFiles()
|
||||
}
|
||||
@@ -16,22 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.com.intellij.lang.java.JavaLanguage
|
||||
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiClass
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiFileFactory
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
internal class ChangedJavaFilesProcessor {
|
||||
private val log = Logging.getLogger(this.javaClass.simpleName)
|
||||
internal class ChangedJavaFilesProcessor(private val reporter: ICReporter) {
|
||||
private val allSymbols = HashSet<LookupSymbol>()
|
||||
private val javaLang = JavaLanguage.INSTANCE
|
||||
private val psiFileFactory: PsiFileFactory by lazy {
|
||||
@@ -50,7 +47,7 @@ internal class ChangedJavaFilesProcessor {
|
||||
val removedJava = filesDiff.removed.filter(File::isJavaFile)
|
||||
|
||||
if (removedJava.any()) {
|
||||
log.kotlinDebug { "Some java files are removed: [${removedJava.joinToString()}]" }
|
||||
reporter.report { "Some java files are removed: [${removedJava.joinToString()}]" }
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
|
||||
@@ -60,7 +57,7 @@ internal class ChangedJavaFilesProcessor {
|
||||
|
||||
val psiFile = javaFile.psiFile()
|
||||
if (psiFile !is PsiJavaFile) {
|
||||
log.kotlinDebug { "Expected PsiJavaFile, got ${psiFile?.javaClass}" }
|
||||
reporter.report { "Expected PsiJavaFile, got ${psiFile?.javaClass}" }
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
|
||||
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
|
||||
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
|
||||
@@ -25,15 +24,18 @@ import org.jetbrains.kotlin.incremental.storage.StringCollectionExternalizer
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import java.io.File
|
||||
|
||||
internal class GradleIncrementalCacheImpl(targetDataRoot: File, targetOutputDir: File?, target: TargetId) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
|
||||
class GradleIncrementalCacheImpl(
|
||||
targetDataRoot: File,
|
||||
targetOutputDir: File?,
|
||||
target: TargetId,
|
||||
private val reporter: ICReporter
|
||||
) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
|
||||
companion object {
|
||||
private val SOURCES_TO_CLASSFILES = "sources-to-classfiles"
|
||||
private val GENERATED_SOURCE_SNAPSHOTS = "generated-source-snapshot"
|
||||
private val SOURCE_SNAPSHOTS = "source-snapshot"
|
||||
}
|
||||
|
||||
private val log = org.gradle.api.logging.Logging.getLogger(this.javaClass)
|
||||
|
||||
internal val sourceToClassfilesMap = registerMap(SourceToClassfilesMap(SOURCES_TO_CLASSFILES.storageFile))
|
||||
internal val generatedSourceSnapshotMap = registerMap(FileSnapshotMap(GENERATED_SOURCE_SNAPSHOTS.storageFile))
|
||||
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
|
||||
@@ -60,7 +62,7 @@ internal class GradleIncrementalCacheImpl(targetDataRoot: File, targetOutputDir:
|
||||
// TODO: do it in the code that uses cache, since cache should not generally delete anything outside of it!
|
||||
// but for a moment it is an easiest solution to implement
|
||||
get(file).forEach {
|
||||
log.kotlinDebug { "Deleting $it on clearing cache for $file" }
|
||||
reporter.report { "Deleting $it on clearing cache for $file" }
|
||||
it.delete()
|
||||
}
|
||||
storage.remove(file.absolutePath)
|
||||
@@ -19,10 +19,11 @@ package org.jetbrains.kotlin.incremental
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import java.io.File
|
||||
|
||||
internal class IncrementalCachesManager (
|
||||
class IncrementalCachesManager (
|
||||
private val targetId: TargetId,
|
||||
private val cacheDirectory: File,
|
||||
private val outputDir: File
|
||||
private val outputDir: File,
|
||||
private val reporter: ICReporter
|
||||
) {
|
||||
private val incrementalCacheDir = File(cacheDirectory, "increCache.${targetId.name}")
|
||||
private val lookupCacheDir = File(cacheDirectory, "lookups")
|
||||
@@ -32,7 +33,8 @@ internal class IncrementalCachesManager (
|
||||
val incrementalCache: GradleIncrementalCacheImpl
|
||||
get() {
|
||||
if (incrementalCacheField == null) {
|
||||
incrementalCacheField = GradleIncrementalCacheImpl(targetDataRoot = incrementalCacheDir.apply { mkdirs() }, targetOutputDir = outputDir, target = targetId)
|
||||
val targetDataRoot = incrementalCacheDir.apply { mkdirs() }
|
||||
incrementalCacheField = GradleIncrementalCacheImpl(targetDataRoot, outputDir, targetId, reporter)
|
||||
}
|
||||
|
||||
return incrementalCacheField!!
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.annotation.SourceAnnotationsRegistry
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
@@ -27,43 +26,39 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.com.intellij.util.io.PersistentEnumeratorBase
|
||||
import com.intellij.util.io.PersistentEnumeratorBase
|
||||
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifference
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import java.io.EOFException
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
internal fun makeIncrementally(
|
||||
fun makeIncrementally(
|
||||
cachesDir: File,
|
||||
sourceRoots: Iterable<File>,
|
||||
args: K2JVMCompilerArguments,
|
||||
messageCollector: MessageCollector = MessageCollector.NONE,
|
||||
reporter: IncReporter = EmptyIncReporter
|
||||
reporter: ICReporter = EmptyICReporter
|
||||
) {
|
||||
val versions = listOf(normalCacheVersion(cachesDir),
|
||||
experimentalCacheVersion(cachesDir),
|
||||
dataContainerCacheVersion(cachesDir),
|
||||
standaloneCacheVersion(cachesDir))
|
||||
val versions = commonCacheVersions(cachesDir) + standaloneCacheVersion(cachesDir)
|
||||
|
||||
val kotlinExtensions = listOf("kt", "kts")
|
||||
val allExtensions = kotlinExtensions + listOf("java")
|
||||
val rootsWalk = sourceRoots.asSequence().map { it.walk() }.flatten()
|
||||
val rootsWalk = sourceRoots.asSequence().flatMap { it.walk() }
|
||||
val files = rootsWalk.filter(File::isFile)
|
||||
val sourceFiles = files.filter { it.extension.toLowerCase() in allExtensions }.toList()
|
||||
val kotlinFiles = sourceFiles.filter { it.extension.toLowerCase() in kotlinExtensions }
|
||||
|
||||
enableIC {
|
||||
withIC {
|
||||
val compiler = IncrementalJvmCompilerRunner(cachesDir, /* javaSourceRoots = */sourceRoots.toSet(), versions, reporter)
|
||||
compiler.compile(kotlinFiles, args, messageCollector) {
|
||||
it.incrementalCache.sourceSnapshotMap.compareAndUpdate(sourceFiles)
|
||||
@@ -71,12 +66,12 @@ internal fun makeIncrementally(
|
||||
}
|
||||
}
|
||||
|
||||
private object EmptyIncReporter : IncReporter() {
|
||||
private object EmptyICReporter : ICReporter() {
|
||||
override fun report(message: ()->String) {
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun enableIC(fn: ()->Unit) {
|
||||
private inline fun withIC(fn: ()->Unit) {
|
||||
val isEnabledBackup = IncrementalCompilation.isEnabled()
|
||||
val isExperimentalBackup = IncrementalCompilation.isExperimental()
|
||||
IncrementalCompilation.setIsEnabled(true)
|
||||
@@ -91,15 +86,14 @@ private inline fun enableIC(fn: ()->Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
internal class IncrementalJvmCompilerRunner(
|
||||
class IncrementalJvmCompilerRunner(
|
||||
workingDir: File,
|
||||
private val javaSourceRoots: Set<File>,
|
||||
private val cacheVersions: List<CacheVersion>,
|
||||
private val reporter: IncReporter,
|
||||
private val reporter: ICReporter,
|
||||
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
private val sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null,
|
||||
private val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null,
|
||||
private val artifactFile: File? = null
|
||||
private val artifactChangesProvider: ArtifactChangesProvider? = null,
|
||||
private val changesRegistry: ChangesRegistry? = null
|
||||
) {
|
||||
var anyClassesCompiled: Boolean = false
|
||||
private set
|
||||
@@ -114,22 +108,21 @@ internal class IncrementalJvmCompilerRunner(
|
||||
getChangedFiles: (IncrementalCachesManager)->ChangedFiles
|
||||
): ExitCode {
|
||||
val targetId = TargetId(name = args.moduleName, type = "java-production")
|
||||
var caches = IncrementalCachesManager(targetId, cacheDirectory, File(args.destination))
|
||||
var caches = IncrementalCachesManager(targetId, cacheDirectory, File(args.destination), reporter)
|
||||
|
||||
fun onError(e: Exception): ExitCode {
|
||||
caches.clean()
|
||||
artifactDifferenceRegistryProvider?.clean()
|
||||
|
||||
// todo: warn?
|
||||
reporter.report { "Possible cache corruption. Rebuilding. $e" }
|
||||
// try to rebuild
|
||||
val javaFilesProcessor = ChangedJavaFilesProcessor()
|
||||
caches = IncrementalCachesManager(targetId, cacheDirectory, args.destinationAsFile)
|
||||
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
|
||||
caches = IncrementalCachesManager(targetId, cacheDirectory, args.destinationAsFile, reporter)
|
||||
return compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, CompilationMode.Rebuild, messageCollector)
|
||||
}
|
||||
|
||||
return try {
|
||||
val javaFilesProcessor = ChangedJavaFilesProcessor()
|
||||
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
|
||||
val changedFiles = getChangedFiles(caches)
|
||||
val compilationMode = calculateSourcesToCompile(javaFilesProcessor, caches, changedFiles, args)
|
||||
compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, compilationMode, messageCollector)
|
||||
@@ -141,9 +134,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
onError(e)
|
||||
}
|
||||
finally {
|
||||
artifactDifferenceRegistryProvider?.withRegistry(reporter) {
|
||||
it.flush(memoryCachesOnly = true)
|
||||
}
|
||||
caches.close(flush = true)
|
||||
reporter.report { "flushed incremental caches" }
|
||||
}
|
||||
@@ -233,10 +223,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
reporter.report {"No classpath changes"}
|
||||
return ChangesEither.Known()
|
||||
}
|
||||
if (artifactDifferenceRegistryProvider == null) {
|
||||
reporter.report {"No artifact history provider"}
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
|
||||
val lastBuildTS = lastBuildInfo?.startTS
|
||||
if (lastBuildTS == null) {
|
||||
@@ -247,23 +233,16 @@ internal class IncrementalJvmCompilerRunner(
|
||||
val symbols = HashSet<LookupSymbol>()
|
||||
val fqNames = HashSet<FqName>()
|
||||
for (file in modifiedClasspath) {
|
||||
val diffs = artifactDifferenceRegistryProvider.withRegistry(reporter) {artifactDifferenceRegistry ->
|
||||
artifactDifferenceRegistry[file]
|
||||
}
|
||||
val diffs = artifactChangesProvider?.getChanges(file, lastBuildTS)
|
||||
|
||||
if (diffs == null) {
|
||||
reporter.report {"Could not get changes for file: $file"}
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
|
||||
val (beforeLastBuild, afterLastBuild) = diffs.partition {it.buildTS < lastBuildTS}
|
||||
if (beforeLastBuild.isEmpty()) {
|
||||
reporter.report {"No known build preceding timestamp $lastBuildTS for file $file"}
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
|
||||
afterLastBuild.forEach {
|
||||
symbols.addAll(it.dirtyData.dirtyLookupSymbols)
|
||||
fqNames.addAll(it.dirtyData.dirtyClassesFqNames)
|
||||
diffs.forEach {
|
||||
symbols.addAll(it.dirtyLookupSymbols)
|
||||
fqNames.addAll(it.dirtyClassesFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +280,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var compilationMode = compilationMode
|
||||
|
||||
reporter.report { "Artifact to register difference for: $artifactFile" }
|
||||
val currentBuildInfo = BuildInfo(startTS = System.currentTimeMillis())
|
||||
BuildInfo.write(currentBuildInfo, lastBuildInfoFile)
|
||||
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
@@ -316,9 +294,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
caches.incrementalCache.removeClassfilesBySources(dirtySources)
|
||||
|
||||
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
||||
if (sourcesToCompile.isNotEmpty()) {
|
||||
reporter.report { "compile iteration: ${reporter.pathsAsString(sourcesToCompile)}" }
|
||||
}
|
||||
|
||||
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
|
||||
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
|
||||
@@ -356,11 +331,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
|
||||
|
||||
if (compilationMode is CompilationMode.Rebuild) {
|
||||
artifactFile?.let { artifactFile ->
|
||||
artifactDifferenceRegistryProvider?.withRegistry(reporter) { registry ->
|
||||
registry.remove(artifactFile)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
@@ -380,21 +350,18 @@ internal class IncrementalJvmCompilerRunner(
|
||||
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
|
||||
buildDirtyLookupSymbols.addAll(javaFilesProcessor.allChangedSymbols)
|
||||
}
|
||||
if (artifactFile != null && artifactDifferenceRegistryProvider != null) {
|
||||
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
||||
val artifactDifference = ArtifactDifference(currentBuildInfo.startTS, dirtyData)
|
||||
artifactDifferenceRegistryProvider.withRegistry(reporter) {registry ->
|
||||
registry.add(artifactFile, artifactDifference)
|
||||
if (changesRegistry != null) {
|
||||
if (compilationMode is CompilationMode.Incremental) {
|
||||
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
||||
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
||||
}
|
||||
reporter.report {
|
||||
val dirtySymbolsSorted = buildDirtyLookupSymbols.map { it.scope + "#" + it.name }.sorted()
|
||||
"Added artifact difference for $artifactFile (ts: ${currentBuildInfo.startTS}): " +
|
||||
"[\n\t${dirtySymbolsSorted.joinToString(",\n\t")}]"
|
||||
else {
|
||||
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode.javaClass}" }
|
||||
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
||||
}
|
||||
}
|
||||
|
||||
if (exitCode == ExitCode.OK) {
|
||||
sourceAnnotationsRegistry?.flush()
|
||||
cacheVersions.forEach { it.saveIfNeeded() }
|
||||
}
|
||||
|
||||
@@ -462,7 +429,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
val outputItemCollector = OutputItemsCollectorImpl()
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val messageCollector = MessageCollectorWrapper(messageCollector, outputItemCollector)
|
||||
sourceAnnotationsRegistry?.clear()
|
||||
|
||||
try {
|
||||
val incrementalCaches = makeIncrementalCachesMap(targets, { listOf<TargetId>() }, getIncrementalCache, { this })
|
||||
@@ -473,7 +439,7 @@ internal class IncrementalJvmCompilerRunner(
|
||||
|
||||
reporter.report { "compiling with args: ${ArgumentUtils.convertArgumentsToStringList(args)}" }
|
||||
reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" }
|
||||
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus, sourceAnnotationsRegistry)
|
||||
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus)
|
||||
val exitCode = compiler.exec(messageCollector, compileServices, args)
|
||||
val generatedFiles = outputItemCollector.generatedFiles(targets, targets.first(), {sourcesToCompile}, {outputDir})
|
||||
reporter.reportCompileIteration(sourcesToCompile, exitCode)
|
||||
@@ -504,10 +470,10 @@ internal class IncrementalJvmCompilerRunner(
|
||||
}
|
||||
}
|
||||
|
||||
internal var K2JVMCompilerArguments.destinationAsFile: File
|
||||
var K2JVMCompilerArguments.destinationAsFile: File
|
||||
get() = File(destination)
|
||||
set(value) { destination = value.path }
|
||||
|
||||
internal var K2JVMCompilerArguments.classpathAsList: List<File>
|
||||
var K2JVMCompilerArguments.classpathAsList: List<File>
|
||||
get() = classpath.split(File.pathSeparator).map(::File)
|
||||
set(value) { classpath = value.joinToString(separator = File.pathSeparator, transform = { it.path }) }
|
||||
@@ -22,10 +22,18 @@ import java.io.File
|
||||
internal const val STANDALONE_CACHE_VERSION = 0
|
||||
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
|
||||
|
||||
internal fun standaloneCacheVersion(dataRoot: File): CacheVersion =
|
||||
CacheVersion(ownVersion = STANDALONE_CACHE_VERSION,
|
||||
versionFile = File(dataRoot, STANDALONE_VERSION_FILE_NAME),
|
||||
fun standaloneCacheVersion(dataRoot: File): CacheVersion =
|
||||
customCacheVersion(STANDALONE_CACHE_VERSION, STANDALONE_VERSION_FILE_NAME, dataRoot)
|
||||
|
||||
fun customCacheVersion(version: Int, fileName: String, dataRoot: File, forceEnable: Boolean = false): CacheVersion =
|
||||
CacheVersion(ownVersion = version,
|
||||
versionFile = File(dataRoot, fileName),
|
||||
whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||
whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||
whenTurnedOff = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||
isEnabled = { IncrementalCompilation.isExperimental() })
|
||||
isEnabled = { IncrementalCompilation.isExperimental() || forceEnable })
|
||||
|
||||
fun commonCacheVersions(cachesDir: File): List<CacheVersion> =
|
||||
listOf(normalCacheVersion(cachesDir),
|
||||
experimentalCacheVersion(cachesDir),
|
||||
dataContainerCacheVersion(cachesDir))
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.multiproject
|
||||
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import java.io.File
|
||||
|
||||
interface ArtifactChangesProvider {
|
||||
fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>?
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.multiproject
|
||||
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
|
||||
interface ChangesRegistry {
|
||||
fun registerChanges(timestamp: Long, dirtyData: DirtyData)
|
||||
fun unknownChanges(timestamp: Long)
|
||||
}
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental.snapshots
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
internal class FileSnapshot(
|
||||
class FileSnapshot(
|
||||
val file: File,
|
||||
val length: Long,
|
||||
val hash: ByteArray
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental.snapshots
|
||||
|
||||
import org.jetbrains.kotlin.com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
internal object FileSnapshotExternalizer : DataExternalizer<FileSnapshot> {
|
||||
object FileSnapshotExternalizer : DataExternalizer<FileSnapshot> {
|
||||
override fun save(out: DataOutput, value: FileSnapshot) {
|
||||
out.writeUTF(value.file.canonicalPath)
|
||||
out.writeLong(value.length)
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
internal class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
|
||||
class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
|
||||
override fun dumpValue(value: FileSnapshot): String =
|
||||
value.toString()
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.incremental.snapshots
|
||||
|
||||
import java.io.File
|
||||
|
||||
internal interface FileSnapshotProvider {
|
||||
interface FileSnapshotProvider {
|
||||
operator fun get(file: File): FileSnapshot
|
||||
}
|
||||
|
||||
internal class SimpleFileSnapshotProviderImpl : FileSnapshotProvider {
|
||||
class SimpleFileSnapshotProviderImpl : FileSnapshotProvider {
|
||||
override fun get(file: File): FileSnapshot {
|
||||
val length = file.length()
|
||||
val hash = file.md5
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import java.io.File
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class TestWithWorkingDir {
|
||||
protected var workingDir: File by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Before
|
||||
open fun setUp() {
|
||||
workingDir = FileUtil.createTempDirectory(this.javaClass.simpleName, null)
|
||||
}
|
||||
|
||||
@After
|
||||
open fun tearDown() {
|
||||
workingDir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,21 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.gradle.incremental.dumpBuildLog
|
||||
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -9,7 +23,7 @@ import org.junit.runners.Parameterized
|
||||
import java.io.File
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class BuildLogParserParametrizedIT : BaseGradleIT() {
|
||||
class BuildLogParserParametrizedTest {
|
||||
|
||||
@Parameterized.Parameter
|
||||
@JvmField
|
||||
@@ -40,7 +54,7 @@ class BuildLogParserParametrizedIT : BaseGradleIT() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TEST_ROOT = File(resourcesRootFile, "buildLogsParserData")
|
||||
private val TEST_ROOT = File("compiler/incremental-compilation-impl/testData/buildLogsParserData")
|
||||
private val LOG_FILE_NAME = "build.log"
|
||||
private val EXPECTED_PARSED_LOG_FILE_NAME = "expected.txt"
|
||||
|
||||
@@ -49,7 +63,7 @@ class BuildLogParserParametrizedIT : BaseGradleIT() {
|
||||
@JvmStatic
|
||||
fun data(): List<Array<String>> {
|
||||
val directories = TEST_ROOT.listFiles().filter { it.isDirectory }
|
||||
return directories.map { arrayOf(it.name) }.toList()
|
||||
return directories.map { arrayOf(it.name) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,14 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.com.intellij.util.containers.HashMap
|
||||
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
|
||||
import com.intellij.util.containers.HashMap
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.jetbrains.kotlin.incremental.testingUtils.*
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
|
||||
@@ -104,7 +103,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
|
||||
|
||||
val rebuildExpectedToSucceed = buildLogSteps.last().compileSucceeded
|
||||
val rebuildSucceeded = rebuildResult.exitCode == ExitCode.OK
|
||||
assertEquals(rebuildExpectedToSucceed, rebuildSucceeded, "Rebuild exit code differs from incremental exit code")
|
||||
assertEquals("Rebuild exit code differs from incremental exit code", rebuildExpectedToSucceed, rebuildSucceeded)
|
||||
|
||||
if (rebuildSucceeded) {
|
||||
assertEqualDirectories(outDir, rebuildOutDir, forgiveExtraFiles = rebuildSucceeded)
|
||||
@@ -125,7 +124,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
|
||||
val compiledSources = arrayListOf<File>()
|
||||
var resultExitCode = ExitCode.OK
|
||||
|
||||
val reporter = object : IncReporter() {
|
||||
val reporter = object : ICReporter() {
|
||||
override fun report(message: ()->String) {
|
||||
}
|
||||
|
||||
@@ -185,7 +184,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val jpsResourcesPath = File("../../../jps-plugin/testData/incremental")
|
||||
private val jpsResourcesPath = File("jps-plugin/testData/incremental")
|
||||
private val ignoredDirs = setOf(File(jpsResourcesPath, "cacheVersionChanged"),
|
||||
File(jpsResourcesPath, "changeIncrementalOption"),
|
||||
File(jpsResourcesPath, "custom"),
|
||||
@@ -1,6 +1,22 @@
|
||||
package org.jetbrains.kotlin.gradle.incremental
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import java.io.File
|
||||
|
||||
private const val BEGIN_COMPILED_FILES = "Compiling files:"
|
||||
@@ -83,7 +99,7 @@ fun parseTestBuildLog(file: File): List<BuildStep> {
|
||||
}
|
||||
}
|
||||
|
||||
// used in integration tests
|
||||
// used in gradle integration tests
|
||||
@Suppress("unused")
|
||||
fun dumpBuildLog(buildSteps: Iterable<BuildStep>): String {
|
||||
val sb = StringBuilder()
|
||||
50
compiler/incremental-compilation-impl/testData/buildLogsParserData/twoStep/build.log
vendored
Normal file
50
compiler/incremental-compilation-impl/testData/buildLogsParserData/twoStep/build.log
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/inline/InlineGetKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/inlineGet.kt
|
||||
End of files
|
||||
Marked as dirty by Kotlin:
|
||||
src/UsageVal.kt
|
||||
src/UsageVar.kt
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/usage/UsageVal.class
|
||||
out/production/module/usage/UsageVar.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/UsageVal.kt
|
||||
src/UsageVar.kt
|
||||
End of files
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Exit code: NOTHING_DONE
|
||||
------------------------------------------
|
||||
|
||||
================ Step #2 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/inline/InlineSetKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/inlineSet.kt
|
||||
End of files
|
||||
Marked as dirty by Kotlin:
|
||||
src/UsageVar.kt
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/usage/UsageVar.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/UsageVar.kt
|
||||
End of files
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Exit code: NOTHING_DONE
|
||||
------------------------------------------
|
||||
16
compiler/incremental-compilation-impl/testData/buildLogsParserData/twoStep/expected.txt
vendored
Normal file
16
compiler/incremental-compilation-impl/testData/buildLogsParserData/twoStep/expected.txt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Compiling files:
|
||||
src/UsageVal.kt
|
||||
src/UsageVar.kt
|
||||
src/inlineGet.kt
|
||||
End of files
|
||||
------------------------------------------
|
||||
|
||||
================ Step #2 =================
|
||||
|
||||
Compiling files:
|
||||
src/UsageVar.kt
|
||||
src/inlineSet.kt
|
||||
End of files
|
||||
------------------------------------------
|
||||
37
compiler/incremental-compilation-impl/testData/buildLogsParserData/withError/build.log
vendored
Normal file
37
compiler/incremental-compilation-impl/testData/buildLogsParserData/withError/build.log
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module1/META-INF/module1.kotlin_module
|
||||
out/production/module1/a/A.class
|
||||
out/production/module1/a/ClassAnnotation.class
|
||||
out/production/module1/a/FileAnnotation.class
|
||||
out/production/module1/a/Module1_aKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
module1/src/module1_a.kt
|
||||
End of files
|
||||
Marked as dirty by Kotlin:
|
||||
module2/src/module2_b.kt
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Exit code: NOTHING_DONE
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module2/META-INF/module2.kotlin_module
|
||||
out/production/module2/b/B.class
|
||||
out/production/module2/b/Module2_bKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
module2/src/module2_b.kt
|
||||
End of files
|
||||
Exit code: ABORT
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
Cannot access 'FileAnnotation': it is internal in 'a'
|
||||
Cannot access 'A': it is internal in 'a'
|
||||
Cannot access 'FileAnnotation': it is internal in 'a'
|
||||
Cannot access 'ClassAnnotation': it is internal in 'a'
|
||||
Cannot access 'ClassAnnotation': it is internal in 'a'
|
||||
Function effective visibility 'public' should be the same or less permissive than its parameter type effective visibility 'internal'
|
||||
Cannot access 'A': it is internal in 'a'
|
||||
Cannot access 'a': it is internal in 'a'
|
||||
16
compiler/incremental-compilation-impl/testData/buildLogsParserData/withError/expected.txt
vendored
Normal file
16
compiler/incremental-compilation-impl/testData/buildLogsParserData/withError/expected.txt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Compiling files:
|
||||
module1/src/module1_a.kt
|
||||
module2/src/module2_b.kt
|
||||
End of files
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
Cannot access 'FileAnnotation': it is internal in 'a'
|
||||
Cannot access 'A': it is internal in 'a'
|
||||
Cannot access 'FileAnnotation': it is internal in 'a'
|
||||
Cannot access 'ClassAnnotation': it is internal in 'a'
|
||||
Cannot access 'ClassAnnotation': it is internal in 'a'
|
||||
Function effective visibility 'public' should be the same or less permissive than its parameter type effective visibility 'internal'
|
||||
Cannot access 'A': it is internal in 'a'
|
||||
Cannot access 'a': it is internal in 'a'
|
||||
17
compiler/incremental-compilation-impl/testData/buildLogsParserData/withJava/build.log
vendored
Normal file
17
compiler/incremental-compilation-impl/testData/buildLogsParserData/withJava/build.log
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/JavaClass.class
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/UsageKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/usage.kt
|
||||
End of files
|
||||
Exit code: ADDITIONAL_PASS_REQUIRED
|
||||
------------------------------------------
|
||||
Compiling files:
|
||||
src/JavaClass.java
|
||||
End of files
|
||||
Exit code: NOTHING_DONE
|
||||
------------------------------------------
|
||||
7
compiler/incremental-compilation-impl/testData/buildLogsParserData/withJava/expected.txt
vendored
Normal file
7
compiler/incremental-compilation-impl/testData/buildLogsParserData/withJava/expected.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Compiling files:
|
||||
src/usage.kt
|
||||
src/JavaClass.java
|
||||
End of files
|
||||
------------------------------------------
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
|
||||
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch
|
||||
import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
|
||||
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
@@ -40,7 +40,7 @@ class LexicalChainedScope @JvmOverloads constructor(
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
||||
= getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
|
||||
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstMatch(memberScopes) { it.getContributedClassifier(name, location) }
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope
|
||||
@@ -36,4 +38,14 @@ class SubpackagesImportingScope(
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation) = super.getContributedVariables(name, location)
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation) = super.getContributedFunctions(name, location)
|
||||
|
||||
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
|
||||
return ImportingScope.Empty.getContributedClassifier(name, location)
|
||||
}
|
||||
|
||||
//TODO: kept old behavior, but it seems very strange (super call seems more applicable)
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
||||
return ImportingScope.Empty.getContributedDescriptors(kindFilter, nameFilter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ package-fragment kotlin.coroutines
|
||||
public final inline suspend fun </*0*/ T> suspendCoroutineOrReturn(/*0*/ block: (kotlin.coroutines.Continuation<T>) -> kotlin.Any?): T
|
||||
}
|
||||
|
||||
@kotlin.SinceKotlin(version = "1.1") @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class RestrictsSuspendExtensions : kotlin.Annotation {
|
||||
/*primary*/ public constructor RestrictsSuspendExtensions()
|
||||
@kotlin.SinceKotlin(version = "1.1") @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class RestrictsSuspension : kotlin.Annotation {
|
||||
/*primary*/ public constructor RestrictsSuspension()
|
||||
}
|
||||
|
||||
122
compiler/testData/codegen/box/coroutines/asyncIterator.kt
vendored
Normal file
122
compiler/testData/codegen/box/coroutines/asyncIterator.kt
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// TARGET_BACKEND: JVM
|
||||
import kotlin.coroutines.*
|
||||
|
||||
interface AsyncGenerator<in T> {
|
||||
suspend fun yield(value: T)
|
||||
}
|
||||
|
||||
interface AsyncSequence<out T> {
|
||||
operator fun iterator(): AsyncIterator<T>
|
||||
}
|
||||
|
||||
interface AsyncIterator<out T> {
|
||||
operator suspend fun hasNext(): Boolean
|
||||
operator suspend fun next(): T
|
||||
}
|
||||
|
||||
fun <T> asyncGenerate(block: suspend AsyncGenerator<T>.() -> Unit): AsyncSequence<T> = object : AsyncSequence<T> {
|
||||
override fun iterator(): AsyncIterator<T> {
|
||||
val iterator = AsyncGeneratorIterator<T>()
|
||||
iterator.nextStep = block.createCoroutine(receiver = iterator, completion = iterator)
|
||||
return iterator
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncGeneratorIterator<T>: AsyncIterator<T>, AsyncGenerator<T>, Continuation<Unit> {
|
||||
var computedNext = false
|
||||
var nextValue: T? = null
|
||||
var nextStep: Continuation<Unit>? = null
|
||||
|
||||
// if (computesNext) computeContinuation is Continuation<T>
|
||||
// if (!computesNext) computeContinuation is Continuation<Boolean>
|
||||
var computesNext = false
|
||||
var computeContinuation: Continuation<*>? = null
|
||||
|
||||
suspend fun computeHasNext(): Boolean = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
|
||||
computesNext = false
|
||||
computeContinuation = c
|
||||
nextStep!!.resume(Unit)
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun computeNext(): T = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
|
||||
computesNext = true
|
||||
computeContinuation = c
|
||||
nextStep!!.resume(Unit)
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun resumeIterator(exception: Throwable?) {
|
||||
if (exception != null) {
|
||||
done()
|
||||
computeContinuation!!.resumeWithException(exception)
|
||||
return
|
||||
}
|
||||
if (computesNext) {
|
||||
computedNext = false
|
||||
(computeContinuation as Continuation<T>).resume(nextValue as T)
|
||||
} else {
|
||||
(computeContinuation as Continuation<Boolean>).resume(nextStep != null)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun hasNext(): Boolean {
|
||||
if (!computedNext) return computeHasNext()
|
||||
return nextStep != null
|
||||
}
|
||||
|
||||
override suspend fun next(): T {
|
||||
if (!computedNext) return computeNext()
|
||||
computedNext = false
|
||||
return nextValue as T
|
||||
}
|
||||
|
||||
private fun done() {
|
||||
computedNext = true
|
||||
nextStep = null
|
||||
}
|
||||
|
||||
// Completion continuation implementation
|
||||
override fun resume(value: Unit) {
|
||||
done()
|
||||
resumeIterator(null)
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
done()
|
||||
resumeIterator(exception)
|
||||
}
|
||||
|
||||
// Generator implementation
|
||||
override suspend fun yield(value: T): Unit = CoroutineIntrinsics.suspendCoroutineOrReturn { c ->
|
||||
computedNext = true
|
||||
nextValue = value
|
||||
nextStep = c
|
||||
resumeIterator(null)
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val seq = asyncGenerate {
|
||||
yield("O")
|
||||
yield("K")
|
||||
}
|
||||
|
||||
var res = ""
|
||||
|
||||
builder {
|
||||
for (i in seq) {
|
||||
res += i
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
46
compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt
vendored
Normal file
46
compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import kotlin.coroutines.*
|
||||
|
||||
suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
|
||||
x.resume("OK")
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
var wasResumeCalled = false
|
||||
c.startCoroutine(object : Continuation<Unit> {
|
||||
override fun resume(value: Unit) {
|
||||
wasResumeCalled = true
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
if (!wasResumeCalled) throw RuntimeException("fail 1")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = ""
|
||||
|
||||
builder {
|
||||
run {
|
||||
if (result == "") return@builder
|
||||
}
|
||||
suspendHere()
|
||||
throw RuntimeException("fail 2")
|
||||
}
|
||||
|
||||
result = "fail1"
|
||||
|
||||
builder {
|
||||
run {
|
||||
if (result == "") return@builder
|
||||
}
|
||||
result = suspendHere()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
42
compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt
vendored
Normal file
42
compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import kotlin.coroutines.*
|
||||
|
||||
suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
|
||||
x.resume("OK")
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
var wasResumeCalled = false
|
||||
c.startCoroutine(object : Continuation<Unit> {
|
||||
override fun resume(value: Unit) {
|
||||
wasResumeCalled = true
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
if (!wasResumeCalled) throw RuntimeException("fail 1")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = ""
|
||||
|
||||
builder {
|
||||
if (result == "") return@builder
|
||||
suspendHere()
|
||||
throw RuntimeException("fail 2")
|
||||
}
|
||||
|
||||
result = "fail"
|
||||
|
||||
builder {
|
||||
if (result == "") return@builder
|
||||
result = suspendHere()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
34
compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt
vendored
Normal file
34
compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// IGNORE_BACKEND: JS
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var result = "0"
|
||||
|
||||
|
||||
suspend fun suspendHere(x: Int): Unit {
|
||||
run {
|
||||
if (x == 0) return
|
||||
if (x == 1) return@suspendHere
|
||||
}
|
||||
|
||||
result = "OK"
|
||||
return CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
|
||||
x.resume(Unit)
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
if (suspendHere(0) != Unit) throw RuntimeException("fail 1")
|
||||
if (suspendHere(1) != Unit) throw RuntimeException("fail 2")
|
||||
if (suspendHere(2) != Unit) throw RuntimeException("fail 3")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
27
compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt
vendored
Normal file
27
compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var result = "0"
|
||||
|
||||
suspend fun suspendHere(x: Int): Unit {
|
||||
if (x == 0) return
|
||||
result = "OK"
|
||||
return CoroutineIntrinsics.suspendCoroutineOrReturn { x ->
|
||||
x.resume(Unit)
|
||||
CoroutineIntrinsics.SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
suspendHere(0)
|
||||
suspendHere(1)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class ComparablePair<T : Comparable<T>>(val first: T, val second: T) : Comparabl
|
||||
fun <T : Comparable<T>> genericRangeTo(start: T, endInclusive: T) = start..endInclusive
|
||||
operator fun Double.rangeTo(other: Double) = genericRangeTo(this, other)
|
||||
// some weird inverted range
|
||||
operator fun Float.rangeTo(other: Float) = object : ClosedComparableRange<Float> {
|
||||
operator fun Float.rangeTo(other: Float) = object : ClosedFloatingPointRange<Float> {
|
||||
override val endInclusive: Float = this@rangeTo
|
||||
override val start: Float = other
|
||||
override fun lessThanOrEquals(a: Float, b: Float) = a >= b
|
||||
|
||||
23
compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt
vendored
Normal file
23
compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline fun <reified T> f() = 1
|
||||
|
||||
fun g() {}
|
||||
|
||||
class Foo {
|
||||
inline fun <reified T> h(t: T) = 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(::g, ::g.javaMethod!!.kotlinFunction)
|
||||
|
||||
val h = Foo::class.members.single { it.name == "h" } as KFunction<*>
|
||||
assertEquals(h, h.javaMethod!!.kotlinFunction)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// WITH_RUNTIME
|
||||
import kotlin.coroutines.*
|
||||
class Controller {
|
||||
suspend fun suspendHere() = CoroutineIntrinsics.suspendCoroutineOrReturn<String> { x ->
|
||||
|
||||
@@ -21,4 +21,5 @@ fun box(): String {
|
||||
|
||||
// 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
|
||||
// 1 GETSTATIC EmptyContinuation.INSTANCE
|
||||
// 2 GETSTATIC
|
||||
// 1 GETSTATIC kotlin/coroutines/CoroutineIntrinsics.INSTANCE
|
||||
// 3 GETSTATIC
|
||||
|
||||
65
compiler/testData/codegen/light-analysis/coroutines/asyncIterator.txt
vendored
Normal file
65
compiler/testData/codegen/light-analysis/coroutines/asyncIterator.txt
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
public interface AsyncGenerator {
|
||||
public abstract @org.jetbrains.annotations.Nullable method yield(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
public final class AsyncGeneratorIterator {
|
||||
private @org.jetbrains.annotations.Nullable field computeContinuation: kotlin.coroutines.Continuation
|
||||
private field computedNext: boolean
|
||||
private field computesNext: boolean
|
||||
private @org.jetbrains.annotations.Nullable field nextStep: kotlin.coroutines.Continuation
|
||||
private @org.jetbrains.annotations.Nullable field nextValue: java.lang.Object
|
||||
public method <init>(): void
|
||||
public final @org.jetbrains.annotations.Nullable method computeHasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method computeNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
private final method done(): void
|
||||
public final @org.jetbrains.annotations.Nullable method getComputeContinuation(): kotlin.coroutines.Continuation
|
||||
public final method getComputedNext(): boolean
|
||||
public final method getComputesNext(): boolean
|
||||
public final @org.jetbrains.annotations.Nullable method getNextStep(): kotlin.coroutines.Continuation
|
||||
public final @org.jetbrains.annotations.Nullable method getNextValue(): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method hasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method next(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public method resume(@org.jetbrains.annotations.NotNull p0: kotlin.Unit): void
|
||||
public synthetic method resume(p0: java.lang.Object): void
|
||||
public final @kotlin.Suppress method resumeIterator(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
public final method setComputeContinuation(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final method setComputedNext(p0: boolean): void
|
||||
public final method setComputesNext(p0: boolean): void
|
||||
public final method setNextStep(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final method setNextValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public @org.jetbrains.annotations.Nullable method yield(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
public interface AsyncIterator {
|
||||
public abstract @org.jetbrains.annotations.Nullable method hasNext(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public abstract @org.jetbrains.annotations.Nullable method next(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
public final class AsyncIteratorKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method asyncGenerate(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): AsyncSequence
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
}
|
||||
|
||||
|
||||
public interface AsyncSequence {
|
||||
public abstract @org.jetbrains.annotations.NotNull method iterator(): AsyncIterator
|
||||
}
|
||||
|
||||
|
||||
public final class CoroutineUtilKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
}
|
||||
|
||||
|
||||
public final class EmptyContinuation {
|
||||
public final static field INSTANCE: EmptyContinuation
|
||||
private method <init>(): void
|
||||
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
}
|
||||
19
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineNonLocalReturn.txt
vendored
Normal file
19
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineNonLocalReturn.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
public final class CoroutineNonLocalReturnKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
public final class CoroutineUtilKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
}
|
||||
|
||||
|
||||
public final class EmptyContinuation {
|
||||
public final static field INSTANCE: EmptyContinuation
|
||||
private method <init>(): void
|
||||
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
}
|
||||
19
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineReturn.txt
vendored
Normal file
19
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineReturn.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
public final class CoroutineReturnKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
public final class CoroutineUtilKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
}
|
||||
|
||||
|
||||
public final class EmptyContinuation {
|
||||
public final static field INSTANCE: EmptyContinuation
|
||||
private method <init>(): void
|
||||
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
}
|
||||
22
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendNonLocalReturn.txt
vendored
Normal file
22
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendNonLocalReturn.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
public final class CoroutineUtilKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
}
|
||||
|
||||
|
||||
public final class EmptyContinuation {
|
||||
public final static field INSTANCE: EmptyContinuation
|
||||
private method <init>(): void
|
||||
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
}
|
||||
|
||||
|
||||
public final class SuspendNonLocalReturnKt {
|
||||
private static @org.jetbrains.annotations.NotNull field result: java.lang.String
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String
|
||||
public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
22
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendReturn.txt
vendored
Normal file
22
compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendReturn.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
public final class CoroutineUtilKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation
|
||||
}
|
||||
|
||||
|
||||
public final class EmptyContinuation {
|
||||
public final static field INSTANCE: EmptyContinuation
|
||||
private method <init>(): void
|
||||
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
|
||||
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
|
||||
}
|
||||
|
||||
|
||||
public final class SuspendReturnKt {
|
||||
private static @org.jetbrains.annotations.NotNull field result: java.lang.String
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String
|
||||
public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
@@ -15,5 +15,5 @@ public final class InComparableRangeKt {
|
||||
public final static method check(p0: float, p1: float, p2: float): boolean
|
||||
public final static @org.jetbrains.annotations.NotNull method genericRangeTo(@org.jetbrains.annotations.NotNull p0: java.lang.Comparable, @org.jetbrains.annotations.NotNull p1: java.lang.Comparable): kotlin.ranges.ClosedRange
|
||||
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: double, p1: double): kotlin.ranges.ClosedRange
|
||||
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: float, p1: float): kotlin.ranges.ClosedComparableRange
|
||||
public final static @org.jetbrains.annotations.NotNull method rangeTo(p0: float, p1: float): kotlin.ranges.ClosedFloatingPointRange
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user