javac-wrapper: refactoring, fixes and tests

This commit is contained in:
baratynskiy
2017-06-27 17:24:10 +03:00
committed by Alexander Baratynskiy
parent 8494e54608
commit 01883a41cb
382 changed files with 42897 additions and 688 deletions
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.common.DefaultAnalyzerFacade
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.SimpleGlobalContext
@@ -72,6 +69,7 @@ import org.junit.Assert
import java.io.File
import java.util.*
import java.util.function.Predicate
import java.util.regex.Pattern
abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
@@ -144,7 +142,12 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
var exceptionFromDescriptorValidation: Throwable? = null
try {
val expectedFile = File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".txt")
val expectedFile = if (InTextDirectivesUtils.isDirectiveDefined(testDataFile.readText(), "// JAVAC_EXPECTED_FILE")
&& environment.configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) {
File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".javac.txt")
} else {
File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".txt")
}
validateAndCompareDescriptorWithFile(expectedFile, files, modules)
}
catch (e: Throwable) {
@@ -308,6 +311,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
val moduleContentScope = GlobalSearchScope.allScope(moduleContext.project)
val moduleClassResolver = SingleModuleClassResolver()
val container = createContainerForTopDownAnalyzerForJvm(
moduleContext,
moduleTrace,
@@ -319,6 +323,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
JvmTarget.JVM_1_6,
languageVersionSettings
)
container.initJvmBuiltInsForTopDownAnalysis()
moduleClassResolver.resolver = container.get<JavaDescriptorResolver>()
@@ -419,13 +424,34 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
KotlinTestUtils.assertEqualsToFile(expectedFile, allPackagesText)
}
protected open fun skipDescriptorsValidation(): Boolean = false
private fun getJavaFilePackage(testFile: TestFile): Name {
val pattern = Pattern.compile("^\\s*package [.\\w\\d]*", Pattern.MULTILINE)
val matcher = pattern.matcher(testFile.expectedText)
if (matcher.find()) {
return testFile.expectedText
.substring(matcher.start(), matcher.end())
.split(" ")
.last()
.filter { !it.isWhitespace() }
.let { Name.identifier(it.split(".").first()) }
}
return SpecialNames.ROOT_PACKAGE
}
private fun createdAffectedPackagesConfiguration(
testFiles: List<TestFile>,
modules: Collection<ModuleDescriptor>
): RecursiveDescriptorComparator.Configuration {
val packagesNames = getTopLevelPackagesFromFileList(getKtFiles(testFiles, false))
val packagesNames = (
testFiles.filter { it.ktFile == null }
.map { getJavaFilePackage(it) } +
getTopLevelPackagesFromFileList(getKtFiles(testFiles, false))
).toSet()
val stepIntoFilter = Predicate<DeclarationDescriptor> { descriptor ->
val module = DescriptorUtils.getContainingModuleOrNull(descriptor)
@@ -278,7 +278,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
return jvmSignatureDiagnostics
}
override fun toString(): String = ktFile!!.name
override fun toString(): String = ktFile?.name ?: "Java file"
}
companion object {
@@ -131,46 +131,9 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
protected void doTest(String filePath) throws Exception {
File file = new File(filePath);
String expectedText = KotlinTestUtils.doLoadFile(file);
Map<String, ModuleAndDependencies> modules = new HashMap<>();
List<F> testFiles =
KotlinTestUtils.createTestFiles(file.getName(), expectedText, new KotlinTestUtils.TestFileFactory<M, F>() {
@Override
public F createFile(
@Nullable M module,
@NotNull String fileName,
@NotNull String text,
@NotNull Map<String, String> directives
) {
if (fileName.endsWith(".java")) {
writeSourceFile(fileName, text, javaFilesDir);
}
if (fileName.endsWith(".kt") && kotlinSourceRoot != null) {
writeSourceFile(fileName, text, kotlinSourceRoot);
}
return createTestFile(module, fileName, text, directives);
}
@Override
public M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) {
M module = createTestModule(name);
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies, friends));
assert oldValue == null : "Module " + name + " declared more than once";
return module;
}
private void writeSourceFile(@NotNull String fileName, @NotNull String content, @NotNull File targetDir) {
File file = new File(targetDir, fileName);
KotlinTestUtils.mkdirs(file.getParentFile());
FilesKt.writeText(file, content, Charsets.UTF_8);
}
});
List<F> testFiles = createTestFiles(file, expectedText, modules);
doMultiFileTest(file, modules, testFiles);
}
@@ -180,4 +143,42 @@ public abstract class KotlinMultiFileTestWithJava<M, F> extends KtUsefulTestCase
protected abstract F createTestFile(M module, String fileName, String text, Map<String, String> directives);
protected abstract void doMultiFileTest(File file, Map<String, ModuleAndDependencies> modules, List<F> files) throws Exception;
protected List<F> createTestFiles(File file, String expectedText, Map<String, ModuleAndDependencies> modules) {
return KotlinTestUtils.createTestFiles(file.getName(), expectedText, new KotlinTestUtils.TestFileFactory<M, F>() {
@Override
public F createFile(
@Nullable M module,
@NotNull String fileName,
@NotNull String text,
@NotNull Map<String, String> directives
) {
if (fileName.endsWith(".java")) {
writeSourceFile(fileName, text, javaFilesDir);
}
if (fileName.endsWith(".kt") && kotlinSourceRoot != null) {
writeSourceFile(fileName, text, kotlinSourceRoot);
}
return createTestFile(module, fileName, text, directives);
}
@Override
public M createModule(@NotNull String name, @NotNull List<String> dependencies, @NotNull List<String> friends) {
M module = createTestModule(name);
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies, friends));
assert oldValue == null : "Module " + name + " declared more than once";
return module;
}
private void writeSourceFile(@NotNull String fileName, @NotNull String content, @NotNull File targetDir) {
File file = new File(targetDir, fileName);
KotlinTestUtils.mkdirs(file.getParentFile());
FilesKt.writeText(file, content, Charsets.UTF_8);
}
});
}
}
@@ -0,0 +1,48 @@
/*
* 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.
*/
package org.jetbrains.kotlin.checkers.javac
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
abstract class AbstractDiagnosticsUsingJavacTest : AbstractDiagnosticsTest() {
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
if (InTextDirectivesUtils.isDirectiveDefined(testDataFile.readText(), "// JAVAC_SKIP")) {
println("${testDataFile.name} test is skipped")
return
}
val groupedByModule = files.groupBy(TestFile::module)
val allKtFiles = groupedByModule.values.flatMap { getKtFiles(it, true) }
val mockJdk = listOf(File(getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/rt.jar"))
environment.registerJavac(kotlinFiles = allKtFiles, bootClasspath = mockJdk)
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
super.analyzeAndCheck(testDataFile, files)
}
private fun getHomeDirectory(): String {
val resourceRoot = PathUtil.getResourcePathForClass(KotlinTestUtils::class.java)
return FileUtil.toSystemIndependentName(resourceRoot.parentFile.parentFile.parent)
}
}
@@ -0,0 +1,43 @@
/*
* 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.
*/
package org.jetbrains.kotlin.checkers.javac
import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import java.io.File
abstract class AbstractJavacDiagnosticsTest : AbstractDiagnosticsTest() {
private var useJavac = true
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
if (useJavac) {
val groupedByModule = files.groupBy(TestFile::module)
val allKtFiles = groupedByModule.values.flatMap { getKtFiles(it, true) }
environment.registerJavac(kotlinFiles = allKtFiles)
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
}
super.analyzeAndCheck(testDataFile, files)
}
fun doTestWithoutJavacWrapper(path: String) {
useJavac = false
super.doTest(path)
}
}
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestCaseWithTmpdir;
import org.jetbrains.kotlin.test.TestJdkKind;
import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.util.DescriptorValidator;
import org.junit.Assert;
@@ -75,9 +72,13 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
File expectedFile = new File(expectedFileName);
File sourcesDir = new File(expectedFileName.replaceFirst("\\.txt$", ""));
if (useJavacWrapper()) return;
List<File> kotlinSources = FileUtil.findFilesByMask(Pattern.compile(".+\\.kt"), sourcesDir);
KotlinCoreEnvironment environment =
KotlinTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(myTestRootDisposable, ConfigurationKind.JDK_ONLY);
registerJavacIfNeeded(environment);
compileKotlinToDirAndGetModule(kotlinSources, tmpdir, environment);
List<File> javaSources = FileUtil.findFilesByMask(Pattern.compile(".+\\.java"), sourcesDir);
@@ -113,7 +114,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
@NotNull String ktFileName, @NotNull ConfigurationKind configurationKind, boolean useTypeTableInSerializer
) throws Exception {
File ktFile = new File(ktFileName);
File txtFile = new File(ktFileName.replaceFirst("\\.kt$", ".txt"));
File txtFile = getTxtFileFromKtFile(ktFileName);
CompilerConfiguration configuration = newConfiguration(configurationKind, TestJdkKind.MOCK_JDK, getAnnotationsJar());
if (useTypeTableInSerializer) {
@@ -121,13 +122,14 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
}
KotlinCoreEnvironment environment =
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
registerJavacIfNeeded(environment);
ModuleDescriptor module = compileKotlinToDirAndGetModule(Collections.singletonList(ktFile), tmpdir, environment);
PackageViewDescriptor packageFromSource = module.getPackage(TEST_PACKAGE_FQNAME);
Assert.assertEquals("test", packageFromSource.getName().asString());
PackageViewDescriptor packageFromBinary = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
tmpdir, getTestRootDisposable(), getJdkKind(), configurationKind, true, false
tmpdir, getTestRootDisposable(), getJdkKind(), configurationKind, true, false, useJavacWrapper()
).first;
for (DeclarationDescriptor descriptor : DescriptorUtils.getAllDescriptors(packageFromBinary.getMemberScope())) {
@@ -146,6 +148,10 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
return false;
}
protected boolean useJavacWrapper() { return false; }
protected void registerJavacIfNeeded(KotlinCoreEnvironment environment) {}
protected void doTestJavaAgainstKotlin(String expectedFileName) throws Exception {
File expectedFile = new File(expectedFileName);
File sourcesDir = new File(expectedFileName.replaceFirst("\\.txt$", ""));
@@ -159,7 +165,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
KotlinCoreEnvironment environment =
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
registerJavacIfNeeded(environment);
AnalysisResult result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
environment.getProject(), environment.getSourceFiles(), new CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
configuration, environment::createPackagePartProvider
@@ -189,7 +195,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
newConfiguration(ConfigurationKind.JDK_ONLY, getJdkKind(), getAnnotationsJar(), libraryOut),
EnvironmentConfigFiles.JVM_CONFIG_FILES
);
registerJavacIfNeeded(environment);
KtFile ktFile = KotlinTestUtils.createFile(kotlinSrc.getPath(), FileUtil.loadFile(kotlinSrc, true), environment.getProject());
ModuleDescriptor module = JvmResolveUtil.analyzeAndCheckForErrors(Collections.singleton(ktFile), environment).getModuleDescriptor();
@@ -216,7 +222,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
Pair<PackageViewDescriptor, BindingContext> javaPackageAndContext = loadTestPackageAndBindingContextFromJavaRoot(
tmpdir, getTestRootDisposable(), getJdkKind(), ConfigurationKind.JDK_ONLY, false,
false);
false, useJavacWrapper());
checkJavaPackage(
expectedFile, javaPackageAndContext.first, javaPackageAndContext.second,
@@ -251,7 +257,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
srcFiles, compiledDir, ConfigurationKind.ALL
);
checkJavaPackage(getExpectedFile(javaFileName.replaceFirst("\\.java$", ".txt")), javaPackageAndContext.first, javaPackageAndContext.second, configuration);
checkJavaPackage(getTxtFile(javaFileName), javaPackageAndContext.first, javaPackageAndContext.second, configuration);
}
@NotNull
@@ -262,7 +268,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
) throws IOException {
compileJavaWithAnnotationsJar(javaFiles, outDir);
return loadTestPackageAndBindingContextFromJavaRoot(outDir, myTestRootDisposable, getJdkKind(), configurationKind, true,
useFastClassFilesReading());
useFastClassFilesReading(), useJavacWrapper());
}
private static void checkJavaPackage(
@@ -295,6 +301,29 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
}
private static File getTxtFile(String javaFileName) {
return new File(javaFileName.replaceFirst("\\.java$", ".txt"));
try {
String fileText = FileUtil.loadFile(new File(javaFileName));
if (InTextDirectivesUtils.isDirectiveDefined(fileText, "// JAVAC_EXPECTED_FILE")) {
return new File(javaFileName.replaceFirst("\\.java$", ".javac.txt"));
}
else return new File(javaFileName.replaceFirst("\\.java$", ".txt"));
}
catch (IOException e) {
return new File(javaFileName.replaceFirst("\\.java$", ".txt"));
}
}
private static File getTxtFileFromKtFile(String ktFileName) {
try {
String fileText = FileUtil.loadFile(new File(ktFileName));
if (InTextDirectivesUtils.isDirectiveDefined(fileText, "// JAVAC_EXPECTED_FILE")) {
return new File(ktFileName.replaceFirst("\\.kt$", ".javac.txt"));
}
else return new File(ktFileName.replaceFirst("\\.kt$", ".txt"));
}
catch (IOException e) {
return new File(ktFileName.replaceFirst("\\.kt$", ".txt"));
}
}
}
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.jvm.compiler.javac.JavacRegistrarForTests;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.KtFile;
@@ -72,7 +73,8 @@ public class LoadDescriptorUtil {
@NotNull TestJdkKind testJdkKind,
@NotNull ConfigurationKind configurationKind,
boolean isBinaryRoot,
boolean useFastClassReading
boolean useFastClassReading,
boolean useJavacWrapper
) {
List<File> javaBinaryRoots = new ArrayList<>();
javaBinaryRoots.add(KotlinTestUtils.getAnnotationsJar());
@@ -88,9 +90,12 @@ public class LoadDescriptorUtil {
CompilerConfiguration configuration =
KotlinTestUtils.newConfiguration(configurationKind, testJdkKind, javaBinaryRoots, javaSourceRoots);
configuration.put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, useFastClassReading);
configuration.put(JVMConfigurationKeys.USE_JAVAC, useJavacWrapper);
KotlinCoreEnvironment environment =
KotlinCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
if (useJavacWrapper) {
JavacRegistrarForTests.INSTANCE.registerJavac(environment);
}
AnalysisResult analysisResult = JvmResolveUtil.analyze(environment);
PackageViewDescriptor packageView = analysisResult.getModuleDescriptor().getPackage(TEST_PACKAGE_FQNAME);
@@ -0,0 +1,37 @@
/*
* 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.
*/
package org.jetbrains.kotlin.jvm.compiler.javac
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest
abstract class AbstractLoadJavaUsingJavacTest : AbstractLoadJavaTest() {
override fun registerJavacIfNeeded(environment: KotlinCoreEnvironment) {
environment.registerJavac()
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
}
override fun useJavacWrapper() = true
}
object JavacRegistrarForTests {
fun registerJavac(environment: KotlinCoreEnvironment) {
environment.registerJavac()
}
}
@@ -105,7 +105,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
}
val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
tmpdir, testRootDisposable, jdkKind, ConfigurationKind.ALL, true, false
tmpdir, testRootDisposable, jdkKind, ConfigurationKind.ALL, true, false, false
).first
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected, actual, comparatorConfiguration, null)
+1
View File
@@ -32,5 +32,6 @@
<orderEntry type="library" exported="" name="idea-full" level="project" />
<orderEntry type="module" module-name="backend.jvm" />
<orderEntry type="library" name="kotlin-reflect" level="project" />
<orderEntry type="module" module-name="javac-wrapper" scope="TEST" />
</component>
</module>