Resolve Kotlin from Java, first drop.

This commit is contained in:
Maxim Shafirov
2011-11-11 19:57:40 +04:00
parent aa02dcd0e7
commit 627a1dbf6f
16 changed files with 842 additions and 317 deletions
@@ -116,18 +116,20 @@ public abstract class ClassBodyCodegen {
if (staticInitializerChunks.size() > 0) {
final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<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) {
chunk.generate(v);
for (CodeChunk chunk : staticInitializerChunks) {
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.MethodVisitor;
public class ClassBuilder {
private final ClassVisitor v;
public abstract class ClassBuilder {
public static class Concrete extends ClassBuilder {
private final ClassVisitor v;
public ClassBuilder(ClassVisitor v) {
this.v = v;
public Concrete(ClassVisitor v) {
this.v = v;
}
@Override
public ClassVisitor getVisitor() {
return v;
}
}
public FieldVisitor newField(@Nullable PsiElement origin,
int access,
String name,
String desc,
@Nullable String signature,
@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,
@@ -32,28 +38,34 @@ public class ClassBuilder {
String desc,
@Nullable String signature,
@Nullable String[] exceptions) {
return v.visitMethod(access, name, desc, signature, exceptions);
return getVisitor().visitMethod(access, name, desc, signature, exceptions);
}
public AnnotationVisitor newAnnotation(PsiElement origin,
String desc,
boolean visible) {
return v.visitAnnotation(desc, visible);
return getVisitor().visitAnnotation(desc, visible);
}
public void done() {
v.visitEnd();
getVisitor().visitEnd();
}
public ClassVisitor getVisitor() {
return v;
}
public abstract ClassVisitor getVisitor();
public void defineClass(int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
v.visit(version, access, name, signature, superName, interfaces);
public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
getVisitor().visit(version, access, name, signature, superName, interfaces);
}
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() {
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder(new TraceClassVisitor(new PrintWriter(new StringWriter())));
return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())));
}
@Override
@@ -39,7 +39,7 @@ public interface ClassBuilderFactory {
ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
@Override
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
@@ -69,7 +69,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
appendType(signatureWriter, funDescriptor.getReturnType(), '=');
signatureWriter.visitEnd();
cv.defineClass(V1_6,
cv.defineClass(fun,
V1_6,
ACC_PUBLIC/*|ACC_SUPER*/,
name,
null,
@@ -112,23 +113,25 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
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]);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
mv.visitInsn(DUP);
Label ret = new Label();
mv.visitJumpInsn(IFNONNULL, ret);
if (cv.generateCode()) {
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
mv.visitInsn(DUP);
Label ret = new Label();
mv.visitJumpInsn(IFNONNULL, ret);
mv.visitInsn(POP);
mv.visitTypeInsn(NEW, name);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
mv.visitInsn(DUP);
mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
mv.visitInsn(POP);
mv.visitTypeInsn(NEW, name);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
mv.visitInsn(DUP);
mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
mv.visitLabel(ret);
mv.visitInsn(ARETURN);
mv.visitMaxs(0,0);
mv.visitEnd();
mv.visitLabel(ret);
mv.visitInsn(ARETURN);
mv.visitMaxs(0,0);
mv.visitEnd();
}
}
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
@@ -157,34 +160,36 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return;
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();
int count = 1;
if (receiver.exists()) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
count++;
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
int count = 1;
if (receiver.exists()) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
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) {
@@ -221,14 +226,15 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
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]);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
if (cv.generateCode()) {
mv.visitCode();
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));
iv.aconst(null); // @todo
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
iv.aconst(null); // @todo
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
i = 1;
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;
}
@@ -70,12 +70,12 @@ public class FunctionCodegen {
if(kind != OwnerKind.TRAIT_IMPL) {
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
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.visitEnd();
}
}
if (!isAbstract) {
if (!isAbstract && v.generateCode()) {
mv.visitCode();
FrameMap frameMap = context.prepareFrame();
@@ -192,103 +192,105 @@ public class FunctionCodegen {
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
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();
var++;
}
if(hasReceiver) {
frameMap.enterTemp();
var++;
}
int maskIndex = 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++;
}
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);
var = 0;
if(!isStatic) {
mv.visitVarInsn(ALOAD, var++);
}
iv.load(var, t);
var += t.getSize();
if (parameterDescriptor.hasDefaultValue()) {
iv.mark(endArg);
if(hasReceiver) {
mv.visitVarInsn(ALOAD, var++);
}
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
if(typeParameterDescriptor.isReified())
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
}
Type[] argumentTypes = jvmSignature.getArgumentTypes();
for (int index = 0; index < paramDescrs.size(); index++) {
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
if(!isStatic) {
if(kind == OwnerKind.TRAIT_IMPL) {
iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor());
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);
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);
mv.visitEnd();
if(!isStatic) {
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.
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
mv.visitCode();
if (v.generateCode()) {
mv.visitCode();
Type[] argTypes = jvmSignature.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
if(argType.getSort() == Type.OBJECT) {
iv.checkcast(argType);
Type[] argTypes = jvmSignature.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
if(argType.getSort() == Type.OBJECT) {
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());
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
StackValue.valueOf(iv, jvmSignature.getReturnType());
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
iv.aconst(null);
iv.areturn(overriden.getReturnType());
mv.visitMaxs(0, 0);
mv.visitEnd();
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
StackValue.valueOf(iv, jvmSignature.getReturnType());
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
iv.aconst(null);
iv.areturn(overriden.getReturnType());
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
}
@@ -104,8 +104,7 @@ public class GenerationState {
bindingContexts.push(bindingContext);
try {
for (JetNamespace namespace : namespaces) {
NamespaceCodegen codegen = forNamespace(namespace);
codegen.generate(namespace);
generateNamespace(namespace);
}
}
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) {
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
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_INTERFACE
: 0/*Opcodes.ACC_SUPER*/),
@@ -108,7 +108,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.visitSource(myClass.getContainingFile().getName(), null);
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) {
@@ -181,22 +181,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Type[] argTypes = method.getArgumentTypes();
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);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
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) {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
@@ -205,37 +207,42 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method method = state.getTypeMapper().mapGetterSignature(bridge, 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);
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.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
mv.visitMaxs(0,0);
mv.visitEnd();
iv.areturn(method.getReturnType());
mv.visitMaxs(0,0);
mv.visitEnd();
}
method = state.getTypeMapper().mapSetterSignature(bridge, 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.visitCode();
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
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 {
throw new UnsupportedOperationException();
@@ -330,6 +337,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
if (!v.generateCode()) return;
mv.visitCode();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
@@ -485,36 +494,38 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
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();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
Type[] argTypes = function.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
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);
}
}
@@ -619,35 +630,37 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO
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);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
if (initializer instanceof JetDelegatorToThisCall) {
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
if (initializer instanceof JetDelegatorToThisCall) {
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
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();
if (bodyExpression != null) {
codegen.gen(bodyExpression, Type.VOID_TYPE);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
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);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
InstructionAdapter iv = null;
if (v.generateCode()) {
iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
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.visitCode();
iv = new InstructionAdapter(mv);
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
}
else {
@@ -820,13 +838,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void genGetStaticGetTypeInfoMethod() {
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
private void staticTypeInfoField() {
@@ -31,7 +31,7 @@ public class NamespaceCodegen {
this.v = v;
this.state = state;
v.defineClass(V1_6,
v.defineClass(sourceFile, V1_6,
ACC_PUBLIC/*|ACC_SUPER*/,
getJVMClassName(fqName),
null,
@@ -82,25 +82,27 @@ public class NamespaceCodegen {
private void generateStaticInitializers(JetNamespace namespace) {
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null);
mv.visitCode();
if (v.generateCode()) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
FrameMap frameMap = new FrameMap();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
}
}
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
@@ -137,7 +137,7 @@ public class PropertyCodegen {
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
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();
InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) {
@@ -182,7 +182,7 @@ public class PropertyCodegen {
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
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();
InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
@@ -45,7 +45,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration() {
v.defineClass(Opcodes.V1_6,
v.defineClass(myClass, Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/,
jvmName(),
null,
@@ -4,7 +4,9 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
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.DescriptorUtils;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
import java.util.*;
@@ -61,7 +64,12 @@ public class JavaDescriptorResolver {
public JavaDescriptorResolver(Project project, JavaSemanticServices semanticServices) {
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;
}
@@ -80,7 +88,7 @@ public class JavaDescriptorResolver {
public ClassDescriptor resolveClass(@NotNull String qualifiedName) {
ClassDescriptor classDescriptor = classDescriptorCache.get(qualifiedName);
if (classDescriptor == null) {
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
PsiClass psiClass = findClass(qualifiedName);
if (psiClass == null) {
return null;
}
@@ -247,15 +255,23 @@ public class JavaDescriptorResolver {
}
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
PsiPackage psiPackage = findPackage(qualifiedName);
if (psiPackage == null) {
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
PsiClass psiClass = findClass(qualifiedName);
if (psiClass == null) return null;
return resolveNamespace(psiClass);
}
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) {
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
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.DiagnosticUtils;
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.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author abreslav
@@ -120,4 +118,25 @@ public class AnalyzingUtils {
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;
}
}
+2
View File
@@ -56,5 +56,7 @@
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
<java.elementFinder implementation="org.jetbrains.jet.plugin.java.JavaElementFinder"/>
</extensions>
</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;
}
}