LIGHT_CLASSES mode for scripts
- Do not generate constructor bodies - Do not generate script class when package contents are requested - NOT DONE: generate script class when its name is requested
This commit is contained in:
@@ -304,13 +304,17 @@ public class PackageCodegen {
|
||||
}
|
||||
else if (declaration instanceof JetClassOrObject) {
|
||||
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
|
||||
if (state.getGenerateDeclaredClassFilter().shouldProcess(classOrObject)) {
|
||||
if (state.getGenerateDeclaredClassFilter().shouldProcessClass(classOrObject)) {
|
||||
generateClassOrObject(classOrObject);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetScript) {
|
||||
JetScript script = (JetScript) declaration;
|
||||
|
||||
// SCRIPT: generate script code, should be separate execution branch
|
||||
ScriptCodegen.createScriptCodegen((JetScript) declaration, state, packagePartContext).generate();
|
||||
if (state.getGenerateDeclaredClassFilter().shouldProcessScript(script)) {
|
||||
ScriptCodegen.createScriptCodegen(script, state, packagePartContext).generate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,68 +140,73 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
|
||||
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
|
||||
null, null);
|
||||
|
||||
mv.visitCode();
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
Type classType = typeMapper.mapType(classDescriptorForScript);
|
||||
Type classType = typeMapper.mapType(classDescriptorForScript);
|
||||
|
||||
iv.load(0, classType);
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||
iv.load(0, classType);
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||
|
||||
iv.load(0, classType);
|
||||
iv.load(0, classType);
|
||||
|
||||
final FrameMap frameMap = new FrameMap();
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
final FrameMap frameMap = new FrameMap();
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
|
||||
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
|
||||
frameMap.enter(importedScript, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
|
||||
int add = 0;
|
||||
|
||||
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) {
|
||||
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i);
|
||||
frameMap.enter(parameter, argTypes[i + add]);
|
||||
}
|
||||
|
||||
generateInitializers(new Function0<ExpressionCodegen>() {
|
||||
@Override
|
||||
public ExpressionCodegen invoke() {
|
||||
return new ExpressionCodegen(iv, frameMap, Type.VOID_TYPE, methodContext, state, ScriptCodegen.this);
|
||||
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
|
||||
frameMap.enter(importedScript, OBJECT_TYPE);
|
||||
}
|
||||
});
|
||||
|
||||
int offset = 1;
|
||||
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
|
||||
int add = 0;
|
||||
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, earlierClassType);
|
||||
offset += earlierClassType.getSize();
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) {
|
||||
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i);
|
||||
frameMap.enter(parameter, argTypes[i + add]);
|
||||
}
|
||||
|
||||
generateInitializers(new Function0<ExpressionCodegen>() {
|
||||
@Override
|
||||
public ExpressionCodegen invoke() {
|
||||
return new ExpressionCodegen(iv, frameMap, Type.VOID_TYPE, methodContext, state, ScriptCodegen.this);
|
||||
}
|
||||
});
|
||||
|
||||
int offset = 1;
|
||||
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, earlierClassType);
|
||||
offset += earlierClassType.getSize();
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) {
|
||||
Type parameterType = typeMapper.mapType(parameter.getType());
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, parameterType);
|
||||
offset += parameterType.getSize();
|
||||
iv.putfield(classType.getInternalName(), parameter.getName().getIdentifier(), parameterType.getDescriptor());
|
||||
}
|
||||
|
||||
StackValue stackValue =
|
||||
new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this)
|
||||
.gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
StackValue.Field resultValue = StackValue
|
||||
.field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.LOCAL_0);
|
||||
resultValue.store(stackValue, iv);
|
||||
}
|
||||
else {
|
||||
stackValue.put(blockType, iv);
|
||||
}
|
||||
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) {
|
||||
Type parameterType = typeMapper.mapType(parameter.getType());
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, parameterType);
|
||||
offset += parameterType.getSize();
|
||||
iv.putfield(classType.getInternalName(), parameter.getName().getIdentifier(), parameterType.getDescriptor());
|
||||
}
|
||||
|
||||
StackValue stackValue =
|
||||
new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this).gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
StackValue.Field resultValue = StackValue
|
||||
.field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.LOCAL_0);
|
||||
resultValue.store(stackValue, iv);
|
||||
} else {
|
||||
stackValue.put(blockType, iv);
|
||||
}
|
||||
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
mv.visitMaxs(-1, -1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
+2
-2
@@ -214,7 +214,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
super.visitObjectDeclaration(declaration);
|
||||
}
|
||||
else {
|
||||
if (!filter.shouldProcess(declaration)) return;
|
||||
if (!filter.shouldProcessClass(declaration)) return;
|
||||
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS, declaration);
|
||||
// working around a problem with shallow analysis
|
||||
@@ -233,7 +233,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
|
||||
@Override
|
||||
public void visitClass(@NotNull JetClass klass) {
|
||||
if (!filter.shouldProcess(klass)) return;
|
||||
if (!filter.shouldProcessClass(klass)) return;
|
||||
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS, klass);
|
||||
// working around a problem with shallow analysis
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticSink;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetScript;
|
||||
import org.jetbrains.jet.lang.reflect.ReflectionTypes;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
@@ -42,11 +43,17 @@ import java.util.List;
|
||||
|
||||
public class GenerationState {
|
||||
public interface GenerateClassFilter {
|
||||
boolean shouldProcess(JetClassOrObject classOrObject);
|
||||
boolean shouldProcessClass(JetClassOrObject classOrObject);
|
||||
boolean shouldProcessScript(JetScript script);
|
||||
|
||||
GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
|
||||
@Override
|
||||
public boolean shouldProcess(JetClassOrObject classOrObject) {
|
||||
public boolean shouldProcessClass(JetClassOrObject classOrObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldProcessScript(JetScript script) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
+15
-2
@@ -51,6 +51,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetScript;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.Diagnostics;
|
||||
@@ -110,11 +111,17 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||
return new GenerationState.GenerateClassFilter() {
|
||||
@Override
|
||||
public boolean shouldProcess(JetClassOrObject classOrObject) {
|
||||
public boolean shouldProcessClass(JetClassOrObject classOrObject) {
|
||||
// Top-level classes and such should not be generated for performance reasons.
|
||||
// Local classes in top-level functions must still be generated
|
||||
return JetPsiUtil.isLocal(classOrObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldProcessScript(JetScript script) {
|
||||
// Scripts yield top-level classes, and should not be generated
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -215,7 +222,7 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||
return new GenerationState.GenerateClassFilter() {
|
||||
@Override
|
||||
public boolean shouldProcess(JetClassOrObject generatedClassOrObject) {
|
||||
public boolean shouldProcessClass(JetClassOrObject generatedClassOrObject) {
|
||||
// Trivial: generate and analyze class we are interested in.
|
||||
if (generatedClassOrObject == classOrObject) return true;
|
||||
|
||||
@@ -246,6 +253,12 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldProcessScript(JetScript script) {
|
||||
// We generate all enclosing classes
|
||||
return PsiTreeUtil.isAncestor(script, classOrObject, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// FILE: script.kts
|
||||
|
||||
annotation class Ann
|
||||
|
||||
[Ann]<!SYNTAX!><!>
|
||||
@@ -0,0 +1,9 @@
|
||||
package
|
||||
|
||||
public final class Script {
|
||||
public constructor Script()
|
||||
public final val rv: [ERROR : getBlockReturnedType returned null]
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -637,6 +637,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DanglingInScript.kt")
|
||||
public void testDanglingInScript() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingInScript.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DanglingMixed.kt")
|
||||
public void testDanglingMixed() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingMixed.kt");
|
||||
|
||||
Reference in New Issue
Block a user