Skip to content

Commit 25c1828

Browse files
committed
JS: write and load pre-release flag on binaries
1 parent de8dd37 commit 25c1828

File tree

13 files changed

+189
-38
lines changed

13 files changed

+189
-38
lines changed

compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
5454
ProtectedInSuperClassCompanionCallChecker(),
5555
UnsupportedSyntheticCallableReferenceChecker(),
5656
SuperCallWithDefaultArgumentsChecker(),
57-
MissingDependencyClassChecker,
5857
ProtectedSyntheticExtensionCallChecker,
5958
ReifiedTypeParameterSubstitutionChecker()
6059
),
@@ -67,7 +66,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
6766
),
6867

6968
additionalClassifierUsageCheckers = listOf(
70-
MissingDependencyClassChecker.ClassifierUsage
7169
),
7270

7371
additionalAnnotationCheckers = listOf(

compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,13 @@ private val DEFAULT_CALL_CHECKERS = listOf(
9292
CapturingInClosureChecker(), InlineCheckerWrapper(), SafeCallChecker(),
9393
DeprecatedCallChecker, CallReturnsArrayOfNothingChecker(), InfixCallChecker(), OperatorCallChecker(),
9494
ConstructorHeaderCallChecker, ProtectedConstructorCallChecker, ApiVersionCallChecker,
95-
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker,
95+
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker, MissingDependencyClassChecker,
9696
CallableReferenceCompatibilityChecker()
9797
)
9898
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
99-
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker)
99+
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
100+
DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage
101+
)
100102

101103

102104
abstract class PlatformConfigurator(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package a
2+
3+
open class A {
4+
class Nested
5+
}
6+
7+
fun foo() = ""
8+
var bar = 42
9+
typealias TA = String
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors
2+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:5:16: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
3+
fun baz(param: A, nested: A.Nested) {
4+
^
5+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:5:27: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
6+
fun baz(param: A, nested: A.Nested) {
7+
^
8+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:5:29: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
9+
fun baz(param: A, nested: A.Nested) {
10+
^
11+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:6:23: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
12+
val constructor = A()
13+
^
14+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:7:18: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
15+
val nested = A.Nested()
16+
^
17+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:7:20: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
18+
val nested = A.Nested()
19+
^
20+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:8:22: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
21+
val methodCall = param.method()
22+
^
23+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:8:28: error: unresolved reference: method
24+
val methodCall = param.method()
25+
^
26+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:9:30: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
27+
val supertype = object : A() {}
28+
^
29+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:11:13: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
30+
val x = foo()
31+
^
32+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:12:13: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
33+
val y = bar
34+
^
35+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:13:5: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
36+
bar = 239
37+
^
38+
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibraryJs/source.kt:14:12: error: package 'a' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
39+
val z: TA = ""
40+
^
41+
COMPILATION_ERROR
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package usage
2+
3+
import a.*
4+
5+
fun baz(param: A, nested: A.Nested) {
6+
val constructor = A()
7+
val nested = A.Nested()
8+
val methodCall = param.method()
9+
val supertype = object : A() {}
10+
11+
val x = foo()
12+
val y = bar
13+
bar = 239
14+
val z: TA = ""
15+
}

compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
import org.jetbrains.kotlin.analyzer.AnalysisResult;
3131
import org.jetbrains.kotlin.cli.AbstractCliTest;
3232
import org.jetbrains.kotlin.cli.WrongBytecodeVersionTest;
33+
import org.jetbrains.kotlin.cli.common.CLICompiler;
3334
import org.jetbrains.kotlin.cli.common.ExitCode;
3435
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport;
3536
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer;
3637
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector;
38+
import org.jetbrains.kotlin.cli.js.K2JSCompiler;
3739
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler;
3840
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
3941
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
@@ -87,10 +89,16 @@ private File getTestDataFileWithExtension(@NotNull String extension) {
8789

8890
@NotNull
8991
private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) {
90-
File result = new File(tmpdir, sourcePath + ".jar");
91-
Pair<String, ExitCode> output = compileKotlin(sourcePath, result, extraClassPath);
92+
File destination = new File(tmpdir, sourcePath + ".jar");
93+
compileLibrary(new K2JVMCompiler(), sourcePath, destination, extraClassPath);
94+
return destination;
95+
}
96+
97+
private void compileLibrary(
98+
@NotNull CLICompiler<?> compiler, @NotNull String sourcePath, @NotNull File destination, @NotNull File... extraClassPath
99+
) {
100+
Pair<String, ExitCode> output = compileKotlin(compiler, sourcePath, destination, Collections.<String>emptyList(), extraClassPath);
92101
Assert.assertEquals(normalizeOutput(new Pair<String, ExitCode>("", ExitCode.OK)), normalizeOutput(output));
93-
return result;
94102
}
95103

96104
@NotNull
@@ -218,22 +226,49 @@ private Pair<String, ExitCode> compileKotlin(
218226
private Pair<String, ExitCode> compileKotlin(
219227
@NotNull String fileName,
220228
@NotNull File output,
221-
List<String> additionalOptions,
229+
@NotNull List<String> additionalOptions,
230+
@NotNull File... classpath
231+
) {
232+
return compileKotlin(new K2JVMCompiler(), fileName, output, additionalOptions, classpath);
233+
}
234+
235+
@NotNull
236+
private Pair<String, ExitCode> compileKotlin(
237+
@NotNull CLICompiler<?> compiler,
238+
@NotNull String fileName,
239+
@NotNull File output,
240+
@NotNull List<String> additionalOptions,
222241
@NotNull File... classpath
223242
) {
224243
List<String> args = new ArrayList<String>();
225244
File sourceFile = new File(getTestDataDirectory(), fileName);
226245
assert sourceFile.exists() : "Source file does not exist: " + sourceFile.getAbsolutePath();
227246
args.add(sourceFile.getPath());
228-
if (classpath.length > 0) {
229-
args.add("-classpath");
230-
args.add(StringsKt.join(Arrays.asList(classpath), File.pathSeparator));
247+
248+
if (compiler instanceof K2JSCompiler) {
249+
if (classpath.length > 0) {
250+
args.add("-libraries");
251+
args.add(StringsKt.join(Arrays.asList(classpath), File.pathSeparator));
252+
}
253+
args.add("-output");
254+
args.add(output.getPath());
255+
args.add("-meta-info");
256+
}
257+
else if (compiler instanceof K2JVMCompiler) {
258+
if (classpath.length > 0) {
259+
args.add("-classpath");
260+
args.add(StringsKt.join(Arrays.asList(classpath), File.pathSeparator));
261+
}
262+
args.add("-d");
263+
args.add(output.getPath());
264+
}
265+
else {
266+
throw new UnsupportedOperationException(compiler.toString());
231267
}
232-
args.add("-d");
233-
args.add(output.getPath());
268+
234269
args.addAll(additionalOptions);
235270

236-
return AbstractCliTest.executeCompilerGrabOutput(new K2JVMCompiler(), args);
271+
return AbstractCliTest.executeCompilerGrabOutput(compiler, args);
237272
}
238273

239274
private void doTestBrokenJavaLibrary(@NotNull String libraryName, @NotNull String... pathsToDelete) throws Exception {
@@ -278,13 +313,18 @@ public Object invoke(String name, Object value) {
278313
}
279314

280315
@SuppressWarnings("deprecation")
281-
private void doTestPreReleaseKotlinLibrary(@NotNull String libraryName, @NotNull String... additionalOptions) throws Exception {
316+
private void doTestPreReleaseKotlinLibrary(
317+
@NotNull CLICompiler<?> compiler,
318+
@NotNull String libraryName,
319+
@NotNull File destination,
320+
@NotNull File result,
321+
@NotNull String... additionalOptions
322+
) throws Exception {
282323
// Compiles the library with the "pre-release" flag, then compiles a usage of this library in the release mode
283324

284-
File library;
285325
try {
286326
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true");
287-
library = compileLibrary(libraryName);
327+
compileLibrary(compiler, libraryName, destination);
288328
}
289329
finally {
290330
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY);
@@ -293,7 +333,7 @@ private void doTestPreReleaseKotlinLibrary(@NotNull String libraryName, @NotNull
293333
Pair<String, ExitCode> output;
294334
try {
295335
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "false");
296-
output = compileKotlin("source.kt", tmpdir, Arrays.asList(additionalOptions), library);
336+
output = compileKotlin(compiler, "source.kt", tmpdir, Arrays.asList(additionalOptions), result);
297337
}
298338
finally {
299339
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY);
@@ -414,11 +454,20 @@ public void testMissingDependencyJavaNestedAnnotation() throws Exception {
414454
}
415455

416456
public void testReleaseCompilerAgainstPreReleaseLibrary() throws Exception {
417-
doTestPreReleaseKotlinLibrary("library");
457+
File destination = new File(tmpdir, "library.jar");
458+
doTestPreReleaseKotlinLibrary(new K2JVMCompiler(), "library", destination, destination);
459+
}
460+
461+
public void testReleaseCompilerAgainstPreReleaseLibraryJs() throws Exception {
462+
doTestPreReleaseKotlinLibrary(new K2JSCompiler(), "library",
463+
new File(tmpdir, "library.js"),
464+
new File(tmpdir, "library.meta.js"));
418465
}
419466

420467
public void testReleaseCompilerAgainstPreReleaseLibrarySkipVersionCheck() throws Exception {
421-
doTestPreReleaseKotlinLibrary("library", "-Xskip-metadata-version-check");
468+
File destination = new File(tmpdir, "library.jar");
469+
doTestPreReleaseKotlinLibrary(new K2JVMCompiler(), "library", destination, destination,
470+
"-Xskip-metadata-version-check");
422471
}
423472

424473
public void testWrongMetadataVersion() throws Exception {

core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsPackageFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ class BuiltInsPackageFragment(
4141
}
4242

4343
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
44-
})
44+
}, containerSource = null)

core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializedPackageFragmentImpl.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,31 @@
1717
package org.jetbrains.kotlin.serialization.deserialization
1818

1919
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
20+
import org.jetbrains.kotlin.descriptors.SourceElement
2021
import org.jetbrains.kotlin.name.FqName
2122
import org.jetbrains.kotlin.serialization.ProtoBuf
23+
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
2224
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
2325
import org.jetbrains.kotlin.storage.StorageManager
2426

2527
abstract class DeserializedPackageFragmentImpl(
2628
fqName: FqName,
2729
storageManager: StorageManager,
2830
module: ModuleDescriptor,
29-
protected val proto: ProtoBuf.PackageFragment
31+
protected val proto: ProtoBuf.PackageFragment,
32+
private val containerSource: DeserializedContainerSource?
3033
) : DeserializedPackageFragment(fqName, storageManager, module) {
3134
protected val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
3235

33-
override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver)
36+
override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver) { containerSource ?: SourceElement.NO_SOURCE }
3437

3538
override fun computeMemberScope() =
3639
DeserializedPackageMemberScope(
37-
this, proto.`package`, nameResolver, containerSource = null, components = components,
38-
classNames = { classDataFinder.allClassIds.filter { classId ->
39-
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
40-
}.map { it.shortClassName } }
40+
this, proto.`package`, nameResolver, containerSource, components,
41+
classNames = {
42+
classDataFinder.allClassIds.filter { classId ->
43+
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
44+
}.map { it.shortClassName }
45+
}
4146
)
4247
}

core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ProtoBasedClassDataFinder.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import org.jetbrains.kotlin.serialization.ProtoBuf
2424

2525
class ProtoBasedClassDataFinder(
2626
proto: ProtoBuf.PackageFragment,
27-
private val nameResolver: NameResolver
27+
private val nameResolver: NameResolver,
28+
private val classSource: (ClassId) -> SourceElement = { SourceElement.NO_SOURCE }
2829
) : ClassDataFinder {
2930
private val classIdToProto =
3031
proto.class_List.associateBy { klass ->
@@ -35,6 +36,6 @@ class ProtoBasedClassDataFinder(
3536

3637
override fun findClassData(classId: ClassId): ClassDataWithSource? {
3738
val classProto = classIdToProto[classId] ?: return null
38-
return ClassDataWithSource(ClassData(nameResolver, classProto), SourceElement.NO_SOURCE)
39+
return ClassDataWithSource(ClassData(nameResolver, classProto), classSource(classId))
3940
}
4041
}

core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberDescriptor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ interface DeserializedMemberDescriptor : MemberDescriptor {
4545
get() = SinceKotlinInfo.create(proto, nameResolver, sinceKotlinInfoTable)
4646

4747
// Information about the origin of this callable's container (class or package part on JVM) or null if there's no such information.
48+
// TODO: merge with sourceElement of containingDeclaration
4849
val containerSource: DeserializedContainerSource?
4950
}
5051

js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616

1717
package org.jetbrains.kotlin.serialization.js
1818

19+
import org.jetbrains.kotlin.config.KotlinCompilerVersion
1920
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
2021
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
2122
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
23+
import org.jetbrains.kotlin.descriptors.SourceFile
2224
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
2325
import org.jetbrains.kotlin.name.FqName
2426
import org.jetbrains.kotlin.resolve.DescriptorUtils
2527
import org.jetbrains.kotlin.serialization.ProtoBuf
2628
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
2729
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragmentImpl
30+
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
2831
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
32+
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
2933
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
3034
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
3135
import org.jetbrains.kotlin.storage.StorageManager
@@ -35,8 +39,9 @@ class KotlinJavascriptPackageFragment(
3539
fqName: FqName,
3640
storageManager: StorageManager,
3741
module: ModuleDescriptor,
38-
proto: ProtoBuf.PackageFragment
39-
) : DeserializedPackageFragmentImpl(fqName, storageManager, module, proto) {
42+
proto: ProtoBuf.PackageFragment,
43+
header: JsProtoBuf.Header
44+
) : DeserializedPackageFragmentImpl(fqName, storageManager, module, proto, JsContainerSource(fqName, header)) {
4045
private val fileMap: Map<Int, FileHolder> by storageManager.createLazyValue {
4146
this.proto.getExtension(JsProtoBuf.packageFragmentFiles).fileList.withIndex().associate { (index, file) ->
4247
(if (file.hasId()) file.id else index) to FileHolder(file.annotationList)
@@ -66,4 +71,21 @@ class KotlinJavascriptPackageFragment(
6671
annotationsProto.map { annotationDeserializer.deserializeAnnotation(it, nameResolver) }
6772
}
6873
}
74+
75+
private class JsContainerSource(private val fqName: FqName, private val header: JsProtoBuf.Header) : DeserializedContainerSource {
76+
// TODO
77+
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
78+
79+
// This is null because we look for incompatible libraries in dependencies in the beginning of the compilation anyway,
80+
// and refuse to compile against them completely
81+
override val incompatibility: IncompatibleVersionErrorData<*>?
82+
get() = null
83+
84+
override val isPreReleaseInvisible: Boolean
85+
get() = (header.flags and 1) != 0 && !KotlinCompilerVersion.isPreRelease()
86+
87+
// TODO: this is not a class
88+
override val presentableString: String
89+
get() = "Package '$fqName'"
90+
}
6991
}

0 commit comments

Comments
 (0)