Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2011-12-14 14:27:12 +04:00
30 changed files with 744 additions and 105 deletions
@@ -1,12 +1,17 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.signature.JetSignatureWriter; import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureAdapter;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureWriter;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter; import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack; import java.util.Stack;
/** /**
@@ -27,13 +32,31 @@ public class BothSignatureWriter {
this.asmType = asmType; this.asmType = asmType;
} }
} }
private enum State {
START,
TYPE_PARAMETERS,
PARAMETERS,
RETURN_TYPE,
METHOD_END,
SUPERS,
CLASS_END,
}
private final SignatureWriter signatureWriter = new SignatureWriter(); private final SignatureWriter signatureWriter = new SignatureWriter();
private final SignatureVisitor signatureVisitor; private final SignatureVisitor signatureVisitor;
private final JetSignatureWriter jetSignatureWriter = new JetSignatureWriter(); private JetSignatureWriter jetSignatureWriter;
private String kotlinClassSignature;
private List<String> kotlinParameterTypes = new ArrayList<String>();
private String kotlinReturnType;
private final Mode mode; private final Mode mode;
private State state = State.START;
public BothSignatureWriter(Mode mode) { public BothSignatureWriter(Mode mode) {
this.mode = mode; this.mode = mode;
@@ -76,20 +99,37 @@ public class BothSignatureWriter {
} }
} }
} }
private void checkState(State state) {
if (DEBUG_SIGNATURE_WRITER) {
if (state != this.state) {
throw new IllegalStateException();
}
if (jetSignatureWriter != null) {
throw new IllegalStateException();
}
checkTopLevel();
}
}
private void transitionState(State from, State to) {
checkState(from);
state = to;
}
/** /**
* Shortcut * Shortcut
*/ */
public void writeAsmType(Type asmType) { public void writeAsmType(Type asmType, boolean nullable) {
switch (asmType.getSort()) { switch (asmType.getSort()) {
case Type.OBJECT: case Type.OBJECT:
writeClassBegin(asmType.getInternalName()); writeClassBegin(asmType.getInternalName(), nullable);
writeClassEnd(); writeClassEnd();
return; return;
case Type.ARRAY: case Type.ARRAY:
writeArrayType(); writeArrayType(nullable);
writeAsmType(asmType.getElementType()); writeAsmType(asmType.getElementType(), false);
writeArrayEnd(); writeArrayEnd();
return; return;
default: default:
@@ -97,20 +137,31 @@ public class BothSignatureWriter {
if (descriptor.length() != 1) { if (descriptor.length() != 1) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
signatureVisitor().visitBaseType(descriptor.charAt(0)); writeBaseType(descriptor.charAt(0), nullable);
} }
} }
public void writeClassBegin(String internalName) { private void writeBaseType(char c, boolean nullable) {
if (nullable) {
throw new IllegalStateException();
}
signatureVisitor().visitBaseType(c);
jetSignatureWriter.visitBaseType(c, nullable);
}
public void writeClassBegin(String internalName, boolean nullable) {
signatureVisitor().visitClassType(internalName); signatureVisitor().visitClassType(internalName);
jetSignatureWriter.visitClassType(internalName, nullable);
} }
public void writeClassEnd() { public void writeClassEnd() {
signatureVisitor().visitEnd(); signatureVisitor().visitEnd();
jetSignatureWriter.visitEnd();
} }
public void writeArrayType() { public void writeArrayType(boolean nullable) {
push(signatureVisitor().visitArrayType()); push(signatureVisitor().visitArrayType());
jetSignatureWriter.visitArrayType(nullable);
} }
public void writeArrayEnd() { public void writeArrayEnd() {
@@ -119,24 +170,39 @@ public class BothSignatureWriter {
public void writeTypeArgument(char c) { public void writeTypeArgument(char c) {
push(signatureVisitor().visitTypeArgument(c)); push(signatureVisitor().visitTypeArgument(c));
jetSignatureWriter.visitTypeArgument(c);
} }
public void writeTypeArgumentEnd() { public void writeTypeArgumentEnd() {
pop(); pop();
} }
public void writeTypeVariable(final String name) { public void writeTypeVariable(final String name, boolean nullable) {
signatureVisitor().visitTypeVariable(name); signatureVisitor().visitTypeVariable(name);
jetSignatureWriter.visitTypeVariable(name, nullable);
} }
public void writeFormalTypeParameter(final String name) { public void writeFormalTypeParameter(final String name) {
checkTopLevel(); checkTopLevel();
signatureVisitor().visitFormalTypeParameter(name); signatureVisitor().visitFormalTypeParameter(name);
jetSignatureWriter.visitFormalTypeParameter(name);
}
public void writerFormalTypeParametersStart() {
checkTopLevel();
transitionState(State.START, State.TYPE_PARAMETERS);
jetSignatureWriter = new JetSignatureWriter();
}
public void writeFormalTypeParametersEnd() {
jetSignatureWriter = null;
checkState(State.TYPE_PARAMETERS);
} }
public void writeClassBound() { public void writeClassBound() {
push(signatureVisitor().visitClassBound()); push(signatureVisitor().visitClassBound());
jetSignatureWriter.visitClassBound();
} }
public void writeClassBoundEnd() { public void writeClassBoundEnd() {
@@ -145,33 +211,75 @@ public class BothSignatureWriter {
public void writeInterfaceBound() { public void writeInterfaceBound() {
push(signatureVisitor().visitInterfaceBound()); push(signatureVisitor().visitInterfaceBound());
jetSignatureWriter.visitInterfaceBound();
} }
public void writeInterfaceBoundEnd() { public void writeInterfaceBoundEnd() {
pop(); pop();
} }
public void writeParametersStart() {
transitionState(State.TYPE_PARAMETERS, State.PARAMETERS);
}
public void writeParametersEnd() {
checkState(State.PARAMETERS);
}
public void writeParameterType() { public void writeParameterType() {
push(signatureVisitor().visitParameterType()); push(signatureVisitor().visitParameterType());
jetSignatureWriter = new JetSignatureWriter();
//jetSignatureWriter.visitParameterType();
} }
public void writeParameterTypeEnd() { public void writeParameterTypeEnd() {
pop(); pop();
String signature = jetSignatureWriter.toString();
kotlinParameterTypes.add(signature);
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(signature).acceptTypeOnly(new JetSignatureAdapter());
}
jetSignatureWriter = null;
} }
public void writeReturnType() { public void writeReturnType() {
transitionState(State.PARAMETERS, State.RETURN_TYPE);
jetSignatureWriter = new JetSignatureWriter();
push(signatureVisitor().visitReturnType()); push(signatureVisitor().visitReturnType());
//jetSignatureWriter.visitReturnType();
} }
public void writeReturnTypeEnd() { public void writeReturnTypeEnd() {
pop(); pop();
kotlinReturnType = jetSignatureWriter.toString();
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(kotlinReturnType).acceptTypeOnly(new JetSignatureAdapter());
}
jetSignatureWriter = null;
transitionState(State.RETURN_TYPE, State.METHOD_END);
}
public void writeSupersStart() {
transitionState(State.TYPE_PARAMETERS, State.SUPERS);
jetSignatureWriter = new JetSignatureWriter();
}
public void writeSupersEnd() {
kotlinClassSignature = jetSignatureWriter.toString();
jetSignatureWriter = null;
transitionState(State.SUPERS, State.CLASS_END);
} }
public void writeSuperclass() { public void writeSuperclass() {
checkTopLevel();
checkMode(Mode.CLASS);
push(signatureVisitor().visitSuperclass()); push(signatureVisitor().visitSuperclass());
jetSignatureWriter.visitSuperclass();
} }
public void writeSuperclassEnd() { public void writeSuperclassEnd() {
@@ -186,6 +294,7 @@ public class BothSignatureWriter {
checkMode(Mode.CLASS); checkMode(Mode.CLASS);
push(signatureVisitor().visitInterface()); push(signatureVisitor().visitInterface());
jetSignatureWriter.visitInterface();
} }
public void writeInterfaceEnd() { public void writeInterfaceEnd() {
@@ -200,16 +309,31 @@ public class BothSignatureWriter {
@Nullable @Nullable
public String makeJavaString() { public String makeJavaString() {
if (!visitors.isEmpty()) { if (state != State.METHOD_END && state != State.CLASS_END) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
checkTopLevel();
// TODO: return null if not generic
return signatureWriter.toString(); return signatureWriter.toString();
} }
@NotNull
public List<String> makeKotlinSignatures() {
checkState(State.METHOD_END);
// TODO: return nulls if equal to #makeJavaString
return kotlinParameterTypes;
}
@Nullable @Nullable
public String makeKotlinString() { public String makeKotlinReturnTypeSignature() {
// TODO: not implemented yet checkState(State.METHOD_END);
return null; return kotlinReturnType;
}
@Nullable
public String makeKotlinClassSignature() {
checkState(State.CLASS_END);
return kotlinClassSignature;
} }
} }
@@ -53,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) { public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd); Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd); String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null, null, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) { if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd); result.setNeedsReceiver(fd);
} }
@@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper()); final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor); fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null), funDescriptor);
return closureContext.outerWasUsed; return closureContext.outerWasUsed;
} }
@@ -90,6 +90,9 @@ public class FunctionCodegen {
if(functionDescriptor.getReturnType().isNullable()) { if(functionDescriptor.getReturnType().isNullable()) {
av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true); av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
} }
if (jvmSignature.getKotlinReturnType() != null) {
av.visit(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD, jvmSignature.getKotlinReturnType());
}
av.visitEnd(); av.visitEnd();
} }
@@ -121,6 +124,9 @@ public class FunctionCodegen {
if(parameterDescriptor.getOutType().isNullable()) { if(parameterDescriptor.getOutType().isNullable()) {
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true); av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
} }
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
av.visit(StdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(i));
}
av.visitEnd(); av.visitEnd();
} }
} }
@@ -61,7 +61,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
? Opcodes.ACC_INTERFACE ? Opcodes.ACC_INTERFACE
: 0/*Opcodes.ACC_SUPER*/), : 0/*Opcodes.ACC_SUPER*/),
signature.getName(), signature.getName(),
signature.getGenericSignature(), signature.getJavaGenericSignature(),
signature.getSuperclassName(), signature.getSuperclassName(),
signature.getInterfaces().toArray(new String[0]) signature.getInterfaces().toArray(new String[0])
); );
@@ -77,57 +77,55 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
annotationVisitor.visitEnd(); annotationVisitor.visitEnd();
} }
} }
private JvmClassSignature signature() { private JvmClassSignature signature() {
String genericSignature;
List<String> superInterfaces; List<String> superInterfaces;
{ LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS); BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
{ // type parameters { // type parameters
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters(); List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor); typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor);
}
{ // superclass
signatureVisitor.writeSuperclass();
if (superClassType == null) {
signatureVisitor.writeClassBegin(superClass);
signatureVisitor.writeClassEnd();
} else {
typeMapper.mapType(superClassType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
}
signatureVisitor.writeSuperclassEnd();
}
{ // superinterfaces
superInterfacesLinkedHashSet.add(StdlibNames.JET_OBJECT_INTERNAL);
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.isInterface(superClassDescriptor)) {
signatureVisitor.writeInterface();
Type jvmName = typeMapper.mapType(superType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
signatureVisitor.writeInterfaceEnd();
superInterfacesLinkedHashSet.add(jvmName.getInternalName());
}
}
superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet);
}
// TODO: null if class is not generic and does not have generic superclasses
genericSignature = signatureVisitor.makeJavaString();
} }
return new JvmClassSignature(jvmName(), superClass, superInterfaces, genericSignature);
signatureVisitor.writeSupersStart();
{ // superclass
signatureVisitor.writeSuperclass();
if (superClassType == null) {
signatureVisitor.writeClassBegin(superClass, false);
signatureVisitor.writeClassEnd();
} else {
typeMapper.mapType(superClassType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
}
signatureVisitor.writeSuperclassEnd();
}
{ // superinterfaces
superInterfacesLinkedHashSet.add(StdlibNames.JET_OBJECT_INTERNAL);
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.isInterface(superClassDescriptor)) {
signatureVisitor.writeInterface();
Type jvmName = typeMapper.mapType(superType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
signatureVisitor.writeInterfaceEnd();
superInterfacesLinkedHashSet.add(jvmName.getInternalName());
}
}
superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet);
}
signatureVisitor.writeSupersEnd();
return new JvmClassSignature(jvmName(), superClass, superInterfaces, signatureVisitor.makeJavaString(), signatureVisitor.makeKotlinClassSignature());
} }
private String jvmName() { private String jvmName() {
@@ -324,7 +322,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList()); callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null, null, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
} }
else { else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
@@ -165,13 +165,13 @@ public class JetTypeMapper {
@NotNull private Type mapReturnType(final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) { @NotNull private Type mapReturnType(final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) { if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeAsmType(Type.VOID_TYPE); signatureVisitor.writeAsmType(Type.VOID_TYPE, false);
} }
return Type.VOID_TYPE; return Type.VOID_TYPE;
} }
if (jetType.equals(JetStandardClasses.getNullableNothingType())) { if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT); visitAsmType(signatureVisitor, TYPE_OBJECT, false);
} }
return TYPE_OBJECT; return TYPE_OBJECT;
} }
@@ -257,7 +257,7 @@ public class JetTypeMapper {
JetType memberType = jetType.getArguments().get(0).getType(); JetType memberType = jetType.getArguments().get(0).getType();
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeArrayType(); signatureVisitor.writeArrayType(jetType.isNullable());
mapType(memberType, kind, signatureVisitor, true); mapType(memberType, kind, signatureVisitor, true);
signatureVisitor.writeArrayEnd(); signatureVisitor.writeArrayEnd();
} }
@@ -271,7 +271,7 @@ public class JetTypeMapper {
if (JetStandardClasses.getAny().equals(descriptor)) { if (JetStandardClasses.getAny().equals(descriptor)) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT); visitAsmType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
} }
return TYPE_OBJECT; return TYPE_OBJECT;
} }
@@ -282,7 +282,7 @@ public class JetTypeMapper {
Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : "")); Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeClassBegin(asmType.getInternalName()); signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
for (TypeProjection proj : jetType.getArguments()) { for (TypeProjection proj : jetType.getArguments()) {
// TODO: +- // TODO: +-
signatureVisitor.writeTypeArgument('='); signatureVisitor.writeTypeArgument('=');
@@ -298,7 +298,7 @@ public class JetTypeMapper {
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptor) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor(); TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName()); signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable());
} }
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
@@ -310,16 +310,16 @@ public class JetTypeMapper {
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean genericTypeParameter) { private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean genericTypeParameter) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
if (genericTypeParameter) { if (genericTypeParameter) {
visitAsmType(signatureVisitor, boxType(asmType)); visitAsmType(signatureVisitor, boxType(asmType), jetType.isNullable());
} else { } else {
visitAsmType(signatureVisitor, asmType); visitAsmType(signatureVisitor, asmType, jetType.isNullable());
} }
} }
return asmType; return asmType;
} }
public static void visitAsmType(BothSignatureWriter visitor, Type asmType) { public static void visitAsmType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
visitor.writeAsmType(asmType); visitor.writeAsmType(asmType, nullable);
} }
public static Type unboxType(final Type type) { public static Type unboxType(final Type type) {
@@ -469,12 +469,16 @@ public class JetTypeMapper {
signatureVisitor.writeParameterTypeEnd(); signatureVisitor.writeParameterTypeEnd();
} }
} }
if (signatureVisitor != null) {
signatureVisitor.writeParametersStart();
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) { for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) { if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO); parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeParameterType(); signatureVisitor.writeParameterType();
visitAsmType(signatureVisitor, TYPE_TYPEINFO); visitAsmType(signatureVisitor, TYPE_TYPEINFO, false);
signatureVisitor.writeParameterTypeEnd(); signatureVisitor.writeParameterTypeEnd();
} }
} }
@@ -490,12 +494,17 @@ public class JetTypeMapper {
valueParameterTypes.add(type); valueParameterTypes.add(type);
parameterTypes.add(type); parameterTypes.add(type);
} }
if (signatureVisitor != null) {
signatureVisitor.writeParametersEnd();
}
Type returnType; Type returnType;
if (f instanceof ConstructorDescriptor) { if (f instanceof ConstructorDescriptor) {
returnType = Type.VOID_TYPE; returnType = Type.VOID_TYPE;
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeReturnType(); signatureVisitor.writeReturnType();
visitAsmType(signatureVisitor, Type.VOID_TYPE); visitAsmType(signatureVisitor, Type.VOID_TYPE, false);
signatureVisitor.writeReturnTypeEnd(); signatureVisitor.writeReturnTypeEnd();
} }
} else { } else {
@@ -509,7 +518,12 @@ public class JetTypeMapper {
} }
} }
Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, signatureVisitor != null ? signatureVisitor.makeJavaString() : null); if (signatureVisitor == null) {
return new JvmMethodSignature(method, null, null, null);
} else {
return new JvmMethodSignature(method, signatureVisitor.makeJavaString(),
signatureVisitor.makeKotlinSignatures(), signatureVisitor.makeKotlinReturnTypeSignature());
}
} }
@@ -518,9 +532,11 @@ public class JetTypeMapper {
return; return;
} }
signatureVisitor.writerFormalTypeParametersStart();
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor); writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
} }
signatureVisitor.writeFormalTypeParametersEnd();
} }
private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) { private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
@@ -567,7 +583,7 @@ public class JetTypeMapper {
} }
Type returnType = mapReturnType(f.getReturnType()); Type returnType = mapReturnType(f.getReturnType());
// TODO: proper generic signature // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null); return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null, null, null);
} }
@@ -592,7 +608,7 @@ public class JetTypeMapper {
} }
// TODO: proper generic signature // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null); return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null);
} }
@Nullable @Nullable
@@ -622,7 +638,7 @@ public class JetTypeMapper {
params.add(mapType(inType)); params.add(mapType(inType));
// TODO: proper generic signature // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null); return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null);
} }
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) { private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -644,7 +660,7 @@ public class JetTypeMapper {
} }
Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, null); // TODO: generics signature return new JvmMethodSignature(method, null, null, null); // TODO: generics signature
} }
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
@@ -1,5 +1,8 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
/** /**
@@ -9,13 +12,16 @@ public class JvmClassSignature {
private final String name; private final String name;
private final String superclassName; private final String superclassName;
private final List<String> interfaces; private final List<String> interfaces;
private final String genericSignature; private final String javaGenericSignature;
private final String kotlinGenericSignature;
public JvmClassSignature(String name, String superclassName, List<String> interfaces, String genericSignature) { public JvmClassSignature(String name, String superclassName, List<String> interfaces,
@Nullable String javaGenericSignature, @Nullable String kotlinGenericSignature) {
this.name = name; this.name = name;
this.superclassName = superclassName; this.superclassName = superclassName;
this.interfaces = interfaces; this.interfaces = interfaces;
this.genericSignature = genericSignature; this.javaGenericSignature = javaGenericSignature;
this.kotlinGenericSignature = kotlinGenericSignature;
} }
public String getName() { public String getName() {
@@ -30,7 +36,11 @@ public class JvmClassSignature {
return interfaces; return interfaces;
} }
public String getGenericSignature() { public String getJavaGenericSignature() {
return genericSignature; return javaGenericSignature;
}
public String getKotlinGenericSignature() {
return kotlinGenericSignature;
} }
} }
@@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import java.util.List;
/** /**
* @author Stepan Koltsov * @author Stepan Koltsov
*/ */
@@ -12,10 +14,16 @@ public class JvmMethodSignature {
private final Method asmMethod; private final Method asmMethod;
/** Null when we don't care about type parameters */ /** Null when we don't care about type parameters */
private final String genericsSignature; private final String genericsSignature;
// TODO: type parameters
private final List<String> kotlinParameterTypes;
private final String kotlinReturnType;
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature) { public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature,
@Nullable List<String> kotlinParameterTypes, @Nullable String kotlinReturnType) {
this.asmMethod = asmMethod; this.asmMethod = asmMethod;
this.genericsSignature = genericsSignature; this.genericsSignature = genericsSignature;
this.kotlinParameterTypes = kotlinParameterTypes;
this.kotlinReturnType = kotlinReturnType;
} }
public Method getAsmMethod() { public Method getAsmMethod() {
@@ -25,4 +33,12 @@ public class JvmMethodSignature {
public String getGenericsSignature() { public String getGenericsSignature() {
return genericsSignature; return genericsSignature;
} }
public List<String> getKotlinParameterTypes() {
return kotlinParameterTypes;
}
public String getKotlinReturnType() {
return kotlinReturnType;
}
} }
@@ -68,6 +68,10 @@ public class SignatureUtil {
private static void genTypeParams(JetClass type, StringBuilder sb) { private static void genTypeParams(JetClass type, StringBuilder sb) {
List<JetTypeParameter> parameters = type.getTypeParameterList().getParameters(); List<JetTypeParameter> parameters = type.getTypeParameterList().getParameters();
if (parameters.isEmpty()) {
return;
}
sb.append('<');
for(JetTypeParameter param : parameters) { for(JetTypeParameter param : parameters) {
sb.append("T"); sb.append("T");
Variance variance = param.getVariance(); Variance variance = param.getVariance();
@@ -78,5 +82,6 @@ public class SignatureUtil {
sb.append(param.getName()); sb.append(param.getName());
sb.append(";"); sb.append(";");
} }
sb.append('>');
} }
} }
@@ -360,6 +360,7 @@ public class JavaDescriptorResolver {
boolean changeNullable = false; boolean changeNullable = false;
boolean nullable = true; boolean nullable = true;
String typeFromAnnotation = null;
// TODO: must be very slow, make it lazy? // TODO: must be very slow, make it lazy?
String name = parameter.getName() != null ? parameter.getName() : "p" + i; String name = parameter.getName() != null ? parameter.getName() : "p" + i;
@@ -383,10 +384,20 @@ public class JavaDescriptorResolver {
nullable = false; nullable = false;
changeNullable = true; changeNullable = true;
} }
PsiLiteralExpression signatureExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD);
if (signatureExpression != null) {
typeFromAnnotation = (String) signatureExpression.getValue();
}
} }
} }
JetType outType = semanticServices.getTypeTransformer().transformToType(psiType); JetType outType;
if (typeFromAnnotation != null) {
outType = semanticServices.getTypeTransformer().transformToType(typeFromAnnotation);
} else {
outType = semanticServices.getTypeTransformer().transformToType(psiType);
}
return new ValueParameterDescriptorImpl( return new ValueParameterDescriptorImpl(
containingDeclaration, containingDeclaration,
i, i,
@@ -509,6 +520,8 @@ public class JavaDescriptorResolver {
private JetType makeReturnType(PsiType returnType, PsiMethod method) { private JetType makeReturnType(PsiType returnType, PsiMethod method) {
boolean changeNullable = false; boolean changeNullable = false;
boolean nullable = true; boolean nullable = true;
String returnTypeFromAnnotation = null;
for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) {
if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) { if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) {
@@ -520,9 +533,19 @@ public class JavaDescriptorResolver {
nullable = false; nullable = false;
changeNullable = true; changeNullable = true;
} }
PsiLiteralExpression returnTypeExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD);
if (returnTypeExpression != null) {
returnTypeFromAnnotation = (String) returnTypeExpression.getValue();
}
} }
} }
JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType); JetType transformedType;
if (returnTypeFromAnnotation != null) {
transformedType = semanticServices.getTypeTransformer().transformToType(returnTypeFromAnnotation);
} else {
transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
}
if (changeNullable) { if (changeNullable) {
return TypeUtils.makeNullableAsSpecified(transformedType, nullable); return TypeUtils.makeNullableAsSpecified(transformedType, nullable);
} else { } else {
@@ -6,6 +6,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collections; import java.util.Collections;
@@ -57,6 +59,19 @@ public class JavaTypeTransformer {
return result; return result;
} }
@NotNull
public JetType transformToType(@NotNull String kotlinSignature) {
final JetType[] r = new JetType[1];
JetTypeJetSignatureReader reader = new JetTypeJetSignatureReader(resolver, standardLibrary) {
@Override
protected void done(@NotNull JetType jetType) {
r[0] = jetType;
}
};
new JetSignatureReader(kotlinSignature).acceptType(reader);
return r[0];
}
@NotNull @NotNull
public JetType transformToType(@NotNull PsiType javaType) { public JetType transformToType(@NotNull PsiType javaType) {
return javaType.accept(new PsiTypeVisitor<JetType>() { return javaType.accept(new PsiTypeVisitor<JetType>() {
@@ -0,0 +1,196 @@
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeImpl;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Stepan Koltsov
*/
public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
private final JavaDescriptorResolver javaDescriptorResolver;
private final JetStandardLibrary jetStandardLibrary;
public JetTypeJetSignatureReader(JavaDescriptorResolver javaDescriptorResolver, JetStandardLibrary jetStandardLibrary) {
this.javaDescriptorResolver = javaDescriptorResolver;
this.jetStandardLibrary = jetStandardLibrary;
}
@Override
public void visitFormalTypeParameter(String name) {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitClassBound() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitInterfaceBound() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitSuperclass() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitInterface() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitParameterType() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitReturnType() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitExceptionType() {
throw new IllegalStateException();
}
private JetType getPrimitiveType(char descriptor, boolean nullable) {
if (!nullable) {
switch (descriptor) {
case 'Z':
return jetStandardLibrary.getBooleanType();
case 'C':
return jetStandardLibrary.getCharType();
case 'B':
return jetStandardLibrary.getByteType();
case 'S':
return jetStandardLibrary.getShortType();
case 'I':
return jetStandardLibrary.getIntType();
case 'F':
return jetStandardLibrary.getFloatType();
case 'J':
return jetStandardLibrary.getLongType();
case 'D':
return jetStandardLibrary.getDoubleType();
case 'V':
return JetStandardClasses.getUnitType();
}
} else {
switch (descriptor) {
case 'Z':
return jetStandardLibrary.getNullableBooleanType();
case 'C':
return jetStandardLibrary.getNullableCharType();
case 'B':
return jetStandardLibrary.getNullableByteType();
case 'S':
return jetStandardLibrary.getNullableShortType();
case 'I':
return jetStandardLibrary.getNullableIntType();
case 'F':
return jetStandardLibrary.getNullableFloatType();
case 'J':
return jetStandardLibrary.getNullableLongType();
case 'D':
return jetStandardLibrary.getNullableDoubleType();
case 'V':
throw new IllegalStateException("incorrect signature: nullable void");
}
}
throw new IllegalStateException("incorrect signature");
}
@Override
public void visitBaseType(char descriptor, boolean nullable) {
done(getPrimitiveType(descriptor, nullable));
}
@Override
public void visitTypeVariable(String name, boolean nullable) {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitArrayType(boolean nullable) {
throw new IllegalStateException();
}
private ClassDescriptor classDescriptor;
private boolean nullable;
private List<TypeProjection> typeArguments;
@Override
public void visitClassType(String name, boolean nullable) {
String ourName = name.replace('/', '.');
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
if (this.classDescriptor == null) {
throw new IllegalStateException("class not found by name: " + ourName); // TODO: wrong exception
}
this.nullable = nullable;
this.typeArguments = new ArrayList<TypeProjection>();
}
@Override
public void visitInnerClassType(String name, boolean nullable) {
throw new IllegalStateException();
}
@Override
public void visitTypeArgument() {
throw new IllegalStateException();
}
private static Variance parseVariance(char wildcard) {
switch (wildcard) {
case '=': return Variance.INVARIANT;
case '+': return Variance.OUT_VARIANCE;
case '-': return Variance.IN_VARIANCE;
default: throw new IllegalStateException();
}
}
@Override
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
return new JetTypeJetSignatureReader(javaDescriptorResolver, jetStandardLibrary) {
@Override
protected void done(@NotNull JetType jetType) {
typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType));
}
};
}
@Override
public void visitEnd() {
JetType jetType = new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classDescriptor.getTypeConstructor(),
nullable,
typeArguments,
ErrorUtils.getErrorScope());
done(jetType);
}
protected abstract void done(@NotNull JetType jetType);
}
@@ -13,6 +13,7 @@ public class StdlibNames {
public static final String JET_VALUE_PARAMETER_NAME_FIELD = "name"; public static final String JET_VALUE_PARAMETER_NAME_FIELD = "name";
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue"; public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable"; public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
public static final String JET_VALUE_PARAMETER_TYPE_FIELD = "type";
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter"; public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
@@ -25,6 +26,7 @@ public class StdlibNames {
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;"; public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType"; public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
public static final String JET_METHOD_RETURN_TYPE_FIELD = "returnType";
public static final String JET_OBJECT_INTERNAL = "jet/JetObject"; public static final String JET_OBJECT_INTERNAL = "jet/JetObject";
@@ -0,0 +1,79 @@
package org.jetbrains.jet.lang.resolve.java.signature;
/**
* @author Stepan Koltsov
*/
public class JetSignatureAdapter implements JetSignatureVisitor {
@Override
public void visitFormalTypeParameter(String name) {
}
@Override
public JetSignatureVisitor visitClassBound() {
return this;
}
@Override
public JetSignatureVisitor visitInterfaceBound() {
return this;
}
@Override
public JetSignatureVisitor visitSuperclass() {
return this;
}
@Override
public JetSignatureVisitor visitInterface() {
return this;
}
@Override
public JetSignatureVisitor visitParameterType() {
return this;
}
@Override
public JetSignatureVisitor visitReturnType() {
return this;
}
@Override
public JetSignatureVisitor visitExceptionType() {
return this;
}
@Override
public void visitBaseType(char descriptor, boolean nullable) {
}
@Override
public void visitTypeVariable(String name, boolean nullable) {
}
@Override
public JetSignatureVisitor visitArrayType(boolean nullable) {
return this;
}
@Override
public void visitClassType(String name, boolean nullable) {
}
@Override
public void visitInnerClassType(String name, boolean nullable) {
}
@Override
public void visitTypeArgument() {
}
@Override
public JetSignatureVisitor visitTypeArgument(char wildcard) {
return this;
}
@Override
public void visitEnd() {
}
}
@@ -1,4 +1,4 @@
package org.jetbrains.jet.codegen.signature; package org.jetbrains.jet.lang.resolve.java.signature;
import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
@@ -60,6 +60,17 @@ public class JetSignatureReader {
} }
} }
public int acceptType(JetSignatureVisitor v) {
return parseType(this.signature, 0, v);
}
public void acceptTypeOnly(JetSignatureVisitor v) {
int r = acceptType(v);
if (r != signature.length()) {
throw new IllegalStateException();
}
}
private static int parseType( private static int parseType(
final String signature, final String signature,
@@ -1,4 +1,4 @@
package org.jetbrains.jet.codegen.signature; package org.jetbrains.jet.lang.resolve.java.signature;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
@@ -1,4 +1,4 @@
package org.jetbrains.jet.codegen.signature; package org.jetbrains.jet.lang.resolve.java.signature;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
@@ -95,7 +95,7 @@ public class ErrorUtils {
true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), getErrorScope(), ERROR_CONSTRUCTOR_GROUP, ERROR_CONSTRUCTOR); true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), getErrorScope(), ERROR_CONSTRUCTOR_GROUP, ERROR_CONSTRUCTOR);
} }
private static JetScope getErrorScope() { public static JetScope getErrorScope() {
return ERROR_SCOPE; return ERROR_SCOPE;
} }
@@ -21,7 +21,7 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
private final boolean nullable; private final boolean nullable;
private JetScope memberScope; private JetScope memberScope;
public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, List<TypeProjection> arguments, JetScope memberScope) { public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, @NotNull List<TypeProjection> arguments, JetScope memberScope) {
super(annotations); super(annotations);
this.constructor = constructor; this.constructor = constructor;
this.nullable = nullable; this.nullable = nullable;
@@ -30,6 +30,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.JetLanguage;
import org.junit.Assert; import org.junit.Assert;
@@ -156,9 +158,23 @@ public class ReadClassDataTest extends UsefulTestCase {
for (int i = 0; i < a.getValueParameters().size(); ++i) { for (int i = 0; i < a.getValueParameters().size(); ++i) {
compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i)); compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i));
} }
Assert.assertEquals(a.getReturnType(), b.getReturnType()); compareTypes(a.getReturnType(), b.getReturnType());
System.out.println("fun " + a.getName() + "(...): " + a.getReturnType()); System.out.println("fun " + a.getName() + "(...): " + a.getReturnType());
} }
private void compareAnything(Object a, Object b) {
if (a instanceof JetType || b instanceof JetType) {
compareTypes((JetType) a, (JetType) b);
} else {
Assert.assertEquals(a, b);
}
}
private void compareTypes(JetType a, JetType b) {
// cannot just call a.equals(b) because "a" and "b" were created in different environments,
// TypeConstructor does not override equals()
Assert.assertEquals(a.toString(), b.toString());
}
private <T> void compareAnything(Class<T> clazz, T a, T b) { private <T> void compareAnything(Class<T> clazz, T a, T b) {
System.out.println("Comparing " + clazz); System.out.println("Comparing " + clazz);
@@ -182,7 +198,7 @@ public class ReadClassDataTest extends UsefulTestCase {
System.out.println(method.getName()); System.out.println(method.getName());
Object ap = invoke(method, a); Object ap = invoke(method, a);
Object bp = invoke(method, b); Object bp = invoke(method, b);
Assert.assertEquals(ap, bp); compareAnything(ap, bp);
} }
} }
@@ -22,6 +22,10 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
@Override @Override
public void handleInsert(InsertionContext context, LookupElement item) { public void handleInsert(InsertionContext context, LookupElement item) {
if (context.getCompletionChar() == '(') {
context.setAddCompletionChar(false);
}
int startOffset = context.getStartOffset(); int startOffset = context.getStartOffset();
int lookupStringLength = item.getLookupString().length(); int lookupStringLength = item.getLookupString().length();
int endOffset = startOffset + lookupStringLength; int endOffset = startOffset + lookupStringLength;
@@ -17,12 +17,16 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler; import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler;
@@ -105,6 +109,7 @@ class JetSimpleNameReference extends JetPsiReference {
@NotNull Iterable<DeclarationDescriptor> descriptors, @NotNull final JetScope scope @NotNull Iterable<DeclarationDescriptor> descriptors, @NotNull final JetScope scope
) { ) {
final Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors); final Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.removeAll( descriptorsSet.removeAll(
Collections2.filter(JetScopeUtils.getAllExtensions(scope), new Predicate<CallableDescriptor>() { Collections2.filter(JetScopeUtils.getAllExtensions(scope), new Predicate<CallableDescriptor>() {
@Override @Override
@@ -121,6 +126,11 @@ class JetSimpleNameReference extends JetPsiReference {
@NotNull final JetScope externalScope, @NotNull final JetScope externalScope,
@NotNull final ReceiverDescriptor receiverDescriptor @NotNull final ReceiverDescriptor receiverDescriptor
) { ) {
// It's impossible to add extension function for namespace
if (receiverDescriptor.getType() instanceof NamespaceType) {
return descriptors;
}
Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors); Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.addAll(Collections2.filter(JetScopeUtils.getAllExtensions(externalScope), descriptorsSet.addAll(Collections2.filter(JetScopeUtils.getAllExtensions(externalScope),
@@ -138,7 +148,7 @@ class JetSimpleNameReference extends JetPsiReference {
List<LookupElement> result = Lists.newArrayList(); List<LookupElement> result = Lists.newArrayList();
for (final DeclarationDescriptor descriptor : descriptors) { for (final DeclarationDescriptor descriptor : descriptors) {
LookupElementBuilder element = LookupElementBuilder.create(descriptor.getName()); LookupElementBuilder element = LookupElementBuilder.create(descriptor, descriptor.getName());
String typeText = ""; String typeText = "";
String tailText = ""; String tailText = "";
boolean tailTextGrayed = false; boolean tailTextGrayed = false;
@@ -155,6 +165,7 @@ class JetSimpleNameReference extends JetPsiReference {
DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType()); DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType());
} }
}, ",") + ")"; }, ",") + ")";
// TODO: A special case when it's impossible to resolve type parameters from arguments. Need '<' caret '>' // TODO: A special case when it's impossible to resolve type parameters from arguments. Need '<' caret '>'
// TODO: Support omitting brackets for one argument functions // TODO: Support omitting brackets for one argument functions
@@ -175,6 +186,7 @@ class JetSimpleNameReference extends JetPsiReference {
else { else {
typeText = DescriptorRenderer.TEXT.render(descriptor); typeText = DescriptorRenderer.TEXT.render(descriptor);
} }
element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText); element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText);
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal()); PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal());
@@ -0,0 +1,24 @@
namespace Test.MyTest
class A {
class object {
public fun testOther() {
}
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.test<caret>
}
// EXIST: testOther
// NUMBER: 3
@@ -0,0 +1,7 @@
namespace Test.MyTest
fun test() {
Test.<caret>
}
// EXIST: MyTest
@@ -0,0 +1,17 @@
namespace Test.MyTest
class A {
class object {
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.testOther<caret>
}
@@ -0,0 +1,17 @@
namespace Test.MyTest
class A {
class object {
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.testOther()
}
@@ -8,6 +8,7 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.PluginTestCaseBase; import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader; import java.io.BufferedReader;
@@ -59,6 +60,11 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase {
assertContainsItems(itemsShouldExist(getFile().getText())); assertContainsItems(itemsShouldExist(getFile().getText()));
assertNotContainItems(itemsShouldAbsent(getFile().getText())); assertNotContainItems(itemsShouldAbsent(getFile().getText()));
Integer itemsNumber = getExpectedNumber(getFile().getText());
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
}
} }
@Override @Override
@@ -85,6 +91,16 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase {
return findListWithPrefix("// ABSENT:", fileText); return findListWithPrefix("// ABSENT:", fileText);
} }
@Nullable
private static Integer getExpectedNumber(String fileText) {
final String[] numberStrings = findListWithPrefix("// NUMBER:", fileText);
if (numberStrings.length > 0) {
return Integer.parseInt(numberStrings[0]);
}
return null;
}
@NotNull @NotNull
private static String[] findListWithPrefix(String prefix, String fileText) { private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>(); ArrayList<String> result = new ArrayList<String>();
@@ -20,6 +20,14 @@ public class FunctionsHandlerTest extends LightCompletionTestCase {
checkResultByFile("ParamsFunction.kt.after"); checkResultByFile("ParamsFunction.kt.after");
} }
public void testSingleBrackets() {
configureByFile("SingleBrackets.kt");
type('(');
checkResultByFile("SingleBrackets.kt.after");
}
// public void
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
+5
View File
@@ -26,4 +26,9 @@ public @interface JetMethod {
* @return is this type returnTypeNullable * @return is this type returnTypeNullable
*/ */
boolean nullableReturnType() default false; boolean nullableReturnType() default false;
/**
* Return type type unless java type is correct Kotlin type.
*/
String returnType () default "";
} }
@@ -34,4 +34,9 @@ public @interface JetValueParameter {
* @return if this parameter has default value * @return if this parameter has default value
*/ */
boolean hasDefaultValue () default false; boolean hasDefaultValue () default false;
/**
* @return type unless Java type is correct Kotlin type.
*/
String type() default "";
} }
+12 -5
View File
@@ -536,13 +536,20 @@ public abstract class TypeInfo<T> implements JetObject {
} }
public void parseVars(Signature signature) { public void parseVars(Signature signature) {
while(cur < string.length && string[cur] == 'T') { if (cur < string.length && string[cur] == '<') {
if(signature.variables == null) { cur++;
signature.variables = new LinkedList<TypeInfoProjection>(); while(cur < string.length && string[cur] != '>') {
signature.varNames = new HashMap<String, Integer>(); if(signature.variables == null) {
signature.variables = new LinkedList<TypeInfoProjection>();
signature.varNames = new HashMap<String, Integer>();
}
if (string[cur] != 'T') {
throw new IllegalStateException(new String(string));
}
cur++;
signature.variables.add(parseVar(signature));
} }
cur++; cur++;
signature.variables.add(parseVar(signature));
} }
signature.variables = signature.variables == null ? Collections.<TypeInfoProjection>emptyList() : signature.variables; signature.variables = signature.variables == null ? Collections.<TypeInfoProjection>emptyList() : signature.variables;
signature.varNames = signature.varNames == null ? Collections.<String,Integer>emptyMap() : signature.varNames; signature.varNames = signature.varNames == null ? Collections.<String,Integer>emptyMap() : signature.varNames;