Resolve Kotlin from Java, first drop.
This commit is contained in:
@@ -116,18 +116,20 @@ public abstract class ClassBodyCodegen {
|
|||||||
if (staticInitializerChunks.size() > 0) {
|
if (staticInitializerChunks.size() > 0) {
|
||||||
final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||||
"<clinit>", "()V", null, null);
|
"<clinit>", "()V", null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
InstructionAdapter v = new InstructionAdapter(mv);
|
InstructionAdapter v = new InstructionAdapter(mv);
|
||||||
|
|
||||||
for (CodeChunk chunk : staticInitializerChunks) {
|
for (CodeChunk chunk : staticInitializerChunks) {
|
||||||
chunk.generate(v);
|
chunk.generate(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,20 +10,26 @@ import org.objectweb.asm.ClassVisitor;
|
|||||||
import org.objectweb.asm.FieldVisitor;
|
import org.objectweb.asm.FieldVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public class ClassBuilder {
|
public abstract class ClassBuilder {
|
||||||
private final ClassVisitor v;
|
public static class Concrete extends ClassBuilder {
|
||||||
|
private final ClassVisitor v;
|
||||||
|
|
||||||
public ClassBuilder(ClassVisitor v) {
|
public Concrete(ClassVisitor v) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassVisitor getVisitor() {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldVisitor newField(@Nullable PsiElement origin,
|
public FieldVisitor newField(@Nullable PsiElement origin,
|
||||||
int access,
|
int access,
|
||||||
String name,
|
String name,
|
||||||
String desc,
|
String desc,
|
||||||
@Nullable String signature,
|
@Nullable String signature,
|
||||||
@Nullable Object value) {
|
@Nullable Object value) {
|
||||||
return v.visitField(access, name, desc, signature, value);
|
return getVisitor().visitField(access, name, desc, signature, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodVisitor newMethod(@Nullable PsiElement origin,
|
public MethodVisitor newMethod(@Nullable PsiElement origin,
|
||||||
@@ -32,28 +38,34 @@ public class ClassBuilder {
|
|||||||
String desc,
|
String desc,
|
||||||
@Nullable String signature,
|
@Nullable String signature,
|
||||||
@Nullable String[] exceptions) {
|
@Nullable String[] exceptions) {
|
||||||
return v.visitMethod(access, name, desc, signature, exceptions);
|
return getVisitor().visitMethod(access, name, desc, signature, exceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnnotationVisitor newAnnotation(PsiElement origin,
|
public AnnotationVisitor newAnnotation(PsiElement origin,
|
||||||
String desc,
|
String desc,
|
||||||
boolean visible) {
|
boolean visible) {
|
||||||
return v.visitAnnotation(desc, visible);
|
return getVisitor().visitAnnotation(desc, visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void done() {
|
public void done() {
|
||||||
v.visitEnd();
|
getVisitor().visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassVisitor getVisitor() {
|
public abstract ClassVisitor getVisitor();
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void defineClass(int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
|
public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
|
||||||
v.visit(version, access, name, signature, superName, interfaces);
|
getVisitor().visit(version, access, name, signature, superName, interfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitSource(String name, @Nullable String debug) {
|
public void visitSource(String name, @Nullable String debug) {
|
||||||
v.visitSource(name, debug);
|
getVisitor().visitSource(name, debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitOuterClass(String owner, String name, String desc) {
|
||||||
|
getVisitor().visitOuterClass(owner, name, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean generateCode() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public interface ClassBuilderFactory {
|
|||||||
ClassBuilderFactory TEXT = new ClassBuilderFactory() {
|
ClassBuilderFactory TEXT = new ClassBuilderFactory() {
|
||||||
@Override
|
@Override
|
||||||
public ClassBuilder newClassBuilder() {
|
public ClassBuilder newClassBuilder() {
|
||||||
return new ClassBuilder(new TraceClassVisitor(new PrintWriter(new StringWriter())));
|
return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -39,7 +39,7 @@ public interface ClassBuilderFactory {
|
|||||||
ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
|
ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
|
||||||
@Override
|
@Override
|
||||||
public ClassBuilder newClassBuilder() {
|
public ClassBuilder newClassBuilder() {
|
||||||
return new ClassBuilder(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
|
return new ClassBuilder.Concrete(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
appendType(signatureWriter, funDescriptor.getReturnType(), '=');
|
appendType(signatureWriter, funDescriptor.getReturnType(), '=');
|
||||||
signatureWriter.visitEnd();
|
signatureWriter.visitEnd();
|
||||||
|
|
||||||
cv.defineClass(V1_6,
|
cv.defineClass(fun,
|
||||||
|
V1_6,
|
||||||
ACC_PUBLIC/*|ACC_SUPER*/,
|
ACC_PUBLIC/*|ACC_SUPER*/,
|
||||||
name,
|
name,
|
||||||
null,
|
null,
|
||||||
@@ -112,23 +113,25 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null);
|
cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null);
|
||||||
|
|
||||||
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]);
|
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]);
|
||||||
mv.visitCode();
|
if (cv.generateCode()) {
|
||||||
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
|
mv.visitCode();
|
||||||
mv.visitInsn(DUP);
|
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
|
||||||
Label ret = new Label();
|
mv.visitInsn(DUP);
|
||||||
mv.visitJumpInsn(IFNONNULL, ret);
|
Label ret = new Label();
|
||||||
|
mv.visitJumpInsn(IFNONNULL, ret);
|
||||||
|
|
||||||
mv.visitInsn(POP);
|
mv.visitInsn(POP);
|
||||||
mv.visitTypeInsn(NEW, name);
|
mv.visitTypeInsn(NEW, name);
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
|
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
|
mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
|
||||||
|
|
||||||
mv.visitLabel(ret);
|
mv.visitLabel(ret);
|
||||||
mv.visitInsn(ARETURN);
|
mv.visitInsn(ARETURN);
|
||||||
mv.visitMaxs(0,0);
|
mv.visitMaxs(0,0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
|
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
|
||||||
@@ -157,34 +160,36 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
|
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
|
||||||
mv.visitCode();
|
if (cv.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
iv.load(0, Type.getObjectType(className));
|
iv.load(0, Type.getObjectType(className));
|
||||||
|
|
||||||
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
|
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
|
||||||
int count = 1;
|
int count = 1;
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
|
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<ValueParameterDescriptor> params = funDescriptor.getValueParameters();
|
||||||
|
for (ValueParameterDescriptor param : params) {
|
||||||
|
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
|
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(param.getOutType()), iv);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
iv.invokespecial(className, "invoke", delegate.getDescriptor());
|
||||||
|
StackValue.onStack(delegate.getReturnType()).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
|
|
||||||
|
iv.areturn(JetTypeMapper.TYPE_OBJECT);
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ValueParameterDescriptor> params = funDescriptor.getValueParameters();
|
|
||||||
for (ValueParameterDescriptor param : params) {
|
|
||||||
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
|
||||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(param.getOutType()), iv);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.invokespecial(className, "invoke", delegate.getDescriptor());
|
|
||||||
StackValue.onStack(delegate.getReturnType()).put(JetTypeMapper.TYPE_OBJECT, iv);
|
|
||||||
|
|
||||||
iv.areturn(JetTypeMapper.TYPE_OBJECT);
|
|
||||||
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
|
private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) {
|
||||||
@@ -221,14 +226,15 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
|
|
||||||
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
||||||
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
|
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
|
||||||
mv.visitCode();
|
if (cv.generateCode()) {
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
mv.visitCode();
|
||||||
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
iv.load(0, Type.getObjectType(funClass));
|
iv.load(0, Type.getObjectType(funClass));
|
||||||
// expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType));
|
// expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType));
|
||||||
iv.aconst(null); // @todo
|
iv.aconst(null); // @todo
|
||||||
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
|
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
for (Type type : argTypes) {
|
for (Type type : argTypes) {
|
||||||
@@ -248,13 +254,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue.field(type, name, fieldName, false).store(iv);
|
iv.visitInsn(RETURN);
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
iv.visitInsn(RETURN);
|
|
||||||
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
|
||||||
return constructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,12 +70,12 @@ public class FunctionCodegen {
|
|||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
|
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
|
||||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||||
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true);
|
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameterName;", true);
|
||||||
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
||||||
annotationVisitor.visitEnd();
|
annotationVisitor.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isAbstract) {
|
if (!isAbstract && v.generateCode()) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
FrameMap frameMap = context.prepareFrame();
|
FrameMap frameMap = context.prepareFrame();
|
||||||
|
|
||||||
@@ -192,103 +192,105 @@ public class FunctionCodegen {
|
|||||||
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
|
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
|
||||||
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
|
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
FrameMap frameMap = owner.prepareFrame();
|
FrameMap frameMap = owner.prepareFrame();
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state);
|
||||||
|
|
||||||
|
int var = 0;
|
||||||
|
if(!isStatic) {
|
||||||
|
frameMap.enterTemp();
|
||||||
|
var++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasReceiver) {
|
||||||
|
frameMap.enterTemp();
|
||||||
|
var++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
|
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
||||||
|
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||||
|
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||||
|
int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize();
|
||||||
|
var += size;
|
||||||
|
frameMap.enter(parameter, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
||||||
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
int slot = frameMap.enterTemp();
|
||||||
|
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
|
var++;
|
||||||
|
}
|
||||||
|
|
||||||
int var = 0;
|
|
||||||
if(!isStatic) {
|
|
||||||
frameMap.enterTemp();
|
frameMap.enterTemp();
|
||||||
var++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasReceiver) {
|
int maskIndex = var;
|
||||||
frameMap.enterTemp();
|
|
||||||
var++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
var = 0;
|
||||||
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
if(!isStatic) {
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
mv.visitVarInsn(ALOAD, var++);
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
|
||||||
int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize();
|
|
||||||
var += size;
|
|
||||||
frameMap.enter(parameter, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
|
||||||
int slot = frameMap.enterTemp();
|
|
||||||
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
|
||||||
var++;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameMap.enterTemp();
|
|
||||||
|
|
||||||
int maskIndex = var;
|
|
||||||
|
|
||||||
var = 0;
|
|
||||||
if(!isStatic) {
|
|
||||||
mv.visitVarInsn(ALOAD, var++);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasReceiver) {
|
|
||||||
mv.visitVarInsn(ALOAD, var++);
|
|
||||||
}
|
|
||||||
|
|
||||||
Type[] argumentTypes = jvmSignature.getArgumentTypes();
|
|
||||||
for (int index = 0; index < paramDescrs.size(); index++) {
|
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
|
|
||||||
|
|
||||||
Type t = argumentTypes[(hasReceiver ? 1 : 0) + index];
|
|
||||||
Label endArg = null;
|
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
|
||||||
iv.load(maskIndex, Type.INT_TYPE);
|
|
||||||
iv.iconst(1 << index);
|
|
||||||
iv.and(Type.INT_TYPE);
|
|
||||||
Label loadArg = new Label();
|
|
||||||
iv.ifeq(loadArg);
|
|
||||||
|
|
||||||
JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor);
|
|
||||||
assert jetParameter != null;
|
|
||||||
codegen.gen(jetParameter.getDefaultValue(), t);
|
|
||||||
|
|
||||||
endArg = new Label();
|
|
||||||
iv.goTo(endArg);
|
|
||||||
|
|
||||||
iv.mark(loadArg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iv.load(var, t);
|
if(hasReceiver) {
|
||||||
var += t.getSize();
|
mv.visitVarInsn(ALOAD, var++);
|
||||||
|
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
|
||||||
iv.mark(endArg);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
Type[] argumentTypes = jvmSignature.getArgumentTypes();
|
||||||
if(typeParameterDescriptor.isReified())
|
for (int index = 0; index < paramDescrs.size(); index++) {
|
||||||
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
|
||||||
}
|
|
||||||
|
|
||||||
if(!isStatic) {
|
Type t = argumentTypes[(hasReceiver ? 1 : 0) + index];
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
Label endArg = null;
|
||||||
iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
if (parameterDescriptor.hasDefaultValue()) {
|
||||||
|
iv.load(maskIndex, Type.INT_TYPE);
|
||||||
|
iv.iconst(1 << index);
|
||||||
|
iv.and(Type.INT_TYPE);
|
||||||
|
Label loadArg = new Label();
|
||||||
|
iv.ifeq(loadArg);
|
||||||
|
|
||||||
|
JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor);
|
||||||
|
assert jetParameter != null;
|
||||||
|
codegen.gen(jetParameter.getDefaultValue(), t);
|
||||||
|
|
||||||
|
endArg = new Label();
|
||||||
|
iv.goTo(endArg);
|
||||||
|
|
||||||
|
iv.mark(loadArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
iv.load(var, t);
|
||||||
|
var += t.getSize();
|
||||||
|
|
||||||
|
if (parameterDescriptor.hasDefaultValue()) {
|
||||||
|
iv.mark(endArg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
iv.invokevirtual(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iv.invokestatic(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.areturn(jvmSignature.getReturnType());
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
if(typeParameterDescriptor.isReified())
|
||||||
|
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
mv.visitMaxs(0, 0);
|
if(!isStatic) {
|
||||||
mv.visitEnd();
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
|
iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iv.invokevirtual(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iv.invokestatic(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
iv.areturn(jvmSignature.getReturnType());
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,29 +302,31 @@ public class FunctionCodegen {
|
|||||||
int flags = ACC_PUBLIC; // TODO.
|
int flags = ACC_PUBLIC; // TODO.
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
if(argType.getSort() == Type.OBJECT) {
|
if(argType.getSort() == Type.OBJECT) {
|
||||||
iv.checkcast(argType);
|
iv.checkcast(argType);
|
||||||
|
}
|
||||||
|
//noinspection AssignmentToForLoopParameter
|
||||||
|
reg += argType.getSize();
|
||||||
}
|
}
|
||||||
//noinspection AssignmentToForLoopParameter
|
|
||||||
reg += argType.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
|
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||||
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
||||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||||
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||||
iv.aconst(null);
|
iv.aconst(null);
|
||||||
iv.areturn(overriden.getReturnType());
|
iv.areturn(overriden.getReturnType());
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ public class GenerationState {
|
|||||||
bindingContexts.push(bindingContext);
|
bindingContexts.push(bindingContext);
|
||||||
try {
|
try {
|
||||||
for (JetNamespace namespace : namespaces) {
|
for (JetNamespace namespace : namespaces) {
|
||||||
NamespaceCodegen codegen = forNamespace(namespace);
|
generateNamespace(namespace);
|
||||||
codegen.generate(namespace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -114,6 +113,11 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void generateNamespace(JetNamespace namespace) {
|
||||||
|
NamespaceCodegen codegen = forNamespace(namespace);
|
||||||
|
codegen.generate(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
||||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||||
Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.defineClass(Opcodes.V1_6,
|
v.defineClass(myClass, Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
|
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
|
||||||
? Opcodes.ACC_INTERFACE
|
? Opcodes.ACC_INTERFACE
|
||||||
: 0/*Opcodes.ACC_SUPER*/),
|
: 0/*Opcodes.ACC_SUPER*/),
|
||||||
@@ -108,7 +108,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||||
|
|
||||||
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||||
v.getVisitor().visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
|
v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(myClass instanceof JetClass) {
|
if(myClass instanceof JetClass) {
|
||||||
@@ -181,22 +181,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Type[] argTypes = method.getArgumentTypes();
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
|
||||||
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
//noinspection AssignmentToForLoopParameter
|
//noinspection AssignmentToForLoopParameter
|
||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
|
||||||
|
|
||||||
iv.areturn(method.getReturnType());
|
|
||||||
mv.visitMaxs(0,0);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
}
|
||||||
else if(entry.getValue() instanceof PropertyDescriptor) {
|
else if(entry.getValue() instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||||
@@ -205,37 +207,42 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
|
Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
InstructionAdapter iv = null;
|
||||||
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
iv.areturn(method.getReturnType());
|
iv.areturn(method.getReturnType());
|
||||||
mv.visitMaxs(0,0);
|
mv.visitMaxs(0,0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
|
originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
iv = new InstructionAdapter(mv);
|
iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
Type[] argTypes = method.getArgumentTypes();
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
//noinspection AssignmentToForLoopParameter
|
//noinspection AssignmentToForLoopParameter
|
||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
|
||||||
|
|
||||||
iv.areturn(method.getReturnType());
|
|
||||||
mv.visitMaxs(0,0);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
@@ -330,6 +337,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
|
||||||
|
if (!v.generateCode()) return;
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
||||||
@@ -485,36 +494,38 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
|
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
codegen.generateThisOrOuter(descriptor);
|
codegen.generateThisOrOuter(descriptor);
|
||||||
|
|
||||||
Type[] argTypes = function.getArgumentTypes();
|
Type[] argTypes = function.getArgumentTypes();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
//noinspection AssignmentToForLoopParameter
|
//noinspection AssignmentToForLoopParameter
|
||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext());
|
||||||
|
Type type = state.getTypeMapper().mapType(jetType);
|
||||||
|
if(type.getInternalName().equals("java/lang/Object")) {
|
||||||
|
jetType = declaration.getDefaultType();
|
||||||
|
type = state.getTypeMapper().mapType(jetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||||
|
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||||
|
if(function.getReturnType().getSort() == Type.OBJECT) {
|
||||||
|
iv.checkcast(function.getReturnType());
|
||||||
|
}
|
||||||
|
iv.areturn(function.getReturnType());
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext());
|
|
||||||
Type type = state.getTypeMapper().mapType(jetType);
|
|
||||||
if(type.getInternalName().equals("java/lang/Object")) {
|
|
||||||
jetType = declaration.getDefaultType();
|
|
||||||
type = state.getTypeMapper().mapType(jetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor());
|
|
||||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
|
||||||
if(function.getReturnType().getSort() == Type.OBJECT) {
|
|
||||||
iv.checkcast(function.getReturnType());
|
|
||||||
}
|
|
||||||
iv.areturn(function.getReturnType());
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
|
||||||
|
|
||||||
FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind);
|
FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -619,35 +630,37 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
|
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
|
||||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
||||||
if (initializer instanceof JetDelegatorToThisCall) {
|
if (initializer instanceof JetDelegatorToThisCall) {
|
||||||
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
|
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
|
||||||
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
|
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
|
||||||
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
|
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
|
||||||
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
|
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
|
||||||
|
}
|
||||||
|
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("unknown initializer type");
|
||||||
}
|
}
|
||||||
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("unknown initializer type");
|
JetExpression bodyExpression = constructor.getBodyExpression();
|
||||||
|
if (bodyExpression != null) {
|
||||||
|
codegen.gen(bodyExpression, Type.VOID_TYPE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
JetExpression bodyExpression = constructor.getBodyExpression();
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
if (bodyExpression != null) {
|
mv.visitMaxs(0, 0);
|
||||||
codegen.gen(bodyExpression, Type.VOID_TYPE);
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
||||||
@@ -792,24 +805,29 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = null;
|
||||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
if (v.generateCode()) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv = new InstructionAdapter(mv);
|
||||||
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
mv.visitMaxs(0, 0);
|
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
mv.visitEnd();
|
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
|
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
iv = new InstructionAdapter(mv);
|
mv.visitCode();
|
||||||
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitEnd();
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -820,13 +838,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
private void genGetStaticGetTypeInfoMethod() {
|
private void genGetStaticGetTypeInfoMethod() {
|
||||||
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
InstructionAdapter v = new InstructionAdapter(mv);
|
mv.visitCode();
|
||||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
InstructionAdapter v = new InstructionAdapter(mv);
|
||||||
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
mv.visitMaxs(0, 0);
|
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
mv.visitEnd();
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void staticTypeInfoField() {
|
private void staticTypeInfoField() {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class NamespaceCodegen {
|
|||||||
this.v = v;
|
this.v = v;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
v.defineClass(V1_6,
|
v.defineClass(sourceFile, V1_6,
|
||||||
ACC_PUBLIC/*|ACC_SUPER*/,
|
ACC_PUBLIC/*|ACC_SUPER*/,
|
||||||
getJVMClassName(fqName),
|
getJVMClassName(fqName),
|
||||||
null,
|
null,
|
||||||
@@ -82,25 +82,27 @@ public class NamespaceCodegen {
|
|||||||
private void generateStaticInitializers(JetNamespace namespace) {
|
private void generateStaticInitializers(JetNamespace namespace) {
|
||||||
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
|
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
|
||||||
"<clinit>", "()V", null, null);
|
"<clinit>", "()V", null, null);
|
||||||
mv.visitCode();
|
if (v.generateCode()) {
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
||||||
|
|
||||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||||
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||||
codegen.genToJVMStack(initializer);
|
codegen.genToJVMStack(initializer);
|
||||||
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
|
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ public class PropertyCodegen {
|
|||||||
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
|
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
|
||||||
String getterName = getterName(propertyDescriptor.getName());
|
String getterName = getterName(propertyDescriptor.getName());
|
||||||
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
|
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
|
||||||
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
|
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
if (kind != OwnerKind.NAMESPACE) {
|
||||||
@@ -182,7 +182,7 @@ public class PropertyCodegen {
|
|||||||
|
|
||||||
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
|
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
|
||||||
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
||||||
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
|
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
v.defineClass(Opcodes.V1_6,
|
v.defineClass(myClass, Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/,
|
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/,
|
||||||
jvmName(),
|
jvmName(),
|
||||||
null,
|
null,
|
||||||
|
|||||||
+20
-4
@@ -4,7 +4,9 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
|
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -14,6 +16,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -61,7 +64,12 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
public JavaDescriptorResolver(Project project, JavaSemanticServices semanticServices) {
|
public JavaDescriptorResolver(Project project, JavaSemanticServices semanticServices) {
|
||||||
this.javaFacade = JavaPsiFacade.getInstance(project);
|
this.javaFacade = JavaPsiFacade.getInstance(project);
|
||||||
this.javaSearchScope = GlobalSearchScope.allScope(project);
|
this.javaSearchScope = new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) {
|
||||||
|
@Override
|
||||||
|
public boolean contains(VirtualFile file) {
|
||||||
|
return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE;
|
||||||
|
}
|
||||||
|
};
|
||||||
this.semanticServices = semanticServices;
|
this.semanticServices = semanticServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +88,7 @@ public class JavaDescriptorResolver {
|
|||||||
public ClassDescriptor resolveClass(@NotNull String qualifiedName) {
|
public ClassDescriptor resolveClass(@NotNull String qualifiedName) {
|
||||||
ClassDescriptor classDescriptor = classDescriptorCache.get(qualifiedName);
|
ClassDescriptor classDescriptor = classDescriptorCache.get(qualifiedName);
|
||||||
if (classDescriptor == null) {
|
if (classDescriptor == null) {
|
||||||
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
|
PsiClass psiClass = findClass(qualifiedName);
|
||||||
if (psiClass == null) {
|
if (psiClass == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -247,15 +255,23 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
|
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
|
||||||
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
|
PsiPackage psiPackage = findPackage(qualifiedName);
|
||||||
if (psiPackage == null) {
|
if (psiPackage == null) {
|
||||||
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
|
PsiClass psiClass = findClass(qualifiedName);
|
||||||
if (psiClass == null) return null;
|
if (psiClass == null) return null;
|
||||||
return resolveNamespace(psiClass);
|
return resolveNamespace(psiClass);
|
||||||
}
|
}
|
||||||
return resolveNamespace(psiPackage);
|
return resolveNamespace(psiPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PsiClass findClass(String qualifiedName) {
|
||||||
|
return javaFacade.findClass(qualifiedName, javaSearchScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiPackage findPackage(String qualifiedName) {
|
||||||
|
return javaFacade.findPackage(qualifiedName);
|
||||||
|
}
|
||||||
|
|
||||||
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
|
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
|
||||||
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
|
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
|
||||||
if (namespaceDescriptor == null) {
|
if (namespaceDescriptor == null) {
|
||||||
|
|||||||
@@ -16,15 +16,13 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
|||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder;
|
||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -120,4 +118,25 @@ public class AnalyzingUtils {
|
|||||||
return bindingTraceContext.getBindingContext();
|
return bindingTraceContext.getBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BindingContext shallowAnalyzeFiles(Collection<PsiFile> files) {
|
||||||
|
assert files.size() > 0;
|
||||||
|
|
||||||
|
Project project = files.iterator().next().getProject();
|
||||||
|
|
||||||
|
Collection<JetNamespace> namespaces = collectRootNamespaces(files);
|
||||||
|
|
||||||
|
return analyzeNamespaces(project, namespaces, Predicates.<PsiFile>alwaysFalse(), JetControlFlowDataTraceFactory.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<JetNamespace> collectRootNamespaces(Collection<PsiFile> files) {
|
||||||
|
List<JetNamespace> namespaces = new ArrayList<JetNamespace>();
|
||||||
|
|
||||||
|
for (PsiFile file : files) {
|
||||||
|
if (file instanceof JetFile) {
|
||||||
|
namespaces.add(((JetFile) file).getRootNamespace());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return namespaces;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,5 +56,7 @@
|
|||||||
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
||||||
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
|
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
|
||||||
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||||
|
|
||||||
|
<java.elementFinder implementation="org.jetbrains.jet.plugin.java.JavaElementFinder"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
*/
|
||||||
|
package org.jetbrains.jet.plugin.java;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Key;
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||||
|
import com.intellij.psi.impl.compiled.ClsEnumConstantImpl;
|
||||||
|
import com.intellij.psi.impl.compiled.ClsFieldImpl;
|
||||||
|
import com.intellij.psi.impl.compiled.ClsMethodImpl;
|
||||||
|
import com.intellij.psi.impl.java.stubs.*;
|
||||||
|
import com.intellij.psi.stubs.StubBase;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||||
|
public static final Key<PsiElement> ORIGIN_ELEMENT = Key.create("ORIGIN_ELEMENT");
|
||||||
|
private final StubPsiFactory delegate = new ClsStubPsiFactory();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiClass createClass(PsiClassStub stub) {
|
||||||
|
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||||
|
if (origin == null) return delegate.createClass(stub);
|
||||||
|
|
||||||
|
return new ClsClassImpl(stub) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiElement getNavigationElement() {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiAnnotation createAnnotation(PsiAnnotationStub stub) {
|
||||||
|
return delegate.createAnnotation(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiClassInitializer createClassInitializer(PsiClassInitializerStub stub) {
|
||||||
|
return delegate.createClassInitializer(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiReferenceList createClassReferenceList(PsiClassReferenceListStub stub) {
|
||||||
|
return delegate.createClassReferenceList(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiField createField(PsiFieldStub stub) {
|
||||||
|
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||||
|
if (origin == null) return delegate.createField(stub);
|
||||||
|
if (stub.isEnumConstant()) {
|
||||||
|
return new ClsEnumConstantImpl(stub) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiElement getNavigationElement() {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new ClsFieldImpl(stub) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiElement getNavigationElement() {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiImportList createImportList(PsiImportListStub stub) {
|
||||||
|
return delegate.createImportList(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiImportStatementBase createImportStatement(PsiImportStatementStub stub) {
|
||||||
|
return delegate.createImportStatement(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiMethod createMethod(PsiMethodStub stub) {
|
||||||
|
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||||
|
if (origin == null) return delegate.createMethod(stub);
|
||||||
|
|
||||||
|
return new ClsMethodImpl(stub) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiElement getNavigationElement() {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiModifierList createModifierList(PsiModifierListStub stub) {
|
||||||
|
return delegate.createModifierList(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiParameter createParameter(PsiParameterStub stub) {
|
||||||
|
return delegate.createParameter(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiParameterList createParameterList(PsiParameterListStub stub) {
|
||||||
|
return delegate.createParameterList(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiTypeParameter createTypeParameter(PsiTypeParameterStub stub) {
|
||||||
|
return delegate.createTypeParameter(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiTypeParameterList createTypeParameterList(PsiTypeParameterListStub stub) {
|
||||||
|
return delegate.createTypeParameterList(stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
*/
|
||||||
|
package org.jetbrains.jet.plugin.java;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Collections2;
|
||||||
|
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
|
||||||
|
import com.intellij.openapi.fileTypes.FileType;
|
||||||
|
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.roots.ProjectRootManager;
|
||||||
|
import com.intellij.openapi.util.Comparing;
|
||||||
|
import com.intellij.openapi.util.Key;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
import com.intellij.psi.impl.PsiManagerImpl;
|
||||||
|
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||||
|
import com.intellij.psi.impl.file.PsiPackageImpl;
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiClassStub;
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
|
||||||
|
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
|
import com.intellij.psi.stubs.PsiClassHolderFileStub;
|
||||||
|
import com.intellij.psi.stubs.StubElement;
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
import com.intellij.util.containers.Stack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||||
|
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||||
|
import org.jetbrains.jet.codegen.GenerationState;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
|
||||||
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class JavaElementFinder extends PsiElementFinder {
|
||||||
|
private final Project project;
|
||||||
|
|
||||||
|
public JavaElementFinder(Project project) {
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Key<PsiJavaFileStub> JAVA_API_STUB = Key.create("JAVA_API_STUB");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||||
|
final PsiClass[] allClasses = findClasses(qualifiedName, scope);
|
||||||
|
return allClasses.length > 0 ? allClasses[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||||
|
// Backend searches for java.lang.String. Will fail with SOE if continue
|
||||||
|
if (qualifiedName.startsWith("java.")) return PsiClass.EMPTY_ARRAY;
|
||||||
|
|
||||||
|
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||||
|
final List<PsiFile> filesInScope = ensureUpToDate(scope);
|
||||||
|
for (PsiFile file : filesInScope) {
|
||||||
|
final PsiJavaFileStub stub = file.getUserData(JAVA_API_STUB);
|
||||||
|
if (stub == null) continue;
|
||||||
|
|
||||||
|
final String packageName = stub.getPackageName();
|
||||||
|
if (packageName != null && qualifiedName.startsWith(packageName)) {
|
||||||
|
collectClasses(answer, qualifiedName, stub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answer.toArray(new PsiClass[answer.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiPackage findPackage(@NotNull String qualifiedName) {
|
||||||
|
final List<PsiFile> psiFiles = collectProjectFiles(project, GlobalSearchScope.allScope(project));
|
||||||
|
|
||||||
|
for (PsiFile psiFile : psiFiles) {
|
||||||
|
if (psiFile instanceof JetFile) {
|
||||||
|
if (qualifiedName.equals(((JetFile) psiFile).getRootNamespace().getFQName())) {
|
||||||
|
return new PsiPackageImpl(psiFile.getManager(), qualifiedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||||
|
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||||
|
final List<PsiFile> filesInScope = ensureUpToDate(scope);
|
||||||
|
final String qualifiedName = psiPackage.getQualifiedName();
|
||||||
|
for (PsiFile file : filesInScope) {
|
||||||
|
final PsiJavaFileStub stub = file.getUserData(JAVA_API_STUB);
|
||||||
|
if (stub == null) continue;
|
||||||
|
|
||||||
|
if (Comparing.equal(qualifiedName, stub.getPackageName())) {
|
||||||
|
for (StubElement child : stub.getChildrenStubs()) {
|
||||||
|
if (child instanceof PsiClassStub) {
|
||||||
|
answer.add((PsiClass) child.getPsi());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answer.toArray(new PsiClass[answer.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void collectClasses(List<PsiClass> answer, String qualifiedName, StubElement<?> stub) {
|
||||||
|
if (stub instanceof PsiClassStub && qualifiedName.equals(((PsiClassStub) stub).getQualifiedName())) {
|
||||||
|
answer.add((PsiClass) stub.getPsi());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (StubElement child : stub.getChildrenStubs()) {
|
||||||
|
collectClasses(answer, qualifiedName, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PsiFile> ensureUpToDate(GlobalSearchScope scope) {
|
||||||
|
final Stack<StubElement> stubStack = new Stack<StubElement>();
|
||||||
|
|
||||||
|
final ClassBuilderFactory builderFactory = new ClassBuilderFactory() {
|
||||||
|
@Override
|
||||||
|
public ClassBuilder newClassBuilder() {
|
||||||
|
return new StubClassBuilder(stubStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asText(ClassBuilder builder) {
|
||||||
|
throw new UnsupportedOperationException("asText is not implemented"); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] asBytes(ClassBuilder builder) {
|
||||||
|
throw new UnsupportedOperationException("asBytes is not implemented"); // TODO
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final GenerationState state = new GenerationState(project, builderFactory) {
|
||||||
|
@Override
|
||||||
|
protected void generateNamespace(JetNamespace namespace) {
|
||||||
|
final PsiJavaFileStubImpl fileStub = new PsiJavaFileStubImpl(namespace.getFQName(), true);
|
||||||
|
PsiManager manager = PsiManager.getInstance(project);
|
||||||
|
stubStack.push(fileStub);
|
||||||
|
|
||||||
|
final PsiFile file = namespace.getContainingFile();
|
||||||
|
file.putUserData(JAVA_API_STUB, fileStub);
|
||||||
|
fileStub.setPsiFactory(new ClsWrapperStubPsiFactory());
|
||||||
|
final ClsFileImpl fakeFile = new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, file.getVirtualFile())) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiClassHolderFileStub getStub() {
|
||||||
|
return fileStub;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fakeFile.setPhysical(false);
|
||||||
|
fileStub.setPsi(fakeFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
super.generateNamespace(namespace);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
final StubElement pop = stubStack.pop();
|
||||||
|
assert pop == fileStub : "Unbalanced stack operations";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final List<PsiFile> psiFiles = collectProjectFiles(project, scope);
|
||||||
|
|
||||||
|
Collection<PsiFile> dirty = Collections2.filter(psiFiles, new Predicate<PsiFile>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(PsiFile psiFile) {
|
||||||
|
return psiFile.getUserData(JAVA_API_STUB) == null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (dirty.size() > 0) {
|
||||||
|
final BindingContext context = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).shallowAnalyzeFiles(dirty);
|
||||||
|
state.compileCorrectNamespaces(context, AnalyzingUtils.collectRootNamespaces(dirty));
|
||||||
|
state.getFactory().files();
|
||||||
|
}
|
||||||
|
|
||||||
|
return psiFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PsiFile> collectProjectFiles(final Project project, @NotNull final GlobalSearchScope scope) {
|
||||||
|
final List<PsiFile> answer = new ArrayList<PsiFile>();
|
||||||
|
|
||||||
|
|
||||||
|
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
|
||||||
|
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||||
|
|
||||||
|
VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||||
|
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
|
||||||
|
@Override
|
||||||
|
protected void acceptFile(VirtualFile file, String fileRoot, String filePath) {
|
||||||
|
final FileType fileType = fileTypeManager.getFileTypeByFile(file);
|
||||||
|
if (fileType != JetFileType.INSTANCE) return;
|
||||||
|
|
||||||
|
if (scope.accept(file)) {
|
||||||
|
final PsiFile psiFile = psiManager.findFile(file);
|
||||||
|
if (psiFile instanceof JetFile) {
|
||||||
|
answer.add(psiFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
*/
|
||||||
|
package org.jetbrains.jet.plugin.java;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.impl.compiled.InnerClassSourceStrategy;
|
||||||
|
import com.intellij.psi.impl.compiled.StubBuildingVisitor;
|
||||||
|
import com.intellij.psi.stubs.StubBase;
|
||||||
|
import com.intellij.psi.stubs.StubElement;
|
||||||
|
import com.intellij.util.containers.Stack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.FieldVisitor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StubClassBuilder extends ClassBuilder {
|
||||||
|
private static final InnerClassSourceStrategy<Object> EMPTY_STRATEGY = new InnerClassSourceStrategy<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object findInnerClass(String s, Object o) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassReader readerForInnerClass(Object o) {
|
||||||
|
throw new UnsupportedOperationException("Shall not be called!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final StubElement parent;
|
||||||
|
private StubBuildingVisitor v;
|
||||||
|
private final Stack<StubElement> parentStack;
|
||||||
|
private boolean isNamespace = false;
|
||||||
|
|
||||||
|
public StubClassBuilder(Stack<StubElement> parentStack) {
|
||||||
|
this.parentStack = parentStack;
|
||||||
|
this.parent = parentStack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassVisitor getVisitor() {
|
||||||
|
assert v != null : "Called before class is defined";
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
|
||||||
|
assert v == null : "defineClass() called twice?";
|
||||||
|
v = new StubBuildingVisitor<Object>(null, EMPTY_STRATEGY, parent, access);
|
||||||
|
|
||||||
|
super.defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||||
|
if (name.equals("namespace") || name.endsWith("/namespace")) {
|
||||||
|
isNamespace = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parentStack.push(v.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodVisitor newMethod(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) {
|
||||||
|
final MethodVisitor answer = super.newMethod(origin, access, name, desc, signature, exceptions);
|
||||||
|
markLastChild(origin);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldVisitor newField(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable Object value) {
|
||||||
|
final FieldVisitor answer = super.newField(origin, access, name, desc, signature, value);
|
||||||
|
markLastChild(origin);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markLastChild(PsiElement origin) {
|
||||||
|
final List children = v.getResult().getChildrenStubs();
|
||||||
|
StubBase last = (StubBase) children.get(children.size() - 1);
|
||||||
|
last.putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void done() {
|
||||||
|
if (!isNamespace) {
|
||||||
|
final StubElement pop = parentStack.pop();
|
||||||
|
assert pop == v.getResult();
|
||||||
|
}
|
||||||
|
super.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean generateCode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user