Reformat and cleanup most JVM codegen test classes
This commit is contained in:
+3
-3
@@ -33,9 +33,9 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
|
||||
|
||||
@Override
|
||||
protected void doMultiFileTest(
|
||||
@NotNull File wholeFile,
|
||||
@NotNull List<TestFile> files,
|
||||
@Nullable File javaFilesDir
|
||||
@NotNull File wholeFile,
|
||||
@NotNull List<TestFile> files,
|
||||
@Nullable File javaFilesDir
|
||||
) throws Exception {
|
||||
boolean isIgnored = IGNORE_EXPECTED_FAILURES && InTextDirectivesUtils.isIgnoredTarget(getBackend(), wholeFile);
|
||||
|
||||
|
||||
+1
-2
@@ -24,8 +24,7 @@ abstract class AbstractBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest()
|
||||
try {
|
||||
InlineTestUtil.checkNoCallsToInline(initializedClassLoader.allGeneratedFiles.filterClassFiles(), myFiles.psiFiles)
|
||||
SMAPTestUtil.checkSMAP(files, generateClassesInFile().getClassFiles(), false)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
println(generateToText())
|
||||
throw e
|
||||
}
|
||||
|
||||
+4
-17
@@ -34,7 +34,7 @@ abstract class AbstractBytecodeListingTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
private fun isWithSignatures(wholeFile: File): Boolean =
|
||||
WITH_SIGNATURES.containsMatchIn(wholeFile.readText())
|
||||
WITH_SIGNATURES.containsMatchIn(wholeFile.readText())
|
||||
|
||||
companion object {
|
||||
private val WITH_SIGNATURES = Regex.fromLiteral("// WITH_SIGNATURES")
|
||||
@@ -132,13 +132,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
|
||||
}
|
||||
}.toString()
|
||||
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
if (!filter.shouldWriteMethod(access, name, desc)) {
|
||||
return null
|
||||
}
|
||||
@@ -176,7 +170,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
|
||||
}.joinToString()
|
||||
val signatureIfRequired = if (withSignatures) "<$signature> " else ""
|
||||
declarationsInsideClass.add(
|
||||
Declaration("${signatureIfRequired}method $name($parameterWithAnnotations): $returnType", methodAnnotations)
|
||||
Declaration("${signatureIfRequired}method $name($parameterWithAnnotations): $returnType", methodAnnotations)
|
||||
)
|
||||
super.visitEnd()
|
||||
}
|
||||
@@ -218,14 +212,7 @@ class BytecodeListingTextCollectingVisitor(val filter: Filter, val withSignature
|
||||
return super.visitAnnotation(desc, visible)
|
||||
}
|
||||
|
||||
override fun visit(
|
||||
version: Int,
|
||||
access: Int,
|
||||
name: String,
|
||||
signature: String?,
|
||||
superName: String?,
|
||||
interfaces: Array<out String>?
|
||||
) {
|
||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<out String>?) {
|
||||
className = name
|
||||
classAccess = access
|
||||
classSignature = signature
|
||||
|
||||
+19
-27
@@ -5,12 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
import org.jetbrains.kotlin.utils.rethrow
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@@ -18,24 +16,25 @@ import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun doMultiFileTest(wholeFile: File, files: List<CodegenTestCase.TestFile>, javaFilesDir: File?) {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, files, TestJdkKind.MOCK_JDK, javaFilesDir)
|
||||
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(
|
||||
ConfigurationKind.ALL,
|
||||
files,
|
||||
TestJdkKind.MOCK_JDK,
|
||||
*listOfNotNull(javaFilesDir).toTypedArray()
|
||||
)
|
||||
loadMultiFiles(files)
|
||||
|
||||
if (isMultiFileTest(files) && !InTextDirectivesUtils.isDirectiveDefined(wholeFile.readText(), "TREAT_AS_ONE_FILE")) {
|
||||
doTestMultiFile(files)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val expected = readExpectedOccurrences(wholeFile.path)
|
||||
val actual = generateToText("helpers/")
|
||||
checkGeneratedTextAgainstExpectedOccurrences(actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun doTestMultiFile(files: List<CodegenTestCase.TestFile>) {
|
||||
private fun doTestMultiFile(files: List<TestFile>) {
|
||||
val expectedOccurrencesByOutputFile = LinkedHashMap<String, List<OccurrenceInfo>>()
|
||||
for (file in files) {
|
||||
readExpectedOccurrencesForMultiFileTest(file, expectedOccurrencesByOutputFile)
|
||||
@@ -50,10 +49,9 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
protected fun readExpectedOccurrences(filename: String): List<OccurrenceInfo> {
|
||||
val result = ArrayList<OccurrenceInfo>()
|
||||
val lines = FileUtil.loadFile(File(filename), Charsets.UTF_8.name(), true).split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
val lines = File(filename).readLines().dropLastWhile(String::isEmpty)
|
||||
|
||||
for (line in lines) {
|
||||
val matcher = EXPECTED_OCCURRENCES_PATTERN.matcher(line)
|
||||
@@ -80,7 +78,7 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
private val AT_OUTPUT_FILE_PATTERN = Pattern.compile("^\\s*//\\s*@(.*):$")
|
||||
private val EXPECTED_OCCURRENCES_PATTERN = Pattern.compile("^\\s*//\\s*(\\d+)\\s*(.*)$")
|
||||
|
||||
private fun isMultiFileTest(files: List<CodegenTestCase.TestFile>): Boolean {
|
||||
private fun isMultiFileTest(files: List<TestFile>): Boolean {
|
||||
var kotlinFiles = 0
|
||||
for (file in files) {
|
||||
if (file.name.endsWith(".kt")) {
|
||||
@@ -90,8 +88,7 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
return kotlinFiles > 1
|
||||
}
|
||||
|
||||
fun checkGeneratedTextAgainstExpectedOccurrences(text: String,
|
||||
expectedOccurrences: List<OccurrenceInfo>) {
|
||||
fun checkGeneratedTextAgainstExpectedOccurrences(text: String, expectedOccurrences: List<OccurrenceInfo>) {
|
||||
val expected = StringBuilder()
|
||||
val actual = StringBuilder()
|
||||
|
||||
@@ -102,10 +99,9 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
|
||||
try {
|
||||
Assert.assertEquals(text, expected.toString(), actual.toString())
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
println(text)
|
||||
throw rethrow(e)
|
||||
throw e
|
||||
}
|
||||
|
||||
}
|
||||
@@ -121,27 +117,23 @@ abstract class AbstractBytecodeTextTest : CodegenTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun readExpectedOccurrencesForMultiFileTest(
|
||||
file: CodegenTestCase.TestFile,
|
||||
occurrenceMap: MutableMap<String, List<OccurrenceInfo>>) {
|
||||
private fun readExpectedOccurrencesForMultiFileTest(file: TestFile, occurrenceMap: MutableMap<String, List<OccurrenceInfo>>) {
|
||||
var currentOccurrenceInfos: MutableList<OccurrenceInfo>? = null
|
||||
for (line in file.content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
val atOutputFileMatcher = AT_OUTPUT_FILE_PATTERN.matcher(line)
|
||||
if (atOutputFileMatcher.matches()) {
|
||||
val outputFileName = atOutputFileMatcher.group(1)
|
||||
if (occurrenceMap.containsKey(outputFileName)) {
|
||||
throw AssertionError(
|
||||
file.name + ": Expected occurrences for output file " + outputFileName + " were already provided")
|
||||
throw AssertionError("${file.name}: Expected occurrences for output file $outputFileName were already provided")
|
||||
}
|
||||
currentOccurrenceInfos = ArrayList<OccurrenceInfo>()
|
||||
occurrenceMap.put(outputFileName, currentOccurrenceInfos)
|
||||
currentOccurrenceInfos = ArrayList()
|
||||
occurrenceMap[outputFileName] = currentOccurrenceInfos
|
||||
}
|
||||
|
||||
val expectedOccurrencesMatcher = EXPECTED_OCCURRENCES_PATTERN.matcher(line)
|
||||
if (expectedOccurrencesMatcher.matches()) {
|
||||
if (currentOccurrenceInfos == null) {
|
||||
throw AssertionError(
|
||||
file.name + ": Should specify output file with '// @<OUTPUT_FILE_NAME>:' before expectations")
|
||||
throw AssertionError("${file.name}: Should specify output file with '// @<OUTPUT_FILE_NAME>:' before expectations")
|
||||
}
|
||||
val occurrenceInfo = parseOccurrenceInfo(expectedOccurrencesMatcher)
|
||||
currentOccurrenceInfos.add(occurrenceInfo)
|
||||
|
||||
+1
-2
@@ -26,8 +26,7 @@ abstract class AbstractCompileKotlinAgainstInlineKotlinTest : AbstractCompileKot
|
||||
val sourceFiles = factory1.inputFiles + factory2.inputFiles
|
||||
InlineTestUtil.checkNoCallsToInline(allGeneratedFiles.filterClassFiles(), sourceFiles)
|
||||
SMAPTestUtil.checkSMAP(files, allGeneratedFiles.filterClassFiles(), true)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
println("FIRST:\n\n${factory1.createText()}\n\nSECOND:\n\n${factory2.createText()}")
|
||||
throw e
|
||||
}
|
||||
|
||||
+2
-2
@@ -49,13 +49,13 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) throws Exception {
|
||||
protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List<TestFile> files, @Nullable File javaFilesDir) {
|
||||
assert javaFilesDir == null : ".java files are not supported yet in this test";
|
||||
doTwoFileTest(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Pair<ClassFileFactory, ClassFileFactory> doTwoFileTest(@NotNull List<TestFile> files) throws Exception {
|
||||
protected Pair<ClassFileFactory, ClassFileFactory> doTwoFileTest(@NotNull List<TestFile> files) {
|
||||
// Note that it may be beneficial to improve this test to handle many files, compiling them successively against all previous
|
||||
assert files.size() == 2 || (files.size() == 3 && files.get(2).name.equals("CoroutineUtil.kt")) : "There should be exactly two files in this test";
|
||||
TestFile fileA = files.get(0);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ abstract class AbstractDumpDeclarationsTest : CodegenTestCase() {
|
||||
|
||||
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
|
||||
val expectedResult = KotlinTestUtils.replaceExtension(wholeFile, "json")
|
||||
dumpToFile = KotlinTestUtils.tmpDirForTest(this).resolve(name + ".json")
|
||||
dumpToFile = KotlinTestUtils.tmpDirForTest(this).resolve("$name.json")
|
||||
compile(files, null)
|
||||
classFileFactory.generationState.destroy()
|
||||
KotlinTestUtils.assertEqualsToFile(expectedResult, dumpToFile.readText()) {
|
||||
|
||||
+6
-6
@@ -34,10 +34,10 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
val fullTxt = compileWithFullAnalysis(files, javaFilesDir)
|
||||
.replace("final enum class", "enum class")
|
||||
.replace("final enum class", "enum class")
|
||||
|
||||
val liteTxt = compileWithLightAnalysis(wholeFile, files, javaFilesDir)
|
||||
.replace("@synthetic.kotlin.jvm.GeneratedByJvmOverloads ", "")
|
||||
.replace("@synthetic.kotlin.jvm.GeneratedByJvmOverloads ", "")
|
||||
|
||||
assertEquals(fullTxt, liteTxt)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
|
||||
assert(!relativePath.startsWith(".."))
|
||||
|
||||
val configuration = createConfiguration(
|
||||
configurationKind, getJdkKind(files), listOf(getAnnotationsJar()), javaFilesDir?.let(::listOf).orEmpty(), files
|
||||
configurationKind, getJdkKind(files), listOf(getAnnotationsJar()), javaFilesDir?.let(::listOf).orEmpty(), files
|
||||
)
|
||||
val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
AnalysisHandlerExtension.registerExtension(environment.project, PartialAnalysisHandlerExtension())
|
||||
@@ -65,14 +65,14 @@ abstract class AbstractLightAnalysisModeTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
protected fun compileWithFullAnalysis(
|
||||
files: List<TestFile>,
|
||||
javaSourceDir: File?
|
||||
files: List<TestFile>,
|
||||
javaSourceDir: File?
|
||||
): String {
|
||||
compile(files, javaSourceDir)
|
||||
classFileFactory.getClassFiles()
|
||||
|
||||
val classInternalNames = classFileFactory.generationState.bindingContext
|
||||
.getSliceContents(CodegenBinding.ASM_TYPE).map { it.value.internalName to it.key }.toMap()
|
||||
.getSliceContents(CodegenBinding.ASM_TYPE).map { it.value.internalName to it.key }.toMap()
|
||||
|
||||
return BytecodeListingTextCollectingVisitor.getText(classFileFactory, object : ListAnalysisFilter() {
|
||||
override fun shouldWriteClass(access: Int, name: String): Boolean {
|
||||
|
||||
@@ -29,7 +29,7 @@ import kotlin.collections.ArrayList
|
||||
abstract class AbstractLineNumberTest : CodegenTestCase() {
|
||||
|
||||
override fun doMultiFileTest(
|
||||
wholeFile: File, files: MutableList<CodegenTestCase.TestFile>, javaFilesDir: File?
|
||||
wholeFile: File, files: MutableList<TestFile>, javaFilesDir: File?
|
||||
) {
|
||||
val isCustomTest = wholeFile.parentFile.name.equals("custom", ignoreCase = true)
|
||||
if (!isCustomTest) {
|
||||
@@ -159,7 +159,7 @@ abstract class AbstractLineNumberTest : CodegenTestCase() {
|
||||
private val TEST_LINE_NUMBER_PATTERN = Pattern.compile("^.*test.$LINE_NUMBER_FUN\\(\\).*$")
|
||||
|
||||
private fun createLineNumberDeclaration() =
|
||||
CodegenTestCase.TestFile(
|
||||
TestFile(
|
||||
"$LINE_NUMBER_FUN.kt",
|
||||
"package test;\n\npublic fun $LINE_NUMBER_FUN(): Int = 0\n"
|
||||
)
|
||||
|
||||
-3
@@ -21,13 +21,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||
import org.jetbrains.kotlin.test.TestJdkKind;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.script.ScriptTestUtilKt.loadScriptingPlugin;
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -82,7 +81,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
private static final String DEFAULT_TEST_FILE_NAME = "a_test";
|
||||
private static final String DEFAULT_JVM_TARGET_FOR_TEST = "kotlin.test.default.jvm.target";
|
||||
private static final String JAVA_COMPILATION_TARGET = "kotlin.test.java.compilation.target";
|
||||
public static final String RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT = "kotlin.test.box.in.separate.process.port";
|
||||
private static final String RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT = "kotlin.test.box.in.separate.process.port";
|
||||
|
||||
protected KotlinCoreEnvironment myEnvironment;
|
||||
protected CodegenTestFiles myFiles;
|
||||
@@ -90,7 +89,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
protected GeneratedClassLoader initializedClassLoader;
|
||||
protected File javaClassesOutputDirectory = null;
|
||||
protected List<File> additionalDependencies = null;
|
||||
protected String coroutinesPackage;
|
||||
protected String coroutinesPackage = "";
|
||||
|
||||
protected ConfigurationKind configurationKind = ConfigurationKind.JDK_ONLY;
|
||||
private final String defaultJvmTarget = System.getProperty(DEFAULT_JVM_TARGET_FOR_TEST);
|
||||
@@ -99,7 +98,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
|
||||
protected final void createEnvironmentWithMockJdkAndIdeaAnnotations(
|
||||
@NotNull ConfigurationKind configurationKind,
|
||||
@Nullable File... javaSourceRoots
|
||||
@NotNull File... javaSourceRoots
|
||||
) {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(configurationKind, Collections.emptyList(), TestJdkKind.MOCK_JDK, javaSourceRoots);
|
||||
}
|
||||
@@ -118,7 +117,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
@NotNull ConfigurationKind configurationKind,
|
||||
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
|
||||
@NotNull TestJdkKind testJdkKind,
|
||||
@Nullable File... javaSourceRoots
|
||||
@NotNull File... javaSourceRoots
|
||||
) {
|
||||
if (myEnvironment != null) {
|
||||
throw new IllegalStateException("must not set up myEnvironment twice");
|
||||
@@ -161,7 +160,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
updateConfigurationByDirectivesInTestFiles(testFilesWithConfigurationDirectives, configuration, "");
|
||||
}
|
||||
|
||||
protected static void updateConfigurationByDirectivesInTestFiles(
|
||||
private static void updateConfigurationByDirectivesInTestFiles(
|
||||
@NotNull List<TestFile> testFilesWithConfigurationDirectives,
|
||||
@NotNull CompilerConfiguration configuration,
|
||||
@NotNull String coroutinesPackage
|
||||
@@ -306,12 +305,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
coroutinesPackage = "";
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myFiles = null;
|
||||
@@ -343,7 +336,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
assert myFiles == null : "Should not initialize myFiles twice";
|
||||
myFiles = CodegenTestFiles.create(file.getName(), content, myEnvironment.getProject());
|
||||
return content;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -512,44 +506,46 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ClassFileFactory generateClassesInFile(boolean reportProblems) {
|
||||
if (classFileFactory == null) {
|
||||
try {
|
||||
GenerationState generationState = GenerationUtils.compileFiles(
|
||||
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
|
||||
new NoScopeRecordCliBindingTrace()
|
||||
);
|
||||
classFileFactory = generationState.getFactory();
|
||||
private ClassFileFactory generateClassesInFile(boolean reportProblems) {
|
||||
if (classFileFactory != null) return classFileFactory;
|
||||
|
||||
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER) {
|
||||
DxChecker.check(classFileFactory);
|
||||
}
|
||||
try {
|
||||
GenerationState generationState = GenerationUtils.compileFiles(
|
||||
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
|
||||
new NoScopeRecordCliBindingTrace()
|
||||
);
|
||||
classFileFactory = generationState.getFactory();
|
||||
|
||||
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER) {
|
||||
DxChecker.check(classFileFactory);
|
||||
}
|
||||
catch (TestsCompiletimeError e) {
|
||||
if (reportProblems) {
|
||||
e.getOriginal().printStackTrace();
|
||||
System.err.println("Generating instructions as text...");
|
||||
try {
|
||||
if (classFileFactory == null) {
|
||||
System.err.println("Cannot generate text: exception was thrown during generation");
|
||||
}
|
||||
else {
|
||||
System.err.println(classFileFactory.createText());
|
||||
}
|
||||
}
|
||||
catch (TestsCompiletimeError e) {
|
||||
if (reportProblems) {
|
||||
e.getOriginal().printStackTrace();
|
||||
System.err.println("Generating instructions as text...");
|
||||
try {
|
||||
if (classFileFactory == null) {
|
||||
System.err.println("Cannot generate text: exception was thrown during generation");
|
||||
}
|
||||
catch (Throwable e1) {
|
||||
System.err.println("Exception thrown while trying to generate text, the actual exception follows:");
|
||||
e1.printStackTrace();
|
||||
System.err.println("-----------------------------------------------------------------------------");
|
||||
else {
|
||||
System.err.println(classFileFactory.createText());
|
||||
}
|
||||
System.err.println("See exceptions above");
|
||||
} else {
|
||||
System.err.println("Compilation failure");
|
||||
}
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
throw new TestsCompilerError(e);
|
||||
catch (Throwable e1) {
|
||||
System.err.println("Exception thrown while trying to generate text, the actual exception follows:");
|
||||
e1.printStackTrace();
|
||||
System.err.println("-----------------------------------------------------------------------------");
|
||||
}
|
||||
System.err.println("See exceptions above");
|
||||
}
|
||||
else {
|
||||
System.err.println("Compilation failure");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new TestsCompilerError(e);
|
||||
}
|
||||
return classFileFactory;
|
||||
}
|
||||
@@ -558,7 +554,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean verifyAllFilesWithAsm(ClassFileFactory factory, ClassLoader loader, boolean reportProblems) {
|
||||
private static boolean verifyAllFilesWithAsm(ClassFileFactory factory, ClassLoader loader, boolean reportProblems) {
|
||||
boolean noErrors = true;
|
||||
for (OutputFile file : ClassFileUtilsKt.getClassFiles(factory)) {
|
||||
noErrors &= verifyWithAsm(file, loader, reportProblems);
|
||||
@@ -607,7 +603,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
Class<?> aClass = generateFacadeClass();
|
||||
try {
|
||||
return findTheOnlyMethod(aClass);
|
||||
} catch (Error e) {
|
||||
}
|
||||
catch (Error e) {
|
||||
System.out.println(generateToText());
|
||||
throw e;
|
||||
}
|
||||
@@ -618,22 +615,11 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
return findDeclaredMethodByName(generateFacadeClass(), name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Annotation> loadAnnotationClassQuietly(@NotNull String fqName) {
|
||||
try {
|
||||
return (Class<? extends Annotation>) initializedClassLoader.loadClass(fqName);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw ExceptionUtilsKt.rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateConfiguration(@NotNull CompilerConfiguration configuration) {
|
||||
|
||||
}
|
||||
|
||||
protected ClassBuilderFactory getClassBuilderFactory(){
|
||||
protected ClassBuilderFactory getClassBuilderFactory() {
|
||||
return ClassBuilderFactories.TEST;
|
||||
}
|
||||
|
||||
@@ -641,7 +627,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
|
||||
}
|
||||
|
||||
protected void setCustomDefaultJvmTarget(CompilerConfiguration configuration) {
|
||||
private void setCustomDefaultJvmTarget(CompilerConfiguration configuration) {
|
||||
JvmTarget target = configuration.get(JVMConfigurationKeys.JVM_TARGET);
|
||||
if (target == null && defaultJvmTarget != null) {
|
||||
JvmTarget value = JvmTarget.fromString(defaultJvmTarget);
|
||||
@@ -663,8 +649,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
boolean reportProblems
|
||||
) {
|
||||
configurationKind = extractConfigurationKind(files);
|
||||
boolean loadAndroidAnnotations = files.stream().anyMatch(it ->
|
||||
InTextDirectivesUtils.isDirectiveDefined(it.content, "ANDROID_ANNOTATIONS")
|
||||
boolean loadAndroidAnnotations = files.stream().anyMatch(
|
||||
it -> InTextDirectivesUtils.isDirectiveDefined(it.content, "ANDROID_ANNOTATIONS")
|
||||
);
|
||||
|
||||
List<String> javacOptions = extractJavacOptions(files);
|
||||
@@ -744,7 +730,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
return javacOptions;
|
||||
}
|
||||
|
||||
protected void updateJavacOptions(List<String> javacOptions) {
|
||||
private void updateJavacOptions(List<String> javacOptions) {
|
||||
if (javaCompilationTarget != null && !javacOptions.contains("-target")) {
|
||||
javacOptions.add("-source");
|
||||
javacOptions.add(javaCompilationTarget);
|
||||
@@ -832,9 +818,9 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
}
|
||||
|
||||
protected void doMultiFileTest(
|
||||
@NotNull File wholeFile,
|
||||
@NotNull List<TestFile> files,
|
||||
@Nullable File javaFilesDir
|
||||
@NotNull File wholeFile,
|
||||
@NotNull List<TestFile> files,
|
||||
@Nullable File javaFilesDir
|
||||
) throws Exception {
|
||||
throw new UnsupportedOperationException("Multi-file test cases are not supported in this test");
|
||||
}
|
||||
@@ -843,7 +829,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
throws IOException, InvocationTargetException, IllegalAccessException {
|
||||
Class<?> aClass = getGeneratedClass(classLoader, className);
|
||||
Method method = getBoxMethodOrNull(aClass);
|
||||
assertTrue("Can't find box method in " + aClass,method != null);
|
||||
assertNotNull("Can't find box method in " + aClass, method);
|
||||
callBoxMethodAndCheckResult(classLoader, aClass, method);
|
||||
}
|
||||
|
||||
@@ -876,7 +862,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
List<URL> classPath = extractUrls(classLoader);
|
||||
if (classLoader instanceof GeneratedClassLoader) {
|
||||
File outDir = KotlinTestUtils.tmpDirForTest(this);
|
||||
SimpleOutputFileCollection currentOutput = new SimpleOutputFileCollection(((GeneratedClassLoader) classLoader).getAllGeneratedFiles());
|
||||
SimpleOutputFileCollection currentOutput =
|
||||
new SimpleOutputFileCollection(((GeneratedClassLoader) classLoader).getAllGeneratedFiles());
|
||||
writeAllTo(currentOutput, outDir);
|
||||
classPath.add(0, outDir.toURI().toURL());
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ public class CodegenTestFiles {
|
||||
String[] values = valueString.split(" ");
|
||||
|
||||
scriptParameterValues.add(values);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
scriptParameterValues.add(ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +39,17 @@ import java.util.List;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class CodegenTestUtil {
|
||||
private CodegenTestUtil() {}
|
||||
private CodegenTestUtil() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassFileFactory generateFiles(@NotNull KotlinCoreEnvironment environment, @NotNull CodegenTestFiles files) {
|
||||
return GenerationUtils.compileFiles(files.getPsiFiles(), environment).getFactory();
|
||||
}
|
||||
|
||||
public static void assertThrows(@NotNull Method foo, @NotNull Class<? extends Throwable> exceptionClass,
|
||||
@Nullable Object instance, @NotNull Object... args) throws IllegalAccessException {
|
||||
public static void assertThrows(
|
||||
@NotNull Method foo, @NotNull Class<? extends Throwable> exceptionClass, @Nullable Object instance, @NotNull Object... args
|
||||
) throws IllegalAccessException {
|
||||
boolean caught = false;
|
||||
try {
|
||||
foo.invoke(instance, args);
|
||||
|
||||
@@ -46,10 +46,6 @@ object GenerationUtils {
|
||||
writeAllTo(output)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun compileFile(ktFile: KtFile, environment: KotlinCoreEnvironment): ClassFileFactory =
|
||||
compileFiles(listOf(ktFile), environment).factory
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun compileFiles(
|
||||
|
||||
@@ -35,7 +35,7 @@ object InlineTestUtil {
|
||||
fun checkNoCallsToInline(outputFiles: Iterable<OutputFile>, sourceFiles: List<KtFile>) {
|
||||
val inlineInfo = obtainInlineInfo(outputFiles)
|
||||
val inlineMethods = inlineInfo.inlineMethods
|
||||
assert(!inlineMethods.isEmpty()) { "There are no inline methods" }
|
||||
assert(inlineMethods.isNotEmpty()) { "There are no inline methods" }
|
||||
|
||||
val notInlinedCalls = checkInlineMethodNotInvoked(outputFiles, inlineMethods)
|
||||
assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") }
|
||||
@@ -48,7 +48,7 @@ object InlineTestUtil {
|
||||
val notInlinedParameters = checkParametersInlined(outputFiles, inlineInfo, sourceFiles)
|
||||
assert(notInlinedParameters.isEmpty()) {
|
||||
"All inline parameters should be inlined but:\n${notInlinedParameters.joinToString("\n")}\n" +
|
||||
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
|
||||
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,9 @@ object InlineTestUtil {
|
||||
val inlineFunctions = inlineFunctionsJvmNames(binaryClass.classHeader)
|
||||
|
||||
val classVisitor = object : ClassVisitorWithName() {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
||||
override fun visitMethod(
|
||||
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
|
||||
): MethodVisitor? {
|
||||
if (name + desc in inlineFunctions) {
|
||||
inlineMethods.add(MethodInfo(className, name, desc))
|
||||
}
|
||||
@@ -70,7 +72,7 @@ object InlineTestUtil {
|
||||
}
|
||||
|
||||
ClassReader(file.asByteArray()).accept(classVisitor, 0)
|
||||
binaryClasses.put(classVisitor.className, binaryClass)
|
||||
binaryClasses[classVisitor.className] = binaryClass
|
||||
}
|
||||
|
||||
return InlineInfo(inlineMethods, binaryClasses)
|
||||
@@ -84,9 +86,11 @@ object InlineTestUtil {
|
||||
|
||||
//if inline function creates anonymous object then do not try to check that all lambdas are inlined
|
||||
val classVisitor = object : ClassVisitorWithName() {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
||||
override fun visitMethod(
|
||||
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
|
||||
): MethodVisitor? {
|
||||
if (name + desc in inlineFunctions) {
|
||||
return object: MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
|
||||
return object : MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
|
||||
override fun onAnonymousConstructorCallOrSingletonAccess(owner: String) {
|
||||
doLambdaInliningCheck = false
|
||||
}
|
||||
@@ -126,7 +130,9 @@ object InlineTestUtil {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
||||
override fun visitMethod(
|
||||
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
|
||||
): MethodVisitor? {
|
||||
if (skipMethodsOfThisClass) {
|
||||
return null
|
||||
}
|
||||
@@ -160,11 +166,13 @@ object InlineTestUtil {
|
||||
return notInlined
|
||||
}
|
||||
|
||||
private fun checkParametersInlined(outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, sourceFiles: List<KtFile>): ArrayList<NotInlinedParameter> {
|
||||
private fun checkParametersInlined(
|
||||
outputFiles: Iterable<OutputFile>, inlineInfo: InlineInfo, sourceFiles: List<KtFile>
|
||||
): ArrayList<NotInlinedParameter> {
|
||||
val skipMethods =
|
||||
sourceFiles.flatMap {
|
||||
InTextDirectivesUtils.findLinesWithPrefixesRemoved(it.text, "// SKIP_INLINE_CHECK_IN: ")
|
||||
}.toSet()
|
||||
sourceFiles.flatMap {
|
||||
InTextDirectivesUtils.findLinesWithPrefixesRemoved(it.text, "// SKIP_INLINE_CHECK_IN: ")
|
||||
}.toSet()
|
||||
|
||||
val inlinedMethods = inlineInfo.inlineMethods
|
||||
val notInlinedParameters = ArrayList<NotInlinedParameter>()
|
||||
@@ -172,7 +180,9 @@ object InlineTestUtil {
|
||||
if (!isClassOrPackagePartKind(loadBinaryClass(file))) continue
|
||||
|
||||
ClassReader(file.asByteArray()).accept(object : ClassVisitorWithName() {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
||||
override fun visitMethod(
|
||||
access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
|
||||
): MethodVisitor? {
|
||||
val declaration = MethodInfo(className, name, desc)
|
||||
|
||||
//do not check anonymous object creation in inline functions and in package facades
|
||||
@@ -184,7 +194,7 @@ object InlineTestUtil {
|
||||
return null
|
||||
}
|
||||
|
||||
return object: MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
|
||||
return object : MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) {
|
||||
override fun onAnonymousConstructorCallOrSingletonAccess(owner: String) {
|
||||
val fromCall = MethodInfo(className, this.name, this.desc)
|
||||
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
|
||||
@@ -201,29 +211,27 @@ object InlineTestUtil {
|
||||
if (classInternalName.startsWith("kotlin/jvm/internal/"))
|
||||
return true
|
||||
|
||||
return isClassOrPackagePartKind(inlineInfo.binaryClasses[classInternalName]!!)
|
||||
return isClassOrPackagePartKind(inlineInfo.binaryClasses.getValue(classInternalName))
|
||||
}
|
||||
|
||||
private fun isClassOrPackagePartKind(klass: KotlinJvmBinaryClass): Boolean {
|
||||
return klass.classHeader.kind == KotlinClassHeader.Kind.CLASS && !klass.classId.isLocal
|
||||
|| klass.classHeader.kind == KotlinClassHeader.Kind.FILE_FACADE /*single file facade equals to package part*/
|
||||
|| klass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
|
||||
|| klass.classHeader.kind == KotlinClassHeader.Kind.FILE_FACADE /*single file facade equals to package part*/
|
||||
|| klass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
|
||||
}
|
||||
|
||||
private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass {
|
||||
val klass = FileBasedKotlinClass.create(file.asByteArray()) {
|
||||
className, classVersion, classHeader, innerClasses ->
|
||||
private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass =
|
||||
FileBasedKotlinClass.create<FileBasedKotlinClass>(file.asByteArray()) { className, classVersion, classHeader, innerClasses ->
|
||||
object : FileBasedKotlinClass(className, classVersion, classHeader, innerClasses) {
|
||||
override val location: String
|
||||
get() = throw UnsupportedOperationException()
|
||||
|
||||
override fun getFileContents(): ByteArray = throw UnsupportedOperationException()
|
||||
override fun hashCode(): Int = throw UnsupportedOperationException()
|
||||
override fun equals(other: Any?): Boolean = throw UnsupportedOperationException()
|
||||
override fun toString(): String = throw UnsupportedOperationException()
|
||||
}
|
||||
}!!
|
||||
return klass
|
||||
}
|
||||
|
||||
private class InlineInfo(val inlineMethods: Set<MethodInfo>, val binaryClasses: Map<String, KotlinJvmBinaryClass>)
|
||||
|
||||
@@ -242,9 +250,11 @@ object InlineTestUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class MethodNodeWithAnonymousObjectCheck(val inlineInfo: InlineInfo, access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?) : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
|
||||
private abstract class MethodNodeWithAnonymousObjectCheck(
|
||||
val inlineInfo: InlineInfo, access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?
|
||||
) : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
|
||||
private fun isInlineParameterLikeOwner(owner: String) =
|
||||
"$" in owner && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
|
||||
"$" in owner && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
|
||||
|
||||
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
|
||||
if ("<init>" == name && isInlineParameterLikeOwner(owner)) {
|
||||
|
||||
@@ -41,7 +41,7 @@ object SMAPTestUtil {
|
||||
}
|
||||
}, 0)
|
||||
|
||||
SMAPAndFile.SMAPAndFile(debugInfo, outputFile.sourceFiles.single(), outputFile.relativePath)
|
||||
SMAPAndFile(debugInfo, outputFile.sourceFiles.single(), outputFile.relativePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,10 @@ object SMAPTestUtil {
|
||||
}
|
||||
|
||||
private fun checkExtension(file: CodegenTestCase.TestFile, separateCompilation: Boolean) =
|
||||
file.name.run { endsWith(".smap") || if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation") }
|
||||
file.name.run {
|
||||
endsWith(".smap") ||
|
||||
if (separateCompilation) endsWith(".smap-separate-compilation") else endsWith(".smap-nonseparate-compilation")
|
||||
}
|
||||
|
||||
fun checkSMAP(inputFiles: List<CodegenTestCase.TestFile>, outputFiles: Iterable<OutputFile>, separateCompilation: Boolean) {
|
||||
if (!GENERATE_SMAP) return
|
||||
@@ -71,15 +74,15 @@ object SMAPTestUtil {
|
||||
val compiledData = compiledSmaps.groupBy {
|
||||
it.sourceFile
|
||||
}.map {
|
||||
val smap = it.value.sortedByDescending { it.outputFile }.mapNotNull { it.smap }.joinToString("\n")
|
||||
val smap = it.value.sortedByDescending(SMAPAndFile::outputFile).mapNotNull(SMAPAndFile::smap).joinToString("\n")
|
||||
SMAPAndFile(if (smap.isNotEmpty()) smap else null, it.key, "NOT_SORTED")
|
||||
}.associateBy { it.sourceFile }
|
||||
|
||||
for (source in sourceData) {
|
||||
val ktFileName = "/" + source.sourceFile.
|
||||
replace(".smap-nonseparate-compilation", ".kt").
|
||||
replace(".smap-separate-compilation", ".kt").
|
||||
replace(".smap", ".kt")
|
||||
val ktFileName = "/" + source.sourceFile
|
||||
.replace(".smap-nonseparate-compilation", ".kt")
|
||||
.replace(".smap-separate-compilation", ".kt")
|
||||
.replace(".smap", ".kt")
|
||||
val data = compiledData[ktFileName]
|
||||
Assert.assertEquals("Smap data differs for $ktFileName", normalize(source.smap), normalize(data?.smap))
|
||||
}
|
||||
@@ -90,37 +93,32 @@ object SMAPTestUtil {
|
||||
private fun checkNoConflictMappings(compiledSmap: List<SMAPAndFile>?) {
|
||||
if (compiledSmap == null) return
|
||||
|
||||
compiledSmap.mapNotNull { it.smap }.forEach {
|
||||
val smap = SMAPParser.parse(it)
|
||||
val conflictingLines = smap.fileMappings.flatMap {
|
||||
fileMapping ->
|
||||
fileMapping.lineMappings.flatMap {
|
||||
lineMapping: RangeMapping ->
|
||||
compiledSmap.mapNotNull(SMAPAndFile::smap).forEach { smapString ->
|
||||
val smap = SMAPParser.parse(smapString)
|
||||
val conflictingLines = smap.fileMappings.flatMap { fileMapping ->
|
||||
fileMapping.lineMappings.flatMap { lineMapping: RangeMapping ->
|
||||
lineMapping.toRange.keysToMap { lineMapping }.entries
|
||||
}
|
||||
}.groupBy { it.key }.entries.filter { it.value.size != 1 }
|
||||
|
||||
|
||||
Assert.assertTrue(
|
||||
conflictingLines.joinToString(separator = "\n") {
|
||||
"Conflicting mapping for line ${it.key} in ${it.value.joinToString { it.toString() }} "
|
||||
},
|
||||
conflictingLines.isEmpty()
|
||||
conflictingLines.joinToString(separator = "\n") {
|
||||
"Conflicting mapping for line ${it.key} in ${it.value.joinToString(transform = Any::toString)}"
|
||||
},
|
||||
conflictingLines.isEmpty()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun normalize(text: String?) =
|
||||
text?.let { StringUtil.convertLineSeparators(it.trim()) }
|
||||
text?.let { StringUtil.convertLineSeparators(it.trim()) }
|
||||
|
||||
private class SMAPAndFile(val smap: String?, val sourceFile: String, val outputFile: String) {
|
||||
companion object {
|
||||
fun SMAPAndFile(smap: String?, sourceFile: File, outputFile: String) =
|
||||
SMAPAndFile(smap, getPath(sourceFile), outputFile)
|
||||
constructor(smap: String?, sourceFile: File, outputFile: String) : this(smap, getPath(sourceFile), outputFile)
|
||||
|
||||
fun getPath(file: File): String {
|
||||
return getPath(file.canonicalPath)
|
||||
}
|
||||
companion object {
|
||||
fun getPath(file: File): String =
|
||||
getPath(file.canonicalPath)
|
||||
|
||||
fun getPath(canonicalPath: String): String {
|
||||
//There are some problems with disk name on windows cause LightVirtualFile return it without disk name
|
||||
|
||||
+1
-1
@@ -20,6 +20,6 @@ import org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
|
||||
abstract class AbstractIrBlackBoxInlineCodegenTest: AbstractBlackBoxCodegenTest() {
|
||||
abstract class AbstractIrBlackBoxInlineCodegenTest : AbstractBlackBoxCodegenTest() {
|
||||
override fun updateConfiguration(configuration: CompilerConfiguration) = configuration.put(JVMConfigurationKeys.IR, true)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.utils.rethrow
|
||||
import java.lang.reflect.Method
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
|
||||
@@ -28,17 +25,13 @@ fun clearReflectionCache(classLoader: ClassLoader) {
|
||||
val klass = classLoader.loadClass(JvmAbi.REFLECTION_FACTORY_IMPL.asSingleFqName().asString())
|
||||
val method = klass.getDeclaredMethod("clearCaches")
|
||||
method.invoke(null)
|
||||
}
|
||||
catch (e: ClassNotFoundException) {
|
||||
} catch (e: ClassNotFoundException) {
|
||||
// This is OK for a test without kotlin-reflect in the dependencies
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun ClassLoader?.extractUrls(): List<URL> {
|
||||
return (this as? URLClassLoader)?.let {
|
||||
it.urLs.toList() + it.parent.extractUrls()
|
||||
} ?: emptyList()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContextOrStlib
|
||||
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
@@ -25,6 +24,7 @@ import kotlin.script.experimental.annotations.KotlinScript
|
||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||
import kotlin.script.experimental.api.implicitReceivers
|
||||
import kotlin.script.experimental.api.providedProperties
|
||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
||||
|
||||
abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
|
||||
private lateinit var scriptDefinitions: List<String>
|
||||
@@ -56,14 +56,14 @@ abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
|
||||
scriptDefinitions = InTextDirectivesUtils.findListWithPrefixes(content, "KOTLIN_SCRIPT_DEFINITION:")
|
||||
if (scriptDefinitions.isNotEmpty()) {
|
||||
additionalDependencies =
|
||||
scriptCompilationClasspathFromContextOrStlib("tests-common", "kotlin-stdlib") +
|
||||
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
|
||||
with(PathUtil.kotlinPathsForDistDirectory) {
|
||||
arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
|
||||
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
|
||||
).mapNotNull { File(libPath, it).takeIf { it.exists() } }
|
||||
}
|
||||
scriptCompilationClasspathFromContextOrStdlib("tests-common", "kotlin-stdlib") +
|
||||
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
|
||||
with(PathUtil.kotlinPathsForDistDirectory) {
|
||||
arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
|
||||
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
|
||||
).mapNotNull { File(libPath, it).takeIf(File::exists) }
|
||||
}
|
||||
}
|
||||
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(configurationKind, files, TestJdkKind.FULL_JDK)
|
||||
|
||||
@@ -71,7 +71,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(getDeprecatedAnnotationFromList(srcClassMethod.getParameterAnnotations()[0]));
|
||||
}
|
||||
|
||||
public void testAnnotationForParamInInstanceFunction() throws NoSuchFieldException, NoSuchMethodException {
|
||||
public void testAnnotationForParamInInstanceFunction() throws NoSuchMethodException {
|
||||
loadText("class A() { fun x(@[java.lang.Deprecated] i: Int) {}}");
|
||||
Class<?> aClass = generateClass("A");
|
||||
Method x = aClass.getMethod("x", int.class);
|
||||
@@ -81,7 +81,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
||||
}
|
||||
|
||||
public void testAnnotationForParamInInstanceExtensionFunction() throws NoSuchFieldException, NoSuchMethodException {
|
||||
public void testAnnotationForParamInInstanceExtensionFunction() throws NoSuchMethodException {
|
||||
loadText("class A() { fun String.x(@[java.lang.Deprecated] i: Int) {}}");
|
||||
Class<?> aClass = generateClass("A");
|
||||
Method x = aClass.getMethod("x", String.class, int.class);
|
||||
@@ -91,7 +91,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
||||
}
|
||||
|
||||
public void testParamInConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
||||
public void testParamInConstructor() throws NoSuchMethodException {
|
||||
loadText("class A (@[java.lang.Deprecated] x: Int) {}");
|
||||
Class<?> aClass = generateClass("A");
|
||||
Constructor constructor = aClass.getDeclaredConstructor(int.class);
|
||||
@@ -101,7 +101,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
||||
}
|
||||
|
||||
public void testParamInEnumConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
||||
public void testParamInEnumConstructor() throws NoSuchMethodException {
|
||||
loadText("enum class E(@[java.lang.Deprecated] p: String)");
|
||||
Class<?> klass = generateClass("E");
|
||||
Constructor constructor = klass.getDeclaredConstructor(String.class, int.class, String.class);
|
||||
@@ -111,7 +111,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
||||
}
|
||||
|
||||
public void testParamInInnerConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
||||
public void testParamInInnerConstructor() throws NoSuchMethodException {
|
||||
loadText("class Outer { inner class Inner(@[java.lang.Deprecated] x: Int) }");
|
||||
Class<?> outer = generateClass("Outer");
|
||||
Class<?> inner = outer.getDeclaredClasses()[0];
|
||||
@@ -134,7 +134,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
|
||||
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
||||
}
|
||||
|
||||
|
||||
public void testAnnotationWithParamForParamInFunction() throws Exception {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
|
||||
@@ -162,7 +162,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
||||
loadText("class A @[java.lang.Deprecated] constructor() {}");
|
||||
@@ -196,14 +196,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertEquals("java.lang.annotation.Annotation", interfaces[0].getName());
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithStringProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
public void testAnnotationClassWithStringProperty() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"" +
|
||||
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
|
||||
@@ -231,13 +224,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithAnnotationProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"" +
|
||||
"annotation class C(val c: String)\n" +
|
||||
@@ -270,13 +257,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithStringArrayProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"" +
|
||||
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<String>)\n" +
|
||||
@@ -301,18 +282,11 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(bClassAnnotation);
|
||||
|
||||
Object invoke = methods[0].invoke(bClassAnnotation);
|
||||
assertEquals("239", ((String[])invoke)[0]);
|
||||
assertEquals("932", ((String[])invoke)[1]);
|
||||
assertEquals("239", ((String[]) invoke)[0]);
|
||||
assertEquals("932", ((String[]) invoke)[1]);
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithIntArrayProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
public void testAnnotationClassWithIntArrayProperty() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"" +
|
||||
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: IntArray)\n" +
|
||||
@@ -337,18 +311,11 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(bClassAnnotation);
|
||||
|
||||
Object invoke = methods[0].invoke(bClassAnnotation);
|
||||
assertEquals(239, ((int[])invoke)[0]);
|
||||
assertEquals(932, ((int[])invoke)[1]);
|
||||
assertEquals(239, ((int[]) invoke)[0]);
|
||||
assertEquals(932, ((int[]) invoke)[1]);
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithEnumArrayProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
public void testAnnotationClassWithEnumArrayProperty() {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"" +
|
||||
"@java.lang.annotation.Target(ElementType.TYPE, ElementType.METHOD) annotation class A");
|
||||
@@ -363,13 +330,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testAnnotationClassWithAnnotationArrayProperty()
|
||||
throws
|
||||
NoSuchFieldException,
|
||||
NoSuchMethodException,
|
||||
ClassNotFoundException,
|
||||
IllegalAccessException,
|
||||
InstantiationException,
|
||||
InvocationTargetException {
|
||||
throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
loadText("import java.lang.annotation.*\n" +
|
||||
"import java.lang.annotation.Retention\n" +
|
||||
"" +
|
||||
@@ -388,7 +349,7 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
assertNotNull(bClassAnnotation);
|
||||
|
||||
Object invoke = methods[0].invoke(bClassAnnotation);
|
||||
Retention[] invoke1 = (Retention[])invoke;
|
||||
Retention[] invoke1 = (Retention[]) invoke;
|
||||
assertEquals(2, invoke1.length);
|
||||
assertEquals(invoke1[0].value(), RetentionPolicy.RUNTIME);
|
||||
assertEquals(invoke1[1].value(), RetentionPolicy.SOURCE);
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.backend.common.bridges.Bridge
|
||||
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
|
||||
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class BridgeTest : TestCase() {
|
||||
@@ -91,14 +90,14 @@ class BridgeTest : TestCase() {
|
||||
return result
|
||||
}
|
||||
|
||||
val vertices = edges.flatMapTo(HashSet<Fun>()) { pair -> listOf(pair.first, pair.second) }
|
||||
val vertices = edges.flatMapTo(HashSet()) { pair -> listOf(pair.first, pair.second) }
|
||||
|
||||
for (vertex in vertices) {
|
||||
val directConcreteSuperFunctions = vertex.overriddenFunctions.filter { !it.isAbstract }
|
||||
assert(directConcreteSuperFunctions.size <= 1) {
|
||||
"Incorrect test data: function $vertex has more than one direct concrete super-function: ${vertex.overriddenFunctions}\n" +
|
||||
"This is not allowed because only classes can contain implementations (concrete functions), and having more than one " +
|
||||
"concrete super-function means having more than one superclass, which is prohibited in Kotlin"
|
||||
"This is not allowed because only classes can contain implementations (concrete functions), and having more than " +
|
||||
"one concrete super-function means having more than one superclass, which is prohibited in Kotlin"
|
||||
}
|
||||
|
||||
if (vertex.isDeclaration) continue
|
||||
@@ -120,7 +119,7 @@ class BridgeTest : TestCase() {
|
||||
}
|
||||
assert(concreteDeclarations.size == 1) {
|
||||
"Incorrect test data: concrete fake override vertex $vertex has more than one concrete super-declaration: " +
|
||||
"$concreteDeclarations"
|
||||
"$concreteDeclarations"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,7 +129,7 @@ class BridgeTest : TestCase() {
|
||||
val actualBridges = generateBridges(function, ::Meth)
|
||||
assert(actualBridges.firstOrNull { it.from == it.to } == null) {
|
||||
"A bridge invoking itself was generated, which makes no sense, since it will result in StackOverflowError" +
|
||||
" once called: $actualBridges"
|
||||
" once called: $actualBridges"
|
||||
}
|
||||
assertEquals(expectedBridges, actualBridges, "Expected and actual bridge sets differ for function $function")
|
||||
}
|
||||
@@ -537,9 +536,11 @@ class BridgeTest : TestCase() {
|
||||
val h = v("-D8")
|
||||
val i = v("-D9")
|
||||
val j = v("+F0")
|
||||
graph(d to a, d to b, d to c,
|
||||
g to d, g to e, g to f,
|
||||
j to g, j to h, j to i)
|
||||
graph(
|
||||
d to a, d to b, d to c,
|
||||
g to d, g to e, g to f,
|
||||
j to g, j to h, j to i
|
||||
)
|
||||
doTest(d, setOf(bridge(b, a), bridge(c, a)))
|
||||
doTest(g, setOf(bridge(e, a), bridge(f, a)))
|
||||
doTest(j, setOf(bridge(h, a), bridge(i, a)))
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
||||
public void testCompareToNull() throws Exception {
|
||||
loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null && null == a && null !== b");
|
||||
String text = generateToText();
|
||||
assertTrue(!text.contains("java/lang/Object.equals"));
|
||||
assertFalse(text.contains("java/lang/Object.equals"));
|
||||
Method main = generateFunction();
|
||||
assertEquals(true, main.invoke(null, null, "lala"));
|
||||
assertEquals(false, main.invoke(null, null, null));
|
||||
|
||||
@@ -22,29 +22,35 @@ import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
class CustomBytecodeTextTest : AbstractBytecodeTextTest() {
|
||||
fun testEnumMapping() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL)
|
||||
myFiles = CodegenTestFiles.create("whenMappingOrder.kt", """
|
||||
enum class MyEnum {
|
||||
ENTRY1, ENTRY2, ENTRY3, ENTRY4
|
||||
}
|
||||
|
||||
fun f(e: MyEnum) {
|
||||
when (e) {
|
||||
MyEnum.ENTRY4 -> {}
|
||||
MyEnum.ENTRY3 -> {}
|
||||
MyEnum.ENTRY2 -> {}
|
||||
MyEnum.ENTRY1 -> {}
|
||||
myFiles = CodegenTestFiles.create(
|
||||
"whenMappingOrder.kt",
|
||||
"""
|
||||
enum class MyEnum {
|
||||
ENTRY1, ENTRY2, ENTRY3, ENTRY4
|
||||
}
|
||||
}
|
||||
""", myEnvironment.project)
|
||||
|
||||
fun f(e: MyEnum) {
|
||||
when (e) {
|
||||
MyEnum.ENTRY4 -> {}
|
||||
MyEnum.ENTRY3 -> {}
|
||||
MyEnum.ENTRY2 -> {}
|
||||
MyEnum.ENTRY1 -> {}
|
||||
}
|
||||
}
|
||||
""",
|
||||
myEnvironment.project
|
||||
)
|
||||
|
||||
val text = generateToText()
|
||||
val getstatics = text.lines().filter { it.contains("GETSTATIC MyEnum.") }.map { it.trim() }
|
||||
KtUsefulTestCase.assertOrderedEquals("actual bytecode:\n" + text, listOf(
|
||||
KtUsefulTestCase.assertOrderedEquals(
|
||||
"actual bytecode:\n$text", listOf(
|
||||
"GETSTATIC MyEnum.${'$'}VALUES : [LMyEnum;",
|
||||
"GETSTATIC MyEnum.ENTRY4 : LMyEnum;",
|
||||
"GETSTATIC MyEnum.ENTRY3 : LMyEnum;",
|
||||
"GETSTATIC MyEnum.ENTRY2 : LMyEnum;",
|
||||
"GETSTATIC MyEnum.ENTRY1 : LMyEnum;"
|
||||
), getstatics)
|
||||
), getstatics
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContextOrStlib
|
||||
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
@@ -19,9 +18,10 @@ import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_COMPILER_IMPL_JAR
|
||||
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR
|
||||
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_JVM_JAR
|
||||
import java.io.File
|
||||
import java.lang.reflect.Constructor
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.annotations.KotlinScript
|
||||
|
||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
||||
|
||||
class CustomScriptCodegenTest : CodegenTestCase() {
|
||||
|
||||
@@ -46,14 +46,14 @@ class CustomScriptCodegenTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
additionalDependencies =
|
||||
scriptCompilationClasspathFromContextOrStlib("tests-common", "kotlin-stdlib") +
|
||||
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
|
||||
with(PathUtil.kotlinPathsForDistDirectory) {
|
||||
arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
|
||||
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
|
||||
).mapNotNull { File(libPath, it).also { assertTrue("$it not found", it.exists()) } }
|
||||
}
|
||||
scriptCompilationClasspathFromContextOrStdlib("tests-common", "kotlin-stdlib") +
|
||||
File(TestScriptWithReceivers::class.java.protectionDomain.codeSource.location.toURI().path) +
|
||||
with(PathUtil.kotlinPathsForDistDirectory) {
|
||||
arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
|
||||
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
|
||||
).mapNotNull { jarName -> File(libPath, jarName).also { assertTrue("$it not found", it.exists()) } }
|
||||
}
|
||||
|
||||
val configuration = createConfiguration(
|
||||
ConfigurationKind.ALL,
|
||||
@@ -75,7 +75,6 @@ class CustomScriptCodegenTest : CodegenTestCase() {
|
||||
testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -83,7 +82,7 @@ private fun Class<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation?
|
||||
getAnnotation(classLoader.loadClass(ann.qualifiedName) as Class<Annotation>)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun java.lang.reflect.Constructor<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation? =
|
||||
private fun Constructor<*>.safeGetAnnotation(ann: KClass<out Annotation>): Annotation? =
|
||||
getAnnotation(this.declaringClass.classLoader.loadClass(ann.qualifiedName) as Class<Annotation>)
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@@ -96,6 +95,5 @@ annotation class MyScriptConstructorAnnotation
|
||||
|
||||
@Suppress("unused")
|
||||
@KotlinScript
|
||||
@MyScriptClassAnnotation()
|
||||
@MyScriptClassAnnotation
|
||||
abstract class TestScriptWithAnnotatedBaseClass @MyScriptConstructorAnnotation constructor()
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, disableCallAssertions);
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, disableParamAssertions);
|
||||
|
||||
myEnvironment = KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
myEnvironment =
|
||||
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
myFiles = null;
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
|
||||
doTestCallAssertions(true);
|
||||
}
|
||||
|
||||
public void testNoAssertionsForKotlinFromSource() throws Exception {
|
||||
public void testNoAssertionsForKotlinFromSource() {
|
||||
setUpEnvironment(false, true);
|
||||
|
||||
loadFiles(getPrefix() + "/noAssertionsForKotlin.kt", getPrefix() + "/noAssertionsForKotlinMain.kt");
|
||||
@@ -95,7 +96,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
|
||||
assertNoIntrinsicsMethodIsCalledInMyClasses(true);
|
||||
}
|
||||
|
||||
public void testNoAssertionsForKotlinFromBinary() throws Exception {
|
||||
public void testNoAssertionsForKotlinFromBinary() {
|
||||
setUpEnvironment(false, true);
|
||||
loadSource("noAssertionsForKotlin.kt");
|
||||
OutputFileCollection outputFiles = generateClassesInFile();
|
||||
@@ -116,7 +117,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
|
||||
generateFunction().invoke(null);
|
||||
}
|
||||
|
||||
public void testDoNotGenerateParamAssertions() throws Exception {
|
||||
public void testDoNotGenerateParamAssertions() {
|
||||
setUpEnvironment(true, true);
|
||||
|
||||
loadSource("doNotGenerateParamAssertions.kt");
|
||||
@@ -124,7 +125,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
|
||||
assertNoIntrinsicsMethodIsCalled("A", true);
|
||||
}
|
||||
|
||||
public void testNoParamAssertionForPrivateMethod() throws Exception {
|
||||
public void testNoParamAssertionForPrivateMethod() {
|
||||
setUpEnvironment(true, false);
|
||||
|
||||
loadSource("noAssertionForPrivateMethod.kt");
|
||||
|
||||
@@ -116,8 +116,6 @@ public class InnerClassInfoGenTest extends CodegenTestCase {
|
||||
extractAndCompareInnerClasses("A$bar$1", bar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void checkAccess(@NotNull String outerName, @NotNull String innerName, int accessFlags) {
|
||||
String name = outerName + "$" + innerName;
|
||||
InnerClassAttribute attribute = CollectionsKt.single(extractInnerClasses(name), value -> innerName.equals(value.innerName));
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit
|
||||
class Java9CodegenTest : AbstractBlackBoxCodegenTest() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
val fileName = KotlinTestUtils.getTestDataPathBase() + "/codegen/" + getPrefix() + "/" + getTestName(true) + ".kt"
|
||||
val fileName = KotlinTestUtils.getTestDataPathBase() + "/codegen/" + prefix + "/" + getTestName(true) + ".kt"
|
||||
val testFile = TestFile(fileName, File(fileName).readText())
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.NO_KOTLIN_REFLECT, listOf(testFile), TestJdkKind.FULL_JDK_9)
|
||||
}
|
||||
|
||||
+14
-2
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
@@ -32,7 +33,7 @@ import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_FQ_NAME
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_VERSION_FIELD_NAME;
|
||||
|
||||
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public static final FqName PACKAGE_NAME = new FqName("test");
|
||||
private static final FqName PACKAGE_NAME = new FqName("test");
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@@ -124,7 +125,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
List<OutputFile> output = generateClassesInFile().asList();
|
||||
Collection<OutputFile> files = CollectionsKt.filter(output, file -> file.getRelativePath().contains(classFilePart));
|
||||
assertFalse("No files with \"" + classFilePart + "\" in the name are found: " + output, files.isEmpty());
|
||||
assertTrue("Exactly one file with \"" + classFilePart + "\" in the name should be found: " + files, files.size() == 1);
|
||||
assertEquals("Exactly one file with \"" + classFilePart + "\" in the name should be found: " + files, 1, files.size());
|
||||
|
||||
String path = files.iterator().next().getRelativePath();
|
||||
String fqName = path.substring(0, path.length() - ".class".length()).replace('/', '.');
|
||||
@@ -144,4 +145,15 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
assertTrue("Annotation " + annotationFqName + " is written with an unsupported format",
|
||||
new JvmMetadataVersion(version).isCompatible());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Annotation> loadAnnotationClassQuietly(@NotNull String fqName) {
|
||||
try {
|
||||
return (Class<? extends Annotation>) initializedClassLoader.loadClass(fqName);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw ExceptionUtilsKt.rethrow(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,111 +24,126 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import java.util.*
|
||||
|
||||
class MethodOrderTest: CodegenTestCase() {
|
||||
class MethodOrderTest : CodegenTestCase() {
|
||||
fun testDelegatedMethod() {
|
||||
doTest(
|
||||
"""
|
||||
interface Trait {
|
||||
fun f0()
|
||||
fun f4()
|
||||
fun f3()
|
||||
fun f2()
|
||||
fun f1()
|
||||
fun f5()
|
||||
}
|
||||
"""
|
||||
interface Trait {
|
||||
fun f0()
|
||||
fun f4()
|
||||
fun f3()
|
||||
fun f2()
|
||||
fun f1()
|
||||
fun f5()
|
||||
}
|
||||
|
||||
val delegate: Trait = throw Error()
|
||||
val delegate: Trait = throw Error()
|
||||
|
||||
val obj = object : Trait by delegate {
|
||||
override fun f3() { }
|
||||
}
|
||||
""",
|
||||
"\$obj$1",
|
||||
listOf("f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
|
||||
val obj = object : Trait by delegate {
|
||||
override fun f3() { }
|
||||
}
|
||||
""",
|
||||
"\$obj$1",
|
||||
listOf("f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
|
||||
)
|
||||
}
|
||||
|
||||
fun testLambdaClosureOrdering() {
|
||||
doTest(
|
||||
"""
|
||||
class Klass {
|
||||
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
|
||||
{ a + b + c + d + e + this@f + this@Klass }()
|
||||
}
|
||||
"""
|
||||
class Klass {
|
||||
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
|
||||
{ a + b + c + d + e + this@f + this@Klass }()
|
||||
}
|
||||
""",
|
||||
"\$f$1",
|
||||
listOf("invoke()Ljava/lang/Object;", "invoke()Ljava/lang/String;", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
|
||||
}
|
||||
""",
|
||||
"\$f$1",
|
||||
listOf(
|
||||
"invoke()Ljava/lang/Object;",
|
||||
"invoke()Ljava/lang/String;",
|
||||
"<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun testAnonymousObjectClosureOrdering() {
|
||||
doTest(
|
||||
"""
|
||||
class Klass {
|
||||
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
a + b + c + d + e + this@f + this@Klass
|
||||
}
|
||||
}.run()
|
||||
}
|
||||
"""
|
||||
class Klass {
|
||||
fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) {
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
a + b + c + d + e + this@f + this@Klass
|
||||
}
|
||||
}.run()
|
||||
}
|
||||
""",
|
||||
"\$f$1",
|
||||
listOf("run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
|
||||
}
|
||||
""",
|
||||
"\$f$1",
|
||||
listOf("run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
|
||||
)
|
||||
}
|
||||
|
||||
fun testMemberAccessor() {
|
||||
doTest(
|
||||
"""
|
||||
class Outer(private val a: Int, private var b: String) {
|
||||
private fun c() {
|
||||
}
|
||||
"""
|
||||
class Outer(private val a: Int, private var b: String) {
|
||||
private fun c() {
|
||||
}
|
||||
|
||||
inner class Inner() {
|
||||
init {
|
||||
b = b + a
|
||||
c()
|
||||
}
|
||||
inner class Inner() {
|
||||
init {
|
||||
b = b + a
|
||||
c()
|
||||
}
|
||||
}
|
||||
""",
|
||||
"Outer",
|
||||
listOf(
|
||||
"c()V",
|
||||
"<init>(ILjava/lang/String;)V",
|
||||
"access\$getB\$p(LOuter;)Ljava/lang/String;",
|
||||
"access\$setB\$p(LOuter;Ljava/lang/String;)V",
|
||||
"access\$getA\$p(LOuter;)I",
|
||||
"access\$c(LOuter;)V"
|
||||
)
|
||||
}
|
||||
""",
|
||||
"Outer",
|
||||
listOf(
|
||||
"c()V",
|
||||
"<init>(ILjava/lang/String;)V",
|
||||
"access\$getB\$p(LOuter;)Ljava/lang/String;",
|
||||
"access\$setB\$p(LOuter;Ljava/lang/String;)V",
|
||||
"access\$getA\$p(LOuter;)I",
|
||||
"access\$c(LOuter;)V"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun testDeterministicDefaultMethodImplOrder() {
|
||||
doTest(
|
||||
"""
|
||||
interface Base<K, V> {
|
||||
fun getSize(): Int = 5
|
||||
fun size(): Int = getSize()
|
||||
fun getKeys(): Int = 4
|
||||
fun keySet() = getKeys()
|
||||
fun getEntries(): Int = 3
|
||||
fun entrySet() = getEntries()
|
||||
fun getValues(): Int = 2
|
||||
fun values() = getValues()
|
||||
"""
|
||||
interface Base<K, V> {
|
||||
fun getSize(): Int = 5
|
||||
fun size(): Int = getSize()
|
||||
fun getKeys(): Int = 4
|
||||
fun keySet() = getKeys()
|
||||
fun getEntries(): Int = 3
|
||||
fun entrySet() = getEntries()
|
||||
fun getValues(): Int = 2
|
||||
fun values() = getValues()
|
||||
|
||||
fun removeEldestEntry(eldest: Any?): Boolean
|
||||
}
|
||||
fun removeEldestEntry(eldest: Any?): Boolean
|
||||
}
|
||||
|
||||
class MinMap<K, V> : Base<K, V> {
|
||||
override fun removeEldestEntry(eldest: Any?) = true
|
||||
}
|
||||
""",
|
||||
"MinMap",
|
||||
listOf("removeEldestEntry(Ljava/lang/Object;)Z", "<init>()V", "getSize()I", "size()I", "getKeys()I", "keySet()I", "getEntries()I", "entrySet()I", "getValues()I", "values()I")
|
||||
class MinMap<K, V> : Base<K, V> {
|
||||
override fun removeEldestEntry(eldest: Any?) = true
|
||||
}
|
||||
""",
|
||||
"MinMap",
|
||||
listOf(
|
||||
"removeEldestEntry(Ljava/lang/Object;)Z",
|
||||
"<init>()V",
|
||||
"getSize()I",
|
||||
"size()I",
|
||||
"getKeys()I",
|
||||
"keySet()I",
|
||||
"getEntries()I",
|
||||
"entrySet()I",
|
||||
"getValues()I",
|
||||
"values()I"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -169,7 +184,13 @@ class MethodOrderTest: CodegenTestCase() {
|
||||
val methodNames = ArrayList<String>()
|
||||
|
||||
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
methodNames.add(name + desc)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -41,110 +41,110 @@ public class OuterClassGenTest extends CodegenTestCase {
|
||||
return "outerClassInfo";
|
||||
}
|
||||
|
||||
public void testClass() throws Exception {
|
||||
public void testClass() {
|
||||
doTest("foo.Foo", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testClassObject() throws Exception {
|
||||
public void testClassObject() {
|
||||
doTest("foo.Foo$" + SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString(), "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testInnerClass() throws Exception {
|
||||
public void testInnerClass() {
|
||||
doTest("foo.Foo$InnerClass", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testInnerObject() throws Exception {
|
||||
public void testInnerObject() {
|
||||
doTest("foo.Foo$InnerObject", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLocalClassInFunction() throws Exception {
|
||||
public void testLocalClassInFunction() {
|
||||
doTest("foo.Foo$foo$LocalClass", "foo.Foo$1LocalClass", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLocalObjectInFunction() throws Exception {
|
||||
public void testLocalObjectInFunction() {
|
||||
doTest("foo.Foo$foo$LocalObject", "foo.Foo$1LocalObject", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testObjectInPackageClass() throws Exception {
|
||||
public void testObjectInPackageClass() {
|
||||
doTest("foo.PackageInnerObject", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLambdaInNoInlineFun() throws Exception {
|
||||
public void testLambdaInNoInlineFun() {
|
||||
doTest("foo.Foo$foo$1", "foo.Foo$1Lambda", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLambdaInConstructor() throws Exception {
|
||||
public void testLambdaInConstructor() {
|
||||
doTest("foo.Foo$s$1", "foo.Foo$1LambdaInConstructor", "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testObjectLiteralInPackageClass() throws Exception {
|
||||
public void testObjectLiteralInPackageClass() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", null, null);
|
||||
doCustomTest("foo/OuterClassInfoKt\\$packageObjectLiteral\\$1", expectedInfo, "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLocalClassInTopLevelFunction() throws Exception {
|
||||
public void testLocalClassInTopLevelFunction() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", "packageMethod", "(Lfoo/Foo;)V");
|
||||
doCustomTest("foo/OuterClassInfoKt\\$packageMethod\\$PackageLocalClass", expectedInfo, "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLocalObjectInTopLevelFunction() throws Exception {
|
||||
public void testLocalObjectInTopLevelFunction() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/OuterClassInfo", "packageMethod", "(Lfoo/Foo;)V");
|
||||
doCustomTest("foo/OuterClassInfoKt\\$packageMethod\\$PackageLocalObject", expectedInfo, "outerClassInfo");
|
||||
}
|
||||
|
||||
public void testLocalObjectInInlineFunction() throws Exception {
|
||||
public void testLocalObjectInInlineFunction() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/jvm/functions/Function0;)V");
|
||||
doCustomTest("foo/Foo\\$inlineFoo\\$localObject\\$1", expectedInfo, "inlineObject");
|
||||
}
|
||||
|
||||
public void testLocalObjectInlined() throws Exception {
|
||||
public void testLocalObjectInlined() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "callToInline", "()V");
|
||||
doCustomTest("foo/Bar\\$callToInline\\$\\$inlined\\$inlineFoo\\$1", expectedInfo, "inlineObject");
|
||||
}
|
||||
|
||||
public void testLocalObjectInInlineLambda() throws Exception {
|
||||
public void testLocalObjectInInlineLambda() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "objectInInlineLambda", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInInlineLambda\\$\\$inlined\\$simpleFoo\\$lambda\\$1", expectedInfo, "inlineObject");
|
||||
}
|
||||
|
||||
public void testLocalObjectInLambdaInlinedIntoObject() throws Exception {
|
||||
public void testLocalObjectInLambdaInlinedIntoObject() {
|
||||
OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", "objectInLambdaInlinedIntoObject", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineObject");
|
||||
}
|
||||
|
||||
public void testLocalObjectInLambdaInlinedIntoObject2() throws Exception {
|
||||
public void testLocalObjectInLambdaInlinedIntoObject2() {
|
||||
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "run", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
|
||||
objectInLambda, "inlineObject");
|
||||
}
|
||||
|
||||
public void testLambdaInInlineFunction() throws Exception {
|
||||
public void testLambdaInInlineFunction() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/jvm/functions/Function0;)V");
|
||||
doCustomTest("foo/Foo\\$inlineFoo\\$1", expectedInfo, "inlineLambda");
|
||||
}
|
||||
|
||||
public void testLambdaInlined() throws Exception {
|
||||
public void testLambdaInlined() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "callToInline", "()V");
|
||||
doCustomTest("foo/Bar\\$callToInline\\$\\$inlined\\$inlineFoo\\$1", expectedInfo, "inlineLambda");
|
||||
}
|
||||
|
||||
public void testLambdaInInlineLambda() throws Exception {
|
||||
public void testLambdaInInlineLambda() {
|
||||
OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", "objectInInlineLambda", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInInlineLambda\\$\\$inlined\\$simpleFoo\\$lambda\\$1", expectedInfo, "inlineLambda");
|
||||
}
|
||||
|
||||
public void testLambdaInLambdaInlinedIntoObject() throws Exception {
|
||||
public void testLambdaInLambdaInlinedIntoObject() {
|
||||
OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", "objectInLambdaInlinedIntoObject", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineLambda");
|
||||
}
|
||||
|
||||
public void testLambdaInLambdaInlinedIntoObject2() throws Exception {
|
||||
public void testLambdaInLambdaInlinedIntoObject2() {
|
||||
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "invoke", "()V");
|
||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
|
||||
objectInLambda, "inlineLambda");
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String classFqName, @NotNull String testDataFile) throws Exception {
|
||||
private void doTest(@NotNull String classFqName, @NotNull String testDataFile) {
|
||||
doTest(classFqName, classFqName, testDataFile);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class OuterClassGenTest extends CodegenTestCase {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String classFqName, @NotNull String javaClassName, @NotNull String testDataFile) throws Exception {
|
||||
private void doTest(@NotNull String classFqName, @NotNull String javaClassName, @NotNull String testDataFile) {
|
||||
File javaOut = CodegenTestUtil.compileJava(
|
||||
Collections.singletonList(KotlinTestUtils.getTestDataPathBase() + "/codegen/" + getPrefix() + "/" + testDataFile + ".java"),
|
||||
Collections.emptyList(),
|
||||
@@ -176,14 +176,10 @@ public class OuterClassGenTest extends CodegenTestCase {
|
||||
) {
|
||||
ClassReader kotlinReader = getKotlinClassReader(internalNameRegexp, testDataFile);
|
||||
OuterClassInfo kotlinInfo = readOuterClassInfo(kotlinReader);
|
||||
assertNotNull(kotlinInfo);
|
||||
String message = "Error in enclosingMethodInfo info for class: " + kotlinReader.getClassName();
|
||||
if (kotlinInfo == null) {
|
||||
assertNull(expectedInfo.getOwner());
|
||||
}
|
||||
else {
|
||||
assertTrue(message + "\n" + kotlinInfo.getOwner() + " doesn't start with " + expectedInfo.getOwner(),
|
||||
kotlinInfo.getOwner().startsWith(expectedInfo.getOwner()));
|
||||
}
|
||||
assertTrue(message + "\n" + kotlinInfo.getOwner() + " doesn't start with " + expectedInfo.getOwner(),
|
||||
kotlinInfo.getOwner().startsWith(expectedInfo.getOwner()));
|
||||
assertEquals(message, expectedInfo.getMethodName(), kotlinInfo.getMethodName());
|
||||
assertEquals(message, expectedInfo.getMethodDesc(), kotlinInfo.getMethodDesc());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
data class OuterClassInfo(
|
||||
val owner: String,
|
||||
val methodName: String?,
|
||||
val methodDesc: String?
|
||||
val owner: String,
|
||||
val methodName: String?,
|
||||
val methodDesc: String?
|
||||
)
|
||||
|
||||
@@ -171,6 +171,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
assertEquals("beer", result.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringOperationCanBeSimplified")
|
||||
public void testJavaEquals() throws Exception {
|
||||
loadText("fun foo(s1: String, s2: String) = s1 == s2");
|
||||
Method main = generateFunction();
|
||||
@@ -178,6 +179,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
assertEquals(Boolean.FALSE, main.invoke(null, new String("kotlin"), new String("ceylon")));
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringOperationCanBeSimplified")
|
||||
public void testJavaNotEquals() throws Exception {
|
||||
loadText("fun foo(s1: String, s2: String) = s1 != s2");
|
||||
Method main = generateFunction();
|
||||
@@ -200,6 +202,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
assertEquals(Boolean.FALSE, main.invoke(null, "kotlin"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringOperationCanBeSimplified")
|
||||
public void testTripleEq() throws Exception {
|
||||
loadText("fun foo(s1: String?, s2: String?) = s1 === s2");
|
||||
Method main = generateFunction();
|
||||
@@ -209,6 +212,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
assertEquals(Boolean.FALSE, main.invoke(null, s1, s2));
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringOperationCanBeSimplified")
|
||||
public void testTripleNotEq() throws Exception {
|
||||
loadText("fun foo(s1: String?, s2: String?) = s1 !== s2");
|
||||
Method main = generateFunction();
|
||||
@@ -301,7 +305,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
assertEquals(610, c.gridx);
|
||||
}
|
||||
|
||||
public void testIncrementAsLastOperation() throws Exception {
|
||||
public void testIncrementAsLastOperation() {
|
||||
loadText("fun foo() { var a = 0; a++; }");
|
||||
generateFunction(); // make sure we're not falling off end of code
|
||||
}
|
||||
@@ -440,7 +444,7 @@ public class PackageGenTest extends CodegenTestCase {
|
||||
public void testExplicitCallOfBooleanNotIntrinsic() throws Exception {
|
||||
loadText("fun foo(a: Boolean) = a.not()");
|
||||
Method main = generateFunction();
|
||||
assertEquals(false, ((Boolean) main.invoke(null, true)).booleanValue());
|
||||
assertFalse(((Boolean) main.invoke(null, true)).booleanValue());
|
||||
}
|
||||
|
||||
public void testAppendArrayToString() throws Exception {
|
||||
|
||||
@@ -89,22 +89,22 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
|
||||
public void testShort() throws Exception {
|
||||
binOpTest("fun foo(a: Short, b: Short): Int = a + b",
|
||||
Short.valueOf((short) 32767), Short.valueOf((short) 32767), 65534);
|
||||
Short.valueOf((short) 32767), Short.valueOf((short) 32767), 65534);
|
||||
}
|
||||
|
||||
public void testShortCmp() throws Exception {
|
||||
binOpTest("fun foo(a: Short, b: Short): Boolean = a == b",
|
||||
Short.valueOf((short) 32767), Short.valueOf((short) 32767), true);
|
||||
Short.valueOf((short) 32767), Short.valueOf((short) 32767), true);
|
||||
}
|
||||
|
||||
public void testByte() throws Exception {
|
||||
binOpTest("fun foo(a: Byte, b: Byte): Int = a + b",
|
||||
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 254);
|
||||
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 254);
|
||||
}
|
||||
|
||||
public void testByteCmp() throws Exception {
|
||||
binOpTest("fun foo(a: Byte, b: Byte): Int = if (a == b) 1 else 0",
|
||||
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 1);
|
||||
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 1);
|
||||
}
|
||||
|
||||
public void testByteLess() throws Exception {
|
||||
|
||||
@@ -39,18 +39,18 @@ class ReflectionClassLoaderTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
fun testSimpleDifferentClassLoaders() {
|
||||
loadFile(prefix + "/differentClassLoaders.kt")
|
||||
loadFile("$prefix/differentClassLoaders.kt")
|
||||
|
||||
doTest(
|
||||
createClassLoader(),
|
||||
createClassLoader()
|
||||
createClassLoader(),
|
||||
createClassLoader()
|
||||
)
|
||||
}
|
||||
|
||||
fun testClassLoaderWithNonTrivialEqualsAndHashCode() {
|
||||
// Check that class loaders do not participate as keys in hash maps (use identity hash maps instead)
|
||||
|
||||
loadFile(prefix + "/differentClassLoaders.kt")
|
||||
loadFile("$prefix/differentClassLoaders.kt")
|
||||
|
||||
class BrokenEqualsClassLoader(parent: ClassLoader) : ClassLoader(parent) {
|
||||
override fun equals(other: Any?) = true
|
||||
@@ -58,23 +58,23 @@ class ReflectionClassLoaderTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
doTest(
|
||||
BrokenEqualsClassLoader(createClassLoader()),
|
||||
BrokenEqualsClassLoader(createClassLoader())
|
||||
BrokenEqualsClassLoader(createClassLoader()),
|
||||
BrokenEqualsClassLoader(createClassLoader())
|
||||
)
|
||||
}
|
||||
|
||||
fun testParentFirst() {
|
||||
// Check that for a child class loader, a class reference would be the same as for his parent
|
||||
|
||||
loadFile(prefix + "/parentFirst.kt")
|
||||
loadFile("$prefix/parentFirst.kt")
|
||||
|
||||
class ChildClassLoader(parent: ClassLoader) : ClassLoader(parent)
|
||||
|
||||
val parent = createClassLoader()
|
||||
|
||||
doTest(
|
||||
parent,
|
||||
ChildClassLoader(parent)
|
||||
parent,
|
||||
ChildClassLoader(parent)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,16 +46,16 @@ class ScriptGenTest : CodegenTestCase() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
additionalDependencies =
|
||||
System.getenv("PROJECT_CLASSES_DIRS")?.split(File.pathSeparator)?.map { File(it) }
|
||||
System.getenv("PROJECT_CLASSES_DIRS")?.split(File.pathSeparator)?.map { File(it) }
|
||||
?: listOf(
|
||||
"compiler/build/classes/kotlin/test",
|
||||
"build/compiler/classes/kotlin/test",
|
||||
"out/test/compiler.test",
|
||||
"out/test/compiler_test"
|
||||
)
|
||||
.mapNotNull { File(it).canonicalFile.takeIf { it.isDirectory } }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: throw IllegalStateException("Unable to get classes output dirs, set PROJECT_CLASSES_DIRS environment variable")
|
||||
.mapNotNull { File(it).canonicalFile.takeIf(File::isDirectory) }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: throw IllegalStateException("Unable to get classes output dirs, set PROJECT_CLASSES_DIRS environment variable")
|
||||
}
|
||||
|
||||
fun testLanguage() {
|
||||
@@ -136,7 +136,9 @@ class ScriptGenTest : CodegenTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@ScriptTemplateDefinition(
|
||||
scriptFilePattern =".*\\.lang\\.kts",
|
||||
resolver = TestKotlinScriptDependenciesResolver::class)
|
||||
scriptFilePattern = ".*\\.lang\\.kts",
|
||||
resolver = TestKotlinScriptDependenciesResolver::class
|
||||
)
|
||||
abstract class ScriptWithIntParam(val num: Int)
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
public class SourceInfoGenTest extends CodegenTestCase {
|
||||
|
||||
private static final String TEST_FOLDER = "sourceInfo/";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -50,7 +51,6 @@ public class SourceInfoGenTest extends CodegenTestCase {
|
||||
public void visitSource(String source, String debug) {
|
||||
producer[0] = source;
|
||||
}
|
||||
|
||||
}, 0);
|
||||
return producer[0];
|
||||
}
|
||||
|
||||
@@ -23,11 +23,13 @@ import java.io.FileInputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
class TestStdlibWithDxTest {
|
||||
@Test fun testRuntimeWithDx() {
|
||||
@Test
|
||||
fun testRuntimeWithDx() {
|
||||
doTest(ForTestCompileRuntime.runtimeJarForTests())
|
||||
}
|
||||
|
||||
@Test fun testReflectWithDx() {
|
||||
@Test
|
||||
fun testReflectWithDx() {
|
||||
doTest(ForTestCompileRuntime.reflectJarForTests())
|
||||
}
|
||||
|
||||
|
||||
@@ -34,56 +34,56 @@ public class VarArgTest extends CodegenTestCase {
|
||||
loadText("fun test(vararg ts: String) = ts");
|
||||
Method main = generateFunction();
|
||||
String[] args = {"mama", "papa"};
|
||||
assertTrue(args == main.invoke(null, new Object[]{ args } ));
|
||||
assertSame(args, main.invoke(null, new Object[] {args}));
|
||||
}
|
||||
|
||||
public void testIntArray() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test(vararg ts: Int) = ts");
|
||||
Method main = generateFunction();
|
||||
int[] args = {3, 4};
|
||||
assertTrue(args == main.invoke(null, new Object[]{ args }));
|
||||
assertSame(args, main.invoke(null, new Object[] {args}));
|
||||
}
|
||||
|
||||
public void testIntArrayKotlinNoArgs() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(); fun testf(vararg ts: Int) = ts");
|
||||
Method main = generateFunction("test");
|
||||
Object res = main.invoke(null);
|
||||
assertTrue(((int[])res).length == 0);
|
||||
assertEquals(0, ((int[]) res).length);
|
||||
}
|
||||
|
||||
public void testIntArrayKotlin() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(239, 7); fun testf(vararg ts: Int) = ts");
|
||||
Method main = generateFunction("test");
|
||||
Object res = main.invoke(null);
|
||||
assertTrue(((int[])res).length == 2);
|
||||
assertTrue(((int[])res)[0] == 239);
|
||||
assertTrue(((int[])res)[1] == 7);
|
||||
assertEquals(2, ((int[]) res).length);
|
||||
assertEquals(239, ((int[]) res)[0]);
|
||||
assertEquals(7, ((int[]) res)[1]);
|
||||
}
|
||||
|
||||
public void testNullableIntArrayKotlin() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(239.toByte(), 7.toByte()); fun testf(vararg ts: Byte?) = ts");
|
||||
Method main = generateFunction("test");
|
||||
Object res = main.invoke(null);
|
||||
assertTrue(((Byte[])res).length == 2);
|
||||
assertTrue(((Byte[])res)[0] == (byte)239);
|
||||
assertTrue(((Byte[])res)[1] == 7);
|
||||
assertEquals(2, ((Byte[]) res).length);
|
||||
assertEquals((byte) ((Byte[]) res)[0], (byte) 239);
|
||||
assertEquals(7, (byte) ((Byte[]) res)[1]);
|
||||
}
|
||||
|
||||
public void testIntArrayKotlinObj() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(\"239\"); fun testf(vararg ts: String) = ts");
|
||||
Method main = generateFunction("test");
|
||||
Object res = main.invoke(null);
|
||||
assertTrue(((String[])res).length == 1);
|
||||
assertTrue(((String[])res)[0].equals("239"));
|
||||
assertEquals(1, ((String[]) res).length);
|
||||
assertEquals("239", ((String[]) res)[0]);
|
||||
}
|
||||
|
||||
public void testArrayT() throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = _array(2, 4); fun <T> _array(vararg elements : T) = elements");
|
||||
Method main = generateFunction("test");
|
||||
Object res = main.invoke(null);
|
||||
assertTrue(((Integer[])res).length == 2);
|
||||
assertTrue(((Integer[])res)[0].equals(2));
|
||||
assertTrue(((Integer[])res)[1].equals(4));
|
||||
assertEquals(2, ((Integer[]) res).length);
|
||||
assertEquals(2, (int) ((Integer[]) res)[0]);
|
||||
assertEquals(4, (int) ((Integer[]) res)[1]);
|
||||
}
|
||||
|
||||
public void testArrayAsVararg() throws InvocationTargetException, IllegalAccessException {
|
||||
@@ -91,7 +91,7 @@ public class VarArgTest extends CodegenTestCase {
|
||||
Method main = generateFunction("test");
|
||||
String[] args = {"mama", "papa"};
|
||||
String[] result = (String []) main.invoke(null, new Object[] {args});
|
||||
assertTrue(args != result);
|
||||
assertNotSame(args, result);
|
||||
assertTrue(Arrays.equals(args, result));
|
||||
}
|
||||
|
||||
|
||||
+16
-27
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.parcel
|
||||
@@ -37,11 +26,11 @@ import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class AbstractParcelBoxTest : CodegenTestCase() {
|
||||
protected companion object {
|
||||
val BASE_DIR = "plugins/android-extensions/android-extensions-compiler/testData/parcel/box"
|
||||
const val BASE_DIR = "plugins/android-extensions/android-extensions-compiler/testData/parcel/box"
|
||||
val LIBRARY_KT = File(File(BASE_DIR).parentFile, "boxLib.kt")
|
||||
|
||||
private val JUNIT_GENERATED_TEST_CLASS_BYTES by lazy { constructSyntheticTestClass() }
|
||||
private val JUNIT_GENERATED_TEST_CLASS_FQNAME = "test.JunitTest"
|
||||
private const val JUNIT_GENERATED_TEST_CLASS_FQNAME = "test.JunitTest"
|
||||
|
||||
private fun constructSyntheticTestClass(): ByteArray {
|
||||
return with(ClassWriter(COMPUTE_MAXS or COMPUTE_FRAMES)) {
|
||||
@@ -104,12 +93,12 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
|
||||
}
|
||||
|
||||
override fun doTest(filePath: String) {
|
||||
super.doTest(File(BASE_DIR, filePath + ".kt").absolutePath)
|
||||
super.doTest(File(BASE_DIR, "$filePath.kt").absolutePath)
|
||||
}
|
||||
|
||||
private val androidPluginPath: String by lazy {
|
||||
System.getProperty("ideaSdk.androidPlugin.path")?.takeIf { File(it).isDirectory }
|
||||
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
|
||||
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
|
||||
}
|
||||
|
||||
private fun getClasspathForTest(): List<File> {
|
||||
@@ -117,10 +106,10 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
|
||||
val layoutLibJars = listOf(File(androidPluginPath, "layoutlib.jar"), File(androidPluginPath, "layoutlib-api.jar"))
|
||||
|
||||
val robolectricClasspath = System.getProperty("robolectric.classpath")
|
||||
?: throw RuntimeException("Unable to get a valid classpath from 'robolectric.classpath' property, please set it accordingly")
|
||||
?: throw RuntimeException("Unable to get a valid classpath from 'robolectric.classpath' property, please set it accordingly")
|
||||
val robolectricJars = robolectricClasspath.split(File.pathSeparator)
|
||||
.map { File(it) }
|
||||
.sortedBy { it.nameWithoutExtension }
|
||||
.map { File(it) }
|
||||
.sortedBy { it.nameWithoutExtension }
|
||||
|
||||
val junitCoreResourceName = JUnitCore::class.java.name.replace('.', '/') + ".class"
|
||||
val junitJar = File(JUnitCore::class.java.classLoader.getResource(junitCoreResourceName).file.substringBeforeLast('!'))
|
||||
@@ -151,12 +140,12 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
|
||||
classFileFactory.getClassFiles().forEach { writeClass(it.relativePath, it.asByteArray()) }
|
||||
|
||||
val process = ProcessBuilder(
|
||||
javaExe.absolutePath,
|
||||
"-ea",
|
||||
"-classpath",
|
||||
(libraryClasspath + dirForTestClasses).joinToString(File.pathSeparator),
|
||||
JUnitCore::class.java.name,
|
||||
JUNIT_GENERATED_TEST_CLASS_FQNAME
|
||||
javaExe.absolutePath,
|
||||
"-ea",
|
||||
"-classpath",
|
||||
(libraryClasspath + dirForTestClasses).joinToString(File.pathSeparator),
|
||||
JUnitCore::class.java.name,
|
||||
JUNIT_GENERATED_TEST_CLASS_FQNAME
|
||||
).inheritIO().start()
|
||||
|
||||
process.waitFor(3, TimeUnit.MINUTES)
|
||||
@@ -175,4 +164,4 @@ abstract class AbstractParcelBoxTest : CodegenTestCase() {
|
||||
addAndroidExtensionsRuntimeLibrary(environment)
|
||||
environment.updateClasspath(listOf(JvmClasspathRoot(File(androidPluginPath, "layoutlib.jar"))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-15
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.parcel
|
||||
@@ -28,7 +17,9 @@ abstract class AbstractParcelBytecodeListingTest : AbstractAsmLikeInstructionLis
|
||||
AndroidComponentRegistrar.registerParcelExtensions(environment.project)
|
||||
addAndroidExtensionsRuntimeLibrary(environment)
|
||||
val androidPluginPath = System.getProperty("ideaSdk.androidPlugin.path")?.takeIf { File(it).isDirectory }
|
||||
?: throw RuntimeException("Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location")
|
||||
?: throw RuntimeException(
|
||||
"Unable to get a valid path from 'ideaSdk.androidPlugin.path' property, please point it to the Idea android plugin location"
|
||||
)
|
||||
environment.updateClasspath(listOf(JvmClasspathRoot(File(androidPluginPath, "layoutlib.jar"))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-36
@@ -1,24 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.test
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.util.ArrayUtil
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
import org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles
|
||||
@@ -28,7 +16,6 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
|
||||
@@ -42,7 +29,9 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
|
||||
}
|
||||
|
||||
private fun createEnvironmentForConfiguration(configuration: CompilerConfiguration, path: String) {
|
||||
val layoutPaths = File(path).listFiles { it -> it.name.startsWith("layout") && it.isDirectory }!!.map { "$path${it.name}/" }
|
||||
val layoutPaths = File(path)
|
||||
.listFiles { file -> file.name.startsWith("layout") && file.isDirectory }!!
|
||||
.map { "$path${it.name}/" }
|
||||
myEnvironment = createTestEnvironment(configuration, layoutPaths)
|
||||
}
|
||||
|
||||
@@ -63,11 +52,12 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
|
||||
}
|
||||
|
||||
private fun getFakeFiles(path: String): Collection<String> {
|
||||
return FileUtil.findFilesByMask(Pattern.compile("^Fake.*\\.kt$"), File(path.replace(getTestName(true), ""))).map { relativePath(it) }
|
||||
return FileUtil.findFilesByMask(Pattern.compile("^Fake.*\\.kt$"), File(path.replace(getTestName(true), "")))
|
||||
.map { relativePath(it) }
|
||||
}
|
||||
|
||||
private fun needsInvocationTest(path: String): Boolean {
|
||||
return !FileUtil.findFilesByMask(Pattern.compile("^0.kt$"), File(path)).isEmpty()
|
||||
return FileUtil.findFilesByMask(Pattern.compile("^0.kt$"), File(path)).isNotEmpty()
|
||||
}
|
||||
|
||||
override fun codegenTestBasePath(): String {
|
||||
@@ -76,35 +66,33 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() {
|
||||
|
||||
private fun doMultiFileTest(path: String, additionalFiles: Collection<String>? = null) {
|
||||
val files = mutableListOf<String>()
|
||||
FileUtil.processFilesRecursively(File(path), object : Processor<File> {
|
||||
override fun process(file: File?): Boolean {
|
||||
when (file!!.name) {
|
||||
"1.kt" -> {
|
||||
if (additionalFiles == null) files.add(relativePath(file))
|
||||
}
|
||||
"0.kt" -> {
|
||||
if (additionalFiles != null) files.add(relativePath(file))
|
||||
}
|
||||
else -> {
|
||||
if (file.name.endsWith(".kt")) files.add(relativePath(file))
|
||||
}
|
||||
FileUtil.processFilesRecursively(File(path)) { file ->
|
||||
when (file!!.name) {
|
||||
"1.kt" -> {
|
||||
if (additionalFiles == null) files.add(relativePath(file))
|
||||
}
|
||||
"0.kt" -> {
|
||||
if (additionalFiles != null) files.add(relativePath(file))
|
||||
}
|
||||
else -> {
|
||||
if (file.name.endsWith(".kt")) files.add(relativePath(file))
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
true
|
||||
}
|
||||
|
||||
for (file in File("plugins/android-extensions/android-extensions-runtime/src").walk()) {
|
||||
if (file.extension == "kt") files += relativePath(file.absoluteFile)
|
||||
}
|
||||
|
||||
Collections.sort(files)
|
||||
files.sort()
|
||||
if (additionalFiles != null) {
|
||||
files.addAll(additionalFiles)
|
||||
}
|
||||
myFiles = CodegenTestFiles.create(
|
||||
myEnvironment!!.project,
|
||||
ArrayUtil.toStringArray(files),
|
||||
KotlinTestUtils.getHomeDirectory() + "/plugins/android-extensions/android-extensions-compiler/testData"
|
||||
myEnvironment!!.project,
|
||||
ArrayUtil.toStringArray(files),
|
||||
KotlinTestUtils.getHomeDirectory() + "/plugins/android-extensions/android-extensions-compiler/testData"
|
||||
)
|
||||
blackBox(true)
|
||||
}
|
||||
|
||||
+10
-21
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.test
|
||||
@@ -41,20 +30,20 @@ abstract class AbstractAndroidSyntheticPropertyDescriptorTest : KtUsefulTestCase
|
||||
val analysisResult = JvmResolveUtil.analyzeAndCheckForErrors(listOf(), env)
|
||||
|
||||
val fragmentProvider =
|
||||
ext.getPackageFragmentProvider(
|
||||
project, analysisResult.moduleDescriptor, LockBasedStorageManager.NO_LOCKS,
|
||||
KotlinTestUtils.DUMMY_EXCEPTION_ON_ERROR_TRACE, null, LookupTracker.DO_NOTHING
|
||||
) as AndroidSyntheticPackageFragmentProvider
|
||||
ext.getPackageFragmentProvider(
|
||||
project, analysisResult.moduleDescriptor, LockBasedStorageManager.NO_LOCKS,
|
||||
KotlinTestUtils.DUMMY_EXCEPTION_ON_ERROR_TRACE, null, LookupTracker.DO_NOTHING
|
||||
) as AndroidSyntheticPackageFragmentProvider
|
||||
|
||||
val renderer = DescriptorRenderer.COMPACT_WITH_MODIFIERS
|
||||
val expected = fragmentProvider.packages.values
|
||||
.map { it() }
|
||||
.sortedBy { it.fqName.asString() }
|
||||
.joinToString(separator = "\n\n\n") {
|
||||
val descriptors = it.getMemberScope().getContributedDescriptors()
|
||||
.joinToString(separator = "\n\n\n") { packageFragment ->
|
||||
val descriptors = packageFragment.getMemberScope().getContributedDescriptors()
|
||||
.sortedWith(MemberComparator.INSTANCE)
|
||||
.map { " " + renderer.render(it) }.joinToString("\n")
|
||||
it.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
|
||||
.joinToString("\n") { " " + renderer.render(it) }
|
||||
packageFragment.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
|
||||
}
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(File(path, "result.txt"), expected)
|
||||
|
||||
+9
-18
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.test
|
||||
@@ -35,8 +24,6 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
|
||||
@@ -52,7 +39,9 @@ fun KtUsefulTestCase.createTestEnvironment(configuration: CompilerConfiguration,
|
||||
|
||||
ExpressionCodegenExtension.registerExtension(project, CliAndroidExtensionsExpressionCodegenExtension(true, CacheImplementation.DEFAULT))
|
||||
StorageComponentContainerContributor.registerExtension(project, AndroidExtensionPropertiesComponentContainerContributor())
|
||||
ClassBuilderInterceptorExtension.registerExtension(project, CliAndroidOnDestroyClassBuilderInterceptorExtension(CacheImplementation.DEFAULT))
|
||||
ClassBuilderInterceptorExtension.registerExtension(
|
||||
project, CliAndroidOnDestroyClassBuilderInterceptorExtension(CacheImplementation.DEFAULT)
|
||||
)
|
||||
PackageFragmentProviderExtension.registerExtension(project, CliAndroidPackageFragmentProviderExtension(true))
|
||||
|
||||
addAndroidExtensionsRuntimeLibrary(myEnvironment)
|
||||
@@ -68,5 +57,7 @@ fun addAndroidExtensionsRuntimeLibrary(environment: KotlinCoreEnvironment) {
|
||||
}
|
||||
|
||||
fun getResPaths(path: String): List<String> {
|
||||
return File(path).listFiles { it -> it.name.startsWith("res") && it.isDirectory }!!.map { "$path${it.name}/" }
|
||||
}
|
||||
return File(path)
|
||||
.listFiles { file -> file.name.startsWith("res") && file.isDirectory }!!
|
||||
.map { "$path${it.name}/" }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user