Merge remote branch 'origin/master'
Conflicts: compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java
This commit is contained in:
@@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.ProjectionErasingJetType;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -117,7 +118,7 @@ public class ClosureCodegen {
|
||||
final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
|
||||
if (enclosingType == null) captureThis = false;
|
||||
|
||||
final Method constructor = generateConstructor(funClass, captureThis);
|
||||
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType());
|
||||
|
||||
if (captureThis) {
|
||||
cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingType.getDescriptor(), null, null);
|
||||
@@ -175,7 +176,7 @@ public class ClosureCodegen {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private Method generateConstructor(String funClass, boolean captureThis) {
|
||||
private Method generateConstructor(String funClass, boolean captureThis, JetType returnType) {
|
||||
int argCount = closure.size();
|
||||
|
||||
if (captureThis) {
|
||||
@@ -199,9 +200,11 @@ public class ClosureCodegen {
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
|
||||
|
||||
iv.load(0, Type.getObjectType(funClass));
|
||||
iv.invokespecial(funClass, "<init>", "()V");
|
||||
expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType));
|
||||
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
|
||||
|
||||
i = 1;
|
||||
for (Type type : argTypes) {
|
||||
|
||||
@@ -52,8 +52,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
private final InstructionAdapter v;
|
||||
private final FrameMap myMap;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private final GenerationState state;
|
||||
private final Type returnType;
|
||||
|
||||
private final BindingContext bindingContext;
|
||||
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
|
||||
private final ClassContext context;
|
||||
@@ -74,6 +76,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
this.intrinsics = state.getIntrinsics();
|
||||
}
|
||||
|
||||
public GenerationState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public BindingContext getBindingContext() {
|
||||
return bindingContext;
|
||||
}
|
||||
|
||||
public JetTypeMapper getTypeMapper() {
|
||||
return state.getTypeMapper();
|
||||
}
|
||||
@@ -207,7 +217,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
else {
|
||||
assert expressionType != null;
|
||||
final DeclarationDescriptor descriptor = expressionType.getConstructor().getDeclarationDescriptor();
|
||||
if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses
|
||||
if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses (now IntRange is final)
|
||||
new ForInRangeLoopGenerator(expression, loopRangeType).invoke();
|
||||
return StackValue.none();
|
||||
}
|
||||
@@ -921,7 +931,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
|
||||
}
|
||||
else if (fd instanceof FunctionDescriptor) {
|
||||
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
|
||||
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, null);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("can't resolve declaration to callable: " + fd);
|
||||
@@ -2076,7 +2086,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
|
||||
void generateTypeInfo(JetType jetType) {
|
||||
public void generateTypeInfo(JetType jetType) {
|
||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||
if(knownTypeInfo != null) {
|
||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||
@@ -2287,7 +2297,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression);
|
||||
assert jetType != null;
|
||||
final DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses
|
||||
if (isClass(descriptor, "IntRange")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2308,7 +2318,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
final String className = "jet/Tuple" + entries.size();
|
||||
Type tupleType = Type.getObjectType(className);
|
||||
StringBuilder signature = new StringBuilder("(");
|
||||
StringBuilder signature = new StringBuilder("(Ljet/typeinfo/TypeInfo;");
|
||||
for (int i = 0; i != entries.size(); ++i) {
|
||||
signature.append("Ljava/lang/Object;");
|
||||
}
|
||||
@@ -2316,6 +2326,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
v.anew(tupleType);
|
||||
v.dup();
|
||||
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
|
||||
for (JetExpression entry : entries) {
|
||||
gen(entry, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ public class JetTypeMapper {
|
||||
|
||||
private final HashMap<JetType,String> knowTypes = new HashMap<JetType, String>();
|
||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
|
||||
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
@@ -316,6 +318,9 @@ public class JetTypeMapper {
|
||||
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
|
||||
return TYPE_OBJECT;
|
||||
}
|
||||
return mapType(jetType, kind);
|
||||
}
|
||||
|
||||
@@ -460,17 +465,16 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
|
||||
private Method mapSignature(JetNamedFunction f, List<Type> valueParameterTypes, OwnerKind kind) {
|
||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.get(BindingContext.TYPE, receiverTypeRef);
|
||||
final List<JetParameter> parameters = f.getValueParameters();
|
||||
private Method mapSignature(FunctionDescriptor f, List<Type> valueParameterTypes, OwnerKind kind) {
|
||||
final ReceiverDescriptor receiverTypeRef = f.getReceiver();
|
||||
final JetType receiverType = receiverTypeRef == ReceiverDescriptor.NO_RECEIVER ? null : receiverTypeRef.getType();
|
||||
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
if (receiverType != null) {
|
||||
parameterTypes.add(mapType(receiverType));
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
||||
Type type = mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
@@ -480,24 +484,15 @@ public class JetTypeMapper {
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
for (JetParameter parameter : parameters) {
|
||||
final Type type = mapType(bindingContext.get(BindingContext.TYPE, parameter.getTypeReference()));
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
final Type type = mapType(parameter.getOutType());
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
for (int n = f.getTypeParameters().size(); n > 0; n--) {
|
||||
parameterTypes.add(TYPE_TYPEINFO);
|
||||
}
|
||||
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
|
||||
Type returnType;
|
||||
if (returnTypeRef == null) {
|
||||
assert functionDescriptor != null;
|
||||
final JetType type = functionDescriptor.getReturnType();
|
||||
returnType = mapReturnType(type);
|
||||
}
|
||||
else {
|
||||
returnType = mapReturnType(bindingContext.get(BindingContext.TYPE, returnTypeRef));
|
||||
}
|
||||
Type returnType = mapReturnType(f.getReturnType());
|
||||
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
@@ -511,9 +506,13 @@ public class JetTypeMapper {
|
||||
JetNamedFunction f = (JetNamedFunction) declaration;
|
||||
final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
assert functionDescriptor != null;
|
||||
return mapToCallableMethod(functionDescriptor, kind);
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
||||
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Method descriptor = mapSignature(f, valueParameterTypes, kind);
|
||||
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
|
||||
String owner;
|
||||
int invokeOpcode;
|
||||
boolean needsReceiver;
|
||||
@@ -521,7 +520,7 @@ public class JetTypeMapper {
|
||||
if (functionParent instanceof NamespaceDescriptor) {
|
||||
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||
invokeOpcode = Opcodes.INVOKESTATIC;
|
||||
needsReceiver = f.getReceiverTypeRef() != null;
|
||||
needsReceiver = functionDescriptor.getReceiver() != ReceiverDescriptor.NO_RECEIVER;
|
||||
}
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
|
||||
@@ -197,6 +197,9 @@ public abstract class StackValue {
|
||||
if (type.getSort() == Type.BOOLEAN) {
|
||||
v.checkcast(JetTypeMapper.JL_BOOLEAN_TYPE);
|
||||
}
|
||||
else if (type.getSort() == Type.CHAR) {
|
||||
v.checkcast(JetTypeMapper.JL_CHAR_TYPE);
|
||||
}
|
||||
else {
|
||||
v.checkcast(JetTypeMapper.JL_NUMBER_TYPE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayIndices implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
v.arraylength();
|
||||
v.invokestatic("jet/IntRange", "count", "(I)Ljet/IntRange;");
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ArrayIterator implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
JetCallExpression call = (JetCallExpression) element;
|
||||
FunctionDescriptor funDescriptor = (FunctionDescriptor) codegen.getBindingContext().get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call.getCalleeExpression());
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal();
|
||||
JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary();
|
||||
if(containingDeclaration.equals(standardLibrary.getArray())) {
|
||||
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType());
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getByteArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([B)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getShortArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([S)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getIntArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([I)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getLongArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([J)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getFloatArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([F)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getDoubleArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([D)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getCharArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([C)Ljet/Iterator;");
|
||||
}
|
||||
else if(containingDeclaration.equals(standardLibrary.getBooleanArrayClass())) {
|
||||
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Z)Ljet/Iterator;");
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(containingDeclaration.toString());
|
||||
}
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR);
|
||||
}
|
||||
}
|
||||
@@ -29,11 +29,13 @@ public class IntrinsicMethods {
|
||||
private static final IntrinsicMethod DEC = new Increment(-1);
|
||||
|
||||
private static final List<String> PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
|
||||
public static final ArraySize ARRAY_SIZE = new ArraySize();
|
||||
public static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
|
||||
public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices();
|
||||
|
||||
private final Project myProject;
|
||||
private final JetStandardLibrary myStdLib;
|
||||
private final Map<DeclarationDescriptor, IntrinsicMethod> myMethods = new HashMap<DeclarationDescriptor, IntrinsicMethod>();
|
||||
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||
|
||||
public IntrinsicMethods(Project project, JetStandardLibrary stdlib) {
|
||||
myProject = project;
|
||||
@@ -87,6 +89,30 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicProperty("DoubleArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("CharArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("BooleanArray", "size", ARRAY_SIZE);
|
||||
|
||||
declareIntrinsicProperty("Array", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("ByteArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("ShortArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("IntArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("LongArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("FloatArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("DoubleArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("CharArray", "indices", ARRAY_INDICES);
|
||||
declareIntrinsicProperty("BooleanArray", "indices", ARRAY_INDICES);
|
||||
|
||||
declareIterator(myStdLib.getArray());
|
||||
declareIterator(myStdLib.getByteArrayClass());
|
||||
declareIterator(myStdLib.getShortArrayClass());
|
||||
declareIterator(myStdLib.getIntArrayClass());
|
||||
declareIterator(myStdLib.getLongArrayClass());
|
||||
declareIterator(myStdLib.getFloatArrayClass());
|
||||
declareIterator(myStdLib.getDoubleArrayClass());
|
||||
declareIterator(myStdLib.getCharArrayClass());
|
||||
declareIterator(myStdLib.getBooleanArrayClass());
|
||||
}
|
||||
|
||||
private void declareIterator(ClassDescriptor classDescriptor) {
|
||||
declareOverload(classDescriptor.getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR);
|
||||
}
|
||||
|
||||
private void declareIntrinsicStringMethods() {
|
||||
|
||||
@@ -16,21 +16,15 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public class RangeTo implements IntrinsicMethod {
|
||||
private static final String INT_RANGE_CONSTRUCTOR_DESCRIPTOR = "(II)V";
|
||||
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
|
||||
private static final String CLASS_INT_RANGE = "jet/IntRange";
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
||||
final Type leftType = codegen.expressionType(expression.getLeft());
|
||||
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
||||
v.anew(INT_RANGE_TYPE);
|
||||
v.dup();
|
||||
codegen.gen(expression.getLeft(), Type.INT_TYPE);
|
||||
codegen.gen(expression.getRight(), Type.INT_TYPE);
|
||||
v.invokespecial(CLASS_INT_RANGE, "<init>", INT_RANGE_CONSTRUCTOR_DESCRIPTOR);
|
||||
return StackValue.onStack(INT_RANGE_TYPE);
|
||||
v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("ranges are only supported for int objects");
|
||||
|
||||
@@ -42,7 +42,7 @@ fun Any?.toString() : String// = this === other
|
||||
|
||||
trait Iterator<out T> {
|
||||
fun next() : T
|
||||
abstract fun hasNext() : Boolean
|
||||
fun hasNext() : Boolean
|
||||
}
|
||||
|
||||
trait Iterable<out T> {
|
||||
@@ -54,6 +54,8 @@ class Array<T>(val size : Int, init : fun(Int) : T = null ) {
|
||||
fun set(index : Int, value : T) : Unit
|
||||
|
||||
fun iterator() : Iterator<T>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class ByteArray(val size : Int) {
|
||||
@@ -61,6 +63,8 @@ class ByteArray(val size : Int) {
|
||||
fun set(index : Int, value : Byte) : Unit
|
||||
|
||||
fun iterator() : Iterator<Byte>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class ShortArray(val size : Int) {
|
||||
@@ -68,6 +72,8 @@ class ShortArray(val size : Int) {
|
||||
fun set(index : Int, value : Short) : Unit
|
||||
|
||||
fun iterator() : Iterator<Short>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class IntArray(val size : Int) {
|
||||
@@ -75,6 +81,8 @@ class IntArray(val size : Int) {
|
||||
fun set(index : Int, value : Int) : Unit
|
||||
|
||||
fun iterator() : Iterator<Int>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class LongArray(val size : Int) {
|
||||
@@ -82,6 +90,8 @@ class LongArray(val size : Int) {
|
||||
fun set(index : Int, value : Long) : Unit
|
||||
|
||||
fun iterator() : Iterator<Long>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class FloatArray(val size : Int) {
|
||||
@@ -89,6 +99,8 @@ class FloatArray(val size : Int) {
|
||||
fun set(index : Int, value : Float) : Unit
|
||||
|
||||
fun iterator() : Iterator<Float>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class DoubleArray(val size : Int) {
|
||||
@@ -96,6 +108,8 @@ class DoubleArray(val size : Int) {
|
||||
fun set(index : Int, value : Double) : Unit
|
||||
|
||||
fun iterator() : Iterator<Double>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class CharArray(val size : Int) {
|
||||
@@ -103,6 +117,8 @@ class CharArray(val size : Int) {
|
||||
fun set(index : Int, value : Char) : Unit
|
||||
|
||||
fun iterator() : Iterator<Char>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
class BooleanArray(val size : Int) {
|
||||
@@ -110,6 +126,8 @@ class BooleanArray(val size : Int) {
|
||||
fun set(index : Int, value : Boolean) : Unit
|
||||
|
||||
fun iterator() : Iterator<Boolean>
|
||||
|
||||
val indices : IntRange
|
||||
}
|
||||
|
||||
trait Comparable<in T> {
|
||||
@@ -152,8 +170,28 @@ trait Range<in T : Comparable<T>> {
|
||||
fun contains(item : T) : Boolean
|
||||
}
|
||||
|
||||
class IntRange<T : Comparable<T>>(val start : Int, val end : Int) : Range<T>, Iterable<T> {
|
||||
class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range<Int>, Iterable<Int> {
|
||||
fun iterator () : Iterator<Int>
|
||||
|
||||
fun contains (elem: Int) : Boolean
|
||||
|
||||
val size : Int
|
||||
|
||||
val end : Int
|
||||
|
||||
val reversed : Boolean
|
||||
}
|
||||
|
||||
class LongRange(val start : Long, size : Long, reversed : Boolean = false) : Range<Long>, Iterable<Long> {
|
||||
fun iterator () : Iterator<Long>
|
||||
|
||||
fun contains (elem: Long) : Boolean
|
||||
|
||||
val size : Long
|
||||
|
||||
val end : Long
|
||||
|
||||
val reversed : Boolean
|
||||
}
|
||||
|
||||
abstract class Number : Hashable {
|
||||
@@ -349,11 +387,11 @@ class Long : Number, Comparable<Long> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Double>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Long>
|
||||
fun rangeTo(other : Short) : IntRange<Long>
|
||||
fun rangeTo(other : Byte) : IntRange<Long>
|
||||
fun rangeTo(other : Char) : IntRange<Long>
|
||||
fun rangeTo(other : Long) : LongRange
|
||||
fun rangeTo(other : Int) : LongRange
|
||||
fun rangeTo(other : Short) : LongRange
|
||||
fun rangeTo(other : Byte) : LongRange
|
||||
fun rangeTo(other : Char) : LongRange
|
||||
|
||||
fun inc() : Long
|
||||
fun dec() : Long
|
||||
@@ -420,11 +458,11 @@ class Int : Number, Comparable<Int> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Double>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Int>
|
||||
fun rangeTo(other : Byte) : IntRange<Int>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
fun rangeTo(other : Long) : LongRange
|
||||
fun rangeTo(other : Int) : IntRange
|
||||
fun rangeTo(other : Short) : IntRange
|
||||
fun rangeTo(other : Byte) : IntRange
|
||||
fun rangeTo(other : Char) : IntRange
|
||||
|
||||
fun inc() : Int
|
||||
fun dec() : Int
|
||||
@@ -491,11 +529,11 @@ class Char : Number, Comparable<Char> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Byte>
|
||||
fun rangeTo(other : Char) : IntRange<Char>
|
||||
fun rangeTo(other : Long) : LongRange
|
||||
fun rangeTo(other : Int) : IntRange
|
||||
fun rangeTo(other : Short) : IntRange
|
||||
fun rangeTo(other : Byte) : IntRange
|
||||
fun rangeTo(other : Char) : IntRange
|
||||
|
||||
fun inc() : Char
|
||||
fun dec() : Char
|
||||
@@ -554,11 +592,11 @@ class Short : Number, Comparable<Short> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Short>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
fun rangeTo(other : Long) : LongRange
|
||||
fun rangeTo(other : Int) : IntRange
|
||||
fun rangeTo(other : Short) : IntRange
|
||||
fun rangeTo(other : Byte) : IntRange
|
||||
fun rangeTo(other : Char) : IntRange
|
||||
|
||||
fun inc() : Short
|
||||
fun dec() : Short
|
||||
@@ -617,11 +655,11 @@ class Byte : Number, Comparable<Byte> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Byte>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
fun rangeTo(other : Long) : LongRange
|
||||
fun rangeTo(other : Int) : IntRange
|
||||
fun rangeTo(other : Short) : IntRange
|
||||
fun rangeTo(other : Byte) : IntRange
|
||||
fun rangeTo(other : Char) : IntRange
|
||||
|
||||
fun inc() : Byte
|
||||
fun dec() : Byte
|
||||
|
||||
@@ -44,8 +44,8 @@ public class JetSemanticServices {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider) {
|
||||
return new JetTypeInferrer(flowInformationProvider, this).getServices(trace);
|
||||
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace) {
|
||||
return new JetTypeInferrer(this).getServices(trace);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -25,6 +25,7 @@ public interface JetControlFlowBuilder {
|
||||
void jumpOnTrue(@NotNull Label label);
|
||||
void nondeterministicJump(Label label); // Maybe, jump to label
|
||||
void jumpToError(JetThrowExpression expression);
|
||||
void jumpToError(JetExpression nothingExpression);
|
||||
|
||||
// Entry/exit points
|
||||
Label getEntryPoint(@NotNull JetElement labelElement);
|
||||
|
||||
@@ -62,6 +62,11 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
builder.jumpToError(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpToError(JetExpression nothingExpression) {
|
||||
builder.jumpToError(nothingExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Label getEntryPoint(@NotNull JetElement labelElement) {
|
||||
return builder.getEntryPoint(labelElement);
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -18,7 +22,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
*/
|
||||
public class JetControlFlowProcessor {
|
||||
|
||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
// private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
|
||||
private final JetControlFlowBuilder builder;
|
||||
private final BindingTrace trace;
|
||||
@@ -33,10 +37,10 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
|
||||
if (subroutineElement instanceof JetNamedDeclaration) {
|
||||
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
|
||||
enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
|
||||
}
|
||||
// if (subroutineElement instanceof JetNamedDeclaration) {
|
||||
// JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
|
||||
// enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
|
||||
// }
|
||||
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
|
||||
builder.enterSubroutine(subroutineElement, functionLiteral);
|
||||
for (JetElement statement : body) {
|
||||
@@ -45,57 +49,55 @@ public class JetControlFlowProcessor {
|
||||
builder.exitSubroutine(subroutineElement, functionLiteral);
|
||||
}
|
||||
|
||||
private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null) {
|
||||
stack = new Stack<JetElement>();
|
||||
labeledElements.put(labelName, stack);
|
||||
}
|
||||
stack.push(labeledElement);
|
||||
}
|
||||
// private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
|
||||
// Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
// if (stack == null) {
|
||||
// stack = new Stack<JetElement>();
|
||||
// labeledElements.put(labelName, stack);
|
||||
// }
|
||||
// stack.push(labeledElement);
|
||||
// }
|
||||
//
|
||||
// private void exitElement(JetElement element) {
|
||||
// // TODO : really suboptimal
|
||||
// for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||
// Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
||||
// Stack<JetElement> stack = entry.getValue();
|
||||
// for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
||||
// JetElement recorded = stackIter.next();
|
||||
// if (recorded == element) {
|
||||
// stackIter.remove();
|
||||
// }
|
||||
// }
|
||||
// if (stack.isEmpty()) {
|
||||
// mapIter.remove();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private void exitElement(JetElement element) {
|
||||
// TODO : really suboptimal
|
||||
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
||||
Stack<JetElement> stack = entry.getValue();
|
||||
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
||||
JetElement recorded = stackIter.next();
|
||||
if (recorded == element) {
|
||||
stackIter.remove();
|
||||
}
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
mapIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (stack.size() > 1) {
|
||||
// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||
trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = stack.peek();
|
||||
trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
return result;
|
||||
}
|
||||
// @Nullable
|
||||
// private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
|
||||
// Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
// if (stack == null || stack.isEmpty()) {
|
||||
// if (reportUnresolved) {
|
||||
//// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// else if (stack.size() > 1) {
|
||||
//// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||
//// trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
// }
|
||||
//
|
||||
// JetElement result = stack.peek();
|
||||
//// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
private class CFPVisitor extends JetVisitorVoid {
|
||||
// private final boolean preferBlock;
|
||||
private final boolean inCondition;
|
||||
|
||||
private CFPVisitor(boolean inCondition) {
|
||||
// this.preferBlock = preferBlock;
|
||||
this.inCondition = inCondition;
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ public class JetControlFlowProcessor {
|
||||
visitor = new CFPVisitor(inCondition);
|
||||
}
|
||||
element.accept(visitor);
|
||||
exitElement(element);
|
||||
// exitElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,12 +124,12 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitThisExpression(JetThisExpression expression) {
|
||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
if (targetLabel != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
resolveLabel(labelName, targetLabel, false);
|
||||
}
|
||||
// JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
// if (targetLabel != null) {
|
||||
// String labelName = expression.getLabelName();
|
||||
// assert labelName != null;
|
||||
// resolveLabel(labelName, targetLabel, false);
|
||||
// }
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@@ -139,6 +141,12 @@ public class JetControlFlowProcessor {
|
||||
@Override
|
||||
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
|
||||
builder.read(expression);
|
||||
if (trace.get(BindingContext.PROCESSED, expression)) {
|
||||
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
builder.jumpToError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,7 +161,7 @@ public class JetControlFlowProcessor {
|
||||
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
||||
if (deparenthesized != null) {
|
||||
enterLabeledElement(labelName, deparenthesized);
|
||||
// enterLabeledElement(labelName, deparenthesized);
|
||||
value(labeledExpression, inCondition);
|
||||
}
|
||||
}
|
||||
@@ -437,12 +445,20 @@ public class JetControlFlowProcessor {
|
||||
if (labelName != null) {
|
||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
assert targetLabel != null;
|
||||
loop = resolveLabel(labelName, targetLabel, true);
|
||||
if (!isLoop(loop)) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
||||
PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), targetLabel);
|
||||
if (labeledElement instanceof JetLoopExpression) {
|
||||
loop = (JetLoopExpression) labeledElement;
|
||||
}
|
||||
else {
|
||||
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
||||
loop = null;
|
||||
}
|
||||
// loop = resolveLabel(labelName, targetLabel, true);
|
||||
// if (!isLoop(loop)) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
||||
// trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
||||
// loop = null;
|
||||
// }
|
||||
}
|
||||
else {
|
||||
loop = builder.getCurrentLoop();
|
||||
@@ -454,11 +470,11 @@ public class JetControlFlowProcessor {
|
||||
return loop;
|
||||
}
|
||||
|
||||
private boolean isLoop(JetElement loop) {
|
||||
return loop instanceof JetWhileExpression ||
|
||||
loop instanceof JetDoWhileExpression ||
|
||||
loop instanceof JetForExpression;
|
||||
}
|
||||
// private boolean isLoop(JetElement loop) {
|
||||
// return loop instanceof JetWhileExpression ||
|
||||
// loop instanceof JetDoWhileExpression ||
|
||||
// loop instanceof JetForExpression;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
@@ -471,13 +487,21 @@ public class JetControlFlowProcessor {
|
||||
if (labelElement != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
subroutine = resolveLabel(labelName, labelElement, true);
|
||||
PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), labelElement);
|
||||
if (labeledElement != null) {
|
||||
assert labeledElement instanceof JetElement;
|
||||
subroutine = (JetElement) labeledElement;
|
||||
}
|
||||
else {
|
||||
subroutine = null;
|
||||
}
|
||||
//subroutine = resolveLabel(labelName, labelElement, true);
|
||||
}
|
||||
else {
|
||||
subroutine = builder.getCurrentSubroutine();
|
||||
// TODO : a context check
|
||||
}
|
||||
if (subroutine != null) {
|
||||
if (subroutine instanceof JetFunction || subroutine instanceof JetFunctionLiteralExpression) {
|
||||
if (returnedExpression == null) {
|
||||
builder.returnNoValue(expression, subroutine);
|
||||
}
|
||||
@@ -485,6 +509,11 @@ public class JetControlFlowProcessor {
|
||||
builder.returnValue(expression, subroutine);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (labelElement != null) {
|
||||
trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -524,6 +553,12 @@ public class JetControlFlowProcessor {
|
||||
value(selectorExpression, false);
|
||||
}
|
||||
builder.read(expression);
|
||||
if (trace.get(BindingContext.PROCESSED, expression)) {
|
||||
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
builder.jumpToError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visitCall(JetCallElement call) {
|
||||
@@ -549,6 +584,12 @@ public class JetControlFlowProcessor {
|
||||
|
||||
value(expression.getCalleeExpression(), false);
|
||||
builder.read(expression);
|
||||
if (trace.get(BindingContext.PROCESSED, expression)) {
|
||||
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
builder.jumpToError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
@@ -11,61 +11,61 @@ import java.util.Collection;
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface JetFlowInformationProvider {
|
||||
JetFlowInformationProvider THROW_EXCEPTION = new JetFlowInformationProvider() {
|
||||
@Override
|
||||
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakable(JetLoopExpression loop) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
|
||||
@Override
|
||||
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakable(JetLoopExpression loop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
// JetFlowInformationProvider THROW_EXCEPTION = new JetFlowInformationProvider() {
|
||||
// @Override
|
||||
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isBreakable(JetLoopExpression loop) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
//
|
||||
// };
|
||||
//
|
||||
// JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
|
||||
// @Override
|
||||
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isBreakable(JetLoopExpression loop) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// };
|
||||
|
||||
/**
|
||||
* Collects expressions returned from the given subroutine and 'return;' expressions
|
||||
|
||||
+5
@@ -250,6 +250,11 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
public void jumpToError(JetThrowExpression expression) {
|
||||
add(new UnconditionalJumpInstruction(error));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpToError(JetExpression nothingExpression) {
|
||||
add(new UnconditionalJumpInstruction(error));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterTryFinally(@NotNull GenerationTrigger generationTrigger) {
|
||||
|
||||
@@ -143,7 +143,6 @@ public interface Errors {
|
||||
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT);
|
||||
|
||||
SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code");
|
||||
ParameterizedDiagnosticFactory1<String> UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because ''{0}'' never terminates normally");
|
||||
|
||||
SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class");
|
||||
SimpleDiagnosticFactory CLASS_OBJECT_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "A class object is not allowed here");
|
||||
@@ -191,6 +190,7 @@ public interface Errors {
|
||||
SimpleDiagnosticFactory RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = SimpleDiagnosticFactory.create(ERROR, "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
SimpleDiagnosticFactory NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = SimpleDiagnosticFactory.create(ERROR, "A 'return' expression required in a function with a block body ('{...}')");
|
||||
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> 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");
|
||||
@@ -221,6 +221,7 @@ public interface Errors {
|
||||
SimpleDiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = SimpleDiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter");
|
||||
SimpleDiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = SimpleDiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop");
|
||||
ParameterizedDiagnosticFactory1<String> NOT_A_LOOP_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label ''{0}'' does not denote a loop");
|
||||
ParameterizedDiagnosticFactory1<String> NOT_A_RETURN_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label ''{0}'' does not reference to a context from which we can return");
|
||||
|
||||
SimpleDiagnosticFactory ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Anonymous initializers are only allowed in the presence of a primary constructor");
|
||||
SimpleDiagnosticFactory NULLABLE_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "A supertype cannot be nullable");
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.jetbrains.jet.JetNodeType;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetExpression extends JetElement {
|
||||
public abstract class JetExpression extends JetElement {
|
||||
public JetExpression(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,796 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class JetTreeVisitor<D> extends JetVisitor<Void, D> {
|
||||
@Override
|
||||
public Void visitNamespace(JetNamespace namespace, D data) {
|
||||
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
|
||||
for (JetImportDirective directive : importDirectives) {
|
||||
directive.visit(this, data);
|
||||
}
|
||||
List<JetDeclaration> declarations = namespace.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitClass(JetClass klass, D data) {
|
||||
List<JetDeclaration> declarations = klass.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitClassObject(JetClassObject classObject, D data) {
|
||||
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
|
||||
if (objectDeclaration != null) {
|
||||
objectDeclaration.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitConstructor(JetConstructor constructor, D data) {
|
||||
visitDeclarationWithBody(constructor, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNamedFunction(JetNamedFunction function, D data) {
|
||||
visitDeclarationWithBody(function, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProperty(JetProperty property, D data) {
|
||||
List<JetPropertyAccessor> accessors = property.getAccessors();
|
||||
for (JetPropertyAccessor accessor : accessors) {
|
||||
accessor.visit(this, data);
|
||||
}
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer != null) {
|
||||
initializer.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypedef(JetTypedef typedef, D data) {
|
||||
return super.visitTypedef(typedef, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitJetFile(JetFile file, D data) {
|
||||
JetNamespace rootNamespace = file.getRootNamespace();
|
||||
return rootNamespace.visit(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitImportDirective(JetImportDirective importDirective, D data) {
|
||||
return super.visitImportDirective(importDirective, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitClassBody(JetClassBody classBody, D data) {
|
||||
List<JetDeclaration> declarations = classBody.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.visit(this, data);
|
||||
}
|
||||
List<JetConstructor> secondaryConstructors = classBody.getSecondaryConstructors();
|
||||
for (JetConstructor constructor : secondaryConstructors) {
|
||||
constructor.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNamespaceBody(JetNamespaceBody body, D data) {
|
||||
List<JetDeclaration> declarations = body.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitModifierList(JetModifierList list, D data) {
|
||||
return super.visitModifierList(list, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAnnotation(JetAnnotation annotation, D data) {
|
||||
return super.visitAnnotation(annotation, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAnnotationEntry(JetAnnotationEntry annotationEntry, D data) {
|
||||
return super.visitAnnotationEntry(annotationEntry, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeParameterList(JetTypeParameterList list, D data) {
|
||||
List<JetTypeParameter> parameters = list.getParameters();
|
||||
for (JetTypeParameter parameter : parameters) {
|
||||
parameter.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeParameter(JetTypeParameter parameter, D data) {
|
||||
return super.visitTypeParameter(parameter, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitEnumEntry(JetEnumEntry enumEntry, D data) {
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers();
|
||||
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
|
||||
delegationSpecifier.visit(this, data);
|
||||
}
|
||||
JetModifierList modifierList = enumEntry.getModifierList();
|
||||
if (modifierList != null) {
|
||||
modifierList.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitParameterList(JetParameterList list, D data) {
|
||||
List<JetParameter> parameters = list.getParameters();
|
||||
for (JetParameter parameter : parameters) {
|
||||
parameter.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitParameter(JetParameter parameter, D data) {
|
||||
return super.visitParameter(parameter, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationSpecifierList(JetDelegationSpecifierList list, D data) {
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = list.getDelegationSpecifiers();
|
||||
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
|
||||
delegationSpecifier.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationSpecifier(JetDelegationSpecifier specifier, D data) {
|
||||
return super.visitDelegationSpecifier(specifier, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier, D data) {
|
||||
return super.visitDelegationByExpressionSpecifier(specifier, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call, D data) {
|
||||
return super.visitDelegationToSuperCallSpecifier(call, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier, D data) {
|
||||
return super.visitDelegationToSuperClassSpecifier(specifier, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDelegationToThisCall(JetDelegatorToThisCall thisCall, D data) {
|
||||
return super.visitDelegationToThisCall(thisCall, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeReference(JetTypeReference typeReference, D data) {
|
||||
return super.visitTypeReference(typeReference, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitValueArgumentList(JetValueArgumentList list, D data) {
|
||||
List<JetValueArgument> arguments = list.getArguments();
|
||||
for (JetValueArgument argument : arguments) {
|
||||
argument.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitArgument(JetValueArgument argument, D data) {
|
||||
return super.visitArgument(argument, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLoopExpression(JetLoopExpression loopExpression, D data) {
|
||||
JetExpression body = loopExpression.getBody();
|
||||
if (body != null) {
|
||||
body.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitConstantExpression(JetConstantExpression expression, D data) {
|
||||
return super.visitConstantExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSimpleNameExpression(JetSimpleNameExpression expression, D data) {
|
||||
return super.visitSimpleNameExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReferenceExpression(JetReferenceExpression expression, D data) {
|
||||
return super.visitReferenceExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTupleExpression(JetTupleExpression expression, D data) {
|
||||
return super.visitTupleExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPrefixExpression(JetPrefixExpression expression, D data) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
if (baseExpression != null) {
|
||||
baseExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPostfixExpression(JetPostfixExpression expression, D data) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
baseExpression.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUnaryExpression(JetUnaryExpression expression, D data) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
assert baseExpression != null;
|
||||
baseExpression.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBinaryExpression(JetBinaryExpression expression, D data) {
|
||||
JetExpression left = expression.getLeft();
|
||||
left.visit(this, data);
|
||||
JetExpression right = expression.getRight();
|
||||
if (right != null) {
|
||||
right.visit(this, data);
|
||||
}
|
||||
return super.visitBinaryExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReturnExpression(JetReturnExpression expression, D data) {
|
||||
JetExpression returnedExpression = expression.getReturnedExpression();
|
||||
if (returnedExpression != null) {
|
||||
returnedExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLabelQualifiedExpression(JetLabelQualifiedExpression expression, D data) {
|
||||
JetExpression labeledExpression = expression.getLabeledExpression();
|
||||
if (labeledExpression != null) {
|
||||
labeledExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitThrowExpression(JetThrowExpression expression, D data) {
|
||||
JetExpression thrownExpression = expression.getThrownExpression();
|
||||
if (thrownExpression != null) {
|
||||
thrownExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBreakExpression(JetBreakExpression expression, D data) {
|
||||
return super.visitBreakExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitContinueExpression(JetContinueExpression expression, D data) {
|
||||
return super.visitContinueExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIfExpression(JetIfExpression expression, D data) {
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
condition.visit(this, data);
|
||||
}
|
||||
JetExpression then = expression.getThen();
|
||||
if (then != null) {
|
||||
then.visit(this, data);
|
||||
}
|
||||
JetExpression anElse = expression.getElse();
|
||||
if (anElse != null) {
|
||||
anElse.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhenExpression(JetWhenExpression expression, D data) {
|
||||
List<JetWhenEntry> entries = expression.getEntries();
|
||||
for (JetWhenEntry entry : entries) {
|
||||
entry.visit(this, data);
|
||||
}
|
||||
JetExpression subjectExpression = expression.getSubjectExpression();
|
||||
if (subjectExpression != null) {
|
||||
subjectExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTryExpression(JetTryExpression expression, D data) {
|
||||
JetBlockExpression tryBlock = expression.getTryBlock();
|
||||
tryBlock.visit(this, data);
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
for (JetCatchClause catchClause : catchClauses) {
|
||||
catchClause.visit(this, data);
|
||||
}
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
if (finallyBlock != null) {
|
||||
finallyBlock.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitForExpression(JetForExpression expression, D data) {
|
||||
JetParameter loopParameter = expression.getLoopParameter();
|
||||
if (loopParameter != null) {
|
||||
loopParameter.visit(this, data);
|
||||
}
|
||||
JetExpression loopRange = expression.getLoopRange();
|
||||
if (loopRange != null) {
|
||||
loopRange.visit(this, data);
|
||||
}
|
||||
visitLoopExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhileExpression(JetWhileExpression expression, D data) {
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
condition.visit(this, data);
|
||||
}
|
||||
visitLoopExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDoWhileExpression(JetDoWhileExpression expression, D data) {
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
condition.visit(this, data);
|
||||
}
|
||||
visitLoopExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, D data) {
|
||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
functionLiteral.visit(this, data);
|
||||
visitDeclarationWithBody(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAnnotatedExpression(JetAnnotatedExpression expression, D data) {
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
baseExpression.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCallExpression(JetCallExpression expression, D data) {
|
||||
JetExpression calleeExpression = expression.getCalleeExpression();
|
||||
if (calleeExpression != null) {
|
||||
calleeExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitArrayAccessExpression(JetArrayAccessExpression expression, D data) {
|
||||
JetExpression arrayExpression = expression.getArrayExpression();
|
||||
arrayExpression.visit(this, data);
|
||||
List<JetExpression> indexExpressions = expression.getIndexExpressions();
|
||||
for (JetExpression indexExpression : indexExpressions) {
|
||||
indexExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitQualifiedExpression(JetQualifiedExpression expression, D data) {
|
||||
JetExpression receiver = expression.getReceiverExpression();
|
||||
receiver.visit(this, data);
|
||||
JetExpression selector = expression.getSelectorExpression();
|
||||
if (selector != null) {
|
||||
selector.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitHashQualifiedExpression(JetHashQualifiedExpression expression, D data) {
|
||||
visitQualifiedExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDotQualifiedExpression(JetDotQualifiedExpression expression, D data) {
|
||||
visitQualifiedExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPredicateExpression(JetPredicateExpression expression, D data) {
|
||||
visitQualifiedExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSafeQualifiedExpression(JetSafeQualifiedExpression expression, D data) {
|
||||
visitQualifiedExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitObjectLiteralExpression(JetObjectLiteralExpression expression, D data) {
|
||||
JetObjectDeclaration objectDeclaration = expression.getObjectDeclaration();
|
||||
objectDeclaration.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitRootNamespaceExpression(JetRootNamespaceExpression expression, D data) {
|
||||
return super.visitRootNamespaceExpression(expression, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBlockExpression(JetBlockExpression expression, D data) {
|
||||
List<JetElement> statements = expression.getStatements();
|
||||
for (JetElement statement : statements) {
|
||||
statement.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCatchSection(JetCatchClause catchClause, D data) {
|
||||
JetParameter catchParameter = catchClause.getCatchParameter();
|
||||
if (catchParameter != null) {
|
||||
catchParameter.visit(this, data);
|
||||
}
|
||||
JetExpression catchBody = catchClause.getCatchBody();
|
||||
if (catchBody != null) {
|
||||
catchBody.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFinallySection(JetFinallySection finallySection, D data) {
|
||||
JetBlockExpression finalExpression = finallySection.getFinalExpression();
|
||||
finalExpression.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeArgumentList(JetTypeArgumentList typeArgumentList, D data) {
|
||||
List<JetTypeProjection> arguments = typeArgumentList.getArguments();
|
||||
for (JetTypeProjection argument : arguments) {
|
||||
argument.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitThisExpression(JetThisExpression expression, D data) {
|
||||
JetReferenceExpression thisReference = expression.getThisReference();
|
||||
thisReference.visit(this, data);
|
||||
JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
|
||||
if (superTypeQualifier != null) {
|
||||
superTypeQualifier.visit(this, data);
|
||||
}
|
||||
visitLabelQualifiedExpression(expression, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitParenthesizedExpression(JetParenthesizedExpression expression, D data) {
|
||||
JetExpression innerExpression = expression.getExpression();
|
||||
if (innerExpression != null) {
|
||||
innerExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInitializerList(JetInitializerList list, D data) {
|
||||
List<JetDelegationSpecifier> initializers = list.getInitializers();
|
||||
for (JetDelegationSpecifier initializer : initializers) {
|
||||
initializer.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAnonymousInitializer(JetClassInitializer initializer, D data) {
|
||||
JetExpression body = initializer.getBody();
|
||||
body.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPropertyAccessor(JetPropertyAccessor accessor, D data) {
|
||||
visitDeclarationWithBody(accessor, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeConstraintList(JetTypeConstraintList list, D data) {
|
||||
List<JetTypeConstraint> constraints = list.getConstraints();
|
||||
for (JetTypeConstraint constraint : constraints) {
|
||||
constraint.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeConstraint(JetTypeConstraint constraint, D data) {
|
||||
JetSimpleNameExpression subjectTypeParameterName = constraint.getSubjectTypeParameterName();
|
||||
if (subjectTypeParameterName != null) {
|
||||
subjectTypeParameterName.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUserType(JetUserType type, D data) {
|
||||
return super.visitUserType(type, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTupleType(JetTupleType type, D data) {
|
||||
return super.visitTupleType(type, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFunctionType(JetFunctionType type, D data) {
|
||||
return super.visitFunctionType(type, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSelfType(JetSelfType type, D data) {
|
||||
return super.visitSelfType(type, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, D data) {
|
||||
JetExpression left = expression.getLeft();
|
||||
left.visit(this, data);
|
||||
JetTypeReference right = expression.getRight();
|
||||
if (right != null) {
|
||||
right.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStringTemplateExpression(JetStringTemplateExpression expression, D data) {
|
||||
JetStringTemplateEntry[] entries = expression.getEntries();
|
||||
for (JetStringTemplateEntry entry : entries) {
|
||||
entry.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNamedDeclaration(JetNamedDeclaration declaration, D data) {
|
||||
return super.visitNamedDeclaration(declaration, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNullableType(JetNullableType nullableType, D data) {
|
||||
return super.visitNullableType(nullableType, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeProjection(JetTypeProjection typeProjection, D data) {
|
||||
return super.visitTypeProjection(typeProjection, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhenEntry(JetWhenEntry jetWhenEntry, D data) {
|
||||
JetExpression expression = jetWhenEntry.getExpression();
|
||||
if (expression != null) {
|
||||
expression.visit(this, data);
|
||||
}
|
||||
JetWhenCondition[] conditions = jetWhenEntry.getConditions();
|
||||
for (JetWhenCondition condition : conditions) {
|
||||
condition.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIsExpression(JetIsExpression expression, D data) {
|
||||
JetExpression leftHandSide = expression.getLeftHandSide();
|
||||
leftHandSide.visit(this, data);
|
||||
JetSimpleNameExpression operationReference = expression.getOperationReference();
|
||||
operationReference.visit(this, data);
|
||||
JetPattern pattern = expression.getPattern();
|
||||
if (pattern != null) {
|
||||
pattern.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhenConditionCall(JetWhenConditionCall condition, D data) {
|
||||
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
|
||||
if (callSuffixExpression != null) {
|
||||
callSuffixExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition, D data) {
|
||||
JetPattern pattern = condition.getPattern();
|
||||
if (pattern != null) {
|
||||
pattern.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhenConditionInRange(JetWhenConditionInRange condition, D data) {
|
||||
JetSimpleNameExpression operationReference = condition.getOperationReference();
|
||||
operationReference.visit(this, data);
|
||||
JetExpression rangeExpression = condition.getRangeExpression();
|
||||
if (rangeExpression != null) {
|
||||
rangeExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypePattern(JetTypePattern pattern, D data) {
|
||||
return super.visitTypePattern(pattern, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWildcardPattern(JetWildcardPattern pattern, D data) {
|
||||
return super.visitWildcardPattern(pattern, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitExpressionPattern(JetExpressionPattern pattern, D data) {
|
||||
JetExpression expression = pattern.getExpression();
|
||||
if (expression != null) {
|
||||
expression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTuplePattern(JetTuplePattern pattern, D data) {
|
||||
List<JetTuplePatternEntry> entries = pattern.getEntries();
|
||||
for (JetTuplePatternEntry entry : entries) {
|
||||
entry.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDecomposerPattern(JetDecomposerPattern pattern, D data) {
|
||||
JetTuplePattern argumentList = pattern.getArgumentList();
|
||||
argumentList.visit(this, data);
|
||||
JetExpression decomposerExpression = pattern.getDecomposerExpression();
|
||||
if (decomposerExpression != null) {
|
||||
decomposerExpression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitObjectDeclaration(JetObjectDeclaration objectDeclaration, D data) {
|
||||
List<JetDeclaration> declarations = objectDeclaration.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.visit(this, data);
|
||||
}
|
||||
JetDelegationSpecifierList delegationSpecifierList = objectDeclaration.getDelegationSpecifierList();
|
||||
if (delegationSpecifierList != null) {
|
||||
delegationSpecifierList.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBindingPattern(JetBindingPattern pattern, D data) {
|
||||
JetWhenCondition condition = pattern.getCondition();
|
||||
if (condition != null) {
|
||||
condition.visit(this, data);
|
||||
}
|
||||
JetProperty variableDeclaration = pattern.getVariableDeclaration();
|
||||
variableDeclaration.visit(this, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStringTemplateEntry(JetStringTemplateEntry entry, D data) {
|
||||
JetExpression expression = entry.getExpression();
|
||||
if (expression != null) {
|
||||
expression.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry, D data) {
|
||||
visitStringTemplateEntry(entry, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBlockStringTemplateEntry(JetBlockStringTemplateEntry entry, D data) {
|
||||
visitStringTemplateEntry(entry, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSimpleNameStringTemplateEntry(JetSimpleNameStringTemplateEntry entry, D data) {
|
||||
visitStringTemplateEntry(entry, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLiteralStringTemplateEntry(JetLiteralStringTemplateEntry entry, D data) {
|
||||
visitStringTemplateEntry(entry, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry, D data) {
|
||||
visitStringTemplateEntry(entry, data);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Void visitDeclarationWithBody(JetDeclarationWithBody declaration, D data) {
|
||||
JetExpression bodyExpression = declaration.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
bodyExpression.visit(this, data);
|
||||
}
|
||||
List<JetParameter> valueParameters = declaration.getValueParameters();
|
||||
for (JetParameter valueParameter : valueParameters) {
|
||||
valueParameter.visit(this, data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class AnnotationResolver {
|
||||
this.trace = trace;
|
||||
// this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
|
||||
// this.services = typeInferrer.getServices(this.trace);
|
||||
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices), DataFlowInfo.getEmpty());
|
||||
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(semanticServices), DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -125,7 +125,7 @@ public class BodyResolver {
|
||||
final JetScope scopeForConstructor = primaryConstructor == null
|
||||
? null
|
||||
: getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true);
|
||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
|
||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors); // TODO : flow
|
||||
|
||||
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@@ -292,7 +292,7 @@ public class BodyResolver {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert primaryConstructor != null;
|
||||
final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(createFieldAssignTrackingTrace(), JetFlowInformationProvider.NONE); // TODO : flow
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(createFieldAssignTrackingTrace()); // TODO : flow
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), NO_EXPECTED_TYPE);
|
||||
}
|
||||
@@ -318,7 +318,7 @@ public class BodyResolver {
|
||||
private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final JetScope declaringScope) {
|
||||
final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope, false);
|
||||
|
||||
final JetTypeInferrer.Services typeInferrerForInitializers = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE);
|
||||
final JetTypeInferrer.Services typeInferrerForInitializers = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class);
|
||||
assert containingClass != null : "This must be guaranteed by the parser";
|
||||
@@ -380,11 +380,11 @@ public class BodyResolver {
|
||||
}
|
||||
JetExpression bodyExpression = declaration.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, flowInformationProvider);
|
||||
//context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, JetStandardClasses.getUnitType());
|
||||
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, descriptor, JetStandardClasses.getUnitType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,8 +519,8 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) {
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, flowInformationProvider);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, NO_EXPECTED_TYPE);
|
||||
|
||||
JetType expectedType = propertyDescriptor.getInType();
|
||||
@@ -555,13 +555,13 @@ public class BodyResolver {
|
||||
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(function.asElement(), bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace, flowInformationProvider);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(function.asElement(), bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor);
|
||||
}
|
||||
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace, JetFlowInformationProvider.THROW_EXCEPTION);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
List<JetParameter> valueParameters = function.getValueParameters();
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = functionDescriptor.getValueParameters().get(i);
|
||||
|
||||
@@ -178,8 +178,8 @@ public class ClassDescriptorResolver {
|
||||
returnType = DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||
@Override
|
||||
protected JetType compute() {
|
||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
||||
return semanticServices.getTypeInferrerServices(trace, flowInformationProvider).inferFunctionReturnType(scope, function, functionDescriptor);
|
||||
//JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
||||
return semanticServices.getTypeInferrerServices(trace).inferFunctionReturnType(scope, function, functionDescriptor);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -540,8 +540,8 @@ public class ClassDescriptorResolver {
|
||||
LazyValue<JetType> lazyValue = new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||
@Override
|
||||
protected JetType compute() {
|
||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||
return semanticServices.getTypeInferrerServices(trace, flowInformationProvider).safeGetType(scope, initializer, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
//JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
}
|
||||
};
|
||||
if (allowDeferred) {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class ControlFlowAnalyzer {
|
||||
private TopDownAnalysisContext context;
|
||||
private JetTypeInferrer.Services typeInferrer;
|
||||
|
||||
public ControlFlowAnalyzer(TopDownAnalysisContext context) {
|
||||
this.context = context;
|
||||
typeInferrer = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||
}
|
||||
|
||||
public void process() {
|
||||
for (Map.Entry<JetNamedFunction, FunctionDescriptorImpl> entry : context.getFunctions().entrySet()) {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
||||
|
||||
final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() ? NO_EXPECTED_TYPE : functionDescriptor.getReturnType();
|
||||
checkFunction(function, functionDescriptor, expectedReturnType);
|
||||
}
|
||||
|
||||
for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : this.context.getConstructors().entrySet()) {
|
||||
JetDeclaration declaration = entry.getKey();
|
||||
assert declaration instanceof JetConstructor;
|
||||
JetConstructor constructor = (JetConstructor) declaration;
|
||||
ConstructorDescriptor descriptor = entry.getValue();
|
||||
|
||||
checkFunction(constructor, descriptor, JetStandardClasses.getUnitType());
|
||||
}
|
||||
|
||||
for (JetProperty property : context.getProperties().keySet()) {
|
||||
checkProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, final @NotNull JetType expectedReturnType) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression == null) return;
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData((JetElement) function, bodyExpression);
|
||||
|
||||
final boolean blockBody = function.hasBlockBody();
|
||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
context.getTrace().report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
|
||||
List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
|
||||
boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
|
||||
returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
|
||||
final JetScope scope = this.context.getDeclaringScopes().get(function);
|
||||
|
||||
if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
context.getTrace().report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
}
|
||||
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
returnedExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
if (!blockBody) {
|
||||
context.getTrace().report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
if (blockBody && expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
JetType type = typeInferrer.getType(scope, expression, expectedReturnType);
|
||||
if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
context.getTrace().report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void checkProperty(JetProperty property) {
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer == null) return;
|
||||
context.getClassDescriptorResolver().computeFlowData(property, initializer);
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ public class TopDownAnalyzer {
|
||||
new OverrideResolver(context).process();
|
||||
new BodyResolver(context).resolveBehaviorDeclarationBodies();
|
||||
new DeclarationsChecker(context).process();
|
||||
new ControlFlowAnalyzer(context).process();
|
||||
}
|
||||
|
||||
public static void processStandardLibraryNamespace(
|
||||
|
||||
@@ -218,7 +218,7 @@ public class TypeHierarchyResolver {
|
||||
if (importDirective.isAllUnder()) {
|
||||
JetExpression importedReference = importDirective.getImportedReference();
|
||||
if (importedReference != null) {
|
||||
JetTypeInferrer.Services typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace(), JetFlowInformationProvider.THROW_EXCEPTION);
|
||||
JetTypeInferrer.Services typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
|
||||
if (type != null) {
|
||||
namespaceScope.importScope(type.getMemberScope());
|
||||
@@ -233,7 +233,7 @@ public class TypeHierarchyResolver {
|
||||
JetExpression importedReference = importDirective.getImportedReference();
|
||||
if (importedReference instanceof JetDotQualifiedExpression) {
|
||||
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
|
||||
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace(), JetFlowInformationProvider.THROW_EXCEPTION).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
|
||||
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
|
||||
JetExpression selectorExpression = reference.getSelectorExpression();
|
||||
if (selectorExpression != null) {
|
||||
referenceExpression = (JetSimpleNameExpression) selectorExpression;
|
||||
|
||||
@@ -312,8 +312,7 @@ public class JetStandardLibrary {
|
||||
|
||||
@NotNull
|
||||
public JetType getArrayType(@NotNull JetType argument) {
|
||||
Variance variance = Variance.INVARIANT;
|
||||
return getArrayType(variance, argument);
|
||||
return getArrayType(Variance.INVARIANT, argument);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
@@ -175,14 +174,16 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final JetFlowInformationProvider flowInformationProvider;
|
||||
// private final JetFlowInformationProvider flowInformationProvider;
|
||||
private final Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo = Maps.newHashMap();
|
||||
|
||||
private final Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists = Maps.newHashMap();
|
||||
|
||||
private final LabelsResolver labelsResolver = new LabelsResolver();
|
||||
|
||||
public JetTypeInferrer(@NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
|
||||
public JetTypeInferrer(@NotNull JetSemanticServices semanticServices) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.flowInformationProvider = flowInformationProvider;
|
||||
// this.flowInformationProvider = flowInformationProvider;
|
||||
}
|
||||
|
||||
public Services getServices(@NotNull BindingTrace trace) {
|
||||
@@ -269,7 +270,7 @@ public class JetTypeInferrer {
|
||||
expectedReturnType = NO_EXPECTED_TYPE;
|
||||
}
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
checkFunctionReturnType(functionInnerScope, function, expectedReturnType, dataFlowInfo);
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, dataFlowInfo);
|
||||
// Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType);
|
||||
// if (typeMap.isEmpty()) {
|
||||
// return; // The function returns Nothing
|
||||
@@ -303,11 +304,11 @@ public class JetTypeInferrer {
|
||||
// }
|
||||
}
|
||||
|
||||
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType) {
|
||||
checkFunctionReturnType(functionInnerScope, function, expectedReturnType, DataFlowInfo.getEmpty());
|
||||
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType) {
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
private void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
private void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression == null) return;
|
||||
|
||||
@@ -325,56 +326,62 @@ public class JetTypeInferrer {
|
||||
typeInferrerVisitor.getType(bodyExpression, context);
|
||||
}
|
||||
|
||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
// List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
// flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
// final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
|
||||
// TODO : (return 1) || (return 2) -- only || and right of it is unreachable
|
||||
// TODO : try {return 1} finally {return 2}. Currently 'return 1' is reported as unreachable,
|
||||
// though it'd better be reported more specifically
|
||||
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
// trace.getErrorHandler().genericError(element.getNode(), "Unreachable code");
|
||||
trace.report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
// for (JetElement element : rootUnreachableElements) {
|
||||
// //trace.report(UNREACHABLE_CODE.on(element));
|
||||
// }
|
||||
|
||||
List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
// List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
// flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
|
||||
boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
// boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
|
||||
returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
//returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
// Map<JetExpression, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, functionInnerScope, function, functionDescriptor);
|
||||
// Set<JetExpression> returnedExpressions = typeMap.keySet();
|
||||
//
|
||||
//
|
||||
// if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty()) {
|
||||
// trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
// }
|
||||
|
||||
if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
}
|
||||
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
returnedExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
if (!blockBody) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
trace.report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
if (blockBody && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
//TODO move to pseudocode
|
||||
JetType type = typeInferrerVisitor.getType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')");
|
||||
trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
//// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
// trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
// }
|
||||
//
|
||||
// for (JetExpression returnedExpression : returnedExpressions) {
|
||||
// returnedExpression.accept(new JetVisitorVoid() {
|
||||
// @Override
|
||||
// public void visitReturnExpression(JetReturnExpression expression) {
|
||||
// if (!blockBody) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
// trace.report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitExpression(JetExpression expression) {
|
||||
// if (blockBody && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
// //TODO move to pseudocode
|
||||
// JetType type = typeInferrerVisitor.getType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
// if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')");
|
||||
// trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -391,26 +398,52 @@ public class JetTypeInferrer {
|
||||
|
||||
@NotNull
|
||||
public JetType inferFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
|
||||
Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor);
|
||||
Map<JetExpression, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor);
|
||||
Collection<JetType> types = typeMap.values();
|
||||
return types.isEmpty()
|
||||
? JetStandardClasses.getNothingType()
|
||||
: semanticServices.getTypeChecker().commonSupertype(types);
|
||||
}
|
||||
|
||||
private Map<JetElement, JetType> collectReturnedExpressionsWithTypes(
|
||||
@NotNull BindingTrace trace,
|
||||
private Map<JetExpression, JetType> collectReturnedExpressionsWithTypes(
|
||||
final @NotNull BindingTrace trace,
|
||||
JetScope outerScope,
|
||||
JetDeclarationWithBody function,
|
||||
final JetDeclarationWithBody function,
|
||||
FunctionDescriptor functionDescriptor) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
assert bodyExpression != null;
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
typeInferrerVisitor.getType(bodyExpression, newContext(trace, functionInnerScope, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, FORBIDDEN));
|
||||
Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
|
||||
Collection<JetElement> elementsReturningUnit = new ArrayList<JetElement>();
|
||||
flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit);
|
||||
Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>();
|
||||
//todo function literals
|
||||
final Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
|
||||
if (function.hasBlockBody()) {
|
||||
//now this code is never invoked!, it should be invoked for inference of return type of function literal with local returns
|
||||
bodyExpression.visit(new JetTreeVisitor<JetDeclarationWithBody>() {
|
||||
@Override
|
||||
public Void visitReturnExpression(JetReturnExpression expression, JetDeclarationWithBody outerFunction) {
|
||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
PsiElement element = targetLabel != null ? trace.get(LABEL_TARGET, targetLabel) : null;
|
||||
if (element == function || (targetLabel == null && outerFunction == function)) {
|
||||
returnedExpressions.add(expression);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, JetDeclarationWithBody outerFunction) {
|
||||
return super.visitFunctionLiteralExpression(expression, expression.getFunctionLiteral());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNamedFunction(JetNamedFunction function, JetDeclarationWithBody outerFunction) {
|
||||
return super.visitNamedFunction(function, function);
|
||||
}
|
||||
}, function);
|
||||
}
|
||||
else {
|
||||
returnedExpressions.add(bodyExpression);
|
||||
}
|
||||
Map<JetExpression, JetType> typeMap = new HashMap<JetExpression, JetType>();
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
JetType cachedType = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, returnedExpression);
|
||||
trace.record(STATEMENT, returnedExpression, false);
|
||||
@@ -418,9 +451,6 @@ public class JetTypeInferrer {
|
||||
typeMap.put(returnedExpression, cachedType);
|
||||
}
|
||||
}
|
||||
for (JetElement jetElement : elementsReturningUnit) {
|
||||
typeMap.put(jetElement, JetStandardClasses.getUnitType());
|
||||
}
|
||||
return typeMap;
|
||||
}
|
||||
|
||||
@@ -438,35 +468,57 @@ public class JetTypeInferrer {
|
||||
trace.record(STATEMENT, statement);
|
||||
final JetExpression statementExpression = (JetExpression) statement;
|
||||
//TODO constructor assert context.expectedType != FORBIDDEN : ""
|
||||
if (!iterator.hasNext() && context.expectedType != NO_EXPECTED_TYPE) {
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT && JetStandardClasses.isUnit(context.expectedType)) {
|
||||
// This implements coercion to Unit
|
||||
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
|
||||
final boolean[] mismatch = new boolean[1];
|
||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||
newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (mismatch[0]) {
|
||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||
mismatch[0] = false;
|
||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||
newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||
if (!iterator.hasNext()) {
|
||||
if (context.expectedType != NO_EXPECTED_TYPE) {
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT && JetStandardClasses.isUnit(context.expectedType)) {
|
||||
// This implements coercion to Unit
|
||||
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
|
||||
final boolean[] mismatch = new boolean[1];
|
||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||
newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (mismatch[0]) {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||
mismatch[0] = false;
|
||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||
newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (mismatch[0]) {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
}
|
||||
else {
|
||||
temporaryTraceNoExpectedType.commit();
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryTraceNoExpectedType.commit();
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
newContext = newContext(trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
newContext = newContext(trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
||||
boolean mightBeUnit = false;
|
||||
if (statementExpression instanceof JetDeclaration) {
|
||||
mightBeUnit = true;
|
||||
}
|
||||
if (statementExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) statementExpression;
|
||||
IElementType operationType = binaryExpression.getOperationToken();
|
||||
if (operationType == JetTokens.EQ || assignmentOperationNames.containsKey(operationType)) {
|
||||
mightBeUnit = true;
|
||||
}
|
||||
}
|
||||
if (mightBeUnit) {
|
||||
// TypeInferrerVisitorWithWritableScope should return only null or Unit for declarations and assignments
|
||||
assert result == null || JetStandardClasses.isUnit(result);
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -712,7 +764,6 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private class TypeInferrerVisitor extends JetVisitor<JetType, TypeInferenceContext> {
|
||||
|
||||
protected DataFlowInfo resultDataFlowInfo;
|
||||
|
||||
@Nullable
|
||||
@@ -761,10 +812,11 @@ public class JetTypeInferrer {
|
||||
}
|
||||
if (result != null) {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result);
|
||||
if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
|
||||
markDominatedExpressionsAsUnreachable(expression, context);
|
||||
}
|
||||
// if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
|
||||
// markDominatedExpressionsAsUnreachable(expression, context);
|
||||
// }
|
||||
}
|
||||
// }
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "Type checking has run into a recursive problem"); // TODO : message
|
||||
@@ -792,16 +844,16 @@ public class JetTypeInferrer {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void markDominatedExpressionsAsUnreachable(JetExpression expression, TypeInferenceContext context) {
|
||||
List<JetElement> dominated = new ArrayList<JetElement>();
|
||||
flowInformationProvider.collectDominatedExpressions(expression, dominated);
|
||||
Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
|
||||
for (JetElement rootExpression : rootExpressions) {
|
||||
// context.trace.getErrorHandler().genericError(rootExpression.getNode(),
|
||||
// "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
|
||||
context.trace.report(UNREACHABLE_BECAUSE_OF_NOTHING.on(rootExpression, expression.getText()));
|
||||
}
|
||||
}
|
||||
// private void markDominatedExpressionsAsUnreachable(JetExpression expression, TypeInferenceContext context) {
|
||||
// List<JetElement> dominated = new ArrayList<JetElement>();
|
||||
// flowInformationProvider.collectDominatedExpressions(expression, dominated);
|
||||
// Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
|
||||
// for (JetElement rootExpression : rootExpressions) {
|
||||
//// context.trace.getErrorHandler().genericError(rootExpression.getNode(),
|
||||
//// "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
|
||||
// context.trace.report(UNREACHABLE_BECAUSE_OF_NOTHING.on(rootExpression, expression.getText()));
|
||||
// }
|
||||
// }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1031,7 +1083,7 @@ public class JetTypeInferrer {
|
||||
JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
|
||||
if (returnTypeRef != null) {
|
||||
returnType = context.typeResolver.resolveType(context.scope, returnTypeRef);
|
||||
context.services.checkFunctionReturnType(functionInnerScope, expression, returnType, context.dataFlowInfo);
|
||||
context.services.checkFunctionReturnType(functionInnerScope, expression, functionDescriptor, returnType, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
if (functionTypeExpected) {
|
||||
@@ -1045,6 +1097,7 @@ public class JetTypeInferrer {
|
||||
if (functionTypeExpected) {
|
||||
JetType expectedReturnType = JetStandardClasses.getReturnType(expectedType);
|
||||
if (JetStandardClasses.isUnit(expectedReturnType)) {
|
||||
functionDescriptor.setReturnType(expectedReturnType);
|
||||
return context.services.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), effectiveReceiverType, parameterTypes, expectedReturnType), expression, context);
|
||||
}
|
||||
|
||||
@@ -1140,6 +1193,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitReturnExpression(JetReturnExpression expression, TypeInferenceContext context) {
|
||||
labelsResolver.recordLabel(expression, context);
|
||||
if (context.expectedReturnType == FORBIDDEN) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "'return' is not allowed here");
|
||||
context.trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
@@ -1162,11 +1216,13 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitBreakExpression(JetBreakExpression expression, TypeInferenceContext context) {
|
||||
labelsResolver.recordLabel(expression, context);
|
||||
return context.services.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitContinueExpression(JetContinueExpression expression, TypeInferenceContext context) {
|
||||
labelsResolver.recordLabel(expression, context);
|
||||
return context.services.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
}
|
||||
|
||||
@@ -1286,50 +1342,7 @@ public class JetTypeInferrer {
|
||||
ReceiverDescriptor thisReceiver = null;
|
||||
String labelName = expression.getLabelName();
|
||||
if (labelName != null) {
|
||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||
int size = declarationsByLabel.size();
|
||||
final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
assert targetLabel != null;
|
||||
if (size == 1) {
|
||||
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
thisReceiver = classDescriptor.getImplicitReceiver();
|
||||
}
|
||||
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||
thisReceiver = functionDescriptor.getReceiverParameter();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
else if (size == 0) {
|
||||
// This uses the info written by the control flow processor
|
||||
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel);
|
||||
if (psiElement instanceof JetFunctionLiteralExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiverParameter();
|
||||
if (thisReceiver.exists()) {
|
||||
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// context.trace.getErrorHandler().genericError(targetLabel.getNode(), "Ambiguous label");
|
||||
context.trace.report(AMBIGUOUS_LABEL.on(targetLabel));
|
||||
}
|
||||
thisReceiver = labelsResolver.resolveThisLabel(expression, context, thisReceiver, labelName);
|
||||
}
|
||||
else {
|
||||
thisReceiver = context.scope.getImplicitReceiver();
|
||||
@@ -1861,12 +1874,36 @@ public class JetTypeInferrer {
|
||||
DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context);
|
||||
getTypeWithNewScopeAndDataFlowInfo(scopeToExtend, body, conditionInfo, context);
|
||||
}
|
||||
if (!flowInformationProvider.isBreakable(expression)) {
|
||||
if (!containsBreak(expression, context)) {
|
||||
// resultScope = newWritableScopeImpl();
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
private boolean containsBreak(final JetLoopExpression loopExpression, final TypeInferenceContext context) {
|
||||
final boolean[] result = new boolean[1];
|
||||
result[0] = false;
|
||||
//todo breaks in inline function literals
|
||||
loopExpression.visit(new JetTreeVisitor<JetLoopExpression>() {
|
||||
@Override
|
||||
public Void visitBreakExpression(JetBreakExpression breakExpression, JetLoopExpression outerLoop) {
|
||||
JetSimpleNameExpression targetLabel = breakExpression.getTargetLabel();
|
||||
PsiElement element = targetLabel != null ? context.trace.get(LABEL_TARGET, targetLabel) : null;
|
||||
if (element == loopExpression || (targetLabel == null && outerLoop == loopExpression)) {
|
||||
result[0] = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLoopExpression(JetLoopExpression loopExpression, JetLoopExpression outerLoop) {
|
||||
return super.visitLoopExpression(loopExpression, loopExpression);
|
||||
}
|
||||
}, loopExpression);
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, TypeInferenceContext contextWithExpectedType) {
|
||||
@@ -1891,7 +1928,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
JetExpression condition = expression.getCondition();
|
||||
checkCondition(conditionScope, condition, context);
|
||||
if (!flowInformationProvider.isBreakable(expression)) {
|
||||
if (!containsBreak(expression, context)) {
|
||||
// resultScope = newWritableScopeImpl();
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
@@ -2276,8 +2313,13 @@ public class JetTypeInferrer {
|
||||
if (baseExpression == null) return null;
|
||||
JetSimpleNameExpression operationSign = expression.getOperationSign();
|
||||
if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
|
||||
String referencedName = operationSign.getReferencedName();
|
||||
referencedName = referencedName == null ? " <?>" : referencedName;
|
||||
labelsResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
|
||||
// TODO : Some processing for the label?
|
||||
return context.services.checkType(getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
|
||||
JetType type = context.services.checkType(getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
|
||||
labelsResolver.exitLabeledElement(baseExpression);
|
||||
return type;
|
||||
}
|
||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||
String name = unaryOperationNames.get(operationType);
|
||||
@@ -2318,6 +2360,7 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
result = returnType;
|
||||
}
|
||||
|
||||
return context.services.checkType(result, expression, context);
|
||||
}
|
||||
|
||||
@@ -2341,10 +2384,10 @@ public class JetTypeInferrer {
|
||||
result = getTypeForBinaryCall(context.scope, binaryOperationNames.get(operationType), context, expression);
|
||||
}
|
||||
else if (operationType == JetTokens.EQ) {
|
||||
result = visitAssignment(expression, context);
|
||||
result = visitAssignment(expression, contextWithExpectedType);
|
||||
}
|
||||
else if (assignmentOperationNames.containsKey(operationType)) {
|
||||
result = visitAssignmentOperation(expression, context);
|
||||
result = visitAssignmentOperation(expression, contextWithExpectedType);
|
||||
}
|
||||
else if (comparisonOperations.contains(operationType)) {
|
||||
JetType compareToReturnType = getTypeForBinaryCall(context.scope, "compareTo", context, expression);
|
||||
@@ -2658,7 +2701,7 @@ public class JetTypeInferrer {
|
||||
PropertyDescriptor propertyDescriptor = context.classDescriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
|
||||
scope.addVariableDescriptor(propertyDescriptor);
|
||||
}
|
||||
return null;
|
||||
return checkExpectedType(declaration, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2694,7 +2737,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
scope.addVariableDescriptor(propertyDescriptor);
|
||||
return null;
|
||||
return checkExpectedType(property, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2702,7 +2745,7 @@ public class JetTypeInferrer {
|
||||
FunctionDescriptorImpl functionDescriptor = context.classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function);
|
||||
scope.addFunctionDescriptor(functionDescriptor);
|
||||
context.services.checkFunctionReturnType(context.scope, function, functionDescriptor, context.dataFlowInfo);
|
||||
return null;
|
||||
return checkExpectedType(function, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2717,7 +2760,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitDeclaration(JetDeclaration dcl, TypeInferenceContext context) {
|
||||
return visitJetElement(dcl, context);
|
||||
return checkExpectedType(dcl, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2739,6 +2782,17 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
temporaryBindingTrace.commit();
|
||||
}
|
||||
return checkExpectedType(expression, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType checkExpectedType(JetExpression expression, TypeInferenceContext context) {
|
||||
if (context.expectedType != NO_EXPECTED_TYPE) {
|
||||
if (JetStandardClasses.isUnit(context.expectedType)) {
|
||||
return JetStandardClasses.getUnitType();
|
||||
}
|
||||
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2771,7 +2825,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return checkExpectedType(expression, context);
|
||||
}
|
||||
|
||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) {
|
||||
@@ -2794,6 +2848,11 @@ public class JetTypeInferrer {
|
||||
return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitAnnotatedExpression(JetAnnotatedExpression expression, TypeInferenceContext data) {
|
||||
return getType(expression.getBaseExpression(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitJetElement(JetElement element, TypeInferenceContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
||||
@@ -2801,4 +2860,135 @@ public class JetTypeInferrer {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class LabelsResolver {
|
||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
|
||||
public void enterLabeledElement(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
||||
if (deparenthesized != null) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null) {
|
||||
stack = new Stack<JetElement>();
|
||||
labeledElements.put(labelName, stack);
|
||||
}
|
||||
stack.push(deparenthesized);
|
||||
}
|
||||
}
|
||||
|
||||
public void exitLabeledElement(@NotNull JetExpression expression) {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression);
|
||||
// TODO : really suboptimal
|
||||
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
||||
Stack<JetElement> stack = entry.getValue();
|
||||
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
||||
JetElement recorded = stackIter.next();
|
||||
if (recorded == deparenthesized) {
|
||||
stackIter.remove();
|
||||
}
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
mapIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JetElement resolveControlLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
|
||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||
int size = declarationsByLabel.size();
|
||||
|
||||
if (size == 1) {
|
||||
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
|
||||
JetElement element;
|
||||
if (declarationDescriptor instanceof FunctionDescriptor || declarationDescriptor instanceof ClassDescriptor) {
|
||||
element = (JetElement) context.trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
context.trace.record(LABEL_TARGET, labelExpression, element);
|
||||
return element;
|
||||
}
|
||||
else if (size == 0) {
|
||||
return resolveNamedLabel(labelName, labelExpression, reportUnresolved, context);
|
||||
}
|
||||
context.trace.report(AMBIGUOUS_LABEL.on(labelExpression));
|
||||
return null;
|
||||
}
|
||||
|
||||
public void recordLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) {
|
||||
JetSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
if (labelElement != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
resolveControlLabel(labelName, labelElement, true, context);
|
||||
}
|
||||
}
|
||||
|
||||
private JetElement resolveNamedLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (stack.size() > 1) {
|
||||
context.trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = stack.peek();
|
||||
context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReceiverDescriptor resolveThisLabel(JetThisExpression expression, TypeInferenceContext context, ReceiverDescriptor thisReceiver, String labelName) {
|
||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||
int size = declarationsByLabel.size();
|
||||
final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
assert targetLabel != null;
|
||||
if (size == 1) {
|
||||
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
thisReceiver = classDescriptor.getImplicitReceiver();
|
||||
}
|
||||
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||
thisReceiver = functionDescriptor.getReceiver();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
PsiElement element = context.trace.get(DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
||||
assert element != null;
|
||||
context.trace.record(LABEL_TARGET, targetLabel, element);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
else if (size == 0) {
|
||||
JetElement element = labelsResolver.resolveNamedLabel(labelName, targetLabel, false, context);
|
||||
if (element instanceof JetFunctionLiteralExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
|
||||
if (thisReceiver.exists()) {
|
||||
context.trace.record(LABEL_TARGET, targetLabel, element);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(AMBIGUOUS_LABEL.on(targetLabel));
|
||||
}
|
||||
return thisReceiver;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*
|
||||
* Utility class used by back-end to
|
||||
*/
|
||||
public class ProjectionErasingJetType implements JetType {
|
||||
private final JetType delegate;
|
||||
private List<TypeProjection> arguments;
|
||||
|
||||
public ProjectionErasingJetType(JetType delegate) {
|
||||
this.delegate = delegate;
|
||||
arguments = new ArrayList<TypeProjection>();
|
||||
for(TypeProjection tp : delegate.getArguments()) {
|
||||
arguments.add(new TypeProjection(Variance.INVARIANT, tp.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
return delegate.getConstructor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetScope getMemberScope() {
|
||||
return delegate.getMemberScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnnotationDescriptor> getAnnotations() {
|
||||
return delegate.getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return ((obj instanceof ProjectionErasingJetType) && delegate.equals(((ProjectionErasingJetType)obj).delegate)) || delegate.equals(obj);
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,7 @@ public interface JetTokens {
|
||||
JetKeywordToken CATCH_KEYWORD = JetKeywordToken.softKeyword("catch");
|
||||
JetKeywordToken OUT_KEYWORD = JetKeywordToken.softKeyword("out");
|
||||
JetKeywordToken VARARG_KEYWORD = JetKeywordToken.softKeyword("vararg");
|
||||
JetKeywordToken INLINE_KEYWORD = JetKeywordToken.softKeyword("inline");
|
||||
|
||||
JetKeywordToken FINALLY_KEYWORD = JetKeywordToken.softKeyword("finally");
|
||||
JetKeywordToken FINAL_KEYWORD = JetKeywordToken.softKeyword("final");
|
||||
@@ -155,12 +156,12 @@ public interface JetTokens {
|
||||
TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD,
|
||||
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, ANNOTATION_KEYWORD,
|
||||
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
|
||||
CATCH_KEYWORD, FINALLY_KEYWORD, REF_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD
|
||||
CATCH_KEYWORD, FINALLY_KEYWORD, REF_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD
|
||||
);
|
||||
|
||||
TokenSet MODIFIER_KEYWORDS = TokenSet.create(ABSTRACT_KEYWORD, ENUM_KEYWORD,
|
||||
OPEN_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD,
|
||||
PROTECTED_KEYWORD, REF_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD
|
||||
PROTECTED_KEYWORD, REF_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD
|
||||
);
|
||||
TokenSet WHITE_SPACE_OR_COMMENT_BIT_SET = TokenSet.create(WHITE_SPACE, BLOCK_COMMENT, EOL_COMMENT, DOC_COMMENT);
|
||||
TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE);
|
||||
|
||||
Reference in New Issue
Block a user