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