Effects: add test on (de)serialization of contracts
- Add ContractDescriptorRenderer - Add option to dump function contracts in DescriptorRendererOptions - Add parsing of LANGUAGE_VERSION directive in AbstractLoadJava - Add tests on serialization-deserializaton identity of contracts ========== Introduction of EffectSystem: 13/18
This commit is contained in:
@@ -26,9 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM;
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.config.ContentRootsKt;
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.*;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
@@ -120,6 +118,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
if (useTypeTableInSerializer) {
|
||||
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true);
|
||||
}
|
||||
updateConfigurationWithLanguageVersionDirective(ktFile, configuration);
|
||||
|
||||
KotlinCoreEnvironment environment =
|
||||
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
registerJavacIfNeeded(environment);
|
||||
@@ -129,7 +129,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
Assert.assertEquals("test", packageFromSource.getName().asString());
|
||||
|
||||
PackageViewDescriptor packageFromBinary = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, getTestRootDisposable(), getJdkKind(), configurationKind, true, false, useJavacWrapper()
|
||||
tmpdir, getTestRootDisposable(), getJdkKind(), configurationKind, true, false, useJavacWrapper(),
|
||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)
|
||||
).first;
|
||||
|
||||
for (DeclarationDescriptor descriptor : DescriptorUtils.getAllDescriptors(packageFromBinary.getMemberScope())) {
|
||||
@@ -140,10 +141,21 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
|
||||
DescriptorValidator.validate(errorTypesForbidden(), packageFromSource);
|
||||
DescriptorValidator.validate(new DeserializedScopeValidationVisitor(), packageFromBinary);
|
||||
Configuration comparatorConfiguration = COMPARATOR_CONFIGURATION.checkPrimaryConstructors(true).checkPropertyAccessors(true);
|
||||
Configuration comparatorConfiguration = COMPARATOR_CONFIGURATION.checkPrimaryConstructors(true).checkPropertyAccessors(true).checkFunctionContracts(true);
|
||||
compareDescriptors(packageFromSource, packageFromBinary, comparatorConfiguration, txtFile);
|
||||
}
|
||||
|
||||
private static void updateConfigurationWithLanguageVersionDirective(File file, CompilerConfiguration configuration) throws IOException {
|
||||
String version = InTextDirectivesUtils.findStringWithPrefixes(FileUtil.loadFile(file, true), "// LANGUAGE_VERSION:");
|
||||
if (version != null) {
|
||||
LanguageVersion explicitVersion = LanguageVersion.fromVersionString(version);
|
||||
CommonConfigurationKeysKt.setLanguageVersionSettings(
|
||||
configuration,
|
||||
new LanguageVersionSettingsImpl(explicitVersion, ApiVersion.createByLanguageVersion(explicitVersion))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean useFastClassFilesReading() {
|
||||
return false;
|
||||
}
|
||||
@@ -222,7 +234,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
|
||||
Pair<PackageViewDescriptor, BindingContext> javaPackageAndContext = loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, getTestRootDisposable(), getJdkKind(), ConfigurationKind.JDK_ONLY, false,
|
||||
false, useJavacWrapper());
|
||||
false, useJavacWrapper(), null);
|
||||
|
||||
checkJavaPackage(
|
||||
expectedFile, javaPackageAndContext.first, javaPackageAndContext.second,
|
||||
@@ -267,7 +279,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
) throws IOException {
|
||||
compileJavaWithAnnotationsJar(javaFiles, outDir);
|
||||
return loadTestPackageAndBindingContextFromJavaRoot(outDir, myTestRootDisposable, getJdkKind(), configurationKind, true,
|
||||
useFastClassFilesReading(), useJavacWrapper());
|
||||
useFastClassFilesReading(), useJavacWrapper(), null);
|
||||
}
|
||||
|
||||
private static void checkJavaPackage(
|
||||
|
||||
@@ -25,6 +25,7 @@ import kotlin.io.FilesKt;
|
||||
import kotlin.sequences.SequencesKt;
|
||||
import kotlin.text.Charsets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
|
||||
@@ -32,8 +33,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
|
||||
import org.jetbrains.kotlin.jvm.compiler.javac.JavacRegistrarForTests;
|
||||
@@ -80,7 +83,8 @@ public class LoadDescriptorUtil {
|
||||
@NotNull ConfigurationKind configurationKind,
|
||||
boolean isBinaryRoot,
|
||||
boolean useFastClassReading,
|
||||
boolean useJavacWrapper
|
||||
boolean useJavacWrapper,
|
||||
@Nullable LanguageVersionSettings explicitLanguageVersionSettings
|
||||
) {
|
||||
List<File> javaBinaryRoots = new ArrayList<>();
|
||||
javaBinaryRoots.add(KotlinTestUtils.getAnnotationsJar());
|
||||
@@ -97,6 +101,9 @@ public class LoadDescriptorUtil {
|
||||
KotlinTestUtils.newConfiguration(configurationKind, testJdkKind, javaBinaryRoots, javaSourceRoots);
|
||||
configuration.put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, useFastClassReading);
|
||||
configuration.put(JVMConfigurationKeys.USE_JAVAC, useJavacWrapper);
|
||||
if (explicitLanguageVersionSettings != null) {
|
||||
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, explicitLanguageVersionSettings);
|
||||
}
|
||||
KotlinCoreEnvironment environment =
|
||||
KotlinCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
if (useJavacWrapper) {
|
||||
|
||||
+2
-1
@@ -97,6 +97,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
|
||||
/* checkPropertyAccessors = */ true,
|
||||
/* includeMethodsOfKotlinAny = */ false,
|
||||
/* renderDeclarationsFromOtherModules = */ true,
|
||||
/* checkFunctionContract = */ false,
|
||||
// Skip Java annotation constructors because order of their parameters is not retained at runtime
|
||||
{ descriptor -> !descriptor!!.isJavaAnnotationConstructor() },
|
||||
errorTypesForbidden(), renderer
|
||||
@@ -109,7 +110,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
|
||||
}
|
||||
|
||||
val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, testRootDisposable, jdkKind, ConfigurationKind.ALL, true, false, false
|
||||
tmpdir, testRootDisposable, jdkKind, ConfigurationKind.ALL, true, false, false, null
|
||||
).first
|
||||
|
||||
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected, actual, comparatorConfiguration, null)
|
||||
|
||||
+42
-10
@@ -22,6 +22,7 @@ import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.contracts.description.*;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope;
|
||||
import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil;
|
||||
@@ -63,12 +64,12 @@ public class RecursiveDescriptorComparator {
|
||||
);
|
||||
|
||||
public static final Configuration DONT_INCLUDE_METHODS_OF_OBJECT = new Configuration(false, false, false, false,
|
||||
descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
false, descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
public static final Configuration RECURSIVE = new Configuration(false, false, true, false,
|
||||
descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
false, descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
|
||||
public static final Configuration RECURSIVE_ALL = new Configuration(true, true, true, false,
|
||||
descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
true, descriptor -> true, errorTypesForbidden(), DEFAULT_RENDERER);
|
||||
|
||||
public static final Predicate<DeclarationDescriptor> SKIP_BUILT_INS_PACKAGES = descriptor -> {
|
||||
if (descriptor instanceof PackageViewDescriptor) {
|
||||
@@ -111,6 +112,11 @@ public class RecursiveDescriptorComparator {
|
||||
boolean isPrimaryConstructor = descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary();
|
||||
printer.print(isPrimaryConstructor && conf.checkPrimaryConstructors ? "/*primary*/ " : "", conf.renderer.render(descriptor));
|
||||
|
||||
if (descriptor instanceof FunctionDescriptor && conf.checkFunctionContracts) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
printEffectsIfAny(functionDescriptor, printer);
|
||||
}
|
||||
|
||||
if (isClassOrPackage) {
|
||||
if (!topLevel) {
|
||||
printer.printlnWithNoIndent(" {").pushIndent();
|
||||
@@ -171,6 +177,24 @@ public class RecursiveDescriptorComparator {
|
||||
}
|
||||
}
|
||||
|
||||
private void printEffectsIfAny(FunctionDescriptor functionDescriptor, Printer printer) {
|
||||
LazyContractProvider contractProvider = functionDescriptor.getUserData(ContractProviderKey.INSTANCE);
|
||||
if (contractProvider == null) return;
|
||||
|
||||
ContractDescription contractDescription = contractProvider.getContractDescription();
|
||||
if (contractDescription == null || contractDescription.getEffects().isEmpty()) return;
|
||||
|
||||
printer.println();
|
||||
printer.pushIndent();
|
||||
for (EffectDeclaration effect : contractDescription.getEffects()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ContractDescriptionRenderer renderer = new ContractDescriptionRenderer(sb);
|
||||
effect.accept(renderer, Unit.INSTANCE);
|
||||
printer.println(sb.toString());
|
||||
}
|
||||
printer.popIndent();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MemberScope getPackageScopeInModule(@NotNull PackageViewDescriptor descriptor, @NotNull ModuleDescriptor module) {
|
||||
// See LazyPackageViewDescriptorImpl#memberScope
|
||||
@@ -298,6 +322,7 @@ public class RecursiveDescriptorComparator {
|
||||
private final boolean checkPropertyAccessors;
|
||||
private final boolean includeMethodsOfKotlinAny;
|
||||
private final boolean renderDeclarationsFromOtherModules;
|
||||
private final boolean checkFunctionContracts;
|
||||
private final Predicate<DeclarationDescriptor> recursiveFilter;
|
||||
private final DescriptorRenderer renderer;
|
||||
private final DescriptorValidator.ValidationVisitor validationStrategy;
|
||||
@@ -307,6 +332,7 @@ public class RecursiveDescriptorComparator {
|
||||
boolean checkPropertyAccessors,
|
||||
boolean includeMethodsOfKotlinAny,
|
||||
boolean renderDeclarationsFromOtherModules,
|
||||
boolean checkFunctionContracts,
|
||||
Predicate<DeclarationDescriptor> recursiveFilter,
|
||||
DescriptorValidator.ValidationVisitor validationStrategy,
|
||||
DescriptorRenderer renderer
|
||||
@@ -315,6 +341,7 @@ public class RecursiveDescriptorComparator {
|
||||
this.checkPropertyAccessors = checkPropertyAccessors;
|
||||
this.includeMethodsOfKotlinAny = includeMethodsOfKotlinAny;
|
||||
this.renderDeclarationsFromOtherModules = renderDeclarationsFromOtherModules;
|
||||
this.checkFunctionContracts = checkFunctionContracts;
|
||||
this.recursiveFilter = recursiveFilter;
|
||||
this.validationStrategy = validationStrategy;
|
||||
this.renderer = renderer;
|
||||
@@ -322,38 +349,43 @@ public class RecursiveDescriptorComparator {
|
||||
|
||||
public Configuration filterRecursion(@NotNull Predicate<DeclarationDescriptor> stepIntoFilter) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, stepIntoFilter,
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, stepIntoFilter,
|
||||
validationStrategy.withStepIntoFilter(stepIntoFilter), renderer);
|
||||
}
|
||||
|
||||
public Configuration checkPrimaryConstructors(boolean checkPrimaryConstructors) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration checkPropertyAccessors(boolean checkPropertyAccessors) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration checkFunctionContracts(boolean checkFunctionContracts) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration includeMethodsOfKotlinAny(boolean includeMethodsOfKotlinAny) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration renderDeclarationsFromOtherModules(boolean renderDeclarationsFromOtherModules) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration withValidationStrategy(@NotNull DescriptorValidator.ValidationVisitor validationStrategy) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
|
||||
public Configuration withRenderer(@NotNull DescriptorRenderer renderer) {
|
||||
return new Configuration(checkPrimaryConstructors, checkPropertyAccessors, includeMethodsOfKotlinAny,
|
||||
renderDeclarationsFromOtherModules, recursiveFilter, validationStrategy, renderer);
|
||||
renderDeclarationsFromOtherModules, checkFunctionContracts, recursiveFilter, validationStrategy, renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user