Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-12-14 16:48:49 +04:00
80 changed files with 2214 additions and 285 deletions
@@ -0,0 +1,339 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureAdapter;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.ArrayList;
import java.util.List;
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 enum State {
START,
TYPE_PARAMETERS,
PARAMETERS,
RETURN_TYPE,
METHOD_END,
SUPERS,
CLASS_END,
}
private final SignatureWriter signatureWriter = new SignatureWriter();
private final SignatureVisitor signatureVisitor;
private JetSignatureWriter jetSignatureWriter;
private String kotlinClassSignature;
private List<String> kotlinParameterTypes = new ArrayList<String>();
private String kotlinReturnType;
private final Mode mode;
private State state = State.START;
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();
}
}
}
private void checkState(State state) {
if (DEBUG_SIGNATURE_WRITER) {
if (state != this.state) {
throw new IllegalStateException();
}
if (jetSignatureWriter != null) {
throw new IllegalStateException();
}
checkTopLevel();
}
}
private void transitionState(State from, State to) {
checkState(from);
state = to;
}
/**
* Shortcut
*/
public void writeAsmType(Type asmType, boolean nullable) {
switch (asmType.getSort()) {
case Type.OBJECT:
writeClassBegin(asmType.getInternalName(), nullable);
writeClassEnd();
return;
case Type.ARRAY:
writeArrayType(nullable);
writeAsmType(asmType.getElementType(), false);
writeArrayEnd();
return;
default:
String descriptor = asmType.getDescriptor();
if (descriptor.length() != 1) {
throw new IllegalStateException();
}
writeBaseType(descriptor.charAt(0), nullable);
}
}
private void writeBaseType(char c, boolean nullable) {
if (nullable) {
throw new IllegalStateException();
}
signatureVisitor().visitBaseType(c);
jetSignatureWriter.visitBaseType(c, nullable);
}
public void writeClassBegin(String internalName, boolean nullable) {
signatureVisitor().visitClassType(internalName);
jetSignatureWriter.visitClassType(internalName, nullable);
}
public void writeClassEnd() {
signatureVisitor().visitEnd();
jetSignatureWriter.visitEnd();
}
public void writeArrayType(boolean nullable) {
push(signatureVisitor().visitArrayType());
jetSignatureWriter.visitArrayType(nullable);
}
public void writeArrayEnd() {
pop();
}
public void writeTypeArgument(char c) {
push(signatureVisitor().visitTypeArgument(c));
jetSignatureWriter.visitTypeArgument(c);
}
public void writeTypeArgumentEnd() {
pop();
}
public void writeTypeVariable(final String name, boolean nullable) {
signatureVisitor().visitTypeVariable(name);
jetSignatureWriter.visitTypeVariable(name, nullable);
}
public void writeFormalTypeParameter(final String name) {
checkTopLevel();
signatureVisitor().visitFormalTypeParameter(name);
jetSignatureWriter.visitFormalTypeParameter(name);
}
public void writerFormalTypeParametersStart() {
checkTopLevel();
transitionState(State.START, State.TYPE_PARAMETERS);
jetSignatureWriter = new JetSignatureWriter();
}
public void writeFormalTypeParametersEnd() {
jetSignatureWriter = null;
checkState(State.TYPE_PARAMETERS);
}
public void writeClassBound() {
push(signatureVisitor().visitClassBound());
jetSignatureWriter.visitClassBound();
}
public void writeClassBoundEnd() {
pop();
}
public void writeInterfaceBound() {
push(signatureVisitor().visitInterfaceBound());
jetSignatureWriter.visitInterfaceBound();
}
public void writeInterfaceBoundEnd() {
pop();
}
public void writeParametersStart() {
transitionState(State.TYPE_PARAMETERS, State.PARAMETERS);
}
public void writeParametersEnd() {
checkState(State.PARAMETERS);
}
public void writeParameterType() {
push(signatureVisitor().visitParameterType());
jetSignatureWriter = new JetSignatureWriter();
//jetSignatureWriter.visitParameterType();
}
public void writeParameterTypeEnd() {
pop();
String signature = jetSignatureWriter.toString();
kotlinParameterTypes.add(signature);
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(signature).acceptTypeOnly(new JetSignatureAdapter());
}
jetSignatureWriter = null;
}
public void writeReturnType() {
transitionState(State.PARAMETERS, State.RETURN_TYPE);
jetSignatureWriter = new JetSignatureWriter();
push(signatureVisitor().visitReturnType());
//jetSignatureWriter.visitReturnType();
}
public void writeReturnTypeEnd() {
pop();
kotlinReturnType = jetSignatureWriter.toString();
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(kotlinReturnType).acceptTypeOnly(new JetSignatureAdapter());
}
jetSignatureWriter = null;
transitionState(State.RETURN_TYPE, State.METHOD_END);
}
public void writeSupersStart() {
transitionState(State.TYPE_PARAMETERS, State.SUPERS);
jetSignatureWriter = new JetSignatureWriter();
}
public void writeSupersEnd() {
kotlinClassSignature = jetSignatureWriter.toString();
jetSignatureWriter = null;
transitionState(State.SUPERS, State.CLASS_END);
}
public void writeSuperclass() {
push(signatureVisitor().visitSuperclass());
jetSignatureWriter.visitSuperclass();
}
public void writeSuperclassEnd() {
pop();
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
}
public void writeInterface() {
checkTopLevel();
checkMode(Mode.CLASS);
push(signatureVisitor().visitInterface());
jetSignatureWriter.visitInterface();
}
public void writeInterfaceEnd() {
pop();
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
}
@Nullable
public String makeJavaString() {
if (state != State.METHOD_END && state != State.CLASS_END) {
throw new IllegalStateException();
}
checkTopLevel();
// TODO: return null if not generic
return signatureWriter.toString();
}
@NotNull
public List<String> makeKotlinSignatures() {
checkState(State.METHOD_END);
// TODO: return nulls if equal to #makeJavaString
return kotlinParameterTypes;
}
@Nullable
public String makeKotlinReturnTypeSignature() {
checkState(State.METHOD_END);
return kotlinReturnType;
}
@Nullable
public String makeKotlinClassSignature() {
checkState(State.CLASS_END);
return kotlinClassSignature;
}
}
@@ -53,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null, null, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd);
}
@@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null), funDescriptor);
return closureContext.outerWasUsed;
}
@@ -2475,9 +2475,13 @@ If finally block is present, its last expression is the value of try expression.
return hasTypeInfoForInstanceOf(type.getArguments().get(0).getType());
}
for(TypeParameterDescriptor proj : classDescriptor.getTypeConstructor().getParameters()) {
if(proj.isReified()) {
return true;
for (int i = 0; i < type.getArguments().size(); i++) {
TypeParameterDescriptor typeParameterDescriptor = classDescriptor.getTypeConstructor().getParameters().get(i);
if(typeParameterDescriptor.isReified()) {
TypeProjection typeProjection = type.getArguments().get(i);
if( !typeProjection.getType().equals(typeParameterDescriptor.getUpperBoundsAsType())) {
return true;
}
}
}
@@ -6,7 +6,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
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.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
@@ -90,19 +90,22 @@ public class FunctionCodegen {
if(functionDescriptor.getReturnType().isNullable()) {
av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
}
if (jvmSignature.getKotlinReturnType() != null) {
av.visit(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD, jvmSignature.getKotlinReturnType());
}
av.visitEnd();
}
if(kind == OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$self");
av.visitEnd();
}
if(receiverParameter.exists()) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$receiver");
if(receiverParameter.getType().isNullable()) {
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
av.visitEnd();
}
@@ -112,14 +115,17 @@ public class FunctionCodegen {
av.visitEnd();
}
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);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
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()) {
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
av.visit(StdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(i));
}
av.visitEnd();
}
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
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.types.JetType;
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.commons.InstructionAdapter;
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.*;
@@ -29,7 +27,9 @@ import java.util.*;
*/
public class ImplementationBodyCodegen extends ClassBodyCodegen {
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 BindingContext bindingContext;
@@ -39,28 +39,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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
protected void generateDeclaration() {
getSuperClass();
List<String> interfaces = new ArrayList<String>();
interfaces.add(JetTypeMapper.TYPE_JET_OBJECT.getInternalName());
interfaces.addAll(getSuperInterfaces(myClass));
JvmClassSignature signature = signature();
boolean isAbstract = false;
boolean isInterface = false;
@@ -77,10 +60,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
? Opcodes.ACC_INTERFACE
: 0/*Opcodes.ACC_SUPER*/),
jvmName(),
genericSignature(),
superClass,
interfaces.toArray(new String[interfaces.size()])
signature.getName(),
signature.getJavaGenericSignature(),
signature.getSuperclassName(),
signature.getInterfaces().toArray(new String[0])
);
v.visitSource(myClass.getContainingFile().getName(), null);
@@ -95,29 +78,54 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
@Nullable
private String genericSignature() {
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
SignatureWriter signatureWriter = new SignatureWriter();
SignatureVisitor signatureVisitor = JetTypeMapper.DEBUG_SIGNATURE_WRITER
? new CheckSignatureAdapter(CheckSignatureAdapter.CLASS_SIGNATURE, signatureWriter)
: signatureWriter;
for (TypeParameterDescriptor typeParameter : typeParameters) {
signatureVisitor.visitFormalTypeParameter(typeParameter.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong
JetTypeMapper.visitAsmType(classBoundVisitor, JetTypeMapper.TYPE_OBJECT);
private JvmClassSignature signature() {
List<String> superInterfaces;
LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
{ // type parameters
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor);
}
SignatureVisitor superclassSignatureVisitor = signatureVisitor.visitSuperclass();
// TODO: wrong
superclassSignatureVisitor.visitClassType("java/lang/Object");
// TODO: add interfaces
superclassSignatureVisitor.visitEnd();
signatureVisitor.writeSupersStart();
// TODO: return null if class is not generic and does not have generic superclasses
{ // superclass
signatureVisitor.writeSuperclass();
if (superClassType == null) {
signatureVisitor.writeClassBegin(superClass, false);
signatureVisitor.writeClassEnd();
} else {
typeMapper.mapType(superClassType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
}
signatureVisitor.writeSuperclassEnd();
}
return signatureWriter.toString();
{ // superinterfaces
superInterfacesLinkedHashSet.add(StdlibNames.JET_OBJECT_INTERNAL);
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.isInterface(superClassDescriptor)) {
signatureVisitor.writeInterface();
Type jvmName = typeMapper.mapType(superType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
signatureVisitor.writeInterfaceEnd();
superInterfacesLinkedHashSet.add(jvmName.getInternalName());
}
}
superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet);
}
signatureVisitor.writeSupersEnd();
return new JvmClassSignature(jvmName(), superClass, superInterfaces, signatureVisitor.makeJavaString(), signatureVisitor.makeKotlinClassSignature());
}
private String jvmName() {
@@ -125,6 +133,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
protected void getSuperClass() {
superClass = "java/lang/Object";
superClassType = null;
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
@@ -136,6 +147,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if(!CodegenUtil.isInterface(superClassDescriptor)) {
superClassType = superType;
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
}
@@ -310,7 +322,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null, null, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
@@ -18,9 +18,6 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
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.*;
@@ -57,7 +54,7 @@ public class JetTypeMapper {
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_GENERIC_TYPE = Type.getType(Object[].class);
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter");
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");
@@ -165,16 +162,16 @@ public class JetTypeMapper {
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 (signatureVisitor != null) {
signatureVisitor.visitBaseType('V');
signatureVisitor.writeAsmType(Type.VOID_TYPE, false);
}
return Type.VOID_TYPE;
}
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT);
visitAsmType(signatureVisitor, TYPE_OBJECT, false);
}
return TYPE_OBJECT;
}
@@ -226,10 +223,10 @@ public class JetTypeMapper {
}
@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);
}
@@ -237,17 +234,22 @@ public class JetTypeMapper {
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);
}
@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);
if (known != null) {
return mapKnownAsmType(jetType, known, signatureVisitor, boxPrimitive);
}
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (ErrorUtils.isError(descriptor)) {
throw new IllegalStateException("should not compile an error type");
}
if (standardLibrary.getArray().equals(descriptor)) {
if (jetType.getArguments().size() != 1) {
throw new UnsupportedOperationException("arrays must have one type argument");
@@ -255,8 +257,9 @@ public class JetTypeMapper {
JetType memberType = jetType.getArguments().get(0).getType();
if (signatureVisitor != null) {
SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType();
mapType(memberType, kind, arraySignatureVisitor, true);
signatureVisitor.writeArrayType(jetType.isNullable());
mapType(memberType, kind, signatureVisitor, true);
signatureVisitor.writeArrayEnd();
}
if (!isGenericsArray(jetType)) {
@@ -268,7 +271,7 @@ public class JetTypeMapper {
if (JetStandardClasses.getAny().equals(descriptor)) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT);
visitAsmType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
}
return TYPE_OBJECT;
}
@@ -279,13 +282,14 @@ public class JetTypeMapper {
Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
if (signatureVisitor != null) {
signatureVisitor.visitClassType(asmType.getInternalName());
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('=');
mapType(proj.getType(), kind, argumentSignatureVisitor, true);
signatureVisitor.writeTypeArgument('=');
mapType(proj.getType(), kind, signatureVisitor, true);
signatureVisitor.writeTypeArgumentEnd();
}
signatureVisitor.visitEnd();
signatureVisitor.writeClassEnd();
}
return asmType;
@@ -294,7 +298,7 @@ public class JetTypeMapper {
if (descriptor instanceof TypeParameterDescriptor) {
if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName());
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable());
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
@@ -303,34 +307,19 @@ public class JetTypeMapper {
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 (genericTypeParameter) {
visitAsmType(signatureVisitor, boxType(asmType));
visitAsmType(signatureVisitor, boxType(asmType), jetType.isNullable());
} else {
visitAsmType(signatureVisitor, asmType);
visitAsmType(signatureVisitor, asmType, jetType.isNullable());
}
}
return asmType;
}
public static void visitAsmType(SignatureVisitor visitor, Type asmType) {
switch (asmType.getSort()) {
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 void visitAsmType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
visitor.writeAsmType(asmType, nullable);
}
public static Type unboxType(final Type type) {
@@ -386,8 +375,6 @@ public class JetTypeMapper {
return asmType;
}
public static final boolean DEBUG_SIGNATURE_WRITER = true;
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if(functionDescriptor == null)
return null;
@@ -451,22 +438,12 @@ public class JetTypeMapper {
needGenericSignature = false;
}
SignatureWriter signatureWriter = null;
SignatureVisitor signatureVisitor = null;
BothSignatureWriter signatureVisitor = null;
if (needGenericSignature) {
signatureWriter = new SignatureWriter();
signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter;
signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
}
for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) {
if (signatureVisitor != null) {
signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong base
visitAsmType(classBoundVisitor, TYPE_OBJECT);
// TODO: interfaces
}
}
writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
@@ -484,24 +461,114 @@ public class JetTypeMapper {
parameterTypes.add(type);
}
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();
}
}
if (signatureVisitor != null) {
signatureVisitor.writeParametersStart();
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
signatureVisitor.writeParameterType();
visitAsmType(signatureVisitor, TYPE_TYPEINFO, false);
signatureVisitor.writeParameterTypeEnd();
}
}
}
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);
parameterTypes.add(type);
}
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
if (signatureVisitor != null) {
signatureVisitor.writeParametersEnd();
}
Type returnType;
if (f instanceof ConstructorDescriptor) {
returnType = Type.VOID_TYPE;
if (signatureVisitor != null) {
signatureVisitor.writeReturnType();
visitAsmType(signatureVisitor, Type.VOID_TYPE, false);
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()]));
return new JvmMethodSignature(method, signatureWriter != null ? signatureWriter.toString() : null);
if (signatureVisitor == null) {
return new JvmMethodSignature(method, null, null, null);
} else {
return new JvmMethodSignature(method, signatureVisitor.makeJavaString(),
signatureVisitor.makeKotlinSignatures(), signatureVisitor.makeKotlinReturnTypeSignature());
}
}
public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) {
if (signatureVisitor == null) {
return;
}
signatureVisitor.writerFormalTypeParametersStart();
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
}
signatureVisitor.writeFormalTypeParametersEnd();
}
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) {
@@ -516,7 +583,7 @@ public class JetTypeMapper {
}
Type returnType = mapReturnType(f.getReturnType());
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null);
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null, null, null);
}
@@ -541,7 +608,7 @@ public class JetTypeMapper {
}
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null);
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null);
}
@Nullable
@@ -571,7 +638,7 @@ public class JetTypeMapper {
params.add(mapType(inType));
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null);
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null);
}
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -593,7 +660,7 @@ public class JetTypeMapper {
}
Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, null); // TODO: generics signature
return new JvmMethodSignature(method, null, null, null); // TODO: generics signature
}
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
@@ -0,0 +1,46 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 javaGenericSignature;
private final String kotlinGenericSignature;
public JvmClassSignature(String name, String superclassName, List<String> interfaces,
@Nullable String javaGenericSignature, @Nullable String kotlinGenericSignature) {
this.name = name;
this.superclassName = superclassName;
this.interfaces = interfaces;
this.javaGenericSignature = javaGenericSignature;
this.kotlinGenericSignature = kotlinGenericSignature;
}
public String getName() {
return name;
}
public String getSuperclassName() {
return superclassName;
}
public List<String> getInterfaces() {
return interfaces;
}
public String getJavaGenericSignature() {
return javaGenericSignature;
}
public String getKotlinGenericSignature() {
return kotlinGenericSignature;
}
}
@@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.commons.Method;
import java.util.List;
/**
* @author Stepan Koltsov
*/
@@ -12,10 +14,16 @@ public class JvmMethodSignature {
private final Method asmMethod;
/** Null when we don't care about type parameters */
private final String genericsSignature;
// TODO: type parameters
private final List<String> kotlinParameterTypes;
private final String kotlinReturnType;
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature) {
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature,
@Nullable List<String> kotlinParameterTypes, @Nullable String kotlinReturnType) {
this.asmMethod = asmMethod;
this.genericsSignature = genericsSignature;
this.kotlinParameterTypes = kotlinParameterTypes;
this.kotlinReturnType = kotlinReturnType;
}
public Method getAsmMethod() {
@@ -25,4 +33,12 @@ public class JvmMethodSignature {
public String getGenericsSignature() {
return genericsSignature;
}
public List<String> getKotlinParameterTypes() {
return kotlinParameterTypes;
}
public String getKotlinReturnType() {
return kotlinReturnType;
}
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiFile;
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.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -43,7 +44,8 @@ public class NamespaceCodegen {
}
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 PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
@@ -68,6 +68,10 @@ public class SignatureUtil {
private static void genTypeParams(JetClass type, StringBuilder sb) {
List<JetTypeParameter> parameters = type.getTypeParameterList().getParameters();
if (parameters.isEmpty()) {
return;
}
sb.append('<');
for(JetTypeParameter param : parameters) {
sb.append("T");
Variance variance = param.getVariance();
@@ -78,5 +82,6 @@ public class SignatureUtil {
sb.append(param.getName());
sb.append(";");
}
sb.append('>');
}
}
@@ -14,7 +14,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
@@ -361,6 +360,7 @@ public class JavaDescriptorResolver {
boolean changeNullable = false;
boolean nullable = true;
String typeFromAnnotation = null;
// TODO: must be very slow, make it lazy?
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
@@ -370,13 +370,13 @@ public class JavaDescriptorResolver {
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
attributes.toString();
if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD);
if (annotation.getQualifiedName().equals(StdlibNames.JET_VALUE_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD);
if (nameExpression != null) {
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) {
nullable = (Boolean) nullableExpression.getValue();
} else {
@@ -384,10 +384,20 @@ public class JavaDescriptorResolver {
nullable = false;
changeNullable = true;
}
PsiLiteralExpression signatureExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD);
if (signatureExpression != null) {
typeFromAnnotation = (String) signatureExpression.getValue();
}
}
}
JetType outType = semanticServices.getTypeTransformer().transformToType(psiType);
JetType outType;
if (typeFromAnnotation != null) {
outType = semanticServices.getTypeTransformer().transformToType(typeFromAnnotation);
} else {
outType = semanticServices.getTypeTransformer().transformToType(psiType);
}
return new ValueParameterDescriptorImpl(
containingDeclaration,
i,
@@ -510,6 +520,8 @@ public class JavaDescriptorResolver {
private JetType makeReturnType(PsiType returnType, PsiMethod method) {
boolean changeNullable = false;
boolean nullable = true;
String returnTypeFromAnnotation = null;
for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) {
if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) {
@@ -521,9 +533,19 @@ public class JavaDescriptorResolver {
nullable = false;
changeNullable = true;
}
PsiLiteralExpression returnTypeExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD);
if (returnTypeExpression != null) {
returnTypeFromAnnotation = (String) returnTypeExpression.getValue();
}
}
}
JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
JetType transformedType;
if (returnTypeFromAnnotation != null) {
transformedType = semanticServices.getTypeTransformer().transformToType(returnTypeFromAnnotation);
} else {
transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
}
if (changeNullable) {
return TypeUtils.makeNullableAsSpecified(transformedType, nullable);
} else {
@@ -77,6 +77,7 @@ public class JavaPackageScope extends JetScopeImpl {
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
if (javaPackage != null) {
boolean isKotlinNamespace = semanticServices.getKotlinNamespaceDescriptor(javaPackage.getQualifiedName()) != null;
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
@@ -84,6 +85,8 @@ public class JavaPackageScope extends JetScopeImpl {
}
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
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(psiClass.getQualifiedName());
if (kotlinClassDescriptor != null) {
@@ -6,6 +6,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
import org.jetbrains.jet.lang.types.*;
import java.util.Collections;
@@ -57,6 +59,19 @@ public class JavaTypeTransformer {
return result;
}
@NotNull
public JetType transformToType(@NotNull String kotlinSignature) {
final JetType[] r = new JetType[1];
JetTypeJetSignatureReader reader = new JetTypeJetSignatureReader(resolver, standardLibrary) {
@Override
protected void done(@NotNull JetType jetType) {
r[0] = jetType;
}
};
new JetSignatureReader(kotlinSignature).acceptType(reader);
return r[0];
}
@NotNull
public JetType transformToType(@NotNull PsiType javaType) {
return javaType.accept(new PsiTypeVisitor<JetType>() {
@@ -0,0 +1,196 @@
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeImpl;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Stepan Koltsov
*/
public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
private final JavaDescriptorResolver javaDescriptorResolver;
private final JetStandardLibrary jetStandardLibrary;
public JetTypeJetSignatureReader(JavaDescriptorResolver javaDescriptorResolver, JetStandardLibrary jetStandardLibrary) {
this.javaDescriptorResolver = javaDescriptorResolver;
this.jetStandardLibrary = jetStandardLibrary;
}
@Override
public void visitFormalTypeParameter(String name) {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitClassBound() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitInterfaceBound() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitSuperclass() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitInterface() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitParameterType() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitReturnType() {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitExceptionType() {
throw new IllegalStateException();
}
private JetType getPrimitiveType(char descriptor, boolean nullable) {
if (!nullable) {
switch (descriptor) {
case 'Z':
return jetStandardLibrary.getBooleanType();
case 'C':
return jetStandardLibrary.getCharType();
case 'B':
return jetStandardLibrary.getByteType();
case 'S':
return jetStandardLibrary.getShortType();
case 'I':
return jetStandardLibrary.getIntType();
case 'F':
return jetStandardLibrary.getFloatType();
case 'J':
return jetStandardLibrary.getLongType();
case 'D':
return jetStandardLibrary.getDoubleType();
case 'V':
return JetStandardClasses.getUnitType();
}
} else {
switch (descriptor) {
case 'Z':
return jetStandardLibrary.getNullableBooleanType();
case 'C':
return jetStandardLibrary.getNullableCharType();
case 'B':
return jetStandardLibrary.getNullableByteType();
case 'S':
return jetStandardLibrary.getNullableShortType();
case 'I':
return jetStandardLibrary.getNullableIntType();
case 'F':
return jetStandardLibrary.getNullableFloatType();
case 'J':
return jetStandardLibrary.getNullableLongType();
case 'D':
return jetStandardLibrary.getNullableDoubleType();
case 'V':
throw new IllegalStateException("incorrect signature: nullable void");
}
}
throw new IllegalStateException("incorrect signature");
}
@Override
public void visitBaseType(char descriptor, boolean nullable) {
done(getPrimitiveType(descriptor, nullable));
}
@Override
public void visitTypeVariable(String name, boolean nullable) {
throw new IllegalStateException();
}
@Override
public JetSignatureVisitor visitArrayType(boolean nullable) {
throw new IllegalStateException();
}
private ClassDescriptor classDescriptor;
private boolean nullable;
private List<TypeProjection> typeArguments;
@Override
public void visitClassType(String name, boolean nullable) {
String ourName = name.replace('/', '.');
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
if (this.classDescriptor == null) {
throw new IllegalStateException("class not found by name: " + ourName); // TODO: wrong exception
}
this.nullable = nullable;
this.typeArguments = new ArrayList<TypeProjection>();
}
@Override
public void visitInnerClassType(String name, boolean nullable) {
throw new IllegalStateException();
}
@Override
public void visitTypeArgument() {
throw new IllegalStateException();
}
private static Variance parseVariance(char wildcard) {
switch (wildcard) {
case '=': return Variance.INVARIANT;
case '+': return Variance.OUT_VARIANCE;
case '-': return Variance.IN_VARIANCE;
default: throw new IllegalStateException();
}
}
@Override
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
return new JetTypeJetSignatureReader(javaDescriptorResolver, jetStandardLibrary) {
@Override
protected void done(@NotNull JetType jetType) {
typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType));
}
};
}
@Override
public void visitEnd() {
JetType jetType = new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classDescriptor.getTypeConstructor(),
nullable,
typeArguments,
ErrorUtils.getErrorScope());
done(jetType);
}
protected abstract void done(@NotNull JetType jetType);
}
@@ -1,4 +1,4 @@
package org.jetbrains.jet.lang.resolve;
package org.jetbrains.jet.lang.resolve.java;
import org.objectweb.asm.Type;
@@ -7,12 +7,13 @@ import org.objectweb.asm.Type;
*/
public class StdlibNames {
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_VALUE_PARAMETER_CLASS = "jet.typeinfo.JetValueParameter";
public static final String JET_VALUE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetValueParameter;";
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 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_VALUE_PARAMETER_TYPE_FIELD = "type";
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
@@ -25,8 +26,10 @@ public class StdlibNames {
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
public static final String JET_METHOD_RETURN_TYPE_FIELD = "returnType";
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;";
@@ -0,0 +1,79 @@
package org.jetbrains.jet.lang.resolve.java.signature;
/**
* @author Stepan Koltsov
*/
public class JetSignatureAdapter implements JetSignatureVisitor {
@Override
public void visitFormalTypeParameter(String name) {
}
@Override
public JetSignatureVisitor visitClassBound() {
return this;
}
@Override
public JetSignatureVisitor visitInterfaceBound() {
return this;
}
@Override
public JetSignatureVisitor visitSuperclass() {
return this;
}
@Override
public JetSignatureVisitor visitInterface() {
return this;
}
@Override
public JetSignatureVisitor visitParameterType() {
return this;
}
@Override
public JetSignatureVisitor visitReturnType() {
return this;
}
@Override
public JetSignatureVisitor visitExceptionType() {
return this;
}
@Override
public void visitBaseType(char descriptor, boolean nullable) {
}
@Override
public void visitTypeVariable(String name, boolean nullable) {
}
@Override
public JetSignatureVisitor visitArrayType(boolean nullable) {
return this;
}
@Override
public void visitClassType(String name, boolean nullable) {
}
@Override
public void visitInnerClassType(String name, boolean nullable) {
}
@Override
public void visitTypeArgument() {
}
@Override
public JetSignatureVisitor visitTypeArgument(char wildcard) {
return this;
}
@Override
public void visitEnd() {
}
}
@@ -0,0 +1,172 @@
package org.jetbrains.jet.lang.resolve.java.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());
}
}
}
public int acceptType(JetSignatureVisitor v) {
return parseType(this.signature, 0, v);
}
public void acceptTypeOnly(JetSignatureVisitor v) {
int r = acceptType(v);
if (r != signature.length()) {
throw new IllegalStateException();
}
}
private static int parseType(
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.lang.resolve.java.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.lang.resolve.java.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;
}
}
+4
View File
@@ -198,6 +198,10 @@ trait Hashable {
class Boolean : Comparable<Boolean> {
fun not() : Boolean
fun and(other : Boolean) : Boolean
fun or(other : Boolean) : Boolean
fun xor(other : Boolean) : Boolean
fun equals(other : Any?) : Boolean
@@ -577,7 +577,7 @@ public class JetControlFlowProcessor {
JetExpression defaultValue = parameter.getDefaultValue();
builder.declare(parameter);
if (defaultValue != null) {
builder.read(defaultValue);
value(defaultValue, inCondition);
}
builder.write(parameter, parameter);
}
@@ -232,6 +232,14 @@ public interface Errors {
ParameterizedDiagnosticFactory1<JetType> RETURN_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "This function must return a value of type {0}");
ParameterizedDiagnosticFactory1<JetType> EXPECTED_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}");
ParameterizedDiagnosticFactory1<JetType> ASSIGNMENT_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value");
ParameterizedDiagnosticFactory1<JetType> IMPLICIT_CAST_TO_UNIT_OR_ANY = ParameterizedDiagnosticFactory1.create(WARNING, "Type was casted to ''{0}''. Please specify ''{0}'' as expected type, if you mean such cast");
ParameterizedDiagnosticFactory1<JetExpression> EXPRESSION_EXPECTED = new ParameterizedDiagnosticFactory1<JetExpression>(ERROR, "{0} is not an expression, and only expression are allowed here") {
@Override
protected String makeMessageFor(JetExpression expression) {
String expressionType = expression.toString();
return expressionType.substring(0, 1) + expressionType.substring(1).toLowerCase();
}
};
ParameterizedDiagnosticFactory1<JetType> UPPER_BOUND_VIOLATED = ParameterizedDiagnosticFactory1.create(ERROR, "An upper bound {0} is violated"); // TODO : Message
ParameterizedDiagnosticFactory1<JetType> FINAL_CLASS_OBJECT_UPPER_BOUND = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is a final type, and thus a class object cannot extend it");
@@ -131,11 +131,15 @@ public class JetPsiUtil {
public static String getFQName(JetClass jetClass) {
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(jetClass, JetNamespace.class, JetClass.class);
if (parent instanceof JetNamespace) {
return getFQName(((JetNamespace) parent)) + "." + jetClass.getName();
return makeFQName(getFQName(((JetNamespace) parent)), jetClass);
}
if (parent instanceof JetClass) {
return getFQName(((JetClass) parent)) + "." + jetClass.getName();
return makeFQName(getFQName(((JetClass) parent)), jetClass);
}
return jetClass.getName();
}
private static String makeFQName(String prefix, JetClass jetClass) {
return (prefix.length() == 0 ? "" : prefix + ".") + jetClass.getName();
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
@@ -449,8 +450,8 @@ public class DescriptorResolver {
}
@NotNull
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, JetScope scope, JetProperty property) {
JetType type = getVariableType(scope, property, false); // For a local variable the type must not be deferred
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, JetScope scope, JetProperty property, DataFlowInfo dataFlowInfo) {
JetType type = getVariableType(scope, property, dataFlowInfo, false); // For a local variable the type must not be deferred
return resolveLocalVariableDescriptorWithType(containingDeclaration, property, type);
}
@@ -548,9 +549,9 @@ public class DescriptorResolver {
? ReceiverDescriptor.NO_RECEIVER
: new ExtensionReceiver(propertyDescriptor, receiverType);
JetScope scope2 = getPropertyDeclarationInnerScope(scope, propertyDescriptor, typeParameterDescriptors, receiverDescriptor);
JetScope propertyScope = getPropertyDeclarationInnerScope(scope, propertyDescriptor, typeParameterDescriptors, receiverDescriptor);
JetType type = getVariableType(scope2, property, true);
JetType type = getVariableType(propertyScope, property, DataFlowInfo.EMPTY, true);
JetType inType = isVar ? type : null;
propertyDescriptor.setType(inType, type, typeParameterDescriptors, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), receiverDescriptor);
@@ -580,7 +581,7 @@ public class DescriptorResolver {
}
@NotNull
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, boolean allowDeferred) {
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, @NotNull final DataFlowInfo dataFlowInfo, boolean allowDeferred) {
// TODO : receiver?
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
@@ -598,8 +599,7 @@ public class DescriptorResolver {
LazyValue<JetType> lazyValue = new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override
protected JetType compute() {
//JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE);
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo);
}
};
if (allowDeferred) {
@@ -95,7 +95,7 @@ public class ErrorUtils {
true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), getErrorScope(), ERROR_CONSTRUCTOR_GROUP, ERROR_CONSTRUCTOR);
}
private static JetScope getErrorScope() {
public static JetScope getErrorScope() {
return ERROR_SCOPE;
}
@@ -242,6 +242,11 @@ public class JetStandardClasses {
public static JetType getAnyType() {
return ANY_TYPE;
}
public static boolean isAny(JetType type) {
return !(type instanceof NamespaceType) &&
type.getConstructor() == ANY_TYPE.getConstructor();
}
public static JetType getNullableAnyType() {
return NULLABLE_ANY_TYPE;
@@ -21,7 +21,7 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
private final boolean nullable;
private JetScope memberScope;
public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, List<TypeProjection> arguments, JetScope memberScope) {
public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, @NotNull List<TypeProjection> arguments, JetScope memberScope) {
super(annotations);
this.constructor = constructor;
this.nullable = nullable;
@@ -361,6 +361,7 @@ public class TypeUtils {
fullSubstitution.put(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
}
}
if (JetStandardClasses.isNothingOrNullableNothing(context)) return;
for (JetType supertype : context.getConstructor().getSupertypes()) {
fillInDeepSubstitutor(supertype, substitutor, substitution, fullSubstitution);
}
@@ -110,11 +110,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
return visitParenthesizedExpression(expression, context, false);
}
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
JetExpression innerExpression = expression.getExpression();
if (innerExpression == null) {
return null;
}
return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope)), expression, context);
return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope), isStatement), expression, context);
}
@Override
@@ -479,7 +483,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
return context.getServices().getBlockReturnedType(context.scope, expression, CoercionStrategy.NO_COERCION, context);
return visitBlockExpression(expression, context, false);
}
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
return context.getServices().getBlockReturnedType(context.scope, expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
}
@Override
@@ -611,6 +619,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
return visitUnaryExpression(expression, context, false);
}
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) {
JetExpression baseExpression = expression.getBaseExpression();
if (baseExpression == null) return null;
JetSimpleNameExpression operationSign = expression.getOperationReference();
@@ -619,9 +631,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
referencedName = referencedName == null ? " <?>" : referencedName;
context.labelResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
// TODO : Some processing for the label?
JetType type = DataFlowUtils.checkType(facade.getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
ExpressionTypingContext newContext = context.replaceExpectedReturnType(context.expectedType);
JetType type = facade.getType(baseExpression, newContext, isStatement);
context.labelResolver.exitLabeledElement(baseExpression);
return type;
return DataFlowUtils.checkType(type, expression, context);
}
IElementType operationType = operationSign.getReferencedNameElementType();
String name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
@@ -835,6 +848,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
facade.checkStatementType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
return null;
}
@@ -52,7 +52,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
return visitIfExpression(expression, context, false);
}
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
JetExpression condition = expression.getCondition();
checkCondition(context.scope, condition, context);
@@ -71,7 +75,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
if (type != null && JetStandardClasses.isNothing(type)) {
facade.setResultingDataFlowInfo(elseInfo);
}
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
}
return null;
}
@@ -80,10 +84,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
if (type != null && JetStandardClasses.isNothing(type)) {
facade.setResultingDataFlowInfo(thenInfo);
}
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
}
JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(thenInfo));
JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(elseInfo));
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo));
JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo));
JetType result;
if (thenType == null) {
@@ -105,11 +110,18 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
else if (jumpInElse && !jumpInThen) {
facade.setResultingDataFlowInfo(thenInfo);
}
return result;
if (result == null) return null;
return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement);
}
@Override
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
return visitWhileExpression(expression, context, false);
}
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
JetExpression condition = expression.getCondition();
checkCondition(context.scope, condition, context);
@@ -150,7 +162,12 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
}
@Override
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
return visitDoWhileExpression(expression, context, false);
}
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
JetExpression body = expression.getBody();
JetScope conditionScope = context.scope;
@@ -179,7 +196,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
}
@Override
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
return visitForExpression(expression, context, false);
}
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
JetParameter loopParameter = expression.getLoopParameter();
JetExpression loopRange = expression.getLoopRange();
@@ -417,6 +440,4 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
context.labelResolver.recordLabel(expression, context);
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.TypeUtils;
@@ -18,8 +19,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
/**
@@ -154,4 +154,30 @@ public class DataFlowUtils {
context.trace.report(TYPE_MISMATCH.on(expression, context.expectedType, expressionType));
return expressionType;
}
@Nullable
public static JetType checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedType)) {
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
return null;
}
return JetStandardClasses.getUnitType();
}
@Nullable
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) {
if (expressionType != null && context.expectedType == TypeUtils.NO_EXPECTED_TYPE && !isStatement &&
(JetStandardClasses.isUnit(expressionType) || JetStandardClasses.isAny(expressionType))) {
context.trace.report(IMPLICIT_CAST_TO_UNIT_OR_ANY.on(expression, expressionType));
}
return expressionType;
}
@Nullable
public static JetType illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
facade.checkStatementType(expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
return null;
}
}
@@ -14,7 +14,7 @@ public interface ExpressionTypingFacade {
@Nullable
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
@Nullable
JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context);
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement);
}
@@ -24,4 +24,6 @@ import org.jetbrains.jet.lang.types.JetType;
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context);
}
@@ -48,7 +48,11 @@ public class ExpressionTypingServices {
@NotNull
public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) {
JetType type = getType(scope, expression, expectedType);
return safeGetType(scope, expression, expectedType, DataFlowInfo.EMPTY);
}
public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo) {
JetType type = getType(scope, expression, expectedType, dataFlowInfo);
if (type != null) {
return type;
}
@@ -61,7 +65,7 @@ public class ExpressionTypingServices {
}
@Nullable
public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, DataFlowInfo dataFlowInfo) {
public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo) {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
semanticServices,
new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
@@ -133,7 +137,7 @@ public class ExpressionTypingServices {
getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context);
}
else {
expressionTypingFacade.getType(bodyExpression, newContext);
expressionTypingFacade.getType(bodyExpression, newContext, !blockBody);
}
}
@@ -159,7 +163,7 @@ public class ExpressionTypingServices {
assert bodyExpression != null;
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext(semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN, false));
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN, false), !function.hasBlockBody());
//todo function literals
final Collection<JetExpression> returnedExpressions = Lists.newArrayList();
if (function.hasBlockBody()) {
@@ -225,13 +229,13 @@ public class ExpressionTypingServices {
final boolean[] mismatch = new boolean[1];
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
if (mismatch[0]) {
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
mismatch[0] = false;
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
if (mismatch[0]) {
temporaryTraceExpectingUnit.commit();
}
@@ -245,11 +249,11 @@ public class ExpressionTypingServices {
}
else {
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
}
}
else {
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
boolean mightBeUnit = false;
if (statementExpression instanceof JetDeclaration) {
@@ -271,7 +275,7 @@ public class ExpressionTypingServices {
}
}
else {
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
}
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
@@ -40,7 +40,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
this.basic = new BasicExpressionTypingVisitor(this);
if (writableScope != null) {
this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic);
this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic, controlStructures, patterns);
}
else {
this.statements = null;
@@ -84,10 +84,22 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
return getType(expression, context, this);
}
@Override
@Nullable
public final JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context) {
return getType(expression, context, statements);
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
if (!isStatement) return getType(expression, context);
if (statements != null) {
return getType(expression, context, statements);
}
return getType(expression, context, createStatementVisitor(context));
}
private ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
return new ExpressionTypingVisitorForStatements(this, ExpressionTypingUtils.newWritableScopeImpl(context).setDebugName("statement scope"), basic, controlStructures, patterns);
}
@Override
public void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context) {
expression.accept(createStatementVisitor(context), context);
}
@Nullable
@@ -1,6 +1,5 @@
package org.jetbrains.jet.lang.types.expressions;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,22 +31,20 @@ import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.get
public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisitor {
private final WritableScope scope;
private final BasicExpressionTypingVisitor basic;
private final ControlStructureTypingVisitor controlStructures;
private final PatternMatchingTypingVisitor patterns;
public ExpressionTypingVisitorForStatements(@NotNull ExpressionTypingInternals facade, @NotNull WritableScope scope, BasicExpressionTypingVisitor basic) {
public ExpressionTypingVisitorForStatements(
@NotNull ExpressionTypingInternals facade,
@NotNull WritableScope scope,
BasicExpressionTypingVisitor basic,
@NotNull ControlStructureTypingVisitor controlStructures,
@NotNull PatternMatchingTypingVisitor patterns) {
super(facade);
this.scope = scope;
this.basic = basic;
}
@Nullable
private JetType checkExpectedType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE) {
if (JetStandardClasses.isUnit(context.expectedType)) {
return JetStandardClasses.getUnitType();
}
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
}
return null;
this.controlStructures = controlStructures;
this.patterns = patterns;
}
@Nullable
@@ -57,7 +54,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
return null;
}
return checkExpectedType(expression, context);
return DataFlowUtils.checkStatementType(expression, context);
}
@Override
@@ -68,7 +65,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
PropertyDescriptor propertyDescriptor = context.getDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
scope.addVariableDescriptor(propertyDescriptor);
}
return checkExpectedType(declaration, context);
return DataFlowUtils.checkStatementType(declaration, context);
}
@Override
@@ -88,7 +85,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter));
}
VariableDescriptor propertyDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
VariableDescriptor propertyDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property, context.dataFlowInfo);
JetExpression initializer = property.getInitializer();
if (property.getPropertyTypeRef() != null && initializer != null) {
JetType outType = propertyDescriptor.getOutType();
@@ -103,7 +100,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
scope.addVariableDescriptor(propertyDescriptor);
return checkExpectedType(property, context);
return DataFlowUtils.checkStatementType(property, context);
}
@Override
@@ -112,7 +109,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
scope.addFunctionDescriptor(functionDescriptor);
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
context.getServices().checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo);
return checkExpectedType(function, context);
return DataFlowUtils.checkStatementType(function, context);
}
@Override
@@ -127,24 +124,24 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
@Override
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
return checkExpectedType(dcl, context);
return DataFlowUtils.checkStatementType(dcl, context);
}
@Override
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
JetType result;
if (operationType == JetTokens.EQ) {
result = visitAssignment(expression, contextWithExpectedType);
result = visitAssignment(expression, context);
}
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
result = visitAssignmentOperation(expression, contextWithExpectedType);
result = visitAssignmentOperation(expression, context);
}
else {
return facade.getType(expression, contextWithExpectedType);
return facade.getType(expression, context);
}
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
return DataFlowUtils.checkType(result, expression, context);
}
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
@@ -218,7 +215,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
if (left instanceof JetSimpleNameExpression) {
ExpressionTypingUtils.checkWrappingInRef(left, context);
}
return checkExpectedType(expression, contextWithExpectedType);
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType);
}
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
@@ -259,4 +256,44 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
context.trace.report(UNSUPPORTED.on(element, "in a block"));
return null;
}
@Override
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
return controlStructures.visitWhileExpression(expression, context, true);
}
@Override
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
return controlStructures.visitDoWhileExpression(expression, context, true);
}
@Override
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
return controlStructures.visitForExpression(expression, context, true);
}
@Override
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
return controlStructures.visitIfExpression(expression, context, true);
}
@Override
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
return patterns.visitWhenExpression(expression, context, true);
}
@Override
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
return basic.visitBlockExpression(expression, context, true);
}
@Override
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
return basic.visitParenthesizedExpression(expression, context, true);
}
@Override
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
return basic.visitUnaryExpression(expression, context, true);
}
}
@@ -13,7 +13,6 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.*;
@@ -21,7 +20,6 @@ import org.jetbrains.jet.lang.types.*;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.ensureBooleanResultWithCustomSubject;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.newWritableScopeImpl;
/**
@@ -48,7 +46,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
}
@Override
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType) {
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
return visitWhenExpression(expression, context, false);
}
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
// TODO :change scope according to the bound value in the when header
final JetExpression subjectExpression = expression.getSubjectExpression();
@@ -92,7 +94,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
}
JetExpression bodyExpression = whenEntry.getExpression();
if (bodyExpression != null) {
JetType type = facade.getType(bodyExpression, contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo));
ExpressionTypingContext newContext = contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo);
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext);
if (type != null) {
expressionTypes.add(type);
}
@@ -100,7 +104,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
}
if (!expressionTypes.isEmpty()) {
return CommonSupertypes.commonSupertype(expressionTypes);
return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement);
}
else if (expression.getEntries().isEmpty()) {
// context.trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression");
@@ -1,3 +1,4 @@
import std.*
import std.io.*
import java.io.*
@@ -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
@@ -0,0 +1,126 @@
namespace kt770_351_735
//+JDK
//KT-770 Reference is not resolved to anything, but is not marked unresolved
fun main(args : Array<String>) {
var i = 0
when (i) {
1 => i--
2 => i = 2 // i is surrounded by a black border
else => <!UNRESOLVED_REFERENCE!>j<!> = 2
}
System.out?.println(i)
}
//KT-351 Distinguish statement and expression positions
val w = <!EXPRESSION_EXPECTED!>while (true) {}<!>
fun foo() {
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 2
val r = { // type fun(): Int is inferred
if (true) {
2
}
else {
z = <!UNUSED_VALUE!>34<!>
}
}
val <!UNUSED_VARIABLE!>f<!>: fun(): Int = <!TYPE_MISMATCH!>r<!>
val <!UNUSED_VARIABLE!>g<!>: fun(): Any = r
}
//KT-735 Statements without braces are prohibited on the right side of when entries.
fun box() : Int {
val d = 2
var z = 0
when(d) {
is 5, is 3 => z++
else => z = -1000
}
return z
}
//More tests
fun test1() = while(true) {}
fun test2(): Unit = while(true) {}
fun testCoercionToUnit() {
val <!UNUSED_VARIABLE!>simple<!>: fun(): Unit = {
41
}
val <!UNUSED_VARIABLE!>withIf<!>: fun(): Unit = {
if (true) {
3
} else {
45
}
}
val i = 34
val <!UNUSED_VARIABLE!>withWhen<!> : fun() : Unit = {
when(i) {
is 1 => {
val d = 34
"1"
doSmth(d)
}
is 2 => '4'
else => true
}
}
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 43
val checkType = {
if (true) {
x = <!UNUSED_VALUE!>4<!>
} else {
45
}
}
val <!UNUSED_VARIABLE!>f<!> : fun() : String = <!TYPE_MISMATCH!>checkType<!>
}
fun doSmth(<!UNUSED_PARAMETER!>i<!>: Int) {}
fun testImplicitCoercion() {
val d = 21
var z = 0
var <!UNUSED_VARIABLE!>i<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>when(d) {
is 3 => null
is 4 => { val <!NAME_SHADOWING, UNUSED_VARIABLE!>z<!> = 23 }
else => z = 20
}<!>
var <!UNUSED_VARIABLE!>u<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>when(d) {
is 3 => {
z = <!UNUSED_VALUE!>34<!>
}
else => <!UNUSED_CHANGED_VALUE!>z--<!>
}<!>
var <!UNUSED_VARIABLE!>iff<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (true) {
z = <!UNUSED_VALUE!>34<!>
}<!>
val <!UNUSED_VARIABLE!>g<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (true) 4<!>
val <!UNUSED_VARIABLE!>h<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (false) 4 else {}<!>
bar(if (true) {
4
}
else {
z = <!UNUSED_VALUE!>342<!>
})
}
fun bar(<!UNUSED_PARAMETER!>a<!>: Unit) {}
fun testStatementInExpressionContext() {
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 34
val <!UNUSED_VARIABLE!>a1<!>: Unit = <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>334<!><!>
val <!UNUSED_VARIABLE!>a2<!>: Unit = <!EXPRESSION_EXPECTED!>while(true) {}<!>
val <!UNUSED_VARIABLE!>f<!> = <!EXPRESSION_EXPECTED!>for (i in 1..10) {}<!>
if (true) return <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>34<!><!>
return <!EXPRESSION_EXPECTED!>while (true) {}<!>
}
@@ -0,0 +1,26 @@
namespace kt786
//KT-786 Exception on incomplete code with 'when'
fun foo() : Int {
val d = 2
var z = 0
when(d) {
is 5, is 3 => <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY, UNUSED_CHANGED_VALUE!>z++<!>
<!ELSE_MISPLACED_IN_WHEN!>else => { <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>z = <!UNUSED_VALUE!>-1000<!><!> }<!>
return z => <!UNREACHABLE_CODE!>34<!>
}
}
//test unreachable code
fun fff(): Int {
var d = 3
when(d) {
is 4 => 21
return 2 => <!UNREACHABLE_CODE!>return 47<!>
<!UNREACHABLE_CODE!>bar()<!> => <!UNREACHABLE_CODE!>45<!>
<!UNREACHABLE_CODE!>444<!> => <!UNREACHABLE_CODE!>true<!>
}
return 34
}
fun bar(): Int = 8
@@ -0,0 +1,34 @@
namespace kt244
//+JDK
// KT-244 Use dataflow info while resolving variable initializers
fun f(s: String?) {
if (s != null) {
s.length //ok
var <!UNUSED_VARIABLE!>i<!> = s.length //error: Only safe calls are allowed on a nullable receiver
System.out?.println(s.length) //error
}
}
// more tests
class A(a: String?) {
val b = if (a != null) a.length else 1
{
if (a != null) {
val c = a.length
}
}
val i : Int
{
if (a is String) {
i = a.length
}
else {
i = 3
}
}
}
@@ -18,6 +18,6 @@ fun box() : Boolean {
fun box2() : Boolean {
var <!UNUSED_VARIABLE!>c<!> = A()
var c = A()
return (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>c.p = "yeah"<!>) && true
}
@@ -30,6 +30,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.plugin.JetLanguage;
import org.junit.Assert;
@@ -156,9 +158,23 @@ public class ReadClassDataTest extends UsefulTestCase {
for (int i = 0; i < a.getValueParameters().size(); ++i) {
compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i));
}
Assert.assertEquals(a.getReturnType(), b.getReturnType());
compareTypes(a.getReturnType(), b.getReturnType());
System.out.println("fun " + a.getName() + "(...): " + a.getReturnType());
}
private void compareAnything(Object a, Object b) {
if (a instanceof JetType || b instanceof JetType) {
compareTypes((JetType) a, (JetType) b);
} else {
Assert.assertEquals(a, b);
}
}
private void compareTypes(JetType a, JetType b) {
// cannot just call a.equals(b) because "a" and "b" were created in different environments,
// TypeConstructor does not override equals()
Assert.assertEquals(a.toString(), b.toString());
}
private <T> void compareAnything(Class<T> clazz, T a, T b) {
System.out.println("Comparing " + clazz);
@@ -182,7 +198,7 @@ public class ReadClassDataTest extends UsefulTestCase {
System.out.println(method.getName());
Object ap = invoke(method, a);
Object bp = invoke(method, b);
Assert.assertEquals(ap, bp);
compareAnything(ap, bp);
}
}
@@ -326,9 +326,9 @@ public class JetTypeCheckerTest extends JetLiteFixture {
}
public void testLoops() throws Exception {
assertType("while (1) {1}", "Unit");
assertType("do {1} while(1)", "Unit");
assertType("for (i in 1) {1}", "Unit");
assertType("{ while (1) {1} }", "fun(): Unit");
assertType("{ do {1} while(1) }", "fun(): Unit");
assertType("{ for (i in 1) {1} }", "fun(): Unit");
}
public void testFunctionLiterals() throws Exception {
+2 -2
View File
@@ -30,7 +30,7 @@ class StandardFList<T> (override val head: T, override val tail: FList<T>) : FLi
fun <T> FList<T>.plus2(element: T): FList<T> =
when(this) {
is EmptyFList<T> => OneElementFList<T>(element)
is EmptyFList<*> => OneElementFList<T>(element)
else => StandardFList<T>(element, this)
}
@@ -67,4 +67,4 @@ fun main(args: Array<String>) {
System.out?.println(System.currentTimeMillis() - start2)
System.out?.println()
}
}
}
@@ -22,6 +22,10 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
if (context.getCompletionChar() == '(') {
context.setAddCompletionChar(false);
}
int startOffset = context.getStartOffset();
int lookupStringLength = item.getLookupString().length();
int endOffset = startOffset + lookupStringLength;
@@ -17,12 +17,16 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler;
@@ -105,6 +109,7 @@ class JetSimpleNameReference extends JetPsiReference {
@NotNull Iterable<DeclarationDescriptor> descriptors, @NotNull final JetScope scope
) {
final Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.removeAll(
Collections2.filter(JetScopeUtils.getAllExtensions(scope), new Predicate<CallableDescriptor>() {
@Override
@@ -121,6 +126,11 @@ class JetSimpleNameReference extends JetPsiReference {
@NotNull final JetScope externalScope,
@NotNull final ReceiverDescriptor receiverDescriptor
) {
// It's impossible to add extension function for namespace
if (receiverDescriptor.getType() instanceof NamespaceType) {
return descriptors;
}
Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.addAll(Collections2.filter(JetScopeUtils.getAllExtensions(externalScope),
@@ -138,7 +148,7 @@ class JetSimpleNameReference extends JetPsiReference {
List<LookupElement> result = Lists.newArrayList();
for (final DeclarationDescriptor descriptor : descriptors) {
LookupElementBuilder element = LookupElementBuilder.create(descriptor.getName());
LookupElementBuilder element = LookupElementBuilder.create(descriptor, descriptor.getName());
String typeText = "";
String tailText = "";
boolean tailTextGrayed = false;
@@ -155,6 +165,7 @@ class JetSimpleNameReference extends JetPsiReference {
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
@@ -175,6 +186,7 @@ class JetSimpleNameReference extends JetPsiReference {
else {
typeText = DescriptorRenderer.TEXT.render(descriptor);
}
element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText);
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal());
@@ -10,4 +10,4 @@ class A() : My<caret> {
}
}
// EXIST: MySecondClass, MyFirstClass
// EXIST: MySecondClass, MyFirstClass
@@ -0,0 +1,24 @@
namespace Test.MyTest
class A {
class object {
public fun testOther() {
}
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.test<caret>
}
// EXIST: testOther
// NUMBER: 3
@@ -0,0 +1,7 @@
namespace Test.MyTest
fun test() {
Test.<caret>
}
// EXIST: MyTest
@@ -0,0 +1,17 @@
namespace Test.MyTest
class A {
class object {
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.testOther<caret>
}
@@ -0,0 +1,17 @@
namespace Test.MyTest
class A {
class object {
public fun testOther(a: Boolean) {
}
public fun testOther(a: Int) {
}
}
}
fun testMy() {
A.testOther()
}
@@ -8,6 +8,7 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader;
@@ -59,6 +60,11 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase {
assertContainsItems(itemsShouldExist(getFile().getText()));
assertNotContainItems(itemsShouldAbsent(getFile().getText()));
Integer itemsNumber = getExpectedNumber(getFile().getText());
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
}
}
@Override
@@ -85,6 +91,16 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase {
return findListWithPrefix("// ABSENT:", fileText);
}
@Nullable
private static Integer getExpectedNumber(String fileText) {
final String[] numberStrings = findListWithPrefix("// NUMBER:", fileText);
if (numberStrings.length > 0) {
return Integer.parseInt(numberStrings[0]);
}
return null;
}
@NotNull
private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>();
@@ -20,6 +20,14 @@ public class FunctionsHandlerTest extends LightCompletionTestCase {
checkResultByFile("ParamsFunction.kt.after");
}
public void testSingleBrackets() {
configureByFile("SingleBrackets.kt");
type('(');
checkResultByFile("SingleBrackets.kt.after");
}
// public void
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
+29
View File
@@ -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() { 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() {
override fun read() : Int {
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)
}
+6 -8
View File
@@ -1,11 +1,9 @@
namespace std
namespace std.util
namespace util {
import java.util.*
import java.util.*
val Collection<*>.size : Int
get() = size()
val Collection<*>.size : Int
get() = size()
val Collection<*>.empty : Boolean
get() = isEmpty()
}
val Collection<*>.empty : Boolean
get() = isEmpty()
+62
View File
@@ -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
+7
View File
@@ -11,6 +11,8 @@ import java.lang.annotation.Target;
* The fact of receiver presence must be deducted from presence of 'this$receiver' parameter
*
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@@ -24,4 +26,9 @@ public @interface JetMethod {
* @return is this type returnTypeNullable
*/
boolean nullableReturnType() default false;
/**
* Return type type unless java type is correct Kotlin type.
*/
String returnType () default "";
}
@@ -7,6 +7,8 @@ import java.util.*;
/**
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
@Retention(RetentionPolicy.RUNTIME)
@interface JetSignature {
@@ -2,6 +2,8 @@ package jet.typeinfo;
/**
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
public @interface JetTypeDescriptor{
//
@@ -9,6 +9,8 @@ import java.lang.annotation.Target;
* Annotation for parameters
*
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@@ -5,6 +5,8 @@ import java.lang.annotation.RetentionPolicy;
/**
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface JetTypeProjection {
@@ -9,10 +9,12 @@ import java.lang.annotation.Target;
* Annotation for parameters
*
* @author alex.tkachman
*
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface JetParameter {
public @interface JetValueParameter {
/**
* @return name of parameter
*/
@@ -32,4 +34,9 @@ public @interface JetParameter {
* @return if this parameter has default value
*/
boolean hasDefaultValue () default false;
/**
* @return type unless Java type is correct Kotlin type.
*/
String type() default "";
}
+17 -10
View File
@@ -376,7 +376,7 @@ public abstract class TypeInfo<T> implements JetObject {
return false;
}
if (superType.projections == null || superType.projections.length != projections.length) {
throw new IllegalArgumentException("inconsistent type infos for the same class");
throw new IllegalArgumentException("inconsistent type info for the same class");
}
for (int i = 0; i < projections.length; i++) {
// TODO handle variance here
@@ -451,18 +451,18 @@ public abstract class TypeInfo<T> implements JetObject {
if(klass == null)
return null;
lock.readLock().lock();
// lock.readLock().lock();
Signature sig = map.get(klass);
lock.readLock().unlock();
// lock.readLock().unlock();
if (sig == null) {
lock.writeLock().lock();
// lock.writeLock().lock();
sig = map.get(klass);
if (sig == null) {
sig = internalParse(klass);
}
lock.writeLock().unlock();
// lock.writeLock().unlock();
}
return sig;
}
@@ -536,13 +536,20 @@ public abstract class TypeInfo<T> implements JetObject {
}
public void parseVars(Signature signature) {
while(cur < string.length && string[cur] == 'T') {
if(signature.variables == null) {
signature.variables = new LinkedList<TypeInfoProjection>();
signature.varNames = new HashMap<String, Integer>();
if (cur < string.length && string[cur] == '<') {
cur++;
while(cur < string.length && string[cur] != '>') {
if(signature.variables == null) {
signature.variables = new LinkedList<TypeInfoProjection>();
signature.varNames = new HashMap<String, Integer>();
}
if (string[cur] != 'T') {
throw new IllegalStateException(new String(string));
}
cur++;
signature.variables.add(parseVar(signature));
}
cur++;
signature.variables.add(parseVar(signature));
}
signature.variables = signature.variables == null ? Collections.<TypeInfoProjection>emptyList() : signature.variables;
signature.varNames = signature.varNames == null ? Collections.<String,Integer>emptyMap() : signature.varNames;