Refactor CompileEnvironmentUtil.getKtFiles, move to KotlinCoreEnvironment

Do not call this method the second time in KotlinToJVMBytecodeCompiler
where all KtFile instances are already created; just get only those
files that are in the needed module, which can be determined solely by
the file path.

Also "kotlinize" getKtFiles and rename to createKtFiles
This commit is contained in:
Alexander Udalov
2018-07-27 14:49:47 +02:00
parent fe829add44
commit 1582354077
3 changed files with 54 additions and 90 deletions
@@ -16,21 +16,9 @@
package org.jetbrains.kotlin.cli.jvm.compiler; package org.jetbrains.kotlin.cli.jvm.compiler;
import com.google.common.collect.Lists;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import kotlin.Unit;
import kotlin.io.FilesKt; import kotlin.io.FilesKt;
import kotlin.jvm.functions.Function1;
import kotlin.sequences.SequencesKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFile;
@@ -38,27 +26,16 @@ import org.jetbrains.kotlin.backend.common.output.OutputFileCollection;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
import org.jetbrains.kotlin.cli.common.modules.ModuleChunk; import org.jetbrains.kotlin.cli.common.modules.ModuleChunk;
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser; import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.extensions.PreprocessedFileCreator;
import org.jetbrains.kotlin.idea.KotlinFileType;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.kotlin.utils.PathUtil; import org.jetbrains.kotlin.utils.PathUtil;
import java.io.*; import java.io.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.*; import java.util.jar.*;
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR; import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
public class CompileEnvironmentUtil { public class CompileEnvironmentUtil {
private static final Logger LOG = Logger.getInstance(CompileEnvironmentUtil.class);
@NotNull @NotNull
public static ModuleChunk loadModuleChunk(File buildFile, MessageCollector messageCollector) { public static ModuleChunk loadModuleChunk(File buildFile, MessageCollector messageCollector) {
if (!buildFile.exists()) { if (!buildFile.exists()) {
@@ -139,61 +116,4 @@ public class CompileEnvironmentUtil {
} }
} }
} }
@NotNull
public static List<KtFile> getKtFiles(
@NotNull Project project,
@NotNull Collection<String> sourceRoots,
@NotNull CompilerConfiguration configuration,
@NotNull Function1<String, Unit> reportError
) throws IOException {
VirtualFileSystem localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL);
Set<VirtualFile> processedFiles = new HashSet<>();
List<KtFile> result = Lists.newArrayList();
PreprocessedFileCreator virtualFileCreator = new PreprocessedFileCreator(project);
for (String sourceRootPath : sourceRoots) {
if (sourceRootPath == null) {
continue;
}
VirtualFile vFile = localFileSystem.findFileByPath(sourceRootPath);
if (vFile == null) {
String message = "Source file or directory not found: " + sourceRootPath;
File buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE);
if (buildFilePath != null && Logger.isInitialized()) {
LOG.warn(message +
"\n\nbuild file path: " + buildFilePath +
"\ncontent:\n" + FileUtil.loadFile(buildFilePath));
}
reportError.invoke(message);
continue;
}
if (!vFile.isDirectory() && vFile.getFileType() != KotlinFileType.INSTANCE) {
reportError.invoke("Source entry is not a Kotlin file: " + sourceRootPath);
continue;
}
SequencesKt.forEach(FilesKt.walkTopDown(new File(sourceRootPath)), file -> {
if (file.isFile()) {
VirtualFile originalVirtualFile = localFileSystem.findFileByPath(file.getAbsolutePath());
VirtualFile virtualFile = originalVirtualFile != null ? virtualFileCreator.create(originalVirtualFile) : null;
if (virtualFile != null && !processedFiles.contains(virtualFile)) {
processedFiles.add(virtualFile);
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (psiFile instanceof KtFile) {
result.add((KtFile) psiFile);
}
}
}
return Unit.INSTANCE;
});
}
return result;
}
} }
@@ -32,6 +32,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.TransactionGuard import com.intellij.openapi.application.TransactionGuard
import com.intellij.openapi.application.TransactionGuardImpl import com.intellij.openapi.application.TransactionGuardImpl
import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint import com.intellij.openapi.fileTypes.FileTypeExtensionPoint
@@ -90,10 +91,7 @@ import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.extensions.CompilerConfigurationExtension import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension
import org.jetbrains.kotlin.extensions.PreprocessedVirtualFileFactoryExtension
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
@@ -218,9 +216,7 @@ class KotlinCoreEnvironment private constructor(
extension.updateConfiguration(configuration) extension.updateConfiguration(configuration)
} }
sourceFiles += CompileEnvironmentUtil.getKtFiles(project, getSourceRootsCheckingForDuplicates(), this.configuration) { message -> sourceFiles += createKtFiles(project)
report(ERROR, message)
}
sourceFiles.sortBy { it.virtualFile.path } sourceFiles.sortBy { it.virtualFile.path }
// If not disabled explicitly, we should always support at least the standard script definition // If not disabled explicitly, we should always support at least the standard script definition
@@ -416,6 +412,52 @@ class KotlinCoreEnvironment private constructor(
fun getSourceFiles(): List<KtFile> = sourceFiles fun getSourceFiles(): List<KtFile> = sourceFiles
private fun createKtFiles(project: Project): List<KtFile> {
val sourceRoots = getSourceRootsCheckingForDuplicates()
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val psiManager = PsiManager.getInstance(project)
val processedFiles = hashSetOf<VirtualFile>()
val result = mutableListOf<KtFile>()
val virtualFileCreator = PreprocessedFileCreator(project)
for (sourceRootPath in sourceRoots) {
val vFile = localFileSystem.findFileByPath(sourceRootPath)
if (vFile == null) {
val message = "Source file or directory not found: $sourceRootPath"
val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
if (buildFilePath != null && Logger.isInitialized()) {
LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
}
report(ERROR, message)
continue
}
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
report(ERROR, "Source entry is not a Kotlin file: $sourceRootPath")
continue
}
for (file in File(sourceRootPath).walkTopDown()) {
if (!file.isFile) continue
val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
if (virtualFile != null && processedFiles.add(virtualFile)) {
val psiFile = psiManager.findFile(virtualFile)
if (psiFile is KtFile) {
result.add(psiFile)
}
}
}
}
return result
}
private fun report(severity: CompilerMessageSeverity, message: String) { private fun report(severity: CompilerMessageSeverity, message: String) {
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message) configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message)
} }
@@ -425,6 +467,8 @@ class KotlinCoreEnvironment private constructor(
setCompatibleBuild() setCompatibleBuild()
} }
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
private val APPLICATION_LOCK = Object() private val APPLICATION_LOCK = Object()
private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null
private var ourProjectCount = 0 private var ourProjectCount = 0
@@ -138,9 +138,9 @@ object KotlinToJVMBytecodeCompiler {
for (module in chunk) { for (module in chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val ktFiles = CompileEnvironmentUtil.getKtFiles( val moduleSourcePaths = getAbsolutePaths(buildFile, module)
environment.project, getAbsolutePaths(buildFile, module), projectConfiguration val ktFiles = environment.getSourceFiles().filter { file -> file.virtualFilePath in moduleSourcePaths }
) { path -> throw IllegalStateException("Should have been checked before: $path") }
if (!checkKotlinPackageUsage(environment, ktFiles)) return false if (!checkKotlinPackageUsage(environment, ktFiles)) return false
val moduleConfiguration = projectConfiguration.copy().apply { val moduleConfiguration = projectConfiguration.copy().apply {