Module mapping generation

This commit is contained in:
Michael Bogdanov
2015-07-30 11:20:35 +03:00
parent 83336553df
commit 42d46853c7
3 changed files with 119 additions and 11 deletions
@@ -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<FqName, PackageCodegen> package2codegen = new HashMap<FqName, PackageCodegen>();
private final Map<String, ClassBuilderAndSourceFileList> generators = new LinkedHashMap<String, ClassBuilderAndSourceFileList>();
private final Map<String, OutAndSourceFileList> generators = new LinkedHashMap<String, OutAndSourceFileList>();
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<PackageCodegen> values = package2codegen.values();
for (PackageCodegen codegen : values) {
codegen.done();
}
writeModuleMappings(values);
}
}
private void writeModuleMappings(Collection<PackageCodegen> 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.<File>emptyList(), new File(outputFilePath));
//TODO: source files?
generators.put(outputFilePath, new OutAndSourceFileList(Collections.<File>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<OutputFile> asList() {
@@ -163,7 +194,7 @@ public class ClassFileFactory implements OutputFileCollection {
@NotNull
@Override
public List<File> 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<File> sourceFiles;
private ClassBuilderAndSourceFileList(ClassBuilder classBuilder, List<File> 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<File> sourceFiles;
private OutAndSourceFileList(List<File> sourceFiles) {
this.sourceFiles = sourceFiles;
}
public abstract byte[] asBytes(ClassBuilderFactory factory);
public abstract String asText(ClassBuilderFactory factory);
}
public void removeInlinedClasses(Set<String> classNamesToRemove) {
@@ -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<DeserializedCallableMemberDescriptor> previouslyCompiledCallables;
private final PackageFacades facades;
public PackageCodegen(@NotNull GenerationState state, @NotNull Collection<JetFile> 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;
}
}
@@ -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<String, PackageFacades>()
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<String>()
fun serialize(out: Writer) {
for (i in parts) {
out.write("$internalName->$i\n")
}
}
}