Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -0,0 +1,215 @@
|
|||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.signature.JetSignatureWriter;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
import org.objectweb.asm.signature.SignatureVisitor;
|
||||||
|
import org.objectweb.asm.signature.SignatureWriter;
|
||||||
|
import org.objectweb.asm.util.CheckSignatureAdapter;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
public class BothSignatureWriter {
|
||||||
|
|
||||||
|
private static final boolean DEBUG_SIGNATURE_WRITER = true;
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
METHOD(CheckSignatureAdapter.METHOD_SIGNATURE),
|
||||||
|
CLASS(CheckSignatureAdapter.CLASS_SIGNATURE),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final int asmType;
|
||||||
|
|
||||||
|
Mode(int asmType) {
|
||||||
|
this.asmType = asmType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SignatureWriter signatureWriter = new SignatureWriter();
|
||||||
|
private final SignatureVisitor signatureVisitor;
|
||||||
|
|
||||||
|
private final JetSignatureWriter jetSignatureWriter = new JetSignatureWriter();
|
||||||
|
|
||||||
|
private final Mode mode;
|
||||||
|
|
||||||
|
public BothSignatureWriter(Mode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
if (DEBUG_SIGNATURE_WRITER) {
|
||||||
|
signatureVisitor = new CheckSignatureAdapter(mode.asmType, signatureWriter);
|
||||||
|
} else {
|
||||||
|
signatureVisitor = signatureWriter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: ignore when debugging is disabled
|
||||||
|
private Stack<SignatureVisitor> visitors = new Stack<SignatureVisitor>();
|
||||||
|
|
||||||
|
private void push(SignatureVisitor visitor) {
|
||||||
|
visitors.push(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pop() {
|
||||||
|
visitors.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private SignatureVisitor signatureVisitor() {
|
||||||
|
return !visitors.isEmpty() ? visitors.peek() : signatureVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTopLevel() {
|
||||||
|
if (DEBUG_SIGNATURE_WRITER) {
|
||||||
|
if (!visitors.isEmpty()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMode(Mode mode) {
|
||||||
|
if (DEBUG_SIGNATURE_WRITER) {
|
||||||
|
if (mode != this.mode) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut
|
||||||
|
*/
|
||||||
|
public void writeAsmType(Type asmType) {
|
||||||
|
switch (asmType.getSort()) {
|
||||||
|
case Type.OBJECT:
|
||||||
|
writeClassBegin(asmType.getInternalName());
|
||||||
|
writeClassEnd();
|
||||||
|
return;
|
||||||
|
case Type.ARRAY:
|
||||||
|
writeArrayType();
|
||||||
|
writeAsmType(asmType.getElementType());
|
||||||
|
writeArrayEnd();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
String descriptor = asmType.getDescriptor();
|
||||||
|
if (descriptor.length() != 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
signatureVisitor().visitBaseType(descriptor.charAt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeClassBegin(String internalName) {
|
||||||
|
signatureVisitor().visitClassType(internalName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeClassEnd() {
|
||||||
|
signatureVisitor().visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeArrayType() {
|
||||||
|
push(signatureVisitor().visitArrayType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeArrayEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTypeArgument(char c) {
|
||||||
|
push(signatureVisitor().visitTypeArgument(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTypeArgumentEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTypeVariable(final String name) {
|
||||||
|
signatureVisitor().visitTypeVariable(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeFormalTypeParameter(final String name) {
|
||||||
|
checkTopLevel();
|
||||||
|
|
||||||
|
signatureVisitor().visitFormalTypeParameter(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeClassBound() {
|
||||||
|
push(signatureVisitor().visitClassBound());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeClassBoundEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInterfaceBound() {
|
||||||
|
push(signatureVisitor().visitInterfaceBound());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInterfaceBoundEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeParameterType() {
|
||||||
|
push(signatureVisitor().visitParameterType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeParameterTypeEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeReturnType() {
|
||||||
|
push(signatureVisitor().visitReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeReturnTypeEnd() {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeSuperclass() {
|
||||||
|
checkTopLevel();
|
||||||
|
checkMode(Mode.CLASS);
|
||||||
|
|
||||||
|
push(signatureVisitor().visitSuperclass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeSuperclassEnd() {
|
||||||
|
pop();
|
||||||
|
if (!visitors.isEmpty()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInterface() {
|
||||||
|
checkTopLevel();
|
||||||
|
checkMode(Mode.CLASS);
|
||||||
|
|
||||||
|
push(signatureVisitor().visitInterface());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInterfaceEnd() {
|
||||||
|
pop();
|
||||||
|
if (!visitors.isEmpty()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String makeJavaString() {
|
||||||
|
if (!visitors.isEmpty()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return signatureWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String makeKotlinString() {
|
||||||
|
// TODO: not implemented yet
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -57,26 +57,18 @@ public class CodegenUtil {
|
|||||||
return (ClassDescriptor) outerDescriptor;
|
return (ClassDescriptor) outerDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasOuterTypeInfo(ClassDescriptor descriptor) {
|
public static boolean hasDerivedTypeInfoField(JetType type) {
|
||||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(descriptor);
|
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||||
if(outerClassDescriptor == null)
|
if(hasTypeInfoField(jetType))
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if(outerClassDescriptor.getTypeConstructor().getParameters().size() > 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return hasOuterTypeInfo(outerClassDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
|
||||||
if(!exceptOwn) {
|
|
||||||
if(!isInterface(type))
|
|
||||||
if(hasTypeInfoField(type))
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
return false;
|
||||||
if(hasDerivedTypeInfoField(jetType, false))
|
}
|
||||||
|
|
||||||
|
public static boolean requireTypeInfoConstructorArg(JetType type) {
|
||||||
|
for (TypeParameterDescriptor parameter : type.getConstructor().getParameters()) {
|
||||||
|
if(parameter.isReified())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,22 +79,10 @@ public class CodegenUtil {
|
|||||||
if(isInterface(type))
|
if(isInterface(type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
|
if(requireTypeInfoConstructorArg(type))
|
||||||
for (TypeParameterDescriptor parameter : parameters) {
|
return true;
|
||||||
if(parameter.isReified())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
return hasDerivedTypeInfoField(type);
|
||||||
if(hasTypeInfoField(jetType))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
|
|
||||||
if(outerClassDescriptor == null || isClassObject(type.getConstructor().getDeclarationDescriptor()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FunctionDescriptor createInvoke(ExpressionAsFunctionDescriptor fd) {
|
public static FunctionDescriptor createInvoke(ExpressionAsFunctionDescriptor fd) {
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ConstructorFrameMap extends FrameMap {
|
public class ConstructorFrameMap extends FrameMap {
|
||||||
private int myOuterThisIndex = -1;
|
private int myOuterThisIndex = -1;
|
||||||
private int myFirstTypeParameter = -1;
|
private int myTypeInfoIndex = -1;
|
||||||
private int myTypeParameterCount = 0;
|
|
||||||
|
|
||||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
|
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
|
||||||
enterTemp(); // this
|
enterTemp(); // this
|
||||||
@@ -27,15 +27,8 @@ public class ConstructorFrameMap extends FrameMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) {
|
||||||
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
|
if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) {
|
||||||
for (TypeParameterDescriptor parameter : parameters) {
|
myTypeInfoIndex = enterTemp();
|
||||||
if(parameter.isReified()) {
|
|
||||||
int index = enterTemp();
|
|
||||||
myTypeParameterCount++;
|
|
||||||
if(myFirstTypeParameter == -1) {
|
|
||||||
myFirstTypeParameter = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +47,7 @@ public class ConstructorFrameMap extends FrameMap {
|
|||||||
return myOuterThisIndex;
|
return myOuterThisIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFirstTypeParameter() {
|
public int getTypeInfoIndex() {
|
||||||
return myFirstTypeParameter;
|
return myTypeInfoIndex;
|
||||||
}
|
|
||||||
|
|
||||||
public int getTypeParameterCount() {
|
|
||||||
return myTypeParameterCount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -979,7 +979,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else if (descriptor instanceof TypeParameterDescriptor) {
|
else if (descriptor instanceof TypeParameterDescriptor) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
||||||
loadTypeParameterTypeInfo(typeParameterDescriptor);
|
loadTypeParameterTypeInfo(typeParameterDescriptor, null);
|
||||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
||||||
v.checkcast(asmType(typeParameterDescriptor.getClassObjectType()));
|
v.checkcast(asmType(typeParameterDescriptor.getClassObjectType()));
|
||||||
|
|
||||||
@@ -2033,26 +2033,32 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private void pushTypeArguments(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
private void pushTypeArguments(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
||||||
if(resolvedCall != null) {
|
if(resolvedCall != null) {
|
||||||
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
if(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) {
|
||||||
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
|
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
ClassDescriptor containingDeclaration = constructorDescriptor.getContainingDeclaration();
|
||||||
if(typeParameterDescriptor.isReified()) {
|
if(CodegenUtil.requireTypeInfoConstructorArg(containingDeclaration.getDefaultType())) {
|
||||||
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
generateTypeInfo(containingDeclaration.getDefaultType(), resolvedCall.getTypeArguments());
|
||||||
generateTypeInfo(jetType);
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||||
|
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
|
||||||
|
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
||||||
|
if(typeParameterDescriptor.isReified()) {
|
||||||
|
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
||||||
|
generateTypeInfo(jetType, typeArguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
// for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
|
||||||
// pushTypeArgument(jetTypeArgument);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushTypeArgument(JetTypeProjection jetTypeArgument) {
|
public void pushTypeArgument(JetTypeProjection jetTypeArgument) {
|
||||||
JetType typeArgument = bindingContext.get(BindingContext.TYPE, jetTypeArgument.getTypeReference());
|
JetType typeArgument = bindingContext.get(BindingContext.TYPE, jetTypeArgument.getTypeReference());
|
||||||
generateTypeInfo(typeArgument);
|
generateTypeInfo(typeArgument, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type generateJavaConstructorCall(JetCallExpression expression) {
|
private Type generateJavaConstructorCall(JetCallExpression expression) {
|
||||||
@@ -2091,7 +2097,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if(isArray) {
|
if(isArray) {
|
||||||
JetType elementType = typeMapper.getGenericsElementType(arrayType);
|
JetType elementType = typeMapper.getGenericsElementType(arrayType);
|
||||||
if(elementType != null) {
|
if(elementType != null) {
|
||||||
generateTypeInfo(elementType);
|
generateTypeInfo(elementType, null);
|
||||||
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
|
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
|
||||||
v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;");
|
v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;");
|
||||||
}
|
}
|
||||||
@@ -2193,9 +2199,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if(getterDescriptor.getReceiverParameter().exists()) {
|
if(getterDescriptor.getReceiverParameter().exists()) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : getterDescriptor.getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : resolvedGetCall.getCandidateDescriptor().getTypeParameters()) {
|
||||||
if(typeParameterDescriptor.isReified()) {
|
if(typeParameterDescriptor.isReified()) {
|
||||||
generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor));
|
generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor), null);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2215,7 +2221,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
|
||||||
if(typeParameterDescriptor.isReified()) {
|
if(typeParameterDescriptor.isReified()) {
|
||||||
generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor));
|
generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2503,7 +2509,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generateTypeInfo(jetType);
|
generateTypeInfo(jetType, null);
|
||||||
expressionToGen.put(TYPE_OBJECT, v);
|
expressionToGen.put(TYPE_OBJECT, v);
|
||||||
if (leaveExpressionOnStack) {
|
if (leaveExpressionOnStack) {
|
||||||
v.dupX1();
|
v.dupX1();
|
||||||
@@ -2512,7 +2518,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateTypeInfo(JetType jetType) {
|
public void generateTypeInfo(JetType jetType, Map<TypeParameterDescriptor, JetType> typeArguments) {
|
||||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||||
if(knownTypeInfo != null) {
|
if(knownTypeInfo != null) {
|
||||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||||
@@ -2521,7 +2527,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
|
|
||||||
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||||
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor);
|
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor, typeArguments);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2551,7 +2557,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
TypeProjection argument = arguments.get(i);
|
TypeProjection argument = arguments.get(i);
|
||||||
v.dup();
|
v.dup();
|
||||||
v.iconst(i);
|
v.iconst(i);
|
||||||
generateTypeInfo(argument.getType());
|
generateTypeInfo(argument.getType(), typeArguments);
|
||||||
genTypeInfoToProjection(v, argument.getProjectionKind());
|
genTypeInfoToProjection(v, argument.getProjectionKind());
|
||||||
v.astore(TYPE_OBJECT);
|
v.astore(TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
@@ -2573,12 +2579,21 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
throw new UnsupportedOperationException(variance.toString());
|
throw new UnsupportedOperationException(variance.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
|
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor, @Nullable Map<TypeParameterDescriptor, JetType> typeArguments) {
|
||||||
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
|
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
value.put(TYPE_TYPEINFO, v);
|
value.put(TYPE_TYPEINFO, v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(typeArguments != null) {
|
||||||
|
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
||||||
|
if(jetType != null && !jetType.equals(typeParameterDescriptor.getDefaultType())) {
|
||||||
|
generateTypeInfo(jetType, typeArguments);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (context.getThisDescriptor() != null) {
|
if (context.getThisDescriptor() != null) {
|
||||||
ClassDescriptor descriptor = context.getThisDescriptor();
|
ClassDescriptor descriptor = context.getThisDescriptor();
|
||||||
@@ -2589,8 +2604,13 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
if (containingDeclaration == context.getThisDescriptor()) {
|
if (containingDeclaration == context.getThisDescriptor()) {
|
||||||
if(!CodegenUtil.isInterface(descriptor)) {
|
if(!CodegenUtil.isInterface(descriptor)) {
|
||||||
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||||
v.load(0, TYPE_OBJECT);
|
if(!(context instanceof CodegenContext.ConstructorContext)) {
|
||||||
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.load(0, TYPE_OBJECT);
|
||||||
|
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.load(((ConstructorFrameMap)myFrameMap).getTypeInfoIndex(), TYPE_OBJECT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
@@ -2598,16 +2618,16 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.load(0, TYPE_OBJECT);
|
v.load(0, TYPE_OBJECT);
|
||||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.load(0, TYPE_OBJECT);
|
v.load(0, TYPE_OBJECT);
|
||||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
|
||||||
while(descriptor != containingDeclaration) {
|
while(descriptor != containingDeclaration) {
|
||||||
descriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
descriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getOuterTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getOuterObject", "()Ljet/JetObject;");
|
||||||
}
|
}
|
||||||
|
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
v.aconst(ownerType);
|
v.aconst(ownerType);
|
||||||
v.iconst(typeParameterDescriptor.getIndex());
|
v.iconst(typeParameterDescriptor.getIndex());
|
||||||
@@ -2737,7 +2757,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
|
|
||||||
v.anew(tupleType);
|
v.anew(tupleType);
|
||||||
v.dup();
|
v.dup();
|
||||||
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
|
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)), null);
|
||||||
for (JetExpression entry : entries) {
|
for (JetExpression entry : entries) {
|
||||||
gen(entry, TYPE_OBJECT);
|
gen(entry, TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ 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.StdlibNames;
|
import org.jetbrains.jet.lang.resolve.java.StdlibNames;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.objectweb.asm.AnnotationVisitor;
|
import org.objectweb.asm.AnnotationVisitor;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
@@ -86,7 +86,7 @@ public class FunctionCodegen {
|
|||||||
if(v.generateCode()) {
|
if(v.generateCode()) {
|
||||||
int start = 0;
|
int start = 0;
|
||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
AnnotationVisitor av = mv.visitAnnotation(StdlibNames.JET_METHOD_TYPE.getDescriptor(), true);
|
AnnotationVisitor av = mv.visitAnnotation(JetTypeMapper.JET_METHOD_TYPE.getDescriptor(), true);
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -94,15 +94,15 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
|
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
|
||||||
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self");
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$self");
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
if(receiverParameter.exists()) {
|
if(receiverParameter.exists()) {
|
||||||
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
|
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
|
||||||
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver");
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$receiver");
|
||||||
if(receiverParameter.getType().isNullable()) {
|
if(receiverParameter.getType().isNullable()) {
|
||||||
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
||||||
}
|
}
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
@@ -112,14 +112,14 @@ public class FunctionCodegen {
|
|||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||||
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
|
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
||||||
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
|
||||||
if(parameterDescriptor.hasDefaultValue()) {
|
if(parameterDescriptor.hasDefaultValue()) {
|
||||||
av.visit(StdlibNames.JET_PARAMETER_HAS_DEFAULT_VALUE_FIELD, true);
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD, true);
|
||||||
}
|
}
|
||||||
if(parameterDescriptor.getOutType().isNullable()) {
|
if(parameterDescriptor.getOutType().isNullable()) {
|
||||||
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
||||||
}
|
}
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ 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.OverridingUtil;
|
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.StdlibNames;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
@@ -16,9 +17,6 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
import org.objectweb.asm.signature.SignatureVisitor;
|
|
||||||
import org.objectweb.asm.signature.SignatureWriter;
|
|
||||||
import org.objectweb.asm.util.CheckSignatureAdapter;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -29,7 +27,9 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||||
private JetDelegationSpecifier superCall;
|
private JetDelegationSpecifier superCall;
|
||||||
private String superClass = "java/lang/Object";
|
private String superClass;
|
||||||
|
@Nullable // null means java/lang/Object
|
||||||
|
private JetType superClassType;
|
||||||
private final JetTypeMapper typeMapper;
|
private final JetTypeMapper typeMapper;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
|
|
||||||
@@ -39,28 +39,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
bindingContext = state.getBindingContext();
|
bindingContext = state.getBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
|
|
||||||
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
|
||||||
Set<String> superInterfaces = new LinkedHashSet<String>();
|
|
||||||
|
|
||||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
|
||||||
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
|
||||||
assert superType != null;
|
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
|
||||||
if(CodegenUtil.isInterface(superClassDescriptor)) {
|
|
||||||
superInterfaces.add(typeMapper.getFQName(superClassDescriptor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return superInterfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
getSuperClass();
|
getSuperClass();
|
||||||
|
|
||||||
List<String> interfaces = new ArrayList<String>();
|
JvmClassSignature signature = signature();
|
||||||
interfaces.add("jet/JetObject");
|
|
||||||
interfaces.addAll(getSuperInterfaces(myClass));
|
|
||||||
|
|
||||||
boolean isAbstract = false;
|
boolean isAbstract = false;
|
||||||
boolean isInterface = false;
|
boolean isInterface = false;
|
||||||
@@ -77,10 +60,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
|
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
|
||||||
? Opcodes.ACC_INTERFACE
|
? Opcodes.ACC_INTERFACE
|
||||||
: 0/*Opcodes.ACC_SUPER*/),
|
: 0/*Opcodes.ACC_SUPER*/),
|
||||||
jvmName(),
|
signature.getName(),
|
||||||
genericSignature(),
|
signature.getGenericSignature(),
|
||||||
superClass,
|
signature.getSuperclassName(),
|
||||||
interfaces.toArray(new String[interfaces.size()])
|
signature.getInterfaces().toArray(new String[0])
|
||||||
);
|
);
|
||||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||||
|
|
||||||
@@ -94,30 +77,57 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
annotationVisitor.visitEnd();
|
annotationVisitor.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JvmClassSignature signature() {
|
||||||
|
String genericSignature;
|
||||||
|
List<String> superInterfaces;
|
||||||
|
|
||||||
@Nullable
|
{
|
||||||
private String genericSignature() {
|
LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
|
||||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
|
|
||||||
|
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
|
||||||
SignatureWriter signatureWriter = new SignatureWriter();
|
|
||||||
SignatureVisitor signatureVisitor = JetTypeMapper.DEBUG_SIGNATURE_WRITER
|
|
||||||
? new CheckSignatureAdapter(CheckSignatureAdapter.CLASS_SIGNATURE, signatureWriter)
|
{ // type parameters
|
||||||
: signatureWriter;
|
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
|
||||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor);
|
||||||
signatureVisitor.visitFormalTypeParameter(typeParameter.getName());
|
}
|
||||||
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
|
|
||||||
// TODO: wrong
|
|
||||||
JetTypeMapper.visitAsmType(classBoundVisitor, JetTypeMapper.TYPE_OBJECT);
|
{ // 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();
|
||||||
}
|
}
|
||||||
SignatureVisitor superclassSignatureVisitor = signatureVisitor.visitSuperclass();
|
return new JvmClassSignature(jvmName(), superClass, superInterfaces, genericSignature);
|
||||||
// TODO: wrong
|
|
||||||
superclassSignatureVisitor.visitClassType("java/lang/Object");
|
|
||||||
// TODO: add interfaces
|
|
||||||
superclassSignatureVisitor.visitEnd();
|
|
||||||
|
|
||||||
// TODO: return null if class is not generic and does not have generic superclasses
|
|
||||||
|
|
||||||
return signatureWriter.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String jvmName() {
|
private String jvmName() {
|
||||||
@@ -125,6 +135,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void getSuperClass() {
|
protected void getSuperClass() {
|
||||||
|
superClass = "java/lang/Object";
|
||||||
|
superClassType = null;
|
||||||
|
|
||||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||||
|
|
||||||
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
||||||
@@ -136,6 +149,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
assert superType != null;
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
if(!CodegenUtil.isInterface(superClassDescriptor)) {
|
if(!CodegenUtil.isInterface(superClassDescriptor)) {
|
||||||
|
superClassType = superType;
|
||||||
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
|
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
|
||||||
superCall = specifier;
|
superCall = specifier;
|
||||||
}
|
}
|
||||||
@@ -305,8 +319,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
|
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType())) {
|
||||||
for (int n = typeParameters.size(); n > 0; n--) {
|
|
||||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,12 +378,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
||||||
|
|
||||||
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
// for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||||
if(constructorDescriptor != null)
|
// if(constructorDescriptor != null)
|
||||||
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
// codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
else
|
// else
|
||||||
codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
// codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
}
|
// }
|
||||||
|
|
||||||
String classname = typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName();
|
String classname = typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName();
|
||||||
final Type classType = Type.getType("L" + classname + ";");
|
final Type classType = Type.getType("L" + classname + ";");
|
||||||
@@ -399,7 +412,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||||
}
|
}
|
||||||
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
|
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
|
||||||
codegen.generateTypeInfo(typeParameterDescriptor.getType());
|
codegen.generateTypeInfo(typeParameterDescriptor.getType(), null);
|
||||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
}
|
}
|
||||||
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||||
@@ -447,10 +460,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.load(0, classType);
|
iv.load(0, classType);
|
||||||
iv.load(frameMap.getOuterThisIndex(), type);
|
iv.load(frameMap.getOuterThisIndex(), type);
|
||||||
iv.putfield(classname, fieldName, interfaceDesc);
|
iv.putfield(classname, fieldName, interfaceDesc);
|
||||||
|
|
||||||
|
Type outerType = typeMapper.mapType(outerDescriptor.getDefaultType());
|
||||||
|
MethodVisitor outer = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getOuterObject", "()Ljet/JetObject;", null, null);
|
||||||
|
outer.visitCode();
|
||||||
|
outer.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
outer.visitFieldInsn(Opcodes.GETFIELD, classname, "this$0", outerType.getDescriptor());
|
||||||
|
outer.visitInsn(Opcodes.ARETURN);
|
||||||
|
outer.visitMaxs(0, 0);
|
||||||
|
outer.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
||||||
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
iv.load(frameMap.getTypeInfoIndex(), JetTypeMapper.TYPE_OBJECT);
|
||||||
|
iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(closure != null) {
|
if(closure != null) {
|
||||||
@@ -691,46 +715,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
|
|
||||||
iv.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
|
||||||
iv.iconst(0);
|
|
||||||
|
|
||||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
|
||||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
iv.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeParamCount != 0) {
|
|
||||||
iv.iconst(typeParamCount);
|
|
||||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
|
||||||
|
|
||||||
for (int i = 0; i < typeParamCount; i++) {
|
|
||||||
iv.dup();
|
|
||||||
iv.iconst(i);
|
|
||||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
|
||||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
|
||||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
|
||||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
@@ -827,15 +811,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
JetType defaultType = descriptor.getDefaultType();
|
JetType defaultType = descriptor.getDefaultType();
|
||||||
if(CodegenUtil.hasTypeInfoField(defaultType)) {
|
if(CodegenUtil.requireTypeInfoConstructorArg(defaultType)) {
|
||||||
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
|
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType)) {
|
||||||
v.newField(myClass, Opcodes.ACC_PROTECTED, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
v.newField(myClass, Opcodes.ACC_PROTECTED, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
|
|
||||||
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
InstructionAdapter iv = null;
|
|
||||||
if (v.generateCode()) {
|
if (v.generateCode()) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
@@ -847,7 +830,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
|
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
|
||||||
if (v.generateCode()) {
|
if (v.generateCode()) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||||
@@ -884,14 +867,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
public void generate(InstructionAdapter v) {
|
public void generate(InstructionAdapter v) {
|
||||||
v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||||
v.iconst(0);
|
v.iconst(0);
|
||||||
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||||
if(outerClassDescriptor == null || CodegenUtil.isClassObject(descriptor)) {
|
|
||||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.getstatic(typeMapper.mapType(outerClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
|
||||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
|
||||||
}
|
|
||||||
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
import org.objectweb.asm.signature.SignatureVisitor;
|
|
||||||
import org.objectweb.asm.signature.SignatureWriter;
|
|
||||||
import org.objectweb.asm.util.CheckSignatureAdapter;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -57,6 +54,9 @@ public class JetTypeMapper {
|
|||||||
public static final Type ARRAY_DOUBLE_TYPE = Type.getType(double[].class);
|
public static final Type ARRAY_DOUBLE_TYPE = Type.getType(double[].class);
|
||||||
public static final Type ARRAY_BOOL_TYPE = Type.getType(boolean[].class);
|
public static final Type ARRAY_BOOL_TYPE = Type.getType(boolean[].class);
|
||||||
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
||||||
|
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetValueParameter");
|
||||||
|
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
|
||||||
|
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
|
||||||
|
|
||||||
private final JetStandardLibrary standardLibrary;
|
private final JetStandardLibrary standardLibrary;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
@@ -86,7 +86,11 @@ public class JetTypeMapper {
|
|||||||
public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator");
|
public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator");
|
||||||
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
|
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
|
||||||
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
|
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
|
||||||
|
|
||||||
|
public JetStandardLibrary getStandardLibrary() {
|
||||||
|
return standardLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
@@ -158,10 +162,10 @@ public class JetTypeMapper {
|
|||||||
return mapReturnType(jetType, null);
|
return mapReturnType(jetType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull private Type mapReturnType(final JetType jetType, @Nullable SignatureVisitor 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.visitBaseType('V');
|
signatureVisitor.writeAsmType(Type.VOID_TYPE);
|
||||||
}
|
}
|
||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
@@ -219,10 +223,10 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull public Type mapType(final JetType jetType) {
|
@NotNull public Type mapType(final JetType jetType) {
|
||||||
return mapType(jetType, (SignatureVisitor) null);
|
return mapType(jetType, (BothSignatureWriter) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull private Type mapType(JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
|
@NotNull private Type mapType(JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||||
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
|
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,17 +234,22 @@ public class JetTypeMapper {
|
|||||||
return mapType(jetType, kind, null);
|
return mapType(jetType, kind, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor) {
|
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable BothSignatureWriter signatureVisitor) {
|
||||||
return mapType(jetType, kind, signatureVisitor, false);
|
return mapType(jetType, kind, signatureVisitor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor, boolean boxPrimitive) {
|
@NotNull public Type mapType(JetType jetType, OwnerKind kind, @Nullable BothSignatureWriter signatureVisitor, boolean boxPrimitive) {
|
||||||
Type known = knowTypes.get(jetType);
|
Type known = knowTypes.get(jetType);
|
||||||
if (known != null) {
|
if (known != null) {
|
||||||
return mapKnownAsmType(jetType, known, signatureVisitor, boxPrimitive);
|
return mapKnownAsmType(jetType, known, signatureVisitor, boxPrimitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
|
|
||||||
|
if (ErrorUtils.isError(descriptor)) {
|
||||||
|
throw new IllegalStateException("should not compile an error type");
|
||||||
|
}
|
||||||
|
|
||||||
if (standardLibrary.getArray().equals(descriptor)) {
|
if (standardLibrary.getArray().equals(descriptor)) {
|
||||||
if (jetType.getArguments().size() != 1) {
|
if (jetType.getArguments().size() != 1) {
|
||||||
throw new UnsupportedOperationException("arrays must have one type argument");
|
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||||
@@ -248,8 +257,9 @@ public class JetTypeMapper {
|
|||||||
JetType memberType = jetType.getArguments().get(0).getType();
|
JetType memberType = jetType.getArguments().get(0).getType();
|
||||||
|
|
||||||
if (signatureVisitor != null) {
|
if (signatureVisitor != null) {
|
||||||
SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType();
|
signatureVisitor.writeArrayType();
|
||||||
mapType(memberType, kind, arraySignatureVisitor, true);
|
mapType(memberType, kind, signatureVisitor, true);
|
||||||
|
signatureVisitor.writeArrayEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isGenericsArray(jetType)) {
|
if (!isGenericsArray(jetType)) {
|
||||||
@@ -272,13 +282,14 @@ 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.visitClassType(asmType.getInternalName());
|
signatureVisitor.writeClassBegin(asmType.getInternalName());
|
||||||
for (TypeProjection proj : jetType.getArguments()) {
|
for (TypeProjection proj : jetType.getArguments()) {
|
||||||
// TODO: +-
|
// TODO: +-
|
||||||
SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('=');
|
signatureVisitor.writeTypeArgument('=');
|
||||||
mapType(proj.getType(), kind, argumentSignatureVisitor, true);
|
mapType(proj.getType(), kind, signatureVisitor, true);
|
||||||
|
signatureVisitor.writeTypeArgumentEnd();
|
||||||
}
|
}
|
||||||
signatureVisitor.visitEnd();
|
signatureVisitor.writeClassEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
return asmType;
|
return asmType;
|
||||||
@@ -287,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.visitTypeVariable(typeParameterDescriptor.getName());
|
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
|
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
|
||||||
@@ -296,7 +307,7 @@ public class JetTypeMapper {
|
|||||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable SignatureVisitor 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));
|
||||||
@@ -307,23 +318,8 @@ public class JetTypeMapper {
|
|||||||
return asmType;
|
return asmType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void visitAsmType(SignatureVisitor visitor, Type asmType) {
|
public static void visitAsmType(BothSignatureWriter visitor, Type asmType) {
|
||||||
switch (asmType.getSort()) {
|
visitor.writeAsmType(asmType);
|
||||||
case Type.OBJECT:
|
|
||||||
visitor.visitClassType(asmType.getInternalName());
|
|
||||||
visitor.visitEnd();
|
|
||||||
return;
|
|
||||||
case Type.ARRAY:
|
|
||||||
SignatureVisitor elementSignatureVisitor = visitor.visitArrayType();
|
|
||||||
visitAsmType(elementSignatureVisitor, asmType.getElementType());
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
String descriptor = asmType.getDescriptor();
|
|
||||||
if (descriptor.length() != 1) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
visitor.visitBaseType(descriptor.charAt(0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type unboxType(final Type type) {
|
public static Type unboxType(final Type type) {
|
||||||
@@ -379,8 +375,6 @@ public class JetTypeMapper {
|
|||||||
return asmType;
|
return asmType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final boolean DEBUG_SIGNATURE_WRITER = true;
|
|
||||||
|
|
||||||
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
|
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
|
||||||
if(functionDescriptor == null)
|
if(functionDescriptor == null)
|
||||||
return null;
|
return null;
|
||||||
@@ -444,22 +438,12 @@ public class JetTypeMapper {
|
|||||||
needGenericSignature = false;
|
needGenericSignature = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignatureWriter signatureWriter = null;
|
BothSignatureWriter signatureVisitor = null;
|
||||||
SignatureVisitor signatureVisitor = null;
|
|
||||||
if (needGenericSignature) {
|
if (needGenericSignature) {
|
||||||
signatureWriter = new SignatureWriter();
|
signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
||||||
signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) {
|
writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
|
||||||
if (signatureVisitor != null) {
|
|
||||||
signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName());
|
|
||||||
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
|
|
||||||
// TODO: wrong base
|
|
||||||
visitAsmType(classBoundVisitor, TYPE_OBJECT);
|
|
||||||
// TODO: interfaces
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
|
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
|
||||||
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
||||||
@@ -477,24 +461,98 @@ public class JetTypeMapper {
|
|||||||
parameterTypes.add(type);
|
parameterTypes.add(type);
|
||||||
}
|
}
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null));
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeParameterType();
|
||||||
|
}
|
||||||
|
parameterTypes.add(mapType(receiverType, signatureVisitor));
|
||||||
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
|
signatureVisitor.writeParameterType();
|
||||||
|
visitAsmType(signatureVisitor, TYPE_TYPEINFO);
|
||||||
|
signatureVisitor.writeParameterTypeEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ValueParameterDescriptor parameter : parameters) {
|
for (ValueParameterDescriptor parameter : parameters) {
|
||||||
Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null);
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeParameterType();
|
||||||
|
}
|
||||||
|
Type type = mapType(parameter.getOutType(), signatureVisitor);
|
||||||
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeParameterTypeEnd();
|
||||||
|
}
|
||||||
valueParameterTypes.add(type);
|
valueParameterTypes.add(type);
|
||||||
parameterTypes.add(type);
|
parameterTypes.add(type);
|
||||||
}
|
}
|
||||||
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
|
Type returnType;
|
||||||
|
if (f instanceof ConstructorDescriptor) {
|
||||||
|
returnType = Type.VOID_TYPE;
|
||||||
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeReturnType();
|
||||||
|
visitAsmType(signatureVisitor, Type.VOID_TYPE);
|
||||||
|
signatureVisitor.writeReturnTypeEnd();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (signatureVisitor != null) {
|
||||||
|
signatureVisitor.writeReturnType();
|
||||||
|
returnType = mapReturnType(f.getReturnType(), signatureVisitor);
|
||||||
|
signatureVisitor.writeReturnTypeEnd();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
returnType = mapReturnType(f.getReturnType(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
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, signatureWriter != null ? signatureWriter.toString() : null);
|
return new JvmMethodSignature(method, signatureVisitor != null ? signatureVisitor.makeJavaString() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) {
|
||||||
|
if (signatureVisitor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
|
||||||
|
signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName());
|
||||||
|
|
||||||
|
classBound:
|
||||||
|
{
|
||||||
|
signatureVisitor.writeClassBound();
|
||||||
|
|
||||||
|
for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
|
||||||
|
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||||
|
if (!CodegenUtil.isInterface(jetType)) {
|
||||||
|
mapType(jetType, signatureVisitor);
|
||||||
|
break classBound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "extends Object" seems to be not optional according to ClassFileFormat-Java5.pdf
|
||||||
|
}
|
||||||
|
signatureVisitor.writeClassBoundEnd();
|
||||||
|
|
||||||
|
for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
|
||||||
|
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||||
|
if (CodegenUtil.isInterface(jetType)) {
|
||||||
|
signatureVisitor.writeInterfaceBound();
|
||||||
|
mapType(jetType, signatureVisitor);
|
||||||
|
signatureVisitor.writeInterfaceBoundEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
|
public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
|
||||||
@@ -575,10 +633,8 @@ public class JetTypeMapper {
|
|||||||
parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
|
if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) {
|
||||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
parameterTypes.add(TYPE_TYPEINFO);
|
||||||
if(typeParameter.isReified())
|
|
||||||
parameterTypes.add(TYPE_TYPEINFO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ValueParameterDescriptor parameter : parameters) {
|
for (ValueParameterDescriptor parameter : parameters) {
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
public class JvmClassSignature {
|
||||||
|
private final String name;
|
||||||
|
private final String superclassName;
|
||||||
|
private final List<String> interfaces;
|
||||||
|
private final String genericSignature;
|
||||||
|
|
||||||
|
public JvmClassSignature(String name, String superclassName, List<String> interfaces, String genericSignature) {
|
||||||
|
this.name = name;
|
||||||
|
this.superclassName = superclassName;
|
||||||
|
this.interfaces = interfaces;
|
||||||
|
this.genericSignature = genericSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuperclassName() {
|
||||||
|
return superclassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getInterfaces() {
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGenericSignature() {
|
||||||
|
return genericSignature;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
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.java.JavaClassDescriptor;
|
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
@@ -42,7 +44,8 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetNamespace namespace) {
|
public void generate(JetNamespace namespace) {
|
||||||
final CodegenContext context = CodegenContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace));
|
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.NAMESPACE, namespace);
|
||||||
|
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||||
|
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
@@ -145,7 +148,7 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
|
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor) && !JetStandardClasses.getAny().equals(declarationDescriptor)) {
|
||||||
// TODO: we need some better checks here
|
// TODO: we need some better checks here
|
||||||
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
|||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
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.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -629,7 +630,7 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
|
||||||
if(typeParameterDescriptor.isReified()) {
|
if(typeParameterDescriptor.isReified()) {
|
||||||
codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor));
|
codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1010,7 +1011,8 @@ public abstract class StackValue {
|
|||||||
return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
|
return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return codegen.typeMapper.mapType(callableMethod.getThisType());
|
JetType thisType = callableMethod.getThisType();
|
||||||
|
return codegen.typeMapper.mapType(thisType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
|
|||||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ public class ArrayIterator implements IntrinsicMethod {
|
|||||||
ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal();
|
ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal();
|
||||||
JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary();
|
JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary();
|
||||||
if(containingDeclaration.equals(standardLibrary.getArray())) {
|
if(containingDeclaration.equals(standardLibrary.getArray())) {
|
||||||
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType());
|
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType(), null);
|
||||||
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
|
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
|
||||||
return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR);
|
return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class ValueTypeInfo implements IntrinsicMethod {
|
|||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
||||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
v.invokeinterface(JetTypeMapper.TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||||
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package org.jetbrains.jet.codegen.signature;
|
||||||
|
|
||||||
|
import org.objectweb.asm.signature.SignatureReader;
|
||||||
|
import org.objectweb.asm.signature.SignatureVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*
|
||||||
|
* @see SignatureReader
|
||||||
|
*/
|
||||||
|
public class JetSignatureReader {
|
||||||
|
|
||||||
|
private final String signature;
|
||||||
|
|
||||||
|
public JetSignatureReader(String signature) {
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void accept(final JetSignatureVisitor v) {
|
||||||
|
String signature = this.signature;
|
||||||
|
int len = signature.length();
|
||||||
|
int pos;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (signature.charAt(0) == '<') {
|
||||||
|
pos = 2;
|
||||||
|
do {
|
||||||
|
int end = signature.indexOf(':', pos);
|
||||||
|
v.visitFormalTypeParameter(signature.substring(pos - 1, end));
|
||||||
|
pos = end + 1;
|
||||||
|
|
||||||
|
c = signature.charAt(pos);
|
||||||
|
if (c == 'L' || c == '[' || c == 'T') {
|
||||||
|
pos = parseType(signature, pos, v.visitClassBound());
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((c = signature.charAt(pos++)) == ':') {
|
||||||
|
pos = parseType(signature, pos, v.visitInterfaceBound());
|
||||||
|
}
|
||||||
|
} while (c != '>');
|
||||||
|
} else {
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature.charAt(pos) == '(') {
|
||||||
|
pos++;
|
||||||
|
while (signature.charAt(pos) != ')') {
|
||||||
|
pos = parseType(signature, pos, v.visitParameterType());
|
||||||
|
}
|
||||||
|
pos = parseType(signature, pos + 1, v.visitReturnType());
|
||||||
|
while (pos < len) {
|
||||||
|
pos = parseType(signature, pos + 1, v.visitExceptionType());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pos = parseType(signature, pos, v.visitSuperclass());
|
||||||
|
while (pos < len) {
|
||||||
|
pos = parseType(signature, pos, v.visitInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int parseType(
|
||||||
|
final String signature,
|
||||||
|
int pos,
|
||||||
|
final JetSignatureVisitor v)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
int start, end;
|
||||||
|
boolean visited, inner;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
boolean nullable = false;
|
||||||
|
if (signature.charAt(pos) == '?') {
|
||||||
|
nullable = true;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c = signature.charAt(pos++)) {
|
||||||
|
case 'Z':
|
||||||
|
case 'C':
|
||||||
|
case 'B':
|
||||||
|
case 'S':
|
||||||
|
case 'I':
|
||||||
|
case 'F':
|
||||||
|
case 'J':
|
||||||
|
case 'D':
|
||||||
|
case 'V':
|
||||||
|
v.visitBaseType(c, nullable);
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
return parseType(signature, pos, v.visitArrayType(nullable));
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
end = signature.indexOf(';', pos);
|
||||||
|
v.visitTypeVariable(signature.substring(pos, end), nullable);
|
||||||
|
return end + 1;
|
||||||
|
|
||||||
|
default: // case 'L':
|
||||||
|
start = pos;
|
||||||
|
visited = false;
|
||||||
|
inner = false;
|
||||||
|
for (;;) {
|
||||||
|
switch (c = signature.charAt(pos++)) {
|
||||||
|
case '.':
|
||||||
|
case ';':
|
||||||
|
if (!visited) {
|
||||||
|
name = signature.substring(start, pos - 1);
|
||||||
|
if (inner) {
|
||||||
|
v.visitInnerClassType(name, nullable);
|
||||||
|
} else {
|
||||||
|
v.visitClassType(name, nullable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == ';') {
|
||||||
|
v.visitEnd();
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
start = pos;
|
||||||
|
visited = false;
|
||||||
|
inner = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
name = signature.substring(start, pos - 1);
|
||||||
|
if (inner) {
|
||||||
|
v.visitInnerClassType(name, nullable);
|
||||||
|
} else {
|
||||||
|
v.visitClassType(name, nullable);
|
||||||
|
}
|
||||||
|
visited = true;
|
||||||
|
top: for (;;) {
|
||||||
|
switch (c = signature.charAt(pos)) {
|
||||||
|
case '>':
|
||||||
|
break top;
|
||||||
|
case '*':
|
||||||
|
++pos;
|
||||||
|
v.visitTypeArgument();
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
pos = parseType(signature,
|
||||||
|
pos + 1,
|
||||||
|
v.visitTypeArgument(c));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pos = parseType(signature,
|
||||||
|
pos,
|
||||||
|
v.visitTypeArgument('='));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package org.jetbrains.jet.codegen.signature;
|
||||||
|
|
||||||
|
import org.objectweb.asm.signature.SignatureVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*
|
||||||
|
* @see SignatureVisitor
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
|
*/
|
||||||
|
public interface JetSignatureVisitor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wildcard for an "extends" type argument.
|
||||||
|
*/
|
||||||
|
char EXTENDS = '+';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wildcard for a "super" type argument.
|
||||||
|
*/
|
||||||
|
char SUPER = '-';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wildcard for a normal type argument.
|
||||||
|
*/
|
||||||
|
char INSTANCEOF = '=';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a formal type parameter.
|
||||||
|
*
|
||||||
|
* @param name the name of the formal parameter.
|
||||||
|
*/
|
||||||
|
void visitFormalTypeParameter(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the class bound of the last visited formal type parameter.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the class bound.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitClassBound();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits an interface bound of the last visited formal type parameter.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the interface bound.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitInterfaceBound();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the type of the super class.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the super class
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitSuperclass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the type of an interface implemented by the class.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the interface type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitInterface();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the type of a method parameter.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the parameter type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitParameterType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the return type of the method.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the return type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitReturnType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the type of a method exception.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the exception type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitExceptionType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a signature corresponding to a primitive type.
|
||||||
|
*
|
||||||
|
* @param descriptor the descriptor of the primitive type, or 'V' for
|
||||||
|
* <tt>void</tt>.
|
||||||
|
*/
|
||||||
|
void visitBaseType(char descriptor, boolean nullable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a signature corresponding to a type variable.
|
||||||
|
*
|
||||||
|
* @param name the name of the type variable.
|
||||||
|
*/
|
||||||
|
void visitTypeVariable(String name, boolean nullable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a signature corresponding to an array type.
|
||||||
|
*
|
||||||
|
* @return a non null visitor to visit the signature of the array element
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitArrayType(boolean nullable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the visit of a signature corresponding to a class or interface
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* @param name the internal name of the class or interface.
|
||||||
|
*/
|
||||||
|
void visitClassType(String name, boolean nullable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits an inner class.
|
||||||
|
*
|
||||||
|
* @param name the local name of the inner class in its enclosing class.
|
||||||
|
*/
|
||||||
|
void visitInnerClassType(String name, boolean nullable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits an unbounded type argument of the last visited class or inner
|
||||||
|
* class type.
|
||||||
|
*/
|
||||||
|
void visitTypeArgument();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a type argument of the last visited class or inner class type.
|
||||||
|
*
|
||||||
|
* @param wildcard '+', '-' or '='.
|
||||||
|
* @return a non null visitor to visit the signature of the type argument.
|
||||||
|
*/
|
||||||
|
JetSignatureVisitor visitTypeArgument(char wildcard);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the visit of a signature corresponding to a class or interface type.
|
||||||
|
*/
|
||||||
|
void visitEnd();
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
package org.jetbrains.jet.codegen.signature;
|
||||||
|
|
||||||
|
import org.objectweb.asm.signature.SignatureWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*
|
||||||
|
* @see SignatureWriter
|
||||||
|
*/
|
||||||
|
public class JetSignatureWriter implements JetSignatureVisitor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer used to construct the signature.
|
||||||
|
*/
|
||||||
|
private final StringBuffer buf = new StringBuffer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the signature contains formal type parameters.
|
||||||
|
*/
|
||||||
|
private boolean hasFormals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the signature contains method parameter types.
|
||||||
|
*/
|
||||||
|
private boolean hasParameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack used to keep track of class types that have arguments. Each element
|
||||||
|
* of this stack is a boolean encoded in one bit. The top of the stack is
|
||||||
|
* the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
|
||||||
|
* /2.
|
||||||
|
*/
|
||||||
|
private int argumentStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link SignatureWriter} object.
|
||||||
|
*/
|
||||||
|
public JetSignatureWriter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Implementation of the SignatureVisitor interface
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFormalTypeParameter(final String name) {
|
||||||
|
if (!hasFormals) {
|
||||||
|
hasFormals = true;
|
||||||
|
buf.append('<');
|
||||||
|
}
|
||||||
|
buf.append(name);
|
||||||
|
buf.append(':');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitClassBound() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitInterfaceBound() {
|
||||||
|
buf.append(':');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitSuperclass() {
|
||||||
|
endFormals();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitInterface() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitParameterType() {
|
||||||
|
endFormals();
|
||||||
|
if (!hasParameters) {
|
||||||
|
hasParameters = true;
|
||||||
|
buf.append('(');
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitReturnType() {
|
||||||
|
endFormals();
|
||||||
|
if (!hasParameters) {
|
||||||
|
buf.append('(');
|
||||||
|
}
|
||||||
|
buf.append(')');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitExceptionType() {
|
||||||
|
buf.append('^');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitNullabe(boolean nullable) {
|
||||||
|
if (nullable) {
|
||||||
|
buf.append('?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBaseType(final char descriptor, boolean nullable) {
|
||||||
|
visitNullabe(nullable);
|
||||||
|
buf.append(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTypeVariable(final String name, boolean nullable) {
|
||||||
|
visitNullabe(nullable);
|
||||||
|
buf.append('T');
|
||||||
|
buf.append(name);
|
||||||
|
buf.append(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitArrayType(boolean nullable) {
|
||||||
|
visitNullabe(nullable);
|
||||||
|
buf.append('[');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClassType(final String name, boolean nullable) {
|
||||||
|
visitNullabe(nullable);
|
||||||
|
buf.append('L');
|
||||||
|
buf.append(name);
|
||||||
|
argumentStack *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitInnerClassType(final String name, boolean nullable) {
|
||||||
|
endArguments();
|
||||||
|
visitNullabe(nullable);
|
||||||
|
buf.append('.');
|
||||||
|
buf.append(name);
|
||||||
|
argumentStack *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTypeArgument() {
|
||||||
|
if (argumentStack % 2 == 0) {
|
||||||
|
++argumentStack;
|
||||||
|
buf.append('<');
|
||||||
|
}
|
||||||
|
buf.append('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSignatureWriter visitTypeArgument(final char wildcard) {
|
||||||
|
if (argumentStack % 2 == 0) {
|
||||||
|
++argumentStack;
|
||||||
|
buf.append('<');
|
||||||
|
}
|
||||||
|
if (wildcard != '=') {
|
||||||
|
buf.append(wildcard);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEnd() {
|
||||||
|
endArguments();
|
||||||
|
buf.append(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Utility methods
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the formal type parameters section of the signature.
|
||||||
|
*/
|
||||||
|
private void endFormals() {
|
||||||
|
if (hasFormals) {
|
||||||
|
hasFormals = false;
|
||||||
|
buf.append('>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the type arguments of a class or inner class type.
|
||||||
|
*/
|
||||||
|
private void endArguments() {
|
||||||
|
if (argumentStack % 2 != 0) {
|
||||||
|
buf.append('>');
|
||||||
|
}
|
||||||
|
argumentStack /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-4
@@ -14,7 +14,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
|||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
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.StdlibNames;
|
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
|
||||||
@@ -370,13 +369,13 @@ public class JavaDescriptorResolver {
|
|||||||
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||||
attributes.toString();
|
attributes.toString();
|
||||||
|
|
||||||
if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) {
|
if (annotation.getQualifiedName().equals(StdlibNames.JET_VALUE_PARAMETER_CLASS)) {
|
||||||
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD);
|
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD);
|
||||||
if (nameExpression != null) {
|
if (nameExpression != null) {
|
||||||
name = (String) nameExpression.getValue();
|
name = (String) nameExpression.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NULLABLE_FIELD);
|
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD);
|
||||||
if (nullableExpression != null) {
|
if (nullableExpression != null) {
|
||||||
nullable = (Boolean) nullableExpression.getValue();
|
nullable = (Boolean) nullableExpression.getValue();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-1
@@ -58,7 +58,6 @@ public class JavaPackageScope extends JetScopeImpl {
|
|||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(psiClass.getQualifiedName());
|
|
||||||
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true);
|
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true);
|
||||||
// return Collections.emptySet();
|
// return Collections.emptySet();
|
||||||
}
|
}
|
||||||
@@ -78,6 +77,7 @@ public class JavaPackageScope extends JetScopeImpl {
|
|||||||
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
|
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
|
||||||
|
|
||||||
if (javaPackage != null) {
|
if (javaPackage != null) {
|
||||||
|
boolean isKotlinNamespace = semanticServices.getKotlinNamespaceDescriptor(javaPackage.getQualifiedName()) != null;
|
||||||
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
|
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
|
||||||
|
|
||||||
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
|
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
|
||||||
@@ -85,6 +85,8 @@ public class JavaPackageScope extends JetScopeImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (PsiClass psiClass : javaPackage.getClasses()) {
|
for (PsiClass psiClass : javaPackage.getClasses()) {
|
||||||
|
if (isKotlinNamespace && "namespace".equals(psiClass.getName())) continue;
|
||||||
|
|
||||||
// If this is a Kotlin class, we have already taken it through a containing namespace descriptor
|
// If this is a Kotlin class, we have already taken it through a containing namespace descriptor
|
||||||
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(psiClass.getQualifiedName());
|
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(psiClass.getQualifiedName());
|
||||||
if (kotlinClassDescriptor != null) {
|
if (kotlinClassDescriptor != null) {
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
public class StdlibNames {
|
||||||
|
|
||||||
|
public static final String JET_VALUE_PARAMETER_CLASS = "jet.typeinfo.JetValueParameter";
|
||||||
|
public static final String JET_VALUE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetValueParameter;";
|
||||||
|
|
||||||
|
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_NULLABLE_FIELD = "nullable";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
|
||||||
|
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
|
||||||
|
|
||||||
|
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String JET_METHOD_CLASS = "jet.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_OBJECT_INTERNAL = "jet/JetObject";
|
||||||
|
public static final String JET_OBJECT_CLASS = "jet.JetObject";
|
||||||
|
public static final String JET_OBJECT_DESCRIPTOR = "Ljet/JetObject;";
|
||||||
|
|
||||||
|
private StdlibNames() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -131,11 +131,15 @@ public class JetPsiUtil {
|
|||||||
public static String getFQName(JetClass jetClass) {
|
public static String getFQName(JetClass jetClass) {
|
||||||
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(jetClass, JetNamespace.class, JetClass.class);
|
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(jetClass, JetNamespace.class, JetClass.class);
|
||||||
if (parent instanceof JetNamespace) {
|
if (parent instanceof JetNamespace) {
|
||||||
return getFQName(((JetNamespace) parent)) + "." + jetClass.getName();
|
return makeFQName(getFQName(((JetNamespace) parent)), jetClass);
|
||||||
}
|
}
|
||||||
if (parent instanceof JetClass) {
|
if (parent instanceof JetClass) {
|
||||||
return getFQName(((JetClass) parent)) + "." + jetClass.getName();
|
return makeFQName(getFQName(((JetClass) parent)), jetClass);
|
||||||
}
|
}
|
||||||
return jetClass.getName();
|
return jetClass.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String makeFQName(String prefix, JetClass jetClass) {
|
||||||
|
return (prefix.length() == 0 ? "" : prefix + ".") + jetClass.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
|
||||||
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Stepan Koltsov
|
|
||||||
*/
|
|
||||||
public class StdlibNames {
|
|
||||||
|
|
||||||
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter");
|
|
||||||
public static final String JET_PARAMETER_CLASS = "jet.typeinfo.JetParameter";
|
|
||||||
public static final String JET_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetParameter;";
|
|
||||||
|
|
||||||
public static final String JET_PARAMETER_NAME_FIELD = "name";
|
|
||||||
public static final String JET_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
|
|
||||||
public static final String JET_PARAMETER_NULLABLE_FIELD = "nullable";
|
|
||||||
|
|
||||||
|
|
||||||
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
|
|
||||||
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
|
|
||||||
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
|
|
||||||
|
|
||||||
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
|
|
||||||
|
|
||||||
|
|
||||||
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
|
|
||||||
public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod";
|
|
||||||
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
|
|
||||||
|
|
||||||
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -29,6 +29,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
|||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.EXPECTED_TYPE;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.VALUE_ARGUMENT;
|
||||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
@@ -470,7 +473,7 @@ public class CallResolver {
|
|||||||
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown);
|
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown);
|
||||||
JetType type = temporaryServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT));
|
JetType type = temporaryServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT));
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
|
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
candidateCall.argumentHasNoType();
|
candidateCall.argumentHasNoType();
|
||||||
@@ -483,12 +486,12 @@ public class CallResolver {
|
|||||||
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
||||||
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
|
||||||
if (receiverArgument.exists() && receiverParameter.exists()) {
|
if (receiverArgument.exists() && receiverParameter.exists()) {
|
||||||
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
|
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type
|
// Return type
|
||||||
if (expectedType != NO_EXPECTED_TYPE) {
|
if (expectedType != NO_EXPECTED_TYPE) {
|
||||||
constraintSystem.addSubtypingConstraint(candidateWithFreshVariables.getReturnType(), expectedType);
|
constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), expectedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Solution
|
// Solution
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
|
import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.util.slicedmap.*;
|
import org.jetbrains.jet.util.slicedmap.*;
|
||||||
@@ -22,8 +22,8 @@ public class ResolutionDebugInfo {
|
|||||||
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
|
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, StringBuilder> ERRORS = Slices.createSimpleSlice();
|
public static final WritableSlice<One, StringBuilder> ERRORS = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, StringBuilder> LOG = Slices.createSimpleSlice();
|
public static final WritableSlice<One, StringBuilder> LOG = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
|
public static final WritableSlice<One, Map<TypeParameterDescriptor, BoundsOwner>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, Map<JetType, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
|
public static final WritableSlice<One, Map<JetType, BoundsOwner>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice();
|
public static final WritableSlice<One, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, Collection<TypeParameterDescriptor>> UNKNOWNS = Slices.createSimpleSlice();
|
public static final WritableSlice<One, Collection<TypeParameterDescriptor>> UNKNOWNS = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ import java.util.Map;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public interface ResolvedCall<D extends CallableDescriptor> {
|
public interface ResolvedCall<D extends CallableDescriptor> {
|
||||||
/** A target callable descriptor as it was accessible in the corresponding scope, i.e. with type parameters not substituted */
|
/** A target callable descriptor as it was accessible in the corresponding scope, i.e. with type arguments not substituted */
|
||||||
@NotNull
|
@NotNull
|
||||||
D getCandidateDescriptor();
|
D getCandidateDescriptor();
|
||||||
|
|
||||||
/** Type parameters are substituted */
|
/** Type arguments are substituted. This descriptor is guaranteed to have NO declared type parameters */
|
||||||
@NotNull
|
@NotNull
|
||||||
D getResultingDescriptor();
|
D getResultingDescriptor();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public interface BoundsOwner {
|
||||||
|
@NotNull
|
||||||
|
Set<TypeValue> getUpperBounds();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Set<TypeValue> getLowerBounds();
|
||||||
|
}
|
||||||
+8
-8
@@ -12,11 +12,11 @@ public interface ConstraintResolutionListener {
|
|||||||
|
|
||||||
public static final ConstraintResolutionListener DO_NOTHING = new ConstraintResolutionListener() {
|
public static final ConstraintResolutionListener DO_NOTHING = new ConstraintResolutionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -24,18 +24,18 @@ public interface ConstraintResolutionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(Object message) {
|
public void log(Object... messageFragments) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Object message) {
|
public void error(Object... messageFragments) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue);
|
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue);
|
||||||
void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue);
|
void constraintsForKnownType(JetType type, BoundsOwner typeValue);
|
||||||
void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors);
|
void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors);
|
||||||
|
|
||||||
void log(Object message);
|
void log(Object... messageFragments);
|
||||||
void error(Object message);
|
void error(Object... messageFragments);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls.inference;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +10,7 @@ import org.jetbrains.jet.lang.types.Variance;
|
|||||||
public interface ConstraintSystem {
|
public interface ConstraintSystem {
|
||||||
void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance);
|
void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance);
|
||||||
|
|
||||||
void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper);
|
void addSubtypingConstraint(@NotNull SubtypingConstraint constraint);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
ConstraintSystemSolution solve();
|
ConstraintSystemSolution solve();
|
||||||
|
|||||||
+29
-21
@@ -143,7 +143,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.log("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
|
listener.log("minimal solution from lowerbounds for ", this, " is ", commonSupertype);
|
||||||
value = new KnownType(commonSupertype);
|
value = new KnownType(commonSupertype);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -247,10 +247,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
|
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
listener.error("-- Failed to equate " + a + " and " + b);
|
listener.error("-- Failed to equate ", a, " and ", b);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -259,16 +259,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||||
boolean result = delegate.assertEqualTypeConstructors(a, b);
|
boolean result = delegate.assertEqualTypeConstructors(a, b);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
listener.error("-- Type constructors are not equal: " + a + " and " + b);
|
listener.error("-- Type constructors are not equal: ", a, " and ", b);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
|
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
|
listener.error("-- ", subtype, " can't be a subtype of ", supertype);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -277,7 +277,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
|
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
|
listener.error("-- ", subtype, " has no supertype corresponding to ", supertype);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
private TypeCheckingProcedure createConstraintExpander() {
|
private TypeCheckingProcedure createConstraintExpander() {
|
||||||
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
|
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
|
||||||
@Override
|
@Override
|
||||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
TypeValue aValue = getTypeValueFor(a);
|
TypeValue aValue = getTypeValueFor(a);
|
||||||
TypeValue bValue = getTypeValueFor(b);
|
TypeValue bValue = getTypeValueFor(b);
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
TypeValue subtypeValue = getTypeValueFor(subtype);
|
TypeValue subtypeValue = getTypeValueFor(subtype);
|
||||||
TypeValue supertypeValue = getTypeValueFor(supertype);
|
TypeValue supertypeValue = getTypeValueFor(supertype);
|
||||||
|
|
||||||
@@ -382,14 +382,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
|
public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) {
|
||||||
TypeValue typeValueForLower = getTypeValueFor(lower);
|
TypeValue typeValueForLower = getTypeValueFor(constraint.getSubtype());
|
||||||
TypeValue typeValueForUpper = getTypeValueFor(upper);
|
TypeValue typeValueForUpper = getTypeValueFor(constraint.getSupertype());
|
||||||
addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper);
|
addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
|
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
|
||||||
listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper);
|
listener.log("Constraint added: ", typeValueForLower, " :< ", typeValueForUpper);
|
||||||
if (typeValueForLower != typeValueForUpper) {
|
if (typeValueForLower != typeValueForUpper) {
|
||||||
typeValueForLower.addUpperBound(typeValueForUpper);
|
typeValueForLower.addUpperBound(typeValueForUpper);
|
||||||
typeValueForUpper.addLowerBound(typeValueForLower);
|
typeValueForUpper.addLowerBound(typeValueForLower);
|
||||||
@@ -409,14 +409,22 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
KnownType knownBoundType = (KnownType) upperBound;
|
KnownType knownBoundType = (KnownType) upperBound;
|
||||||
boolean ok = constraintExpander.isSubtypeOf(jetType, knownBoundType.getType());
|
boolean ok = constraintExpander.isSubtypeOf(jetType, knownBoundType.getType());
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
listener.error("Error while expanding '" + jetType + " :< " + knownBoundType.getType() + "'");
|
listener.error("Error while expanding '", jetType, " :< ", knownBoundType.getType(), "'");
|
||||||
return new Solution().registerError("Mismatch while expanding constraints");
|
return new Solution().registerError("Mismatch while expanding constraints");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lower bounds?
|
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
|
||||||
|
if (lowerBound instanceof KnownType) {
|
||||||
|
KnownType knownBoundType = (KnownType) lowerBound;
|
||||||
|
boolean ok = constraintExpander.isSubtypeOf(knownBoundType.getType(), jetType);
|
||||||
|
if (!ok) {
|
||||||
|
listener.error("Error while expanding '" + knownBoundType.getType() + " :< " + jetType + "'");
|
||||||
|
return new Solution().registerError("Mismatch while expanding constraints");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in upper bounds from type parameter bounds
|
// Fill in upper bounds from type parameter bounds
|
||||||
@@ -435,11 +443,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (UnknownType unknownType : unknownTypes.values()) {
|
for (UnknownType unknownType : unknownTypes.values()) {
|
||||||
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
|
// listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (KnownType knownType : knownTypes.values()) {
|
for (KnownType knownType : knownTypes.values()) {
|
||||||
listener.constraintsForKnownType(knownType.getType(), knownType);
|
// listener.constraintsForKnownType(knownType.getType(), knownType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find inconsistencies
|
// Find inconsistencies
|
||||||
@@ -469,14 +477,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
|
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
|
||||||
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
|
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
|
||||||
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
|
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
|
||||||
listener.error("Constraint violation: " + type + " :< " + boundingType);
|
listener.error("Constraint violation: ", type, " :< ", boundingType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
|
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
|
||||||
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
|
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
|
||||||
if (!typeChecker.isSubtypeOf(boundingType, type)) {
|
if (!typeChecker.isSubtypeOf(boundingType, type)) {
|
||||||
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
|
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
|
||||||
listener.error("Constraint violation: " + boundingType + " :< " + type);
|
listener.error("Constraint violation: ", boundingType, " :< ", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,7 +542,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
|
|
||||||
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
|
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
|
||||||
|
|
||||||
listener.log(descriptor + " |-> " + typeProjection);
|
listener.log(descriptor, " |-> ", typeProjection);
|
||||||
|
|
||||||
return typeProjection;
|
return typeProjection;
|
||||||
}
|
}
|
||||||
|
|||||||
+470
@@ -0,0 +1,470 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.TypingConstraints;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.PARAMETER_BOUND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class ConstraintSystemWithPriorities implements ConstraintSystem {
|
||||||
|
|
||||||
|
public static final Comparator<SubtypingConstraint> SUBTYPING_CONSTRAINT_ORDER = new Comparator<SubtypingConstraint>() {
|
||||||
|
@Override
|
||||||
|
public int compare(SubtypingConstraint o1, SubtypingConstraint o2) {
|
||||||
|
return o1.getType().compareTo(o2.getType());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static class LoopInTypeVariableConstraintsException extends RuntimeException {
|
||||||
|
public LoopInTypeVariableConstraintsException() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================================================================================================
|
||||||
|
|
||||||
|
private final Map<JetType, TypeValue> knownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging
|
||||||
|
private final Map<TypeParameterDescriptor, TypeValue> unknownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging
|
||||||
|
private final Set<TypeValue> unsolvedUnknowns = Sets.newLinkedHashSet(); // linked - for easier debugging
|
||||||
|
private final PriorityQueue<SubtypingConstraint> constraintQueue = new PriorityQueue<SubtypingConstraint>(10, SUBTYPING_CONSTRAINT_ORDER);
|
||||||
|
|
||||||
|
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||||
|
private final TypeCheckingProcedure constraintExpander;
|
||||||
|
private final ConstraintResolutionListener listener;
|
||||||
|
|
||||||
|
public ConstraintSystemWithPriorities(ConstraintResolutionListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
this.constraintExpander = createConstraintExpander();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
||||||
|
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||||
|
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||||
|
// Checking that this is not a T?, but exactly T
|
||||||
|
if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) {
|
||||||
|
TypeValue unknownType = unknownTypes.get(typeParameterDescriptor);
|
||||||
|
if (unknownType != null) {
|
||||||
|
return unknownType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeValue typeValue = knownTypes.get(type);
|
||||||
|
if (typeValue == null) {
|
||||||
|
typeValue = new TypeValue(type);
|
||||||
|
knownTypes.put(type, typeValue);
|
||||||
|
}
|
||||||
|
return typeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) {
|
||||||
|
assert !unknownTypes.containsKey(typeParameterDescriptor);
|
||||||
|
TypeValue typeValue = new TypeValue(typeParameterDescriptor, positionVariance);
|
||||||
|
unknownTypes.put(typeParameterDescriptor, typeValue);
|
||||||
|
unsolvedUnknowns.add(typeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private TypeValue getTypeVariable(TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
|
TypeValue unknownType = unknownTypes.get(typeParameterDescriptor);
|
||||||
|
if (unknownType == null) {
|
||||||
|
throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system: " + typeParameterDescriptor);
|
||||||
|
}
|
||||||
|
return unknownType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) {
|
||||||
|
constraintQueue.add(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constraint expansion
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private TypeCheckingProcedure createConstraintExpander() {
|
||||||
|
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
|
TypeValue aValue = getTypeValueFor(a);
|
||||||
|
TypeValue bValue = getTypeValueFor(b);
|
||||||
|
|
||||||
|
return expandEqualityConstraint(aValue, bValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||||
|
return a.equals(b)
|
||||||
|
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|
||||||
|
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
|
TypeValue subtypeValue = getTypeValueFor(subtype);
|
||||||
|
TypeValue supertypeValue = getTypeValueFor(supertype);
|
||||||
|
|
||||||
|
if (someUnknown(subtypeValue, supertypeValue)) {
|
||||||
|
expandSubtypingConstraint(subtypeValue, supertypeValue);
|
||||||
|
}
|
||||||
|
return true; // For known types further expansion happens automatically
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
// If some of the types is an unknown, the constraint must be generated, and we should carry on
|
||||||
|
// otherwise there can be no solution, and we should fail
|
||||||
|
TypeValue subTypeValue = getTypeValueFor(subtype);
|
||||||
|
TypeValue superTypeValue = getTypeValueFor(supertype);
|
||||||
|
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
|
||||||
|
if (someUnknown) {
|
||||||
|
expandSubtypingConstraint(subTypeValue, superTypeValue);
|
||||||
|
}
|
||||||
|
return someUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
|
||||||
|
return !subtypeValue.isKnown() || !supertypeValue.isKnown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean assignValueTo(TypeValue unknown, JetType value) {
|
||||||
|
if (unknown.hasValue()) {
|
||||||
|
// If we have already assigned a value to this unknown,
|
||||||
|
// it is a conflict to assign another one, unless this new one is equal to the previous
|
||||||
|
return TypeUtils.equalTypes(unknown.getType(), value);
|
||||||
|
}
|
||||||
|
unsolvedUnknowns.remove(unknown);
|
||||||
|
unknown.setValue(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mergeUnknowns(@NotNull TypeValue a, @NotNull TypeValue b) {
|
||||||
|
assert !a.isKnown() && !b.isKnown();
|
||||||
|
listener.error("!!!mergeUnknowns() is not implemented!!!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean expandEqualityConstraint(TypeValue a, TypeValue b) {
|
||||||
|
if (a.isKnown() && b.isKnown()) {
|
||||||
|
return constraintExpander.equalTypes(a.getType(), b.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// At least one of them is unknown
|
||||||
|
if (a.isKnown()) {
|
||||||
|
TypeValue tmp = a;
|
||||||
|
a = b;
|
||||||
|
b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now a is definitely unknown
|
||||||
|
if (b.isKnown()) {
|
||||||
|
return assignValueTo(a, b.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// They are both unknown
|
||||||
|
return mergeUnknowns(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean expandSubtypingConstraint(TypeValue lower, TypeValue upper) {
|
||||||
|
listener.log("Constraint added: ", lower, " :< ", upper);
|
||||||
|
|
||||||
|
if (lower == upper) return true;
|
||||||
|
|
||||||
|
// Remember for a later check
|
||||||
|
lower.addUpperBound(upper);
|
||||||
|
upper.addLowerBound(lower);
|
||||||
|
|
||||||
|
if (lower.isKnown() && upper.isKnown()) {
|
||||||
|
// Two known types: expand constraints
|
||||||
|
return constraintExpander.isSubtypeOf(lower.getType(), upper.getType());
|
||||||
|
}
|
||||||
|
else if (!lower.isKnown() && !upper.isKnown()) {
|
||||||
|
// Two unknown types: merge them into one variable
|
||||||
|
return mergeUnknowns(lower, upper);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// One unknown and one known
|
||||||
|
if (upper.isKnown()) {
|
||||||
|
if (TypeUtils.canHaveSubtypes(typeChecker, upper.getType())) {
|
||||||
|
// Upper bound is final -> we have to equate the lower bounds to it
|
||||||
|
return expandEqualityConstraint(lower, upper);
|
||||||
|
}
|
||||||
|
if (lower.getLowerBounds().contains(upper)) {
|
||||||
|
// upper :< lower :< upper
|
||||||
|
return expandEqualityConstraint(lower, upper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (upper.getUpperBounds().contains(lower)) {
|
||||||
|
// lower :< upper :< lower
|
||||||
|
return expandEqualityConstraint(lower, upper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public ConstraintSystemSolution solve() {
|
||||||
|
Solution solution = new Solution();
|
||||||
|
// At this point we only have type values, no bounds added for them, no values computed for unknown types
|
||||||
|
|
||||||
|
// Generate low-priority constraints from bounds
|
||||||
|
for (Map.Entry<TypeParameterDescriptor, TypeValue> entry : Sets.newHashSet(unknownTypes.entrySet())) {
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = entry.getKey();
|
||||||
|
TypeValue typeValue = entry.getValue();
|
||||||
|
for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) {
|
||||||
|
addSubtypingConstraint(PARAMETER_BOUND.assertSubtyping(typeValue.getOriginalType(), getTypeValueFor(upperBound).getOriginalType()));
|
||||||
|
}
|
||||||
|
for (JetType lowerBound : typeParameterDescriptor.getLowerBounds()) {
|
||||||
|
addSubtypingConstraint(PARAMETER_BOUND.assertSubtyping(getTypeValueFor(lowerBound).getOriginalType(), typeValue.getOriginalType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand and solve constraints
|
||||||
|
while (!constraintQueue.isEmpty()) {
|
||||||
|
SubtypingConstraint constraint = constraintQueue.poll();
|
||||||
|
|
||||||
|
// Apply constraint
|
||||||
|
TypeValue lower = getTypeValueFor(constraint.getSubtype());
|
||||||
|
TypeValue upper = getTypeValueFor(constraint.getSupertype());
|
||||||
|
boolean success = expandSubtypingConstraint(lower, upper);
|
||||||
|
if (!success) {
|
||||||
|
solution.registerError(constraint.getErrorMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (???) Propagate info
|
||||||
|
|
||||||
|
// Any unknowns left?
|
||||||
|
if (unsolvedUnknowns.isEmpty()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, let's check the rest of the constraints
|
||||||
|
|
||||||
|
// Expand custom bounds, e.g. List<T> <: List<Int>
|
||||||
|
// for (Map.Entry<JetType, TypeValue> entry : Sets.newHashSet(knownTypes.entrySet())) {
|
||||||
|
// JetType jetType = entry.getKey();
|
||||||
|
// TypeValue typeValue = entry.getValue();
|
||||||
|
//
|
||||||
|
// for (TypeValue upperBound : typeValue.getUpperBounds()) {
|
||||||
|
// if (upperBound.isKnown()) {
|
||||||
|
// boolean ok = constraintExpander.isSubtypeOf(jetType, upperBound.getType());
|
||||||
|
// if (!ok) {
|
||||||
|
// listener.error("Error while expanding '" + jetType + " :< " + upperBound.getType() + "'");
|
||||||
|
// return new Solution().registerError("Mismatch while expanding constraints");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Lower bounds. Probably not needed for known types, as everything is symmetrical anyway
|
||||||
|
// }
|
||||||
|
|
||||||
|
// effective bounds for each node
|
||||||
|
// Set<TypeValue> visited = Sets.newHashSet();
|
||||||
|
// for (TypeValue unknownType : unknownTypes.values()) {
|
||||||
|
// transitiveClosure(unknownType, visited);
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (TypeValue unknownType : unknownTypes.values()) {
|
||||||
|
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
|
||||||
|
}
|
||||||
|
for (TypeValue knownType : knownTypes.values()) {
|
||||||
|
listener.constraintsForKnownType(knownType.getType(), knownType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find inconsistencies
|
||||||
|
|
||||||
|
// Compute values and check that all bounds are respected by solutions:
|
||||||
|
// we have set some of them from equality constraints with known types
|
||||||
|
// and thus the bounds may be violated if some of the constraints conflict
|
||||||
|
for (TypeValue unknownType : unknownTypes.values()) {
|
||||||
|
check(unknownType, solution);
|
||||||
|
}
|
||||||
|
for (TypeValue knownType : knownTypes.values()) {
|
||||||
|
check(knownType, solution);
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.done(solution, unknownTypes.keySet());
|
||||||
|
|
||||||
|
return solution;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transitiveClosure(TypeValue current, Set<TypeValue> visited) {
|
||||||
|
if (!visited.add(current)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) {
|
||||||
|
if (upperBound.isKnown()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
transitiveClosure(upperBound, visited);
|
||||||
|
Set<TypeValue> upperBounds = upperBound.getUpperBounds();
|
||||||
|
for (TypeValue transitiveBound : upperBounds) {
|
||||||
|
expandSubtypingConstraint(current, transitiveBound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void check(TypeValue typeValue, Solution solution) {
|
||||||
|
try {
|
||||||
|
JetType resultingType = typeValue.getType();
|
||||||
|
JetType type = solution.getSubstitutor().substitute(resultingType, Variance.INVARIANT); // TODO
|
||||||
|
for (TypeValue upperBound : typeValue.getUpperBounds()) {
|
||||||
|
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getType(), Variance.INVARIANT);
|
||||||
|
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
|
||||||
|
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
|
||||||
|
listener.error("Constraint violation: ", type, " :< ", boundingType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
|
||||||
|
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getType(), Variance.INVARIANT);
|
||||||
|
if (!typeChecker.isSubtypeOf(boundingType, type)) {
|
||||||
|
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
|
||||||
|
listener.error("Constraint violation: ", boundingType, " :< ", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (LoopInTypeVariableConstraintsException e) {
|
||||||
|
listener.error("Loop detected");
|
||||||
|
solution.registerError("[TODO] Loop in constraints");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Error implements SolutionStatus {
|
||||||
|
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
private Error(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSuccessful() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Solution implements ConstraintSystemSolution {
|
||||||
|
private final TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(new TypeSubstitutor.TypeSubstitution() {
|
||||||
|
@Override
|
||||||
|
public TypeProjection get(TypeConstructor key) {
|
||||||
|
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
|
||||||
|
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||||
|
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||||
|
|
||||||
|
if (!unknownTypes.containsKey(descriptor)) return null;
|
||||||
|
|
||||||
|
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
|
||||||
|
|
||||||
|
listener.log(descriptor, " |-> ", typeProjection);
|
||||||
|
|
||||||
|
return typeProjection;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private SolutionStatus status;
|
||||||
|
|
||||||
|
public Solution() {
|
||||||
|
this.status = SolutionStatus.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Solution registerError(String message) {
|
||||||
|
status = new Error(message);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public SolutionStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getValue(TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
|
return getTypeVariable(typeParameterDescriptor).getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeSubstitutor getSubstitutor() {
|
||||||
|
return typeSubstitutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
|
||||||
|
private final TypingConstraints delegate;
|
||||||
|
private final ConstraintResolutionListener listener;
|
||||||
|
|
||||||
|
private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
|
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
|
||||||
|
if (!result) {
|
||||||
|
listener.error("-- Failed to equate ", a, " and ", b);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||||
|
boolean result = delegate.assertEqualTypeConstructors(a, b);
|
||||||
|
if (!result) {
|
||||||
|
listener.error("-- Type constructors are not equal: ", a, " and ", b);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
|
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
|
||||||
|
if (!result) {
|
||||||
|
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
|
||||||
|
if (!result) {
|
||||||
|
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public enum ConstraintType implements Comparable<ConstraintType> {
|
||||||
|
// The order of these constants DOES matter
|
||||||
|
// they are compared according to ordinal() values
|
||||||
|
// First element has the highest priority
|
||||||
|
RECEIVER("{0} is not a subtype of the expected receiver type {1}"),
|
||||||
|
VALUE_ARGUMENT("Type mismatch: argument type is {0}, but {1} was expected"),
|
||||||
|
EXPECTED_TYPE("Resulting type is {0} but {1} was expected"),
|
||||||
|
PARAMETER_BOUND("Type parameter bound is not satisfied: {0} is not a subtype of {1}");
|
||||||
|
|
||||||
|
private final String errorMessageTemplate; // {0} is subtype, {1} is supertye
|
||||||
|
|
||||||
|
private ConstraintType(@NotNull String errorMessageTemplate) {
|
||||||
|
this.errorMessageTemplate = errorMessageTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public SubtypingConstraint assertSubtyping(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
return new SubtypingConstraint(this, subtype, supertype);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String makeErrorMessage(@NotNull SubtypingConstraint constraint) {
|
||||||
|
return MessageFormat.format(errorMessageTemplate, constraint.getSubtype(), constraint.getSupertype());
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-8
@@ -23,9 +23,9 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
|
||||||
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
||||||
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
|
Map<TypeParameterDescriptor, BoundsOwner> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = Maps.newLinkedHashMap();
|
map = Maps.newLinkedHashMap();
|
||||||
debugInfo.set(BOUNDS_FOR_UNKNOWNS, map);
|
debugInfo.set(BOUNDS_FOR_UNKNOWNS, map);
|
||||||
@@ -34,9 +34,9 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
|
||||||
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
||||||
Map<JetType,ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
|
Map<JetType,BoundsOwner> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = Maps.newLinkedHashMap();
|
map = Maps.newLinkedHashMap();
|
||||||
debugInfo.set(BOUNDS_FOR_KNOWNS, map);
|
debugInfo.set(BOUNDS_FOR_KNOWNS, map);
|
||||||
@@ -52,24 +52,30 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(Object message) {
|
public void log(Object... messageFragments) {
|
||||||
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
||||||
StringBuilder stringBuilder = debugInfo.get(LOG);
|
StringBuilder stringBuilder = debugInfo.get(LOG);
|
||||||
if (stringBuilder == null) {
|
if (stringBuilder == null) {
|
||||||
stringBuilder = new StringBuilder();
|
stringBuilder = new StringBuilder();
|
||||||
debugInfo.set(LOG, stringBuilder);
|
debugInfo.set(LOG, stringBuilder);
|
||||||
}
|
}
|
||||||
stringBuilder.append(message).append("\n");
|
for (Object m : messageFragments) {
|
||||||
|
stringBuilder.append(m);
|
||||||
|
}
|
||||||
|
stringBuilder.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Object message) {
|
public void error(Object... messageFragments) {
|
||||||
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
|
||||||
StringBuilder stringBuilder = debugInfo.get(ERRORS);
|
StringBuilder stringBuilder = debugInfo.get(ERRORS);
|
||||||
if (stringBuilder == null) {
|
if (stringBuilder == null) {
|
||||||
stringBuilder = new StringBuilder();
|
stringBuilder = new StringBuilder();
|
||||||
debugInfo.set(ERRORS, stringBuilder);
|
debugInfo.set(ERRORS, stringBuilder);
|
||||||
}
|
}
|
||||||
stringBuilder.append(message).append("\n");
|
for (Object m : messageFragments) {
|
||||||
|
stringBuilder.append(m);
|
||||||
|
}
|
||||||
|
stringBuilder.append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-9
@@ -12,13 +12,13 @@ import java.util.Set;
|
|||||||
public class PrintingConstraintResolutionListener implements ConstraintResolutionListener {
|
public class PrintingConstraintResolutionListener implements ConstraintResolutionListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
|
||||||
println("Constraints for " + typeParameterDescriptor);
|
println("Constraints for " + typeParameterDescriptor);
|
||||||
printTypeValue(typeValue);
|
printTypeValue(typeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
|
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
|
||||||
println("Constraints for " + type);
|
println("Constraints for " + type);
|
||||||
printTypeValue(typeValue);
|
printTypeValue(typeValue);
|
||||||
}
|
}
|
||||||
@@ -31,20 +31,24 @@ public class PrintingConstraintResolutionListener implements ConstraintResolutio
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(Object message) {
|
public void log(Object... messageFragments) {
|
||||||
println(message);
|
for (Object fragment : messageFragments) {
|
||||||
|
println(fragment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Object message) {
|
public void error(Object... messageFragments) {
|
||||||
println(message);
|
for (Object fragment : messageFragments) {
|
||||||
|
println(fragment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printTypeValue(ConstraintSystemImpl.TypeValue typeValue) {
|
private void printTypeValue(BoundsOwner typeValue) {
|
||||||
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
|
for (BoundsOwner bound : typeValue.getUpperBounds()) {
|
||||||
println(" :< " + bound);
|
println(" :< " + bound);
|
||||||
}
|
}
|
||||||
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
|
for (BoundsOwner bound : typeValue.getLowerBounds()) {
|
||||||
println(" :> " + bound);
|
println(" :> " + bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class SubtypingConstraint {
|
||||||
|
private final ConstraintType type;
|
||||||
|
private final JetType subtype;
|
||||||
|
private final JetType supertype;
|
||||||
|
|
||||||
|
public SubtypingConstraint(@NotNull ConstraintType type, @NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
this.type = type;
|
||||||
|
this.subtype = subtype;
|
||||||
|
this.supertype = supertype;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getSubtype() {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getSupertype() {
|
||||||
|
return supertype;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ConstraintType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return type.makeErrorMessage(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.calls.inference;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class TypeValue implements BoundsOwner {
|
||||||
|
private final Set<TypeValue> upperBounds = Sets.newLinkedHashSet();
|
||||||
|
private final Set<TypeValue> lowerBounds = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
|
private final Variance positionVariance;
|
||||||
|
private final TypeParameterDescriptor typeParameterDescriptor; // Null for known types
|
||||||
|
private final JetType originalType;
|
||||||
|
private JetType value; // For an unknown — the value found by constraint resolution, for a known — just it's value
|
||||||
|
|
||||||
|
// Unknown type
|
||||||
|
public TypeValue(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) {
|
||||||
|
this.positionVariance = positionVariance;
|
||||||
|
this.typeParameterDescriptor = typeParameterDescriptor;
|
||||||
|
this.originalType = typeParameterDescriptor.getDefaultType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Known type
|
||||||
|
public TypeValue(@NotNull JetType knownType) {
|
||||||
|
this.positionVariance = null;
|
||||||
|
this.typeParameterDescriptor = null;
|
||||||
|
this.originalType = knownType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isKnown() {
|
||||||
|
return typeParameterDescriptor == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeParameterDescriptor getTypeParameterDescriptor() {
|
||||||
|
return typeParameterDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Set<TypeValue> getUpperBounds() {
|
||||||
|
return upperBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Set<TypeValue> getLowerBounds() {
|
||||||
|
return lowerBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getType() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getOriginalType() {
|
||||||
|
return originalType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUpperBound(@NotNull TypeValue bound) {
|
||||||
|
upperBounds.add(bound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLowerBound(@NotNull TypeValue bound) {
|
||||||
|
lowerBounds.add(bound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(@NotNull JetType value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasValue() {
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,7 +203,7 @@ public class ErrorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isError(@NotNull DeclarationDescriptor candidate) {
|
public static boolean isError(@NotNull DeclarationDescriptor candidate) {
|
||||||
return candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
|
return candidate == getErrorClass() || candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ErrorTypeImpl implements JetType {
|
private static class ErrorTypeImpl implements JetType {
|
||||||
|
|||||||
@@ -1,19 +1,41 @@
|
|||||||
package org.jetbrains.jet.lang.types;
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class TypeSubstitutor {
|
public class TypeSubstitutor {
|
||||||
|
|
||||||
|
public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
|
||||||
|
final Set<TypeConstructor> constructors = Sets.newHashSet();
|
||||||
|
for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
|
||||||
|
constructors.add(typeParameterDescriptor.getTypeConstructor());
|
||||||
|
}
|
||||||
|
final TypeProjection projection = new TypeProjection(type);
|
||||||
|
|
||||||
|
return create(new TypeSubstitution() {
|
||||||
|
@Override
|
||||||
|
public TypeProjection get(TypeConstructor key) {
|
||||||
|
if (constructors.contains(key)) {
|
||||||
|
return projection;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public interface TypeSubstitution {
|
public interface TypeSubstitution {
|
||||||
TypeSubstitution EMPTY = new TypeSubstitution() {
|
TypeSubstitution EMPTY = new TypeSubstitution() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class JetTypeChecker {
|
|||||||
|
|
||||||
private static class TypeCheckerTypingConstraints implements TypingConstraints {
|
private static class TypeCheckerTypingConstraints implements TypingConstraints {
|
||||||
@Override
|
@Override
|
||||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
return typeCheckingProcedure.equalTypes(a, b);
|
return typeCheckingProcedure.equalTypes(a, b);
|
||||||
// return TypeUtils.equalTypes(a, b);
|
// return TypeUtils.equalTypes(a, b);
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
|
||||||
return typeCheckingProcedure.isSubtypeOf(subtype, supertype);
|
return typeCheckingProcedure.isSubtypeOf(subtype, supertype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import org.jetbrains.jet.lang.types.TypeConstructor;
|
|||||||
* Methods of this class return true to continue type checking and false to fail
|
* Methods of this class return true to continue type checking and false to fail
|
||||||
*/
|
*/
|
||||||
public interface TypingConstraints {
|
public interface TypingConstraints {
|
||||||
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure);
|
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure);
|
||||||
|
|
||||||
boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b);
|
boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b);
|
||||||
|
|
||||||
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure);
|
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure);
|
||||||
|
|
||||||
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import std.*
|
||||||
import std.io.*
|
import std.io.*
|
||||||
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
class A() {}
|
class A() {}
|
||||||
|
|
||||||
open class B<T>() {
|
open class B<T>() {
|
||||||
fun isT (a : Any?) : Boolean {
|
fun isT (a : Any?) : Boolean {
|
||||||
return a is T
|
return a is T
|
||||||
@@ -167,7 +168,6 @@ fun t26 () : Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun box() : String {
|
fun box() : String {
|
||||||
/*
|
|
||||||
if(!t1()) {
|
if(!t1()) {
|
||||||
return "t1 failed"
|
return "t1 failed"
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,6 @@ fun box() : String {
|
|||||||
if(!t25()) {
|
if(!t25()) {
|
||||||
return "t25 failed"
|
return "t25 failed"
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if(!t26()) {
|
if(!t26()) {
|
||||||
return "t26 failed"
|
return "t26 failed"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class A() {
|
||||||
|
var x : Int = 0
|
||||||
|
|
||||||
|
var z = { () =>
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val a = A()
|
||||||
|
a.z() //problem is here
|
||||||
|
return if (a.x == 1) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun <T> Array<T>?.get(i : Int?) = this.sure().get(i.sure())
|
||||||
|
fun <T> array(vararg t : T) : Array<T> = t
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val a : Array<String>? = array<String>("Str", "Str2")
|
||||||
|
val i : Int? = 1
|
||||||
|
return if(a[i] == "Str2") "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
open class A<T> () {
|
open class A<out T> () {
|
||||||
fun plus(e: T) = B<T> (e)
|
fun plus(e: T) = B<T> (e)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,4 +6,6 @@ class B<T> (val e: T) : A<T>() {
|
|||||||
fun add() = B<T> (e)
|
fun add() = B<T> (e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box() = if( A<String>().plus("239").add().e == "239" ) "OK" else "fail"
|
fun box() : String {
|
||||||
|
return if(A<String>().plus("239").add().e == "239" ) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ class Box<T>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Inner2() : Inner() {
|
class Inner2() : Inner() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inner() = Inner2()
|
fun inner() = Inner2()
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class ExtendsAbstractListT {
|
||||||
|
{
|
||||||
|
Mine<String> mine = null;
|
||||||
|
java.util.List<String> list = mine;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
abstract class Mine<T>() : java.util.AbstractList<T>()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
class PlainExtendsListString {
|
||||||
|
{
|
||||||
|
Mine mine = null;
|
||||||
|
java.util.List<String> list = mine;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
abstract class Mine : java.util.List<String>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
class ImplementsMapPP {
|
||||||
|
{
|
||||||
|
Mine<String, Integer> mine = null;
|
||||||
|
java.util.Map<Integer, String> map = mine;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
abstract class Mine<P1, P2> : java.util.Map<P2, P1>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
class Question {
|
||||||
|
// id2 is to prevent java type parameter type inference
|
||||||
|
static <T> T id2(T p) { return p; }
|
||||||
|
{
|
||||||
|
java.util.List<String> s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import java.util.List
|
||||||
|
|
||||||
|
fun <P1 : List<String>> id(p: P1) = p
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
class Question {
|
||||||
|
// id2 is to prevent java type parameter type inference
|
||||||
|
static <T> T id2(T p) { return p; }
|
||||||
|
{
|
||||||
|
String s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fun <T : String> id(p: T) = p
|
||||||
@@ -24,7 +24,7 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testArrayListInheritance() throws Exception {
|
public void testArrayListInheritance() throws Exception {
|
||||||
loadFile("classes/inheritingFromArrayList.jet");
|
loadFile("classes/inheritingFromArrayList.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
final Class aClass = loadClass("Foo", generateClassesInFile());
|
final Class aClass = loadClass("Foo", generateClassesInFile());
|
||||||
assertInstanceOf(aClass.newInstance(), List.class);
|
assertInstanceOf(aClass.newInstance(), List.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ public class FunctionGenTest extends CodegenTestCase {
|
|||||||
blackBoxFile("regressions/kt395.jet");
|
blackBoxFile("regressions/kt395.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt785 () {
|
||||||
|
// blackBoxFile("regressions/kt785.jet");
|
||||||
|
}
|
||||||
|
|
||||||
public void testFunction () throws InvocationTargetException, IllegalAccessException {
|
public void testFunction () throws InvocationTargetException, IllegalAccessException {
|
||||||
blackBoxFile("functions/functionExpression.jet");
|
blackBoxFile("functions/functionExpression.jet");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class TypeInfoTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testInner() throws Exception {
|
public void testInner() throws Exception {
|
||||||
blackBoxFile("typeInfo/inner.jet");
|
blackBoxFile("typeInfo/inner.jet");
|
||||||
// System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInheritance() throws Exception {
|
public void testInheritance() throws Exception {
|
||||||
@@ -148,4 +148,3 @@ public class TypeInfoTest extends CodegenTestCase {
|
|||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,4 +74,8 @@ public class VarArgTest extends CodegenTestCase {
|
|||||||
createEnvironmentWithFullJdk();
|
createEnvironmentWithFullJdk();
|
||||||
blackBoxFile("regressions/kt581.jet");
|
blackBoxFile("regressions/kt581.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt797() {
|
||||||
|
blackBoxFile("regressions/kt796_797.jet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
abstract public class FList<T> {
|
||||||
|
abstract T getHead();
|
||||||
|
|
||||||
|
abstract FList<T> getTail();
|
||||||
|
|
||||||
|
abstract FList<T> plus(T element);
|
||||||
|
|
||||||
|
static class Empty<T> extends FList<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
T getHead() {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> getTail() {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> plus(T element) {
|
||||||
|
return new OneElementList<T>(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class OneElementList<T> extends FList<T> {
|
||||||
|
private T element;
|
||||||
|
|
||||||
|
public OneElementList(T element) {
|
||||||
|
super();
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
T getHead() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> getTail() {
|
||||||
|
return new Empty<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> plus(T element) {
|
||||||
|
return new StandardList<T>(element, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StandardList<T> extends FList<T> {
|
||||||
|
private T head;
|
||||||
|
private FList<T> tail;
|
||||||
|
|
||||||
|
public StandardList(T head, FList<T> tail) {
|
||||||
|
this.head = head;
|
||||||
|
this.tail = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
T getHead() {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> getTail() {
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
FList<T> plus(T element) {
|
||||||
|
return new StandardList<T>(element, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for(int k = 0; k != 10; ++k) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
FList<Integer> list = new Empty();
|
||||||
|
for(int i = 0; i != 5000000; ++i)
|
||||||
|
list = list.plus(i);
|
||||||
|
System.out.println(System.currentTimeMillis()-start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
namespace flist
|
||||||
|
|
||||||
|
abstract class FList<T> {
|
||||||
|
abstract val head : T
|
||||||
|
abstract val tail : FList<T>
|
||||||
|
|
||||||
|
abstract fun plus(element: T) : FList<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmptyFList<T>() : FList<T> {
|
||||||
|
override val head: T
|
||||||
|
get() = throw java.util.NoSuchElementException()
|
||||||
|
|
||||||
|
override val tail : EmptyFList<T>
|
||||||
|
get() = EmptyFList<T>()
|
||||||
|
|
||||||
|
override fun plus(element: T) : FList<T> = OneElementFList<T>(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
class OneElementFList<T> (override val head: T): FList<T> {
|
||||||
|
override val tail : EmptyFList<T>
|
||||||
|
get() = EmptyFList<T>()
|
||||||
|
|
||||||
|
override fun plus(element: T) : FList<T> = StandardFList<T>(element, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class StandardFList<T> (override val head: T, override val tail: FList<T>) : FList<T> {
|
||||||
|
override fun plus(element: T) : FList<T> = StandardFList<T>(element, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> FList<T>.plus2(element: T): FList<T> =
|
||||||
|
when(this) {
|
||||||
|
is EmptyFList<T> => OneElementFList<T>(element)
|
||||||
|
else => StandardFList<T>(element, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> FList<T>.plus3(element: T) : FList<T> =
|
||||||
|
if(this is EmptyFList<*>)
|
||||||
|
OneElementFList<T>(element)
|
||||||
|
else
|
||||||
|
StandardFList<T>(element, this)
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
for(k in 0..3) {
|
||||||
|
val start0 = System.currentTimeMillis()
|
||||||
|
|
||||||
|
var flist0 : FList<Int> = EmptyFList<Int>()
|
||||||
|
for(i in 0..5000000)
|
||||||
|
flist0 = flist0 + i
|
||||||
|
|
||||||
|
System.out?.println(System.currentTimeMillis() - start0)
|
||||||
|
|
||||||
|
val start = System.currentTimeMillis()
|
||||||
|
|
||||||
|
var flist : FList<Int> = EmptyFList<Int>()
|
||||||
|
for(i in 0..5000000)
|
||||||
|
flist = flist.plus2(i)
|
||||||
|
|
||||||
|
System.out?.println(System.currentTimeMillis() - start)
|
||||||
|
|
||||||
|
val start2 = System.currentTimeMillis()
|
||||||
|
|
||||||
|
var flist2 : FList<Int> = EmptyFList<Int>()
|
||||||
|
for(i in 0..5000000)
|
||||||
|
flist2 = flist2.plus3(i)
|
||||||
|
|
||||||
|
System.out?.println(System.currentTimeMillis() - start2)
|
||||||
|
System.out?.println()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.jet.plugin.completion;
|
package org.jetbrains.jet.plugin.completion;
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.*;
|
import com.intellij.codeInsight.completion.*;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||||
import com.intellij.patterns.PlatformPatterns;
|
import com.intellij.patterns.PlatformPatterns;
|
||||||
import com.intellij.patterns.PsiElementPattern;
|
import com.intellij.patterns.PsiElementPattern;
|
||||||
@@ -11,6 +12,7 @@ import com.intellij.psi.filters.position.FilterPattern;
|
|||||||
import com.intellij.psi.filters.position.LeftNeighbour;
|
import com.intellij.psi.filters.position.LeftNeighbour;
|
||||||
import com.intellij.util.ProcessingContext;
|
import com.intellij.util.ProcessingContext;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.plugin.completion.handlers.JetKeywordInsertHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A keyword contributor for Kotlin
|
* A keyword contributor for Kotlin
|
||||||
@@ -21,7 +23,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class JetKeywordCompletionContributor extends CompletionContributor {
|
public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||||
|
|
||||||
private static class JetTopKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
|
private static class JetTopKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||||
|
|
||||||
|
private final static InsertHandler<LookupElement> KEYWORDS_INSERT_HANDLER = new JetKeywordInsertHandler();
|
||||||
|
|
||||||
private final static String[] COMPLETE_KEYWORD = new String[] {
|
private final static String[] COMPLETE_KEYWORD = new String[] {
|
||||||
"namespace", "as", "type", "class", "this", "super", "val", "var", "fun", "for", "null", "true",
|
"namespace", "as", "type", "class", "this", "super", "val", "var", "fun", "for", "null", "true",
|
||||||
"false", "is", "in", "throw", "return", "break", "continue", "object", "if", "try", "else", "while",
|
"false", "is", "in", "throw", "return", "break", "continue", "object", "if", "try", "else", "while",
|
||||||
@@ -32,18 +36,19 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
|
|||||||
"import", "where", "by", "get", "set", "abstract", "enum", "open", "annotation", "override", "private",
|
"import", "where", "by", "get", "set", "abstract", "enum", "open", "annotation", "override", "private",
|
||||||
"public", "internal", "protected", "catch", "out", "vararg", "inline", "finally", "final", "ref"
|
"public", "internal", "protected", "catch", "out", "vararg", "inline", "finally", "final", "ref"
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||||
ProcessingContext context,
|
ProcessingContext context,
|
||||||
@NotNull CompletionResultSet result) {
|
@NotNull CompletionResultSet result) {
|
||||||
|
|
||||||
for (String keyword : COMPLETE_KEYWORD) {
|
for (String keyword : COMPLETE_KEYWORD) {
|
||||||
result.addElement(LookupElementBuilder.create(keyword).setBold());
|
|
||||||
|
result.addElement(LookupElementBuilder.create(keyword).setInsertHandler(KEYWORDS_INSERT_HANDLER).setBold());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String softKeyword : COMPLETE_SOFT_KEYWORDS) {
|
for (String softKeyword : COMPLETE_SOFT_KEYWORDS) {
|
||||||
result.addElement(LookupElementBuilder.create(softKeyword));
|
result.addElement(LookupElementBuilder.create(softKeyword).setInsertHandler(KEYWORDS_INSERT_HANDLER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.jetbrains.jet.plugin.completion.handlers;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.InsertHandler;
|
||||||
|
import com.intellij.codeInsight.completion.InsertionContext;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts '()' after function proposal insert.
|
||||||
|
*
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
|
||||||
|
|
||||||
|
public enum CaretPosition { IN_BRACKETS, AFTER_BRACKETS }
|
||||||
|
|
||||||
|
private final CaretPosition caretPosition;
|
||||||
|
|
||||||
|
public JetFunctionInsertHandler(CaretPosition caretPosition) {
|
||||||
|
this.caretPosition = caretPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||||
|
int startOffset = context.getStartOffset();
|
||||||
|
int lookupStringLength = item.getLookupString().length();
|
||||||
|
int endOffset = startOffset + lookupStringLength;
|
||||||
|
|
||||||
|
context.getDocument().insertString(endOffset, "()");
|
||||||
|
|
||||||
|
Editor editor = context.getEditor();
|
||||||
|
if (caretPosition == CaretPosition.IN_BRACKETS) {
|
||||||
|
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1);
|
||||||
|
} else {
|
||||||
|
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.jetbrains.jet.plugin.completion.handlers;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.intellij.codeInsight.completion.InsertHandler;
|
||||||
|
import com.intellij.codeInsight.completion.InsertionContext;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class JetKeywordInsertHandler implements InsertHandler<LookupElement> {
|
||||||
|
|
||||||
|
private final static Set<String> NO_SPACE_AFTER = Sets.newHashSet("this", "super", "This", "true", "false", "null");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||||
|
String keyword = item.getLookupString();
|
||||||
|
|
||||||
|
// Add space after keyword
|
||||||
|
if (!NO_SPACE_AFTER.contains(keyword)) {
|
||||||
|
Editor editor = context.getEditor();
|
||||||
|
Document document = editor.getDocument();
|
||||||
|
|
||||||
|
int offset = context.getStartOffset() + keyword.length();
|
||||||
|
context.setAddCompletionChar(false);
|
||||||
|
document.insertString(offset, " ");
|
||||||
|
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
|
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
|
||||||
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;
|
||||||
@@ -190,9 +191,9 @@ public class ResolveToolwindow extends JPanel {
|
|||||||
result.append("Log: \n").append(log).append(bar);
|
result.append("Log: \n").append(log).append(bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<JetType, ConstraintSystemImpl.TypeValue> knowns = debugInfo.get(BOUNDS_FOR_KNOWNS);
|
Map<JetType, BoundsOwner> knowns = debugInfo.get(BOUNDS_FOR_KNOWNS);
|
||||||
renderMap(knowns, result);
|
renderMap(knowns, result);
|
||||||
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
|
Map<TypeParameterDescriptor, BoundsOwner> unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
|
||||||
renderMap(unknowns, result);
|
renderMap(unknowns, result);
|
||||||
|
|
||||||
result.append(bar);
|
result.append(bar);
|
||||||
@@ -205,17 +206,17 @@ public class ResolveToolwindow extends JPanel {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private <K> void renderMap(Map<K, ConstraintSystemImpl.TypeValue> map, StringBuilder builder) {
|
private <K> void renderMap(Map<K, BoundsOwner> map, StringBuilder builder) {
|
||||||
if (map == null) return;
|
if (map == null) return;
|
||||||
|
|
||||||
for (Map.Entry<K, ConstraintSystemImpl.TypeValue> entry : map.entrySet()) {
|
for (Map.Entry<K, BoundsOwner> entry : map.entrySet()) {
|
||||||
K key = entry.getKey();
|
K key = entry.getKey();
|
||||||
ConstraintSystemImpl.TypeValue typeValue = entry.getValue();
|
BoundsOwner typeValue = entry.getValue();
|
||||||
builder.append("Bounds for ").append(key).append("\n");
|
builder.append("Bounds for ").append(key).append("\n");
|
||||||
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
|
for (BoundsOwner bound : typeValue.getLowerBounds()) {
|
||||||
builder.append(" >: ").append(bound).append("\n");
|
builder.append(" >: ").append(bound).append("\n");
|
||||||
}
|
}
|
||||||
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
|
for (BoundsOwner bound : typeValue.getUpperBounds()) {
|
||||||
builder.append(" <: ").append(bound).append("\n");
|
builder.append(" <: ").append(bound).append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,7 @@ 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.ConstraintResolutionListener;
|
import org.jetbrains.jet.lang.resolve.calls.inference.*;
|
||||||
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;
|
||||||
@@ -28,15 +25,25 @@ 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.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.resolve.DescriptorRenderer;
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
class JetSimpleNameReference extends JetPsiReference {
|
class JetSimpleNameReference extends JetPsiReference {
|
||||||
|
|
||||||
|
private final static JetFunctionInsertHandler EMPTY_FUNCTION_HANDLER = new JetFunctionInsertHandler(
|
||||||
|
JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS);
|
||||||
|
|
||||||
|
private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler(
|
||||||
|
JetFunctionInsertHandler.CaretPosition.IN_BRACKETS);
|
||||||
|
|
||||||
private final JetSimpleNameExpression myExpression;
|
private final JetSimpleNameExpression myExpression;
|
||||||
|
|
||||||
public JetSimpleNameReference(JetSimpleNameExpression jetSimpleNameExpression) {
|
public JetSimpleNameReference(JetSimpleNameExpression jetSimpleNameExpression) {
|
||||||
@@ -135,10 +142,12 @@ class JetSimpleNameReference extends JetPsiReference {
|
|||||||
String typeText = "";
|
String typeText = "";
|
||||||
String tailText = "";
|
String tailText = "";
|
||||||
boolean tailTextGrayed = false;
|
boolean tailTextGrayed = false;
|
||||||
|
|
||||||
if (descriptor instanceof FunctionDescriptor) {
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||||
JetType returnType = functionDescriptor.getReturnType();
|
JetType returnType = functionDescriptor.getReturnType();
|
||||||
typeText = DescriptorRenderer.TEXT.renderType(returnType);
|
typeText = DescriptorRenderer.TEXT.renderType(returnType);
|
||||||
|
|
||||||
tailText = "(" + StringUtil.join(functionDescriptor.getValueParameters(), new Function<ValueParameterDescriptor, String>() {
|
tailText = "(" + StringUtil.join(functionDescriptor.getValueParameters(), new Function<ValueParameterDescriptor, String>() {
|
||||||
@Override
|
@Override
|
||||||
public String fun(ValueParameterDescriptor valueParameterDescriptor) {
|
public String fun(ValueParameterDescriptor valueParameterDescriptor) {
|
||||||
@@ -146,6 +155,14 @@ 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: Support omitting brackets for one argument functions
|
||||||
|
if (functionDescriptor.getValueParameters().isEmpty()) {
|
||||||
|
element = element.setInsertHandler(EMPTY_FUNCTION_HANDLER);
|
||||||
|
} else {
|
||||||
|
element = element.setInsertHandler(PARAMS_FUNCTION_HANDLER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof VariableDescriptor) {
|
else if (descriptor instanceof VariableDescriptor) {
|
||||||
JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
||||||
@@ -170,8 +187,8 @@ class JetSimpleNameReference extends JetPsiReference {
|
|||||||
return result.toArray();
|
return result.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Checks that receiver declaration could be resolved to call expected receiver.
|
* Checks if receiver declaration could be resolved to call expected receiver.
|
||||||
*/
|
*/
|
||||||
private static boolean checkReceiverResolution (
|
private static boolean checkReceiverResolution (
|
||||||
@NotNull ReceiverDescriptor expectedReceiver,
|
@NotNull ReceiverDescriptor expectedReceiver,
|
||||||
@@ -184,7 +201,7 @@ class JetSimpleNameReference extends JetPsiReference {
|
|||||||
|
|
||||||
ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter();
|
||||||
if (expectedReceiver.exists() && receiverParameter.exists()) {
|
if (expectedReceiver.exists() && receiverParameter.exists()) {
|
||||||
constraintSystem.addSubtypingConstraint(expectedReceiver.getType(), receiverParameter.getType());
|
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(expectedReceiver.getType(), receiverParameter.getType()));
|
||||||
}
|
}
|
||||||
else if (expectedReceiver.exists() || receiverParameter.exists()) {
|
else if (expectedReceiver.exists() || receiverParameter.exists()) {
|
||||||
// Only one of receivers exist
|
// Only one of receivers exist
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ class A() : My<caret> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: MySecondClass, MyFirstClass
|
// EXIST: MySecondClass, MyFirstClass
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
te<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT: test
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
test()<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT: test
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun test(a: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
te<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun test(a: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
test(<caret>)
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package org.jetbrains.jet.completion.handlers;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||||
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class FunctionsHandlerTest extends LightCompletionTestCase {
|
||||||
|
|
||||||
|
public void testNoParamsFunction() {
|
||||||
|
configureByFile("NoParamsFunction.kt");
|
||||||
|
checkResultByFile("NoParamsFunction.kt.after");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionWithParams() {
|
||||||
|
configureByFile("ParamsFunction.kt");
|
||||||
|
checkResultByFile("ParamsFunction.kt.after");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTestDataPath() {
|
||||||
|
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
|
||||||
|
File.separator;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.jetbrains.jet.completion.handlers;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||||
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class KeywordsHandlerTest extends LightCompletionTestCase {
|
||||||
|
|
||||||
|
public void testSpaceAfter() throws IOException {
|
||||||
|
configureFromFileText("Test.kt", "protecte<caret>");
|
||||||
|
complete();
|
||||||
|
checkResultByText("protected <caret>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoSpaceAfter() throws IOException {
|
||||||
|
configureFromFileText("Test.kt", "nul<caret>");
|
||||||
|
complete();
|
||||||
|
checkResultByText("null<caret>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTestDataPath() {
|
||||||
|
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
|
||||||
|
File.separator;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
namespace std
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
|
// Array "constructor"
|
||||||
|
inline fun <T> array(vararg t : T) : Array<T> = t
|
||||||
|
|
||||||
|
// "constructors" for primitive types array
|
||||||
|
inline fun doubleArray(vararg content : Double) = content
|
||||||
|
|
||||||
|
inline fun floatArray(vararg content : Float) = content
|
||||||
|
|
||||||
|
inline fun longArray(vararg content : Long) = content
|
||||||
|
|
||||||
|
inline fun intArray(vararg content : Int) = content
|
||||||
|
|
||||||
|
inline fun charArray(vararg content : Char) = content
|
||||||
|
|
||||||
|
inline fun shortArray(vararg content : Short) = content
|
||||||
|
|
||||||
|
inline fun byteArray(vararg content : Byte) = content
|
||||||
|
|
||||||
|
inline fun booleanArray(vararg content : Boolean) = content
|
||||||
|
|
||||||
|
inline val ByteArray.inputStream : ByteArrayInputStream
|
||||||
|
get() = ByteArrayInputStream(this)
|
||||||
|
|
||||||
|
inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStream(this, offset, length)
|
||||||
|
|
||||||
@@ -27,47 +27,6 @@ namespace io {
|
|||||||
inline fun println(message : CharArray) { System.out?.println(message) }
|
inline fun println(message : CharArray) { System.out?.println(message) }
|
||||||
inline fun println() { System.out?.println() }
|
inline fun println() { System.out?.println() }
|
||||||
|
|
||||||
val ByteArray.inputStream : ByteArrayInputStream
|
|
||||||
get() = ByteArrayInputStream(this)
|
|
||||||
|
|
||||||
// inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStream(this, offset, length)
|
|
||||||
|
|
||||||
fun InputStream.iterator() : ByteIterator =
|
|
||||||
object: ByteIterator() {
|
|
||||||
override val hasNext : Boolean
|
|
||||||
get() = available() > 0
|
|
||||||
|
|
||||||
override fun nextByte() = read().byt
|
|
||||||
}
|
|
||||||
|
|
||||||
val InputStream.buffered : BufferedInputStream
|
|
||||||
get() = if(this is BufferedInputStream) this else BufferedInputStream(this)
|
|
||||||
|
|
||||||
// inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize)
|
|
||||||
|
|
||||||
val InputStream.reader : InputStreamReader
|
|
||||||
get() = InputStreamReader(this)
|
|
||||||
|
|
||||||
val InputStream.bufferedReader : BufferedReader
|
|
||||||
get() = BufferedReader(reader)
|
|
||||||
|
|
||||||
/*
|
|
||||||
inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset)
|
|
||||||
|
|
||||||
inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetNme)
|
|
||||||
|
|
||||||
inline fun InputStream.reader(charset: Charset) = InputStreamReader(this, charset)
|
|
||||||
|
|
||||||
inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// val Reader.buffered : BufferedReader
|
|
||||||
// get() = if(this instanceof BufferedReader) this else BufferedReader(this)
|
|
||||||
|
|
||||||
// inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize)
|
|
||||||
|
|
||||||
// val String.reader = StringReader(this)
|
|
||||||
|
|
||||||
private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() {
|
private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() {
|
||||||
override fun read() : Int {
|
override fun read() : Int {
|
||||||
return System.`in`?.read() ?: -1
|
return System.`in`?.read() ?: -1
|
||||||
@@ -106,5 +65,35 @@ namespace io {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
fun readLine() : String? = stdin.readLine()
|
inline fun readLine() : String? = stdin.readLine()
|
||||||
|
|
||||||
|
fun InputStream.iterator() : ByteIterator =
|
||||||
|
object: ByteIterator() {
|
||||||
|
override val hasNext : Boolean
|
||||||
|
get() = available() > 0
|
||||||
|
|
||||||
|
override fun nextByte() = read().byt
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize)
|
||||||
|
|
||||||
|
inline val InputStream.reader : InputStreamReader
|
||||||
|
get() = InputStreamReader(this)
|
||||||
|
|
||||||
|
inline val InputStream.bufferedReader : BufferedReader
|
||||||
|
get() = BufferedReader(reader)
|
||||||
|
|
||||||
|
inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset)
|
||||||
|
|
||||||
|
inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetName)
|
||||||
|
|
||||||
|
inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder)
|
||||||
|
|
||||||
|
inline val InputStream.buffered : BufferedInputStream
|
||||||
|
get() = if(this is BufferedInputStream) this else BufferedInputStream(this)
|
||||||
|
|
||||||
|
// inline val Reader.buffered : BufferedReader
|
||||||
|
// get() = if(this is BufferedReader) this else BufferedReader(this)
|
||||||
|
|
||||||
|
inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize)
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
namespace std
|
namespace std.util
|
||||||
|
|
||||||
namespace util {
|
import java.util.*
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
val Collection<*>.size : Int
|
val Collection<*>.size : Int
|
||||||
get() = size()
|
get() = size()
|
||||||
|
|
||||||
val Collection<*>.empty : Boolean
|
val Collection<*>.empty : Boolean
|
||||||
get() = isEmpty()
|
get() = isEmpty()
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
namespace std
|
||||||
|
|
||||||
|
import java.io.StringReader
|
||||||
|
|
||||||
|
inline fun <T> T?.plus(str: String?) : String { return toString() + str }
|
||||||
|
|
||||||
|
inline fun String.lastIndexOf(s: String) = (this as java.lang.String).lastIndexOf(s)
|
||||||
|
|
||||||
|
inline fun String.lastIndexOf(s: Char) = (this as java.lang.String).lastIndexOf(s.toString()) }
|
||||||
|
|
||||||
|
inline fun String.indexOf(s : String) = (this as java.lang.String).indexOf(s)
|
||||||
|
|
||||||
|
inline fun String.indexOf(p0 : String, p1 : Int) = (this as java.lang.String).indexOf(p0, p1)
|
||||||
|
|
||||||
|
inline fun String.replaceAll(s: String, s1 : String) = (this as java.lang.String).replaceAll(s, s1).sure()
|
||||||
|
|
||||||
|
inline fun String.trim() = (this as java.lang.String).trim().sure()
|
||||||
|
|
||||||
|
inline fun String.toUpperCase() = (this as java.lang.String).toUpperCase().sure()
|
||||||
|
|
||||||
|
inline fun String.toLowerCase() = (this as java.lang.String).toLowerCase().sure()
|
||||||
|
|
||||||
|
inline fun String.length() = (this as java.lang.String).length()
|
||||||
|
|
||||||
|
inline fun String.getBytes() = (this as java.lang.String).getBytes().sure()
|
||||||
|
|
||||||
|
inline fun String.toCharArray() = (this as java.lang.String).toCharArray().sure()
|
||||||
|
|
||||||
|
inline fun String.format(s : String, vararg objects : Any?) = java.lang.String.format(s, objects).sure()
|
||||||
|
|
||||||
|
inline fun String.split(s : String) = (this as java.lang.String).split(s)
|
||||||
|
|
||||||
|
inline fun String.substring(i : Int) = (this as java.lang.String).substring(i).sure()
|
||||||
|
|
||||||
|
inline fun String.substring(i0 : Int, i1 : Int) = (this as java.lang.String).substring(i0, i1).sure()
|
||||||
|
|
||||||
|
inline val String.size : Int
|
||||||
|
get() = length()
|
||||||
|
|
||||||
|
inline val String.reader : StringReader
|
||||||
|
get() = StringReader(this)
|
||||||
|
|
||||||
|
// "constructors" for String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray, i : Int, i1 : Int, s : String) = java.lang.String(bytes, i, i1, s) as String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray, i : Int, i1 : Int, charset : java.nio.charset.Charset) = java.lang.String(bytes, i, i1, charset) as String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray, s : String?) = java.lang.String(bytes, s) as String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray, charset : java.nio.charset.Charset) = java.lang.String(bytes, charset) as String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray, i : Int, i1 : Int) = java.lang.String(bytes, i, i1) as String
|
||||||
|
|
||||||
|
inline fun String(bytes : ByteArray) = java.lang.String(bytes) as String
|
||||||
|
|
||||||
|
inline fun String(chars : CharArray) = java.lang.String(chars) as String
|
||||||
|
|
||||||
|
inline fun String(stringBuffer : java.lang.StringBuffer) = java.lang.String(stringBuffer) as String
|
||||||
|
|
||||||
|
inline fun String(stringBuilder : java.lang.StringBuilder) = java.lang.String(stringBuilder) as String
|
||||||
|
|
||||||
@@ -23,4 +23,9 @@ public class DefaultJetObject implements JetObject {
|
|||||||
public final TypeInfo<?> getTypeInfo() {
|
public final TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,12 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static IntRange count(int length) {
|
public static IntRange count(int length) {
|
||||||
return new IntRange(0, length);
|
return new IntRange(0, length);
|
||||||
}
|
}
|
||||||
@@ -95,5 +100,10 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import jet.typeinfo.TypeInfo;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public interface JetObject {
|
public interface JetObject {
|
||||||
TypeInfo<?> getTypeInfo();
|
TypeInfo<?> getTypeInfo();
|
||||||
|
JetObject getOuterObject();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
|||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static IntRange count(int length) {
|
public static IntRange count(int length) {
|
||||||
return new IntRange(0, length);
|
return new IntRange(0, length);
|
||||||
}
|
}
|
||||||
@@ -95,5 +100,10 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,9 @@ public class Tuple0 implements JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,12 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo});
|
return TypeInfo.getTypeInfo(GenericIterator.class, false, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +74,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteIterator iterator(byte[] array) {
|
public static ByteIterator iterator(byte[] array) {
|
||||||
@@ -99,6 +109,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShortIterator iterator(short[] array) {
|
public static ShortIterator iterator(short[] array) {
|
||||||
@@ -129,6 +144,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IntIterator iterator(int[] array) {
|
public static IntIterator iterator(int[] array) {
|
||||||
@@ -159,6 +179,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LongIterator iterator(long[] array) {
|
public static LongIterator iterator(long[] array) {
|
||||||
@@ -189,6 +214,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FloatIterator iterator(float[] array) {
|
public static FloatIterator iterator(float[] array) {
|
||||||
@@ -219,6 +249,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DoubleIterator iterator(double[] array) {
|
public static DoubleIterator iterator(double[] array) {
|
||||||
@@ -249,6 +284,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharIterator iterator(char[] array) {
|
public static CharIterator iterator(char[] array) {
|
||||||
@@ -279,6 +319,11 @@ public abstract class ArrayIterator<T> implements Iterator<T>, JetObject {
|
|||||||
public TypeInfo<?> getTypeInfo() {
|
public TypeInfo<?> getTypeInfo() {
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BooleanIterator iterator(boolean[] array) {
|
public static BooleanIterator iterator(boolean[] array) {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import java.lang.annotation.Target;
|
|||||||
* The fact of receiver presence must be deducted from presence of 'this$receiver' parameter
|
* The fact of receiver presence must be deducted from presence of 'this$receiver' parameter
|
||||||
*
|
*
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.METHOD})
|
@Target({ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface JetSignature {
|
@interface JetSignature {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package jet.typeinfo;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
public @interface JetTypeDescriptor{
|
public @interface JetTypeDescriptor{
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import java.lang.annotation.Target;
|
|||||||
* Annotation for parameters
|
* Annotation for parameters
|
||||||
*
|
*
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.PARAMETER})
|
@Target({ElementType.PARAMETER})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface JetTypeProjection {
|
public @interface JetTypeProjection {
|
||||||
|
|||||||
+3
-1
@@ -9,10 +9,12 @@ import java.lang.annotation.Target;
|
|||||||
* Annotation for parameters
|
* Annotation for parameters
|
||||||
*
|
*
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
|
*
|
||||||
|
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.PARAMETER})
|
@Target({ElementType.PARAMETER})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface JetParameter {
|
public @interface JetValueParameter {
|
||||||
/**
|
/**
|
||||||
* @return name of parameter
|
* @return name of parameter
|
||||||
*/
|
*/
|
||||||
@@ -79,14 +79,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
return new TypeInfoImpl<T>(klazz, nullable);
|
return new TypeInfoImpl<T>(klazz, nullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfo outerTypeInfo) {
|
|
||||||
return new TypeInfoImpl<T>(klazz, nullable, outerTypeInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) {
|
|
||||||
return new TypeInfoImpl<T>(klazz, nullable, outerTypeInfo, projections);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) {
|
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) {
|
||||||
return new TypeInfoImpl<T>(klazz, nullable, projections);
|
return new TypeInfoImpl<T>(klazz, nullable, projections);
|
||||||
}
|
}
|
||||||
@@ -99,15 +91,13 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
public abstract int getProjectionCount();
|
public abstract int getProjectionCount();
|
||||||
|
|
||||||
public abstract TypeInfo getOuterTypeInfo();
|
|
||||||
|
|
||||||
public abstract TypeInfoProjection getProjection(int index);
|
public abstract TypeInfoProjection getProjection(int index);
|
||||||
|
|
||||||
public abstract TypeInfo getArgumentType(Class klass, int index);
|
public abstract TypeInfo getArgumentType(Class klass, int index);
|
||||||
|
|
||||||
protected abstract TypeInfo substitute(List<TypeInfo> myVars);
|
protected abstract TypeInfo substitute(List<TypeInfo> myVars);
|
||||||
|
|
||||||
protected abstract TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections);
|
protected abstract TypeInfo substitute(TypeInfoProjection[] projections);
|
||||||
|
|
||||||
private static class TypeInfoVar<T> extends TypeInfo<T> {
|
private static class TypeInfoVar<T> extends TypeInfo<T> {
|
||||||
final int varIndex;
|
final int varIndex;
|
||||||
@@ -151,11 +141,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeInfo getOuterTypeInfo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeInfoProjection getProjection(int index) {
|
public TypeInfoProjection getProjection(int index) {
|
||||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||||
@@ -172,7 +157,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections) {
|
protected TypeInfo substitute(TypeInfoProjection[] projections) {
|
||||||
return projections[varIndex].getType();
|
return projections[varIndex].getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +166,11 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "T:" + signature.klazz.getName() + ":" + varIndex;
|
return "T:" + signature.klazz.getName() + ":" + varIndex;
|
||||||
@@ -192,22 +182,12 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
private final Signature signature;
|
private final Signature signature;
|
||||||
private final boolean nullable;
|
private final boolean nullable;
|
||||||
private final TypeInfoProjection[] projections;
|
private final TypeInfoProjection[] projections;
|
||||||
private final TypeInfo outerTypeInfo;
|
|
||||||
|
|
||||||
private TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
private TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
||||||
this(theClass, nullable, null, EMPTY);
|
this(theClass, nullable, EMPTY);
|
||||||
}
|
|
||||||
|
|
||||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfo outerTypeInfo) {
|
|
||||||
this(theClass, nullable, outerTypeInfo, EMPTY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
||||||
this(theClass, nullable, null, projections);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) {
|
|
||||||
this.outerTypeInfo = outerTypeInfo;
|
|
||||||
this.signature = Parser.parse(theClass);
|
this.signature = Parser.parse(theClass);
|
||||||
this.nullable = nullable;
|
this.nullable = nullable;
|
||||||
this.projections = projections;
|
this.projections = projections;
|
||||||
@@ -247,7 +227,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
if(klass == this.signature.klazz)
|
if(klass == this.signature.klazz)
|
||||||
return projections[index].getType();
|
return projections[index].getType();
|
||||||
else {
|
else {
|
||||||
return getSuperTypeInfo(klass).substitute(outerTypeInfo, projections).getArgumentType(klass, index);
|
return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,14 +263,14 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] prj) {
|
protected TypeInfo substitute(TypeInfoProjection[] prj) {
|
||||||
if(projections.length == 0)
|
if(projections.length == 0)
|
||||||
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
|
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
|
||||||
else {
|
else {
|
||||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||||
for(int i = 0; i != proj.length; ++i) {
|
for(int i = 0; i != proj.length; ++i) {
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
final TypeInfo substitute = projections[finalI].getType().substitute(outer, prj);
|
final TypeInfo substitute = projections[finalI].getType().substitute(prj);
|
||||||
proj[i] = new TypeInfoProjection(){
|
proj[i] = new TypeInfoProjection(){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -359,11 +339,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
return projections.length;
|
return projections.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeInfo getOuterTypeInfo() {
|
|
||||||
return outerTypeInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
|
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
|
||||||
@@ -388,6 +363,11 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetObject getOuterObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean isSubtypeOf(TypeInfoImpl<?> superType) {
|
public final boolean isSubtypeOf(TypeInfoImpl<?> superType) {
|
||||||
if (nullable && !superType.nullable) {
|
if (nullable && !superType.nullable) {
|
||||||
return false;
|
return false;
|
||||||
@@ -410,7 +390,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Signature {
|
public static class Signature {
|
||||||
final Signature outer;
|
|
||||||
final Class klazz;
|
final Class klazz;
|
||||||
|
|
||||||
List<TypeInfoProjection> variables;
|
List<TypeInfoProjection> variables;
|
||||||
@@ -419,8 +398,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
final HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
|
final HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
|
||||||
|
|
||||||
public Signature(Signature outer, Class klazz) {
|
public Signature(Class klazz) {
|
||||||
this.outer = outer;
|
|
||||||
this.klazz = klazz;
|
this.klazz = klazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +480,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
if(value != null) {
|
if(value != null) {
|
||||||
Parser parser = new Parser(value, klass.getClassLoader());
|
Parser parser = new Parser(value, klass.getClassLoader());
|
||||||
Class enclosingClass = klass.getEnclosingClass();
|
Class enclosingClass = klass.getEnclosingClass();
|
||||||
Signature signature = new Signature(parse(enclosingClass), klass);
|
Signature signature = new Signature(klass);
|
||||||
map.put(klass, signature);
|
map.put(klass, signature);
|
||||||
parser.parseVars(signature);
|
parser.parseVars(signature);
|
||||||
parser.parseTypes(signature);
|
parser.parseTypes(signature);
|
||||||
@@ -517,7 +495,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
// todo complete impl
|
// todo complete impl
|
||||||
|
|
||||||
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
||||||
Signature signature = new Signature(parse(klass.getEnclosingClass()), klass);
|
Signature signature = new Signature(klass);
|
||||||
|
|
||||||
TypeVariable[] typeParameters = klass.getTypeParameters();
|
TypeVariable[] typeParameters = klass.getTypeParameters();
|
||||||
if(typeParameters == null || typeParameters.length == 0) {
|
if(typeParameters == null || typeParameters.length == 0) {
|
||||||
@@ -682,14 +660,14 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
if(klazz.equals(signature.klazz.getName()))
|
if(klazz.equals(signature.klazz.getName()))
|
||||||
return new TypeInfoVar(signature, nullable, signature.varNames.get(name));
|
return new TypeInfoVar(signature, nullable, signature.varNames.get(name));
|
||||||
else {
|
else {
|
||||||
Signature sig = signature;
|
// Signature sig = signature;
|
||||||
while(!klazz.equals(sig.klazz.getName())) {
|
// while(!klazz.equals(sig.klazz.getName())) {
|
||||||
sig = sig.outer;
|
// sig = sig.outer;
|
||||||
if(sig == null)
|
// if(sig == null)
|
||||||
throw new IllegalStateException();
|
// throw new IllegalStateException();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return new TypeInfoVar(sig, nullable, sig.varNames.get(name));
|
throw new UnsupportedOperationException("outer type info does not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,7 +694,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
private static class ArraySignature extends Signature {
|
private static class ArraySignature extends Signature {
|
||||||
public ArraySignature(Class klass) {
|
public ArraySignature(Class klass) {
|
||||||
super(null, klass);
|
super(klass);
|
||||||
variables = new LinkedList<TypeInfoProjection>();
|
variables = new LinkedList<TypeInfoProjection>();
|
||||||
varNames = new HashMap<String, Integer>();
|
varNames = new HashMap<String, Integer>();
|
||||||
varNames.put("T", 0);
|
varNames.put("T", 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user