Report correct source to output mapping for kjsm files

Now IC can correctly remove kjsm files when source files are changed
This commit is contained in:
Alexey Tsvetkov
2018-03-19 01:06:15 +03:00
parent ea09f4caf6
commit 2584143e92
4 changed files with 35 additions and 31 deletions
@@ -27,8 +27,6 @@ import com.intellij.util.SmartList;
import com.intellij.util.containers.HashMap;
import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt;
import kotlin.io.FilesKt;
import kotlin.sequences.SequencesKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
@@ -66,7 +64,6 @@ import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.utils.*;
@@ -297,23 +294,12 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
if (config.getConfiguration().getBoolean(JSConfigurationKeys.META_INFO)) {
removeKjsmFilesFromOutput(outputDir);
}
OutputUtilsKt.writeAll(outputFiles, outputDir, messageCollector,
configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES));
return OK;
}
private static void removeKjsmFilesFromOutput(File outputDir) {
for (File file : SequencesKt.toList(FilesKt.walkTopDown(outputDir))) {
if (file.isFile() && file.getPath().endsWith(KotlinJavascriptSerializationUtil.INSTANCE.getCLASS_METADATA_FILE_EXTENSION())) {
file.delete();
}
}
}
private static void checkDuplicateSourceFileNames(
@NotNull MessageCollector log,
@NotNull List<KtFile> sourceFiles,
@@ -94,16 +94,6 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
private val PATH_TO_KOTLIN_JS_LIBRARY = AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/KotlinJavaScriptProjectWithDirectoryAsLibrary/" + KOTLIN_JS_LIBRARY
private val KOTLIN_JS_LIBRARY_JAR = "$KOTLIN_JS_LIBRARY.jar"
private fun k2jsOutput(vararg moduleNames: String): Array<String> {
val list = arrayListOf<String>()
for (moduleName in moduleNames) {
val outputDir = File("out/production/$moduleName")
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputFile(outputDir, moduleName, false).path))
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputMetaFile(outputDir, moduleName, false).path))
}
return list.toTypedArray()
}
private fun getMethodsOfClass(classFile: File): Set<String> {
val result = TreeSet<String>()
ClassReader(FileUtil.loadFileBytes(classFile)).accept(object : ClassVisitor(Opcodes.ASM5) {
@@ -257,6 +247,21 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
private fun k2jsOutput(vararg moduleNames: String): Array<String> {
val list = arrayListOf<String>()
for (moduleName in moduleNames) {
val outputDir = File("out/production/$moduleName")
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputFile(outputDir, moduleName, false).path))
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputMetaFile(outputDir, moduleName, false).path))
val kjsmFiles = File(workDir, outputDir.path).walk()
.filter { it.isFile && it.extension.equals("kjsm", ignoreCase = true) }
list.addAll(kjsmFiles.map { toSystemIndependentName(it.relativeTo(workDir).path) })
}
return list.toTypedArray()
}
fun testKotlinJavaScriptProjectWithSourceMap() {
initProject(JS_STDLIB)
buildAllModules().assertSuccessful()
@@ -115,8 +115,10 @@ object KotlinJavascriptSerializationUtil {
private val jsDescriptor: JsModuleDescriptor<ModuleDescriptor>,
private val languageVersionSettings: LanguageVersionSettings
) {
fun asContentMap(): Map<String, ByteArray> {
val contentMap = mutableMapOf<String, ByteArray>()
class SerializedPackage(val fqName: FqName, val bytes: ByteArray)
fun serializedPackages(): List<SerializedPackage> {
val packages = arrayListOf<SerializedPackage>()
for ((fqName, part) in serializedFragments) {
val stream = ByteArrayOutputStream()
@@ -129,10 +131,10 @@ object KotlinJavascriptSerializationUtil {
serializeHeader(jsDescriptor.data, fqName, languageVersionSettings).writeDelimitedTo(stream)
part.writeTo(stream)
contentMap[JsSerializerProtocol.getKjsmFilePath(fqName)] = stream.toByteArray()
packages.add(SerializedPackage(fqName, stream.toByteArray()))
}
return contentMap
return packages
}
fun asString(): String =
@@ -32,10 +32,12 @@ import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
import org.jetbrains.kotlin.js.util.TextOutput
import org.jetbrains.kotlin.js.util.TextOutputImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
import java.io.File
@@ -114,9 +116,9 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
val jsMetaFile = SimpleOutputFile(sourceFilesForMetaFile, metaFileName, metaFileContent)
outputFiles.add(jsMetaFile)
serializedMetadata.asContentMap().forEach {
// TODO Add correct source files
outputFiles.add(SimpleOutputBinaryFile(emptyList(), config.moduleId + VfsUtilCore.VFS_SEPARATOR_CHAR + it.key, it.value))
for (serializedPackage in serializedMetadata.serializedPackages()) {
val outputBinaryFile = kjsmFileForPackage(serializedPackage.fqName, serializedPackage.bytes)
outputFiles.add(outputBinaryFile)
}
}
@@ -130,6 +132,15 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
return SimpleOutputFileCollection(outputFiles)
}
private fun kjsmFileForPackage(packageFqName: FqName, bytes: ByteArray): SimpleOutputBinaryFile {
val ktFiles = (bindingContext.get(BindingContext.PACKAGE_TO_FILES, packageFqName) ?: emptyList())
val sourceFiles = ktFiles.map { VfsUtilCore.virtualToIoFile(it.virtualFile) }
val relativePath = config.moduleId +
VfsUtilCore.VFS_SEPARATOR_CHAR +
JsSerializerProtocol.getKjsmFilePath(packageFqName)
return SimpleOutputBinaryFile(sourceFiles, relativePath, bytes)
}
private fun getCode(output: TextOutput, sourceLocationConsumer: SourceLocationConsumer?) {
program.accept(JsToStringGenerationVisitor(output, sourceLocationConsumer ?: NoOpSourceLocationConsumer))
}