From 42d46853c717e7c24a22edab55dc7d7bf602af90 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Thu, 30 Jul 2015 11:20:35 +0300 Subject: [PATCH] Module mapping generation --- .../kotlin/codegen/ClassFileFactory.java | 75 ++++++++++++++++--- .../kotlin/codegen/PackageCodegen.java | 11 +++ .../kotlin/load/kotlin/ModuleMapping.kt | 44 +++++++++++ 3 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java index b4def89bf7b..f0f51b74793 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java @@ -24,22 +24,24 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.psi.JetFile; -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; -import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFileCollection; +import org.jetbrains.kotlin.codegen.state.GenerationState; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.psi.JetFile; +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.org.objectweb.asm.Type; import java.io.File; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.util.*; public class ClassFileFactory implements OutputFileCollection { private final GenerationState state; private final ClassBuilderFactory builderFactory; private final Map package2codegen = new HashMap(); - private final Map generators = new LinkedHashMap(); + private final Map generators = new LinkedHashMap(); private boolean isDone = false; @@ -72,12 +74,41 @@ public class ClassFileFactory implements OutputFileCollection { void done() { if (!isDone) { isDone = true; - for (PackageCodegen codegen : package2codegen.values()) { + Collection values = package2codegen.values(); + for (PackageCodegen codegen : values) { codegen.done(); } + + writeModuleMappings(values); } } + private void writeModuleMappings(Collection values) { + String outputFilePath = "META-INF/module.mapping"; + final StringWriter moduleMapping = new StringWriter(1024); + for (PackageCodegen codegen : values) { + codegen.getFacades().serialize(moduleMapping); + } + state.getProgress().reportOutput(Collections.emptyList(), new File(outputFilePath)); + //TODO: source files? + generators.put(outputFilePath, new OutAndSourceFileList(Collections.emptyList()) { + @Override + public byte[] asBytes(ClassBuilderFactory factory) { + try { + return moduleMapping.toString().getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + @Override + public String asText(ClassBuilderFactory factory) { + return moduleMapping.toString(); + } + }); + } + @NotNull @Override public List asList() { @@ -163,7 +194,7 @@ public class ClassFileFactory implements OutputFileCollection { @NotNull @Override public List getSourceFiles() { - ClassBuilderAndSourceFileList pair = generators.get(relativeClassFilePath); + OutAndSourceFileList pair = generators.get(relativeClassFilePath); if (pair == null) { throw new IllegalStateException("No record for binary file " + relativeClassFilePath); } @@ -174,13 +205,13 @@ public class ClassFileFactory implements OutputFileCollection { @NotNull @Override public byte[] asByteArray() { - return builderFactory.asBytes(generators.get(relativeClassFilePath).classBuilder); + return generators.get(relativeClassFilePath).asBytes(builderFactory); } @NotNull @Override public String asText() { - return builderFactory.asText(generators.get(relativeClassFilePath).classBuilder); + return generators.get(relativeClassFilePath).asText(builderFactory); } @NotNull @@ -190,14 +221,36 @@ public class ClassFileFactory implements OutputFileCollection { } } - private static final class ClassBuilderAndSourceFileList { + private static final class ClassBuilderAndSourceFileList extends OutAndSourceFileList { private final ClassBuilder classBuilder; - private final List sourceFiles; private ClassBuilderAndSourceFileList(ClassBuilder classBuilder, List sourceFiles) { + super(sourceFiles); this.classBuilder = classBuilder; + } + + @Override + public byte[] asBytes(ClassBuilderFactory factory) { + return factory.asBytes(classBuilder); + } + + @Override + public String asText(ClassBuilderFactory factory) { + return factory.asText(classBuilder); + } + } + + private static abstract class OutAndSourceFileList { + + protected final List sourceFiles; + + private OutAndSourceFileList(List sourceFiles) { this.sourceFiles = sourceFiles; } + + public abstract byte[] asBytes(ClassBuilderFactory factory); + + public abstract String asText(ClassBuilderFactory factory); } public void removeInlinedClasses(Set classNamesToRemove) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java index f80a113ec2d..ef43de9ec67 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.context.PackageContext; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.config.IncrementalCompilation; +import org.jetbrains.kotlin.load.kotlin.PackageFacades; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; @@ -83,6 +84,8 @@ public class PackageCodegen { private final PackageFragmentDescriptor compiledPackageFragment; private final List previouslyCompiledCallables; + private final PackageFacades facades; + public PackageCodegen(@NotNull GenerationState state, @NotNull Collection files, @NotNull FqName fqName) { this.state = state; this.files = files; @@ -117,6 +120,7 @@ public class PackageCodegen { return v; } }); + facades = new PackageFacades(fqName.asString().replaceAll("\\.", "/")); } // Returns null if file has callables in several files @@ -329,8 +333,11 @@ public class PackageCodegen { } } + if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return null; + facades.getParts().add(packagePartType.getInternalName()); + ClassBuilder builder = state.getFactory().newVisitor(PackagePart(file, packageFragment), packagePartType, file); new PackagePartCodegen(builder, file, packagePartType, packagePartContext, state).generate(); @@ -412,4 +419,8 @@ public class PackageCodegen { public void done() { v.done(); } + + public PackageFacades getFacades() { + return facades; + } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt new file mode 100644 index 00000000000..72e2dc45f73 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2015 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.load.kotlin + +import java.io.Writer + +public class ModuleMapping(val moduleMapping: String) { + + val package2MiniFacades = hashMapOf() + + init { + for (i in moduleMapping.split("\n")) { + if(i.isEmpty()) continue + val (pakage, facade) = i.split("->") + val miniFacades = package2MiniFacades.getOrPut(pakage, { PackageFacades(pakage) }) + miniFacades.parts.add(facade) + } + } +} + +public class PackageFacades(val internalName: String) { + + val parts = hashSetOf() + + fun serialize(out: Writer) { + for (i in parts) { + out.write("$internalName->$i\n") + } + } +} \ No newline at end of file