Merge remote branch 'origin/master'
This commit is contained in:
@@ -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('>');
|
||||
}
|
||||
}
|
||||
|
||||
+28
-6
@@ -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) {
|
||||
|
||||
+15
@@ -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>() {
|
||||
|
||||
+196
@@ -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);
|
||||
}
|
||||
+9
-6
@@ -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;";
|
||||
|
||||
+79
@@ -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() {
|
||||
}
|
||||
}
|
||||
+172
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+141
@@ -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();
|
||||
}
|
||||
+201
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+18
-4
@@ -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;
|
||||
}
|
||||
|
||||
+32
-11
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
+2
@@ -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);
|
||||
}
|
||||
|
||||
+13
-9
@@ -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();
|
||||
|
||||
+16
-4
@@ -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
|
||||
|
||||
+62
-25
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -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
|
||||
+126
@@ -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 {
|
||||
|
||||
@@ -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() +
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+8
-1
@@ -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 "";
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user