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) {
|
else if (declaration instanceof JetClassOrObject) {
|
||||||
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
|
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
|
||||||
if (state.getGenerateDeclaredClassFilter().shouldProcess(classOrObject)) {
|
if (state.getGenerateDeclaredClassFilter().shouldProcessClass(classOrObject)) {
|
||||||
generateClassOrObject(classOrObject);
|
generateClassOrObject(classOrObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetScript) {
|
else if (declaration instanceof JetScript) {
|
||||||
|
JetScript script = (JetScript) declaration;
|
||||||
|
|
||||||
// SCRIPT: generate script code, should be separate execution branch
|
// 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(),
|
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
|
||||||
null, null);
|
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.load(0, classType);
|
||||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||||
|
|
||||||
iv.load(0, classType);
|
iv.load(0, classType);
|
||||||
|
|
||||||
final FrameMap frameMap = new FrameMap();
|
final FrameMap frameMap = new FrameMap();
|
||||||
frameMap.enterTemp(OBJECT_TYPE);
|
frameMap.enterTemp(OBJECT_TYPE);
|
||||||
|
|
||||||
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
|
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
|
||||||
frameMap.enter(importedScript, OBJECT_TYPE);
|
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);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
int offset = 1;
|
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
|
||||||
|
int add = 0;
|
||||||
|
|
||||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) {
|
||||||
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i);
|
||||||
iv.load(0, classType);
|
frameMap.enter(parameter, argTypes[i + add]);
|
||||||
iv.load(offset, earlierClassType);
|
}
|
||||||
offset += earlierClassType.getSize();
|
|
||||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
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.visitMaxs(-1, -1);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -214,7 +214,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
|||||||
super.visitObjectDeclaration(declaration);
|
super.visitObjectDeclaration(declaration);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!filter.shouldProcess(declaration)) return;
|
if (!filter.shouldProcessClass(declaration)) return;
|
||||||
|
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS, declaration);
|
ClassDescriptor classDescriptor = bindingContext.get(CLASS, declaration);
|
||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
@@ -233,7 +233,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClass(@NotNull JetClass klass) {
|
public void visitClass(@NotNull JetClass klass) {
|
||||||
if (!filter.shouldProcess(klass)) return;
|
if (!filter.shouldProcessClass(klass)) return;
|
||||||
|
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS, klass);
|
ClassDescriptor classDescriptor = bindingContext.get(CLASS, klass);
|
||||||
// working around a problem with shallow analysis
|
// 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.diagnostics.DiagnosticSink;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
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.reflect.ReflectionTypes;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
@@ -42,11 +43,17 @@ import java.util.List;
|
|||||||
|
|
||||||
public class GenerationState {
|
public class GenerationState {
|
||||||
public interface GenerateClassFilter {
|
public interface GenerateClassFilter {
|
||||||
boolean shouldProcess(JetClassOrObject classOrObject);
|
boolean shouldProcessClass(JetClassOrObject classOrObject);
|
||||||
|
boolean shouldProcessScript(JetScript script);
|
||||||
|
|
||||||
GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
|
GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldProcess(JetClassOrObject classOrObject) {
|
public boolean shouldProcessClass(JetClassOrObject classOrObject) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldProcessScript(JetScript script) {
|
||||||
return true;
|
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.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
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.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||||
import org.jetbrains.jet.lang.resolve.Diagnostics;
|
import org.jetbrains.jet.lang.resolve.Diagnostics;
|
||||||
@@ -110,11 +111,17 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
|||||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||||
return new GenerationState.GenerateClassFilter() {
|
return new GenerationState.GenerateClassFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldProcess(JetClassOrObject classOrObject) {
|
public boolean shouldProcessClass(JetClassOrObject classOrObject) {
|
||||||
// Top-level classes and such should not be generated for performance reasons.
|
// Top-level classes and such should not be generated for performance reasons.
|
||||||
// Local classes in top-level functions must still be generated
|
// Local classes in top-level functions must still be generated
|
||||||
return JetPsiUtil.isLocal(classOrObject);
|
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() {
|
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||||
return new GenerationState.GenerateClassFilter() {
|
return new GenerationState.GenerateClassFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldProcess(JetClassOrObject generatedClassOrObject) {
|
public boolean shouldProcessClass(JetClassOrObject generatedClassOrObject) {
|
||||||
// Trivial: generate and analyze class we are interested in.
|
// Trivial: generate and analyze class we are interested in.
|
||||||
if (generatedClassOrObject == classOrObject) return true;
|
if (generatedClassOrObject == classOrObject) return true;
|
||||||
|
|
||||||
@@ -246,6 +253,12 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
|||||||
|
|
||||||
return false;
|
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);
|
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")
|
@TestMetadata("DanglingMixed.kt")
|
||||||
public void testDanglingMixed() throws Exception {
|
public void testDanglingMixed() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingMixed.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingMixed.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user