Refactor PackageCodegen and ClassBuilderOnDemand

Make ClassBuilderOnDemand non-abstract and create its instance directly in
PackageCodegen's constructor
This commit is contained in:
Alexander Udalov
2014-05-23 19:10:02 +04:00
parent 4ee7d2e72a
commit 9dd81bdb3d
3 changed files with 40 additions and 68 deletions
@@ -16,49 +16,30 @@
package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.NotNullLazyValue;
import java.util.List;
public class ClassBuilderOnDemand {
private final NotNullLazyValue<ClassBuilder> classBuilder;
public abstract class ClassBuilderOnDemand {
private ClassBuilder classBuilder;
private final List<ClassBuilderCallback> optionalDeclarations = Lists.newArrayList();
interface ClassBuilderCallback {
void doSomething(@NotNull ClassBuilder classBuilder);
}
@NotNull
protected abstract ClassBuilder createClassBuilder();
public void addOptionalDeclaration(@NotNull ClassBuilderCallback callback) {
optionalDeclarations.add(callback);
if (classBuilder != null) {
callback.doSomething(classBuilder);
}
public ClassBuilderOnDemand(@NotNull Function0<ClassBuilder> createClassBuilder) {
this.classBuilder = LockBasedStorageManager.NO_LOCKS.createLazyValue(createClassBuilder);
}
@NotNull
public ClassBuilder getClassBuilder() {
if (classBuilder == null) {
classBuilder = createClassBuilder();
for (ClassBuilderCallback callback : optionalDeclarations) {
callback.doSomething(classBuilder);
}
}
return classBuilder;
return classBuilder.invoke();
}
public void done() {
if (classBuilder != null) {
classBuilder.done();
if (isActivated()) {
classBuilder.invoke().done();
}
}
public boolean isActivated() {
return classBuilder != null;
return classBuilder.isComputed();
}
}
@@ -35,9 +35,6 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.io.File;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
public class ClassFileFactory implements OutputFileCollection {
private final GenerationState state;
private final ClassBuilderFactory builderFactory;
@@ -57,7 +54,7 @@ public class ClassFileFactory implements OutputFileCollection {
}
@NotNull
private ClassBuilder newVisitor(@NotNull Type asmType, @NotNull Collection<? extends PsiFile> sourceFiles) {
public ClassBuilder newVisitor(@NotNull Type asmType, @NotNull Collection<? extends PsiFile> sourceFiles) {
String outputFilePath = asmType.getInternalName() + ".class";
state.getProgress().reportOutput(toIoFilesIgnoringNonPhysical(sourceFiles), new File(outputFilePath));
ClassBuilder answer = builderFactory.newClassBuilder();
@@ -106,18 +103,11 @@ public class ClassFileFactory implements OutputFileCollection {
}
@NotNull
public PackageCodegen forPackage(@NotNull final FqName fqName, @NotNull final Collection<JetFile> files) {
public PackageCodegen forPackage(@NotNull FqName fqName, @NotNull Collection<JetFile> files) {
assert !isDone : "Already done!";
PackageCodegen codegen = package2codegen.get(fqName);
if (codegen == null) {
ClassBuilderOnDemand onDemand = new ClassBuilderOnDemand() {
@NotNull
@Override
protected ClassBuilder createClassBuilder() {
return newVisitor(asmTypeByFqNameWithoutInnerClasses(getPackageClassFqName(fqName)), files);
}
};
codegen = new PackageCodegen(onDemand, fqName, state, files);
codegen = new PackageCodegen(state, files, fqName);
package2codegen.put(fqName, codegen);
}
@@ -22,10 +22,10 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.context.CodegenContext;
@@ -74,28 +74,27 @@ public class PackageCodegen {
private final Collection<JetFile> files;
private final PackageFragmentDescriptor packageFragment;
private final PackageFragmentDescriptor compiledPackageFragment;
private final List<DeserializedCallableMemberDescriptor> previouslyCompiledCallables;
public PackageCodegen(
@NotNull ClassBuilderOnDemand v,
@NotNull final FqName fqName,
@NotNull GenerationState state,
@NotNull Collection<JetFile> packageFiles
) {
public PackageCodegen(@NotNull GenerationState state, @NotNull Collection<JetFile> files, @NotNull final FqName fqName) {
this.state = state;
this.v = v;
this.files = packageFiles;
this.files = files;
this.packageFragment = getOnlyPackageFragment();
this.compiledPackageFragment = getCompiledPackageFragment();
this.compiledPackageFragment = getCompiledPackageFragment(packageFragment);
this.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
final PsiFile sourceFile = packageFiles.size() == 1 && getPreviouslyCompiledCallables().isEmpty()
? packageFiles.iterator().next().getContainingFile() : null;
v.addOptionalDeclaration(new ClassBuilderOnDemand.ClassBuilderCallback() {
this.v = new ClassBuilderOnDemand(new Function0<ClassBuilder>() {
@Override
public void doSomething(@NotNull ClassBuilder v) {
public ClassBuilder invoke() {
Collection<JetFile> files = PackageCodegen.this.files;
JetFile sourceFile = files.size() == 1 && previouslyCompiledCallables.isEmpty()
? files.iterator().next() : null;
String className = JvmClassName.byFqNameWithoutInnerClasses(getPackageClassFqName(fqName)).getInternalName();
ClassBuilder v = PackageCodegen.this.state.getFactory().newVisitor(Type.getObjectType(className), files);
v.defineClass(sourceFile, V1_6,
ACC_PUBLIC | ACC_FINAL,
JvmClassName.byFqNameWithoutInnerClasses(getPackageClassFqName(fqName)).getInternalName(),
className,
null,
"java/lang/Object",
ArrayUtil.EMPTY_STRING_ARRAY
@@ -104,12 +103,13 @@ public class PackageCodegen {
if (sourceFile != null) {
v.visitSource(sourceFile.getName(), null);
}
return v;
}
});
}
@Nullable
private PackageFragmentDescriptor getCompiledPackageFragment() {
private static PackageFragmentDescriptor getCompiledPackageFragment(@NotNull PackageFragmentDescriptor packageFragment) {
if (!IncrementalCompilation.ENABLED) {
return null;
}
@@ -125,20 +125,21 @@ public class PackageCodegen {
}
@NotNull
private List<DeserializedCallableMemberDescriptor> getPreviouslyCompiledCallables() {
private static List<DeserializedCallableMemberDescriptor> filterDeserializedCallables(@Nullable PackageFragmentDescriptor packageFragment) {
if (packageFragment == null) {
return Collections.emptyList();
}
List<DeserializedCallableMemberDescriptor> callables = Lists.newArrayList();
if (compiledPackageFragment != null) {
for (DeclarationDescriptor member : compiledPackageFragment.getMemberScope().getAllDescriptors()) {
if (member instanceof DeserializedCallableMemberDescriptor) {
callables.add((DeserializedCallableMemberDescriptor) member);
}
for (DeclarationDescriptor member : packageFragment.getMemberScope().getAllDescriptors()) {
if (member instanceof DeserializedCallableMemberDescriptor) {
callables.add((DeserializedCallableMemberDescriptor) member);
}
}
return callables;
}
private void generateDelegationsToPreviouslyCompiled(Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks) {
for (final DeserializedCallableMemberDescriptor member : getPreviouslyCompiledCallables()) {
private void generateDelegationsToPreviouslyCompiled(@NotNull Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks) {
for (final DeserializedCallableMemberDescriptor member : previouslyCompiledCallables) {
generateCallableMemberTasks.put(member, new Runnable() {
@Override
public void run() {