Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2011-10-14 07:43:02 +02:00
198 changed files with 5644 additions and 2010 deletions
@@ -73,7 +73,7 @@ public class ClassContext {
thisIdx++;
}
final boolean hasReceiver = descriptor.getReceiver().exists();
final boolean hasReceiver = descriptor.getReceiverParameter().exists();
if (hasReceiver) {
thisIdx++;
}
@@ -104,7 +104,7 @@ public class ClassContext {
}
private ReceiverDescriptor receiver() {
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverParameter() : ReceiverDescriptor.NO_RECEIVER;
}
private boolean hasReceiver() {
@@ -42,7 +42,7 @@ public class ClosureCodegen {
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
boolean isExtensionFunction = fd.getReceiver().exists();
boolean isExtensionFunction = fd.getReceiverParameter().exists();
int paramCount = fd.getValueParameters().size();
if (isExtensionFunction) {
paramCount++;
@@ -117,7 +117,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);
@@ -151,7 +151,7 @@ public class ClosureCodegen {
iv.load(0, Type.getObjectType(className));
final ReceiverDescriptor receiver = funDescriptor.getReceiver();
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
int count = 1;
if (receiver.exists()) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
@@ -175,7 +175,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 +199,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) {
@@ -229,7 +231,7 @@ public class ClosureCodegen {
public static String getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
if (descriptor.getReceiver().exists()) {
if (descriptor.getReceiverParameter().exists()) {
return "jet/ExtensionFunction" + paramCount;
}
else {
@@ -250,7 +252,7 @@ public class ClosureCodegen {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiver().exists()) {
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(null);
}
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
@@ -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);
}
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import jet.Function1;
import jet.JetObject;
import jet.typeinfo.TypeInfo;
import jet.typeinfo.TypeInfoProjection;
@@ -58,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;
@@ -317,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);
}
@@ -461,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.getReceiverParameter();
final JetType receiverType = !receiverTypeRef.exists() ? 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")) {
@@ -481,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()]));
}
@@ -512,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;
@@ -522,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.getReceiverParameter().exists();
}
else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
@@ -546,7 +544,7 @@ public class JetTypeMapper {
}
public Method mapSignature(String name, FunctionDescriptor f) {
final ReceiverDescriptor receiver = f.getReceiver();
final ReceiverDescriptor receiver = f.getReceiverParameter();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
if (receiver.exists()) {
@@ -0,0 +1,67 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
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);
}
}
@@ -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");
@@ -3,14 +3,12 @@ package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -22,7 +20,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
private TypeConstructor typeConstructor;
private JavaClassMembersScope unsubstitutedMemberScope;
private JetType classObjectType;
// private JetType classObjectType;
private final Set<FunctionDescriptor> constructors = Sets.newLinkedHashSet();
private Modality modality;
private Visibility visibility;
@@ -52,19 +50,19 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
this.unsubstitutedMemberScope = memberScope;
}
public void setClassObjectMemberScope(JavaClassMembersScope memberScope) {
classObjectType = new JetTypeImpl(
new TypeConstructorImpl(
JavaDescriptorResolver.JAVA_CLASS_OBJECT,
Collections.<AnnotationDescriptor>emptyList(),
true,
"Class object emulation for " + getName(),
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<JetType>emptyList()
),
memberScope
);
}
// public void setClassObjectMemberScope(JavaClassMembersScope memberScope) {
// classObjectType = new JetTypeImpl(
// new TypeConstructorImpl(
// JavaDescriptorResolver.JAVA_CLASS_OBJECT,
// Collections.<AnnotationDescriptor>emptyList(),
// true,
// "Class object emulation for " + getName(),
// Collections.<TypeParameterDescriptor>emptyList(),
// Collections.<JetType>emptyList()
// ),
// memberScope
// );
// }
public void addConstructor(ConstructorDescriptor constructorDescriptor) {
this.constructors.add(constructorDescriptor);
@@ -133,7 +131,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
@Override
public JetType getClassObjectType() {
return classObjectType;
return null;
}
@Override
@@ -27,8 +27,8 @@ public class JavaClassMembersScope implements JetScope {
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
private Collection<DeclarationDescriptor> allDescriptors;
public JavaClassMembersScope(@NotNull DeclarationDescriptor classDescriptor, PsiClass psiClass, JavaSemanticServices semanticServices, boolean staticMembers) {
this.containingDeclaration = classDescriptor;
public JavaClassMembersScope(@NotNull DeclarationDescriptor classOrNamespaceDescriptor, PsiClass psiClass, JavaSemanticServices semanticServices, boolean staticMembers) {
this.containingDeclaration = classOrNamespaceDescriptor;
this.psiClass = psiClass;
this.semanticServices = semanticServices;
this.staticMembers = staticMembers;
@@ -161,11 +161,11 @@ public class JavaClassMembersScope implements JetScope {
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class...
return ReceiverDescriptor.NO_RECEIVER; // Should never occur, we don't sit in a Java class...
}
@Override
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class...
// we cannot really be scoped inside here
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.*;
import java.util.*;
@@ -53,7 +54,7 @@ public class JavaDescriptorResolver {
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
protected final Map<PsiPackage, NamespaceDescriptor> namespaceDescriptorCache = Maps.newHashMap();
protected final Map<PsiElement, NamespaceDescriptor> namespaceDescriptorCache = Maps.newHashMap();
protected final JavaPsiFacade javaFacade;
protected final GlobalSearchScope javaSearchScope;
protected final JavaSemanticServices semanticServices;
@@ -108,7 +109,6 @@ public class JavaDescriptorResolver {
name,
typeParameters,
supertypes
));
classDescriptor.setModality(Modality.convertFromFlags(
psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(),
@@ -117,7 +117,7 @@ public class JavaDescriptorResolver {
classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), psiClass));
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
classDescriptor.setClassObjectMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, true));
// classDescriptor.setClassObjectMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, true));
// UGLY HACK
supertypes.addAll(getSupertypes(psiClass));
if (psiClass.isInterface()) {
@@ -238,7 +238,9 @@ public class JavaDescriptorResolver {
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
if (psiPackage == null) {
return null;
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
if (psiClass == null) return null;
return resolveNamespace(psiClass);
}
return resolveNamespace(psiPackage);
}
@@ -246,20 +248,21 @@ public class JavaDescriptorResolver {
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
if (namespaceDescriptor == null) {
// TODO : packages
// PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
// if (psiClass != null) {
// namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
// }
// else {
namespaceDescriptor = createJavaNamespaceDescriptor(psiPackage);
// }
namespaceDescriptor = createJavaNamespaceDescriptor(psiPackage);
namespaceDescriptorCache.put(psiPackage, namespaceDescriptor);
}
return namespaceDescriptor;
}
private NamespaceDescriptor resolveNamespace(@NotNull PsiClass psiClass) {
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiClass);
if (namespaceDescriptor == null) {
namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
namespaceDescriptorCache.put(psiClass, namespaceDescriptor);
}
return namespaceDescriptor;
}
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull PsiPackage psiPackage) {
String name = psiPackage.getName();
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
@@ -325,6 +328,7 @@ public class JavaDescriptorResolver {
resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), field),
!isFinal,
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
field.getName(),
isFinal ? null : type,
type);
@@ -399,6 +403,7 @@ public class JavaDescriptorResolver {
methodDescriptorCache.put(method, functionDescriptorImpl);
functionDescriptorImpl.initialize(
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()),
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
semanticServices.getTypeTransformer().transformToType(returnType),
@@ -11,7 +11,6 @@ import java.util.Set;
* @author abreslav
*/
public class JavaPackageScope extends JetScopeImpl {
private final JavaSemanticServices semanticServices;
private final DeclarationDescriptor containingDescriptor;
private final String packagePrefix;
+65 -27
View File
@@ -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
@@ -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) {
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -14,7 +13,10 @@ import java.util.Set;
*/
public interface CallableDescriptor extends DeclarationDescriptor {
@NotNull
ReceiverDescriptor getReceiver();
ReceiverDescriptor getReceiverParameter();
@NotNull
ReceiverDescriptor getExpectedThisObject();
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@@ -3,6 +3,8 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
@@ -28,16 +30,27 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
@Override
@Deprecated
public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, @NotNull Visibility visibility) {
public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull ReceiverDescriptor expectedThisObject, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, @NotNull Visibility visibility) {
assert receiverType == null;
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality, visibility);
return super.initialize(null, expectedThisObject, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality, visibility);
}
public ConstructorDescriptorImpl initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, Modality modality, Visibility visibility) {
super.initialize(null, typeParameters, unsubstitutedValueParameters, null, modality, visibility);
super.initialize(null, getExpectedThisObject(getContainingDeclaration()), typeParameters, unsubstitutedValueParameters, null, modality, visibility);
return this;
}
@NotNull
private static ReceiverDescriptor getExpectedThisObject(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ConstructorDescriptor) {
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) descriptor;
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
return getExpectedThisObject(classDescriptor);
}
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
return DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration);
}
@NotNull
@Override
public ClassDescriptor getContainingDeclaration() {
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -27,6 +28,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType;
private ReceiverDescriptor receiver;
private ReceiverDescriptor expectedThisObject;
private Modality modality;
private Visibility visibility;
@@ -51,6 +53,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
public FunctionDescriptorImpl initialize(
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@@ -62,6 +65,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
this.modality = modality;
this.visibility = visibility;
this.receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType);
this.expectedThisObject = expectedThisObject;
return this;
}
@@ -71,10 +75,16 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return receiver;
}
@NotNull
@Override
public ReceiverDescriptor getExpectedThisObject() {
return expectedThisObject;
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenDescriptors() {
@@ -132,12 +142,21 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
JetType substitutedReceiverType = null;
if (receiver != NO_RECEIVER) {
substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
if (receiver.exists()) {
substitutedReceiverType = substitutor.substitute(getReceiverParameter().getType(), Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
}
ReceiverDescriptor substitutedExpectedThis = NO_RECEIVER;
if (expectedThisObject.exists()) {
JetType substitutedType = substitutor.substitute(expectedThisObject.getType(), Variance.INVARIANT);
if (substitutedType == null) {
return null;
}
substitutedExpectedThis = new TransientReceiver(substitutedType);
}
List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor);
if (substitutedValueParameters == null) {
@@ -151,6 +170,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
substitutedDescriptor.initialize(
substitutedReceiverType,
substitutedExpectedThis,
substitutedTypeParameters,
substitutedValueParameters,
substitutedReturnType,
@@ -181,7 +201,8 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
FunctionDescriptorImpl copy = new FunctionDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), getName());
copy.initialize(
getReceiver().exists() ? getReceiver().getType() : null,
getReceiverParameter().exists() ? getReceiverParameter().getType() : null,
expectedThisObject,
DescriptorUtils.copyTypeParameters(copy, typeParameters),
DescriptorUtils.copyValueParameters(copy, unsubstitutedValueParameters),
unsubstitutedReturnType,
@@ -95,7 +95,7 @@ public class FunctionDescriptorUtil {
@NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope");
ReceiverDescriptor receiver = descriptor.getReceiver();
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
if (receiver.exists()) {
parameterScope.setImplicitReceiver(receiver);
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.Collections;
@@ -77,6 +78,18 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
return correspondingProperty;
}
@NotNull
@Override
public ReceiverDescriptor getReceiverParameter() {
return getCorrespondingProperty().getReceiverParameter();
}
@NotNull
@Override
public ReceiverDescriptor getExpectedThisObject() {
return getCorrespondingProperty().getExpectedThisObject();
}
@NotNull
@Override
public PropertyAccessorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
@@ -24,6 +25,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
private final Visibility visibility;
private final boolean isVar;
private final ReceiverDescriptor receiver;
private final ReceiverDescriptor expectedThisObject;
private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet();
private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0);
private final PropertyDescriptor original;
@@ -38,6 +40,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
@NotNull Visibility visibility,
boolean isVar,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject,
@NotNull String name,
@Nullable JetType inType,
@NotNull JetType outType) {
@@ -48,6 +51,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
this.modality = modality;
this.visibility = visibility;
this.receiver = receiverType == null ? ReceiverDescriptor.NO_RECEIVER : new ExtensionReceiver(this, receiverType);
this.expectedThisObject = expectedThisObject;
this.original = original == null ? this : original.getOriginal();
}
@@ -58,15 +62,17 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
@NotNull Visibility visibility,
boolean isVar,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject,
@NotNull String name,
@Nullable JetType inType,
@NotNull JetType outType) {
this(null, containingDeclaration, annotations, modality, visibility, isVar, receiverType, name, inType, outType);
this(null, containingDeclaration, annotations, modality, visibility, isVar, receiverType, expectedThisObject, name, inType, outType);
}
private PropertyDescriptor(
@NotNull PropertyDescriptor original,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject,
@Nullable JetType inType,
@NotNull JetType outType) {
this(
@@ -77,6 +83,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
original.getVisibility(),
original.isVar,
receiverType,
expectedThisObject,
original.getName(),
inType,
outType);
@@ -95,10 +102,16 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
}
@NotNull
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return receiver;
}
@NotNull
@Override
public ReceiverDescriptor getExpectedThisObject() {
return expectedThisObject;
}
@NotNull
@Override
public JetType getReturnType() {
@@ -132,7 +145,6 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
return setter;
}
@NotNull
@Override
public PropertyDescriptor substitute(TypeSubstitutor substitutor) {
JetType originalInType = getInType();
@@ -142,9 +154,18 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out
}
JetType substitutedReceiverType;
if (receiver.exists()) {
substitutedReceiverType = substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE);
if (substitutedReceiverType == null) return null;
}
else {
substitutedReceiverType = null;
}
return new PropertyDescriptor(
this,
receiver.exists() ? substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE) : null,
substitutedReceiverType,
expectedThisObject.exists() ? new TransientReceiver(substitutor.substitute(expectedThisObject.getType(), Variance.IN_VARIANCE)) : expectedThisObject,
inType,
outType
);
@@ -171,6 +192,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
return overriddenProperties;
}
@NotNull
@Override
public PropertyDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
@@ -178,7 +200,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
newOwner,
Lists.newArrayList(getAnnotations()),
DescriptorUtils.convertModality(modality, makeNonAbstract), visibility, isVar,
receiver.exists() ? receiver.getType() : null, getName(), getInType(), getOutType());
receiver.exists() ? receiver.getType() : null,
expectedThisObject,
getName(), getInType(), getOutType());
PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor(
propertyDescriptor, Lists.newArrayList(getter.getAnnotations()),
DescriptorUtils.convertModality(getter.getModality(), makeNonAbstract), getter.getVisibility(),
@@ -33,12 +33,6 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
overriddenGetters.add(overriddenGetter);
}
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
}
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
@@ -3,7 +3,6 @@ package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
@@ -42,12 +41,6 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
overriddenSetters.add(overriddenSetter);
}
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
}
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
@@ -16,7 +17,7 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
assert outType != null;
assert JetStandardClasses.isFunctionType(outType);
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
result.initialize(JetStandardClasses.getReceiverType(outType), Collections.<TypeParameterDescriptor>emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL, Visibility.LOCAL);
result.initialize(JetStandardClasses.getReceiverType(outType), ReceiverDescriptor.NO_RECEIVER, Collections.<TypeParameterDescriptor>emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL, Visibility.LOCAL);
return result;
}
@@ -26,7 +26,6 @@ public interface VariableDescriptor extends CallableDescriptor {
@NotNull
DeclarationDescriptor getContainingDeclaration();
@NotNull
@Override
VariableDescriptor substitute(TypeSubstitutor substitutor);
@@ -74,7 +74,13 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
@NotNull
@Override
public ReceiverDescriptor getReceiver() {
public ReceiverDescriptor getReceiverParameter() {
return ReceiverDescriptor.NO_RECEIVER;
}
@NotNull
@Override
public ReceiverDescriptor getExpectedThisObject() {
return ReceiverDescriptor.NO_RECEIVER;
}
@@ -1,7 +1,8 @@
package org.jetbrains.jet.lang.diagnostics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.Collection;
@@ -9,7 +10,7 @@ import java.util.Collection;
/**
* @author abreslav
*/
public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> {
public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosticFactory1<Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>> {
public static AmbiguousDescriptorDiagnosticFactory create(String messageTemplate) {
return new AmbiguousDescriptorDiagnosticFactory(messageTemplate);
}
@@ -19,10 +20,10 @@ public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosti
}
@Override
protected String makeMessageFor(@NotNull Collection<? extends CallableDescriptor> argument) {
protected String makeMessageFor(@NotNull Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> argument) {
StringBuilder stringBuilder = new StringBuilder("\n");
for (CallableDescriptor descriptor : argument) {
stringBuilder.append(DescriptorRenderer.TEXT.render(descriptor)).append("\n");
for (ResolvedCall<? extends DeclarationDescriptor> call : argument) {
stringBuilder.append(DescriptorRenderer.TEXT.render(call.getResultingDescriptor())).append("\n");
}
return stringBuilder.toString();
}
@@ -59,7 +59,7 @@ public interface Errors {
return sb.toString();
}
};
ParameterizedDiagnosticFactory1<JetKeywordToken> ILLEGAL_MODIFIER = ParameterizedDiagnosticFactory1.create(ERROR, "Illegal modifier ''{0}''");
DiagnosticWithParameterFactory<JetModifierList, JetKeywordToken> ILLEGAL_MODIFIER = DiagnosticWithParameterFactory.create(ERROR, "Illegal modifier ''{0}''", DiagnosticParameters.MODIFIER);
PsiElementOnlyDiagnosticFactory2<JetModifierList, JetKeywordToken, JetKeywordToken> REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2<JetModifierList, JetKeywordToken, JetKeywordToken>(Severity.WARNING, "Modifier {0} is redundant because {1} is present") {
@NotNull
@@ -69,6 +69,7 @@ public interface Errors {
}
};
DiagnosticWithParameterFactory<JetModifierList, JetKeywordToken> REDUNDANT_MODIFIER_IN_TRAIT = DiagnosticWithParameterFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", DiagnosticParameters.MODIFIER);
DiagnosticWithParameterFactory<JetModifierList, JetKeywordToken> REDUNDANT_MODIFIER_IN_GETTER = DiagnosticWithParameterFactory.create(WARNING, "Visibility modifiers are redundant in getter", DiagnosticParameters.MODIFIER);
SimplePsiElementOnlyDiagnosticFactory<JetClass> TRAIT_CAN_NOT_BE_FINAL = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Trait can not be final");
SimpleDiagnosticFactory SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES = SimpleDiagnosticFactory.create(ERROR, "Safe calls are not allowed on namespaces");
SimpleDiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = SimpleDiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem"); // TODO: message
@@ -94,6 +95,8 @@ public interface Errors {
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithParameterFactory.create(ERROR, "Property with initializer cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with getter implementation cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with setter implementation cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetModifierList, JetKeywordToken> GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY = DiagnosticWithParameterFactory.create(ERROR, "Getter visibility must be the same as property visibility", DiagnosticParameters.MODIFIER);
SimpleDiagnosticFactory BACKING_FIELD_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property in a trait cannot have a backing field");
SimpleDiagnosticFactory MUST_BE_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "Property must be initialized");
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract");
@@ -106,22 +109,21 @@ public interface Errors {
return super.on(elementToBlame, textRangeToMark, s, classDescriptor, aClass).add(DiagnosticParameters.CLASS, aClass);
}
};
PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetClass> ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetClass>(ERROR, "Abstract function {0} in non-abstract class {1}") {
PsiElementOnlyDiagnosticFactory3<JetFunction, String, ClassDescriptor, JetClass> ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetFunction, String, ClassDescriptor, JetClass>(ERROR, "Abstract function {0} in non-abstract class {1}") {
@NotNull
public DiagnosticWithPsiElement<JetFunctionOrPropertyAccessor> on(@NotNull JetFunctionOrPropertyAccessor elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) {
public DiagnosticWithPsiElement<JetFunction> on(@NotNull JetFunction elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) {
return super.on(elementToBlame, nodeToMark, s, classDescriptor, modifierListOwner).add(DiagnosticParameters.CLASS, modifierListOwner);
}
};
PsiElementOnlyDiagnosticFactory1<JetFunctionOrPropertyAccessor, FunctionDescriptor> ABSTRACT_FUNCTION_WITH_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract");
PsiElementOnlyDiagnosticFactory1<JetFunctionOrPropertyAccessor, FunctionDescriptor> NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract");
PsiElementOnlyDiagnosticFactory1<JetFunction, FunctionDescriptor> ABSTRACT_FUNCTION_WITH_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract");
PsiElementOnlyDiagnosticFactory1<JetFunction, FunctionDescriptor> NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract");
PsiElementOnlyDiagnosticFactory1<JetModifierListOwner, FunctionDescriptor> NON_MEMBER_ABSTRACT_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract");
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> NON_MEMBER_ABSTRACT_ACCESSOR = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property is not a class or trait member and thus cannot have abstract accessors"); // TODO : Better message
PsiElementOnlyDiagnosticFactory1<JetFunctionOrPropertyAccessor, FunctionDescriptor> NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body");
PsiElementOnlyDiagnosticFactory1<JetFunction, FunctionDescriptor> NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body");
DiagnosticWithParameterFactory<JetNamedDeclaration, JetClass> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticWithParameterFactory.create(ERROR, "Non final member in a final class", DiagnosticParameters.CLASS);
DiagnosticWithParameterFactory<JetPropertyAccessor, JetProperty> NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY = DiagnosticWithParameterFactory.create(ERROR, "Non final accessor of a final property", DiagnosticParameters.PROPERTY);
DiagnosticWithParameterFactory<JetPropertyAccessor, JetProperty> ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY = DiagnosticWithParameterFactory.create(ERROR, "Abstract accessor of a final property", DiagnosticParameters.PROPERTY);
DiagnosticWithParameterFactory<JetNamedDeclaration, JetType> PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Public member should specify a type", DiagnosticParameters.TYPE);
SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning
SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here");
@@ -130,7 +132,7 @@ public interface Errors {
SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors");
SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required");
SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed");
PsiElementOnlyDiagnosticFactory1<JetModifierListOwner, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT);
PsiElementOnlyDiagnosticFactory1<JetModifierList, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT);
PsiElementOnlyDiagnosticFactory1<JetClass, PropertyDescriptor> PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field");
ParameterizedDiagnosticFactory1<JetClassOrObject> PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1<JetClassOrObject>(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") {
@Override
@@ -141,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");
@@ -189,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");
@@ -219,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");
@@ -237,7 +240,7 @@ public interface Errors {
return constraintOwner.getName();
}
};
ParameterizedDiagnosticFactory2<JetType, VariableDescriptor> AUTOCAST_IMPOSSIBLE = ParameterizedDiagnosticFactory2.create(ERROR, "Automatic cast to {0} is impossible, because variable {1} is mutable", NAME);
ParameterizedDiagnosticFactory2<JetType, String> AUTOCAST_IMPOSSIBLE = ParameterizedDiagnosticFactory2.create(ERROR, "Automatic cast to {0} is impossible, because {1} could have changed since the is-check");
ParameterizedDiagnosticFactory2<JetType, JetType> TYPE_MISMATCH_IN_FOR_LOOP = ParameterizedDiagnosticFactory2.create(ERROR, "The loop iterates over values of type {0} but the parameter is declared to be {1}");
ParameterizedDiagnosticFactory1<JetType> TYPE_MISMATCH_IN_CONDITION = ParameterizedDiagnosticFactory1.create(ERROR, "Condition must be of type Boolean, but was of type {0}");
@@ -348,10 +351,10 @@ public interface Errors {
};
ParameterizedDiagnosticFactory3<String, JetType, JetType> RESULT_TYPE_MISMATCH = ParameterizedDiagnosticFactory3.create(ERROR, "{0} must return {1} but returns {2}");
ParameterizedDiagnosticFactory3<String, String, String> UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead");
ParameterizedDiagnosticFactory3<String, String, String> UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})'' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead");
ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}");
ParameterizedDiagnosticFactory1<Collection<? extends CallableDescriptor>> NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}");
AmbiguousDescriptorDiagnosticFactory OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}");
AmbiguousDescriptorDiagnosticFactory NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}");
ParameterizedDiagnosticFactory1<ValueParameterDescriptor> NO_VALUE_FOR_PARAMETER = ParameterizedDiagnosticFactory1.create(ERROR, "No value passed for parameter {0}", DescriptorRenderer.TEXT);
ParameterizedDiagnosticFactory1<JetType> MISSING_RECEIVER = ParameterizedDiagnosticFactory1.create(ERROR, "A receiver of type {0} is required");
SimpleDiagnosticFactory NO_RECEIVER_ADMITTED = SimpleDiagnosticFactory.create(ERROR, "No receiver can be passed to this function or property");
@@ -1,7 +1,10 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.List;
@@ -9,6 +12,14 @@ import java.util.List;
* @author abreslav
*/
public interface Call {
// SAFE_ACCESS or DOT or so
@Nullable
ASTNode getCallOperationNode();
@NotNull
ReceiverDescriptor getExplicitReceiver();
@Nullable
JetExpression getCalleeExpression();
@@ -26,4 +37,10 @@ public interface Call {
@Nullable
JetTypeArgumentList getTypeArgumentList();
@NotNull
ASTNode getCallNode();
@Nullable
PsiElement getCallElement();
}
@@ -9,6 +9,22 @@ import java.util.List;
/**
* @author abreslav
*/
public interface JetCallElement extends PsiElement, Call {
public interface JetCallElement extends PsiElement {
@Nullable
JetExpression getCalleeExpression();
@Nullable
JetValueArgumentList getValueArgumentList();
@NotNull
List<? extends ValueArgument> getValueArguments();
@NotNull
List<JetExpression> getFunctionLiteralArguments();
@NotNull
List<JetTypeProjection> getTypeArguments();
@Nullable
JetTypeArgumentList getTypeArgumentList();
}
@@ -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);
}
@@ -14,7 +14,7 @@ import java.util.List;
/**
* @author abreslav
*/
abstract public class JetFunction extends JetTypeParameterListOwner implements JetFunctionOrPropertyAccessor {
abstract public class JetFunction extends JetTypeParameterListOwner implements JetDeclarationWithBody, JetModifierListOwner {
public JetFunction(@NotNull ASTNode node) {
super(node);
}
@@ -1,7 +0,0 @@
package org.jetbrains.jet.lang.psi;
/**
* @author svtk
*/
public interface JetFunctionOrPropertyAccessor extends JetDeclarationWithBody, JetModifierListOwner {
}
@@ -13,7 +13,7 @@ import java.util.List;
/**
* @author max
*/
public class JetPropertyAccessor extends JetDeclaration implements JetFunctionOrPropertyAccessor {
public class JetPropertyAccessor extends JetDeclaration implements JetDeclarationWithBody, JetModifierListOwner {
public JetPropertyAccessor(@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;
}
}
@@ -9,12 +9,11 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInferrer;
import org.jetbrains.jet.lang.types.*;
import java.util.Collections;
import java.util.List;
@@ -27,11 +26,15 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
public class AnnotationResolver {
private final BindingTrace trace;
private final JetTypeInferrer typeInferrer;
// private final JetTypeInferrer typeInferrer;
private final CallResolver callResolver;
// private final JetTypeInferrer.Services services;
public AnnotationResolver(JetSemanticServices semanticServices, BindingTrace trace) {
this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
this.trace = trace;
// this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
// this.services = typeInferrer.getServices(this.trace);
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(semanticServices), DataFlowInfo.getEmpty());
}
@NotNull
@@ -47,7 +50,7 @@ public class AnnotationResolver {
}
public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) {
JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, ReceiverDescriptor.NO_RECEIVER, entryElement, NO_EXPECTED_TYPE);
JetType jetType = callResolver.resolveCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE);
descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType);
}
@@ -112,4 +115,4 @@ public class AnnotationResolver {
}
return createAnnotationStubs(modifierList.getAnnotationEntries());
}
}
}
@@ -6,9 +6,9 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.CommonSuppliers;
@@ -20,15 +20,16 @@ import java.util.Collection;
* @author abreslav
*/
public interface BindingContext {
WritableSlice<JetElement, ReceiverDescriptor> RECEIVER = Slices.createSimpleSlice("RECEIVER");
WritableSlice<JetAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice("ANNOTATION");
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE");
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice("TYPE");
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
WritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>> RESOLVED_CALL = new BasicWritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>>("RESOLVED_CALL", RewritePolicy.DO_NOTHING);
WritableSlice<JetReferenceExpression, Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends ResolvedCall<? extends DeclarationDescriptor>>>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_ITERATOR = Slices.createSimpleSlice("LOOP_RANGE_ITERATOR");
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT");
@@ -43,9 +44,12 @@ public interface BindingContext {
WritableSlice<JetExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice("PROCESSED");
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
WritableSlice<VariableDescriptor, Boolean> MUST_BE_WRAPPED_IN_A_REF = Slices.createSimpleSetSlice("MUST_BE_WRAPPED_IN_A_REF");
enum DeferredTypeKey {DEFERRED_TYPE_KEY}
WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice("DEFERRED_TYPES");
WritableSlice<DeferredTypeKey, DeferredType> DEFERRED_TYPE = new CollectionSliceWrapper<DeferredTypeKey, DeferredType>(DEFERRED_TYPES, CommonSuppliers.<DeferredType>getArrayListSupplier());
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
@@ -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() {
@@ -172,7 +172,9 @@ public class BodyResolver {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
if (descriptor.getUnsubstitutedPrimaryConstructor() != null) {
JetType supertype = typeInferrer.getCallResolver().resolveCall(context.getTrace(), scopeForConstructor, ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
JetType supertype = typeInferrer.getCallResolver().resolveCall(
context.getTrace(), scopeForConstructor,
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE);
if (supertype != null) {
recordSupertype(typeReference, supertype);
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
@@ -290,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);
}
@@ -316,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";
@@ -334,7 +336,8 @@ public class BodyResolver {
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), functionInnerScope, null, call, NO_EXPECTED_TYPE);
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), functionInnerScope,
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE);
}
}
@@ -346,7 +349,7 @@ public class BodyResolver {
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(),
functionInnerScope,
ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE);
// call.getThisReference(),
// classDescriptor,
// classDescriptor.getDefaultType(),
@@ -377,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());
}
}
@@ -456,7 +459,7 @@ public class BodyResolver {
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
result.addTypeParameterDescriptor(typeParameterDescriptor);
}
ReceiverDescriptor receiver = propertyDescriptor.getReceiver();
ReceiverDescriptor receiver = propertyDescriptor.getReceiverParameter();
if (receiver.exists()) {
result.setImplicitReceiver(receiver);
}
@@ -516,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();
@@ -552,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);
}
});
}
@@ -195,6 +195,7 @@ public class ClassDescriptorResolver {
Visibility visibility = resolveVisibilityFromModifiers(function.getModifierList());
functionDescriptor.initialize(
receiverType,
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDescriptor),
typeParameterDescriptors,
valueParameterDescriptors,
returnType,
@@ -438,6 +439,7 @@ public class ClassDescriptorResolver {
resolveVisibilityFromModifiers(objectDeclaration.getModifierList()),
false,
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
JetPsiUtil.safeName(objectDeclaration.getName()),
null,
classDescriptor.getDefaultType());
@@ -481,17 +483,7 @@ public class ClassDescriptorResolver {
JetType type = getVariableType(scopeWithTypeParameters, property, true);
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
boolean hasBody = hasBody(property);
Modality defaultModality = getDefaultModality(containingDeclaration, hasBody);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
@@ -500,6 +492,7 @@ public class ClassDescriptorResolver {
resolveVisibilityFromModifiers(property.getModifierList()),
isVar,
receiverType,
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
JetPsiUtil.safeName(property.getName()),
isVar ? type : null,
type);
@@ -513,6 +506,21 @@ public class ClassDescriptorResolver {
return propertyDescriptor;
}
/*package*/ static boolean hasBody(JetProperty property) {
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
return hasBody;
}
@NotNull
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, boolean allowDeferred) {
// TODO : receiver?
@@ -532,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) {
@@ -756,6 +764,7 @@ public class ClassDescriptorResolver {
resolveVisibilityFromModifiers(parameter.getModifierList()),
isMutable,
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
name == null ? "<no name>" : name,
isMutable ? type : null,
type);
@@ -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);
}
}
@@ -117,9 +117,9 @@ public class DeclarationResolver {
@Override
public void visitEnumEntry(JetEnumEntry enumEntry) {
if (enumEntry.getPrimaryConstructorParameterList() == null) {
PropertyDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(namespaceLike, enumEntry, context.getClasses().get(enumEntry));
MutableClassDescriptor classObjectDescriptor = ((MutableClassDescriptor) namespaceLike).getClassObjectDescriptor();
assert classObjectDescriptor != null;
PropertyDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(classObjectDescriptor, enumEntry, context.getClasses().get(enumEntry));
classObjectDescriptor.addPropertyDescriptor(propertyDescriptor);
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Pair;
@@ -10,7 +11,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetKeywordToken;
@@ -20,7 +20,6 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
@@ -114,7 +113,7 @@ public class DeclarationsChecker {
private void checkObject(JetObjectDeclaration objectDeclaration, MutableClassDescriptor classDescriptor) {
checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD);
checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), Sets.newHashSet(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD));
}
private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) {
@@ -122,7 +121,9 @@ public class DeclarationsChecker {
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor);
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
ASTNode openModifierNode = member.getModifierList().getModifierNode(JetTokens.OPEN_KEYWORD);
JetModifierList modifierList = member.getModifierList();
assert modifierList != null;
ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD);
context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass));
}
}
@@ -136,6 +137,29 @@ public class DeclarationsChecker {
checkPropertyAbstractness(property, propertyDescriptor, classDescriptor);
checkPropertyInitializer(property, propertyDescriptor, classDescriptor);
checkAccessors(property, propertyDescriptor);
checkDeclaredTypeInPublicMember(property, propertyDescriptor);
}
private void checkDeclaredTypeInPublicMember(JetNamedDeclaration member, CallableMemberDescriptor memberDescriptor) {
PsiElement nameIdentifier = member.getNameIdentifier();
boolean hasDeferredType;
if (member instanceof JetProperty) {
hasDeferredType = ((JetProperty) member).getPropertyTypeRef() == null && ClassDescriptorResolver.hasBody((JetProperty) member);
}
else {
assert member instanceof JetFunction;
JetFunction function = (JetFunction) member;
hasDeferredType = function.getReturnTypeRef() == null && function.getBodyExpression() != null && !function.hasBlockBody();
}
if ((memberDescriptor.getVisibility() == Visibility.PUBLIC || memberDescriptor.getVisibility() == Visibility.PROTECTED) &&
hasDeferredType && nameIdentifier != null) {
JetType returnType = memberDescriptor.getReturnType();
if (returnType instanceof DeferredType) {
returnType = ((DeferredType) returnType).getActualType();
}
context.getTrace().report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member, nameIdentifier, returnType));
}
}
private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {
@@ -225,24 +249,13 @@ public class DeclarationsChecker {
}
}
protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
protected void checkFunction(JetNamedFunction function, FunctionDescriptor functionDescriptor) {
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
PsiElement nameIdentifier;
boolean isPropertyAccessor = false;
if (function instanceof JetNamedFunction) {
nameIdentifier = ((JetNamedFunction) function).getNameIdentifier();
}
else if (function instanceof JetPropertyAccessor) {
isPropertyAccessor = true;
nameIdentifier = ((JetPropertyAccessor) function).getNamePlaceholder();
}
else {
throw new UnsupportedOperationException();
}
JetFunctionOrPropertyAccessor functionOrPropertyAccessor = (JetFunctionOrPropertyAccessor) function;
JetModifierList modifierList = functionOrPropertyAccessor.getModifierList();
PsiElement nameIdentifier = function.getNameIdentifier();
JetModifierList modifierList = function.getModifierList();
ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;
boolean hasAbstractModifier = abstractNode != null;
checkDeclaredTypeInPublicMember(function, functionDescriptor);
if (containingDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
@@ -251,46 +264,45 @@ public class DeclarationsChecker {
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetClass;
context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement));
context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement));
}
if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
if (hasAbstractModifier && inTrait) {
context.getTrace().report(REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, abstractNode, JetTokens.ABSTRACT_KEYWORD));
}
if (function.getBodyExpression() != null && hasAbstractModifier) {
context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor));
context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(function, abstractNode, functionDescriptor));
}
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) {
context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor));
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null) {
context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, nameIdentifier, functionDescriptor));
}
return;
}
if (hasAbstractModifier) {
if (!isPropertyAccessor) {
context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(functionOrPropertyAccessor, abstractNode, functionDescriptor));
}
else {
context.getTrace().report(NON_MEMBER_ABSTRACT_ACCESSOR.on(functionOrPropertyAccessor, abstractNode));
}
context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, abstractNode, functionDescriptor));
}
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) {
context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor));
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) {
context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, nameIdentifier, functionDescriptor));
}
}
private void checkAccessors(JetProperty property, PropertyDescriptor propertyDescriptor) {
for (JetPropertyAccessor accessor : property.getAccessors()) {
PropertyAccessorDescriptor accessorDescriptor = accessor.isGetter()
? propertyDescriptor.getGetter()
: propertyDescriptor.getSetter();
checkFunction(accessor, accessorDescriptor);
checkModifiers(accessor.getModifierList());
if (propertyDescriptor.getModality() == Modality.FINAL && accessor.hasModifier(JetTokens.OPEN_KEYWORD)) {
ASTNode openModifierNode = accessor.getModifierList().getModifierNode(JetTokens.OPEN_KEYWORD);
context.getTrace().report(NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY.on(accessor, openModifierNode, property));
checkIllegalInThisContextModifiers(accessor.getModifierList(), Sets.newHashSet(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD, JetTokens.OVERRIDE_KEYWORD));
}
JetPropertyAccessor getter = property.getGetter();
PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null;
if (getterModifierList != null && getterDescriptor != null) {
Map<JetKeywordToken, ASTNode> nodes = getNodesCorrespondingToModifiers(getterModifierList, Sets.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.INTERNAL_KEYWORD));
if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
for (Map.Entry<JetKeywordToken, ASTNode> entry : nodes.entrySet()) {
context.getTrace().report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(getterModifierList, entry.getValue(), entry.getKey()));
}
}
if (propertyDescriptor.getModality() != Modality.ABSTRACT && accessor.hasModifier(JetTokens.ABSTRACT_KEYWORD)) {
ASTNode abstractModifierNode = accessor.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD);
context.getTrace().report(ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY.on(accessor, abstractModifierNode, property));
else {
for (Map.Entry<JetKeywordToken, ASTNode> entry : nodes.entrySet()) {
context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(getterModifierList, entry.getValue(), entry.getKey()));
}
}
}
}
@@ -346,12 +358,23 @@ public class DeclarationsChecker {
}
}
private void checkIllegalInThisContextModifiers(@Nullable JetModifierList modifierList, JetKeywordToken... illegalModifiers) {
private void checkIllegalInThisContextModifiers(@Nullable JetModifierList modifierList, Collection<JetKeywordToken> illegalModifiers) {
if (modifierList == null) return;
for (JetKeywordToken modifier : illegalModifiers) {
if (modifierList.hasModifier(modifier)) {
context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList.getModifierNode(modifier), modifier));
context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList, modifierList.getModifierNode(modifier), modifier));
}
}
}
@NotNull
public static Map<JetKeywordToken, ASTNode> getNodesCorrespondingToModifiers(@NotNull JetModifierList modifierList, Collection<JetKeywordToken> possibleModifiers) {
Map<JetKeywordToken, ASTNode> nodes = Maps.newHashMap();
for (JetKeywordToken modifier : possibleModifiers) {
if (modifierList.hasModifier(modifier)) {
nodes.put(modifier, modifierList.getModifierNode(modifier));
}
}
return nodes;
}
}
@@ -4,11 +4,14 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author abreslav
*/
@@ -22,7 +25,7 @@ public class DescriptorUtils {
@Override
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
return descriptor.getReceiver().exists();
return descriptor.getReceiverParameter().exists();
}
@Override
@@ -32,7 +35,7 @@ public class DescriptorUtils {
@Override
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
return descriptor.getReceiver().exists();
return descriptor.getReceiverParameter().exists();
}
}, null);
}
@@ -111,4 +114,13 @@ public class DescriptorUtils {
if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
return modality;
}
@NotNull
public static ReceiverDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) {
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
return classDescriptor.getImplicitReceiver();
}
return NO_RECEIVER;
}
}
@@ -253,7 +253,7 @@ public class OverrideResolver {
}
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declared.getName() + " overrides nothing");
context.getTrace().report(NOTHING_TO_OVERRIDE.on(member, overrideNode, declared));
context.getTrace().report(NOTHING_TO_OVERRIDE.on(modifierList, overrideNode, declared));
}
PsiElement nameIdentifier = member.getNameIdentifier();
if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
@@ -4,6 +4,7 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.types.*;
@@ -37,24 +38,31 @@ public class OverridingUtil {
}
public static <D extends CallableDescriptor> Set<D> filterOverrides(Set<D> candidateSet) {
return filterOverrides(candidateSet, Function.ID);
}
public static <D> Set<D> filterOverrides(Set<D> candidateSet, Function<? super D, ? extends CallableDescriptor> transform) {
Set<D> candidates = Sets.newLinkedHashSet();
outerLoop:
for (D me : candidateSet) {
for (D other : candidateSet) {
for (D meD : candidateSet) {
CallableDescriptor me = transform.fun(meD);
for (D otherD : candidateSet) {
CallableDescriptor other = transform.fun(otherD);
if (me == other) continue;
if (overrides(other, me)) {
continue outerLoop;
}
}
for (D other : candidates) {
for (D otherD : candidates) {
CallableDescriptor other = transform.fun(otherD);
if (me.getOriginal() == other.getOriginal()
&& isOverridableBy(other, me).isSuccess()
&& isOverridableBy(me, other).isSuccess()) {
&& isOverridableBy(other, me).isSuccess()
&& isOverridableBy(me, other).isSuccess()) {
continue outerLoop;
}
}
// System.out.println(me);
candidates.add(me);
candidates.add(meD);
}
// Set<D> candidates = Sets.newLinkedHashSet(candidateSet);
// for (D descriptor : candidateSet) {
@@ -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());
@@ -227,18 +227,20 @@ public class TypeHierarchyResolver {
}
else {
ClassifierDescriptor classifierDescriptor = null;
NamespaceDescriptor namespaceDescriptor = null;
JetSimpleNameExpression referenceExpression = null;
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;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
}
}
}
@@ -249,15 +251,28 @@ public class TypeHierarchyResolver {
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
String aliasName = importDirective.getAliasName();
String importedClassifierName = aliasName != null ? aliasName : classifierDescriptor.getName();
namespaceScope.importClassifierAlias(importedClassifierName, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
}
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.scopes.receivers.AbstractReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptorVisitor;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class AutoCastReceiver extends AbstractReceiverDescriptor {
private final ReceiverDescriptor original;
private final boolean canCast;
public AutoCastReceiver(@NotNull ReceiverDescriptor original, @NotNull JetType castTo, boolean canCast) {
super(castTo);
this.original = original;
this.canCast = canCast;
}
public boolean canCast() {
return canCast;
}
@NotNull
public ReceiverDescriptor getOriginal() {
return original;
}
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return original.accept(visitor, data);
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public interface AutoCastService {
AutoCastService NO_AUTO_CASTS = new AutoCastService() {
@Override
public DataFlowInfo getDataFlowInfo() {
return DataFlowInfo.getEmpty();
}
@Override
public boolean isNotNull(@NotNull ReceiverDescriptor receiver) {
return !receiver.getType().isNullable();
}
@Override
public List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor) {
return Collections.singletonList(receiverDescriptor);
}
};
List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor);
DataFlowInfo getDataFlowInfo();
boolean isNotNull(@NotNull ReceiverDescriptor receiver);
}
@@ -0,0 +1,42 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import java.util.List;
/**
* @author abreslav
*/
public class AutoCastServiceImpl implements AutoCastService {
private final DataFlowInfo dataFlowInfo;
private final BindingContext bindingContext;
public AutoCastServiceImpl(DataFlowInfo dataFlowInfo, BindingContext bindingContext) {
this.dataFlowInfo = dataFlowInfo;
this.bindingContext = bindingContext;
}
@Override
public List<ReceiverDescriptor> getVariantsForReceiver(ReceiverDescriptor receiverDescriptor) {
return AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverDescriptor);
}
@Override
public DataFlowInfo getDataFlowInfo() {
return dataFlowInfo;
}
@Override
public boolean isNotNull(@NotNull ReceiverDescriptor receiver) {
if (!receiver.getType().isNullable()) return true;
List<ReceiverDescriptor> autoCastVariants = AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiver);
for (ReceiverDescriptor autoCastVariant : autoCastVariants) {
if (!autoCastVariant.getType().isNullable()) return true;
}
return false;
}
}
@@ -0,0 +1,149 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.JetThisExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
/**
* @author abreslav
*/
public class AutoCastUtils {
private AutoCastUtils() {}
public static List<ReceiverDescriptor> getAutoCastVariants(@NotNull final BindingContext bindingContext, @NotNull final DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiverToCast) {
return receiverToCast.accept(new ReceiverDescriptorVisitor<List<ReceiverDescriptor>, Object>() {
@Override
public List<ReceiverDescriptor> visitNoReceiver(ReceiverDescriptor noReceiver, Object data) {
return Collections.emptyList();
}
@Override
public List<ReceiverDescriptor> visitTransientReceiver(TransientReceiver receiver, Object data) {
return Collections.emptyList();
}
@Override
public List<ReceiverDescriptor> visitExtensionReceiver(ExtensionReceiver receiver, Object data) {
return castThis(dataFlowInfo, receiver);
}
@Override
public List<ReceiverDescriptor> visitClassReceiver(ClassReceiver receiver, Object data) {
return castThis(dataFlowInfo, receiver);
}
@Override
public List<ReceiverDescriptor> visitExpressionReceiver(ExpressionReceiver receiver, Object data) {
JetExpression expression = receiver.getExpression();
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(bindingContext, expression);
if (variableDescriptor != null) {
List<ReceiverDescriptor> result = Lists.newArrayList();
for (JetType possibleType : dataFlowInfo.getPossibleTypesForVariable(variableDescriptor)) {
result.add(new AutoCastReceiver(receiver, possibleType, isAutoCastable(variableDescriptor)));
}
return result;
}
else if (expression instanceof JetThisExpression) {
return castThis(dataFlowInfo, receiver);
}
return Collections.emptyList();
}
}, null);
}
private static List<ReceiverDescriptor> castThis(@NotNull DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiver) {
assert receiver.exists();
List<ReceiverDescriptor> result = Lists.newArrayList();
for (JetType possibleType : dataFlowInfo.getPossibleTypesForReceiver(receiver)) {
result.add(new AutoCastReceiver(receiver, possibleType, true));
}
return result;
}
@Nullable
public static JetType castExpression(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) {
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(trace.getBindingContext(), expression);
// boolean appropriateTypeFound = false;
if (variableDescriptor != null) {
List<JetType> possibleTypes = Lists.newArrayList(dataFlowInfo.getPossibleTypesForVariable(variableDescriptor));
Collections.reverse(possibleTypes);
for (JetType possibleType : possibleTypes) {
if (typeChecker.isSubtypeOf(possibleType, expectedType)) {
if (isAutoCastable(variableDescriptor)) {
trace.record(AUTOCAST, expression, possibleType);
}
else {
trace.report(AUTOCAST_IMPOSSIBLE.on(expression, possibleType, expression.getText()));
}
return possibleType;
}
}
// if (!appropriateTypeFound) {
// JetType notnullType = dataFlowInfo.getOutType(variableDescriptor);
// if (notnullType != null && typeChecker.isSubtypeOf(notnullType, expectedType)) {
// appropriateTypeFound = true;
// }
// }
}
return null;
}
@Nullable
public static VariableDescriptor getVariableDescriptorFromSimpleName(@NotNull BindingContext bindingContext, @NotNull JetExpression expression) {
// if (expression instanceof JetBinaryExpressionWithTypeRHS) {
// JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) expression;
// if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) {
// return getVariableDescriptorFromSimpleName(bindingContext, expression.getLeft());
// }
// }
JetExpression receiver = JetPsiUtil.deparenthesize(expression);
VariableDescriptor variableDescriptor = null;
if (receiver instanceof JetSimpleNameExpression) {
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiver;
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, nameExpression);
if (declarationDescriptor instanceof VariableDescriptor) {
variableDescriptor = (VariableDescriptor) declarationDescriptor;
}
}
return variableDescriptor;
}
public static boolean isAutoCastable(@NotNull VariableDescriptor variableDescriptor) {
if (variableDescriptor.isVar()) return false;
if (variableDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if (classDescriptor.getModality().isOverridable() && propertyDescriptor.getModality().isOverridable()) return false;
}
else {
assert !propertyDescriptor.getModality().isOverridable() : "Property outside a class must not be overridable";
}
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
if (getter == null || !getter.isDefault()) return false;
}
return true;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,22 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public class DefaultValueArgument implements ResolvedValueArgument {
public static final DefaultValueArgument DEFAULT = new DefaultValueArgument();
private DefaultValueArgument() {}
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
return Collections.emptyList(); //throw new UnsupportedOperationException("Look into the default value of the parameter");
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public class ExpressionValueArgument implements ResolvedValueArgument {
private final JetExpression expression;
public ExpressionValueArgument(@Nullable JetExpression expression) {
this.expression = expression;
}
// Nullable when something like f(a, , b) was in the source code
@Nullable
public JetExpression getExpression() {
return expression;
}
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
if (expression == null) return Collections.emptyList();
return Collections.singletonList(expression);
}
}
@@ -1,96 +0,0 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
/**
* @author abreslav
*/
public class OverloadResolutionResult<D> {
public enum Code {
SUCCESS(true),
NAME_NOT_FOUND(false),
SINGLE_CANDIDATE_ARGUMENT_MISMATCH(false),
AMBIGUITY(false),
MANY_FAILED_CANDIDATES(false);
private final boolean success;
Code(boolean success) {
this.success = success;
}
boolean isSuccess() {
return success;
}
}
public static <D> OverloadResolutionResult<D> success(@NotNull D descriptor) {
return new OverloadResolutionResult<D>(Code.SUCCESS, Collections.singleton(descriptor));
}
public static <D> OverloadResolutionResult<D> nameNotFound() {
return new OverloadResolutionResult<D>(Code.NAME_NOT_FOUND, Collections.<D>emptyList());
}
public static <D> OverloadResolutionResult<D> singleFailedCandidate(D candidate) {
return new OverloadResolutionResult<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
}
public static <D> OverloadResolutionResult<D> manyFailedCandidates(Set<D> failedCandidates) {
return new OverloadResolutionResult<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
}
public static <D> OverloadResolutionResult<D> ambiguity(Collection<D> descriptors) {
return new OverloadResolutionResult<D>(Code.AMBIGUITY, descriptors);
}
private final Collection<D> descriptors;
private final Code resultCode;
public OverloadResolutionResult(@NotNull Code resultCode, @NotNull Collection<D> descriptors) {
this.descriptors = descriptors;
this.resultCode = resultCode;
}
@NotNull
public Collection<D> getDescriptors() {
return descriptors;
}
@NotNull
public D getDescriptor() {
assert singleDescriptor();
return descriptors.iterator().next();
}
@NotNull
public Code getResultCode() {
return resultCode;
}
public boolean isSuccess() {
return resultCode.isSuccess();
}
public boolean singleDescriptor() {
return isSuccess() || resultCode == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH;
}
public boolean isNothing() {
return resultCode == Code.NAME_NOT_FOUND;
}
public boolean isAmbiguity() {
return resultCode == Code.AMBIGUITY;
}
public OverloadResolutionResult<D> newContents(@NotNull Collection<D> functionDescriptors) {
return new OverloadResolutionResult<D>(resultCode, functionDescriptors);
}
}
@@ -0,0 +1,94 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public class OverloadResolutionResults<D extends CallableDescriptor> {
public enum Code {
SUCCESS(true),
NAME_NOT_FOUND(false),
SINGLE_CANDIDATE_ARGUMENT_MISMATCH(false),
AMBIGUITY(false),
MANY_FAILED_CANDIDATES(false);
private final boolean success;
Code(boolean success) {
this.success = success;
}
boolean isSuccess() {
return success;
}
}
public static <D extends CallableDescriptor> OverloadResolutionResults<D> success(@NotNull ResolvedCall<D> descriptor) {
return new OverloadResolutionResults<D>(Code.SUCCESS, Collections.singleton(descriptor));
}
public static <D extends CallableDescriptor> OverloadResolutionResults<D> nameNotFound() {
return new OverloadResolutionResults<D>(Code.NAME_NOT_FOUND, Collections.<ResolvedCall<D>>emptyList());
}
public static <D extends CallableDescriptor> OverloadResolutionResults<D> singleFailedCandidate(ResolvedCall<D> candidate) {
return new OverloadResolutionResults<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
}
public static <D extends CallableDescriptor> OverloadResolutionResults<D> manyFailedCandidates(Collection<ResolvedCall<D>> failedCandidates) {
return new OverloadResolutionResults<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
}
public static <D extends CallableDescriptor> OverloadResolutionResults<D> ambiguity(Collection<ResolvedCall<D>> descriptors) {
return new OverloadResolutionResults<D>(Code.AMBIGUITY, descriptors);
}
private final Collection<ResolvedCall<D>> results;
private final Code resultCode;
private OverloadResolutionResults(@NotNull Code resultCode, @NotNull Collection<ResolvedCall<D>> results) {
this.results = results;
this.resultCode = resultCode;
}
@NotNull
public Collection<ResolvedCall<D>> getResults() {
return results;
}
@NotNull
public ResolvedCall<D> getResult() {
assert singleDescriptor();
return results.iterator().next();
}
@NotNull
public Code getResultCode() {
return resultCode;
}
public boolean isSuccess() {
return resultCode.isSuccess();
}
public boolean singleDescriptor() {
return isSuccess() || resultCode == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH;
}
public boolean isNothing() {
return resultCode == Code.NAME_NOT_FOUND;
}
public boolean isAmbiguity() {
return resultCode == Code.AMBIGUITY;
}
//
// public OverloadResolutionResults<D> newContents(@NotNull Collection<D> functionDescriptors) {
// return new OverloadResolutionResults<D>(resultCode, functionDescriptors);
// }
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Maps;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
@@ -8,13 +9,12 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author abreslav
@@ -28,22 +28,35 @@ public class OverloadingConflictResolver {
}
@Nullable
public <Descriptor extends CallableDescriptor> Descriptor findMaximallySpecific(Map<Descriptor, Descriptor> candidates, Map<Descriptor, TemporaryBindingTrace> traces, boolean discriminateGenericDescriptors) {
Map<Descriptor, TemporaryBindingTrace> maximallySpecific = Maps.newHashMap();
public <D extends CallableDescriptor> ResolvedCall<D> findMaximallySpecific(Set<ResolvedCall<D>> candidates, boolean discriminateGenericDescriptors) {
// Different autocasts may lead to the same candidate descriptor wrapped into different ResolvedCall objects
Set<ResolvedCall<D>> maximallySpecific = new THashSet<ResolvedCall<D>>(new TObjectHashingStrategy<ResolvedCall<D>>() {
@Override
public boolean equals(ResolvedCall<D> o1, ResolvedCall<D> o2) {
return o1 == null ? o2 == null : o1.getResultingDescriptor().equals(o2.getResultingDescriptor());
}
@Override
public int computeHashCode(ResolvedCall<D> object) {
return object == null ? 0 : object.getResultingDescriptor().hashCode();
}
});
meLoop:
for (Map.Entry<Descriptor, Descriptor> myEntry : candidates.entrySet()) {
Descriptor me = myEntry.getValue();
TemporaryBindingTrace myTrace = traces.get(myEntry.getKey());
for (Descriptor other : candidates.values()) {
for (ResolvedCall<D> candidateCall : candidates) {
D me = candidateCall.getResultingDescriptor();
for (ResolvedCall<D> otherCall : candidates) {
D other = otherCall.getResultingDescriptor();
if (other == me) continue;
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) continue meLoop;
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) {
continue meLoop;
}
}
maximallySpecific.put(me, myTrace);
maximallySpecific.add(candidateCall);
}
if (maximallySpecific.size() == 1) {
Map.Entry<Descriptor, TemporaryBindingTrace> result = maximallySpecific.entrySet().iterator().next();
result.getValue().commit();
return result.getKey();
ResolvedCall<D> result = maximallySpecific.iterator().next();
result.getTrace().commit();
return result;
}
return null;
}
@@ -59,9 +72,9 @@ public class OverloadingConflictResolver {
if (OverridingUtil.overrides(f, g)) return true;
if (OverridingUtil.overrides(g, f)) return false;
ReceiverDescriptor receiverOfF = f.getReceiver();
ReceiverDescriptor receiverOfG = g.getReceiver();
if (f.getReceiver().exists() && g.getReceiver().exists()) {
ReceiverDescriptor receiverOfF = f.getReceiverParameter();
ReceiverDescriptor receiverOfG = g.getReceiverParameter();
if (f.getReceiverParameter().exists() && g.getReceiverParameter().exists()) {
if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve.calls;
/**
* @author abreslav
*/
public enum ResolutionStatus {
UNKNOWN_STATUS,
UNSAFE_CALL_ERROR,
OTHER_ERROR,
SUCCESS(true);
private final boolean success;
private ResolutionStatus(boolean success) {
this.success = success;
}
private ResolutionStatus() {
this(false);
}
public boolean isSuccess() {
return success;
}
public ResolutionStatus combine(ResolutionStatus other) {
if (this.isSuccess()) return other;
if (this.isWeakError() && !other.isSuccess()) return other;
return this;
}
public boolean isWeakError() {
return this == UNSAFE_CALL_ERROR;
}
}
@@ -1,81 +1,53 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetTypeProjection;
import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import java.util.Collection;
import java.util.List;
/**
* @author abreslav
*/
/*package*/ class ResolutionTask<Descriptor extends CallableDescriptor> {
private final Collection<Descriptor> candidates;
private final ReceiverDescriptor receiver;
private final List<JetTypeProjection> typeArguments;
private final List<? extends ValueArgument> valueArguments;
private final List<JetExpression> functionLiteralArguments;
/*package*/ class ResolutionTask<D extends CallableDescriptor> {
private final Call call;
private final Collection<ResolvedCall<D>> candidates;
private final DataFlowInfo dataFlowInfo;
private DescriptorCheckStrategy checkingStrategy;
public ResolutionTask(
@NotNull Collection<Descriptor> candidates,
@NotNull ReceiverDescriptor receiver,
@NotNull List<JetTypeProjection> typeArguments,
@NotNull List<? extends ValueArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments) {
this.candidates = candidates;
this.receiver = receiver;
this.typeArguments = typeArguments;
this.valueArguments = valueArguments;
this.functionLiteralArguments = functionLiteralArguments;
}
public ResolutionTask(
@NotNull Collection<Descriptor> candidates,
@NotNull ReceiverDescriptor receiver,
@NotNull Call call
@NotNull Collection<ResolvedCall<D>> candidates,
@NotNull Call call,
@NotNull DataFlowInfo dataFlowInfo
) {
this(candidates, receiver, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
this.candidates = candidates;
this.call = call;
this.dataFlowInfo = dataFlowInfo;
}
@NotNull
public Collection<Descriptor> getCandidates() {
public DataFlowInfo getDataFlowInfo() {
return dataFlowInfo;
}
@NotNull
public Collection<ResolvedCall<D>> getCandidates() {
return candidates;
}
@NotNull
public ReceiverDescriptor getReceiver() {
return receiver;
public Call getCall() {
return call;
}
@NotNull
public List<JetTypeProjection> getTypeArguments() {
return typeArguments;
}
@NotNull
public List<? extends ValueArgument> getValueArguments() {
return valueArguments;
}
@NotNull
public List<JetExpression> getFunctionLiteralArguments() {
return functionLiteralArguments;
}
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
checkingStrategy = strategy;
}
public boolean performAdvancedChecks(Descriptor descriptor, BindingTrace trace, TracingStrategy tracing) {
public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) {
return false;
}
@@ -0,0 +1,147 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.UNKNOWN_STATUS;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author abreslav
*/
public class ResolvedCall<D extends CallableDescriptor> {
public static final Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor>() {
@Override
public CallableDescriptor fun(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
return resolvedCall.getCandidateDescriptor();
}
};
public static final Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_RESULT = new Function<ResolvedCall<? extends CallableDescriptor>, CallableDescriptor>() {
@Override
public CallableDescriptor fun(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
return resolvedCall.getResultingDescriptor();
}
};
@NotNull
public static <D extends CallableDescriptor> ResolvedCall<D> create(@NotNull D descriptor) {
return new ResolvedCall<D>(descriptor);
}
@NotNull
public static <D extends CallableDescriptor> List<ResolvedCall<D>> convertCollection(@NotNull Collection<D> descriptors) {
List<ResolvedCall<D>> result = Lists.newArrayList();
for (D descriptor : descriptors) {
result.add(create(descriptor));
}
return result;
}
private final D candidateDescriptor;
private D resultingDescriptor; // Probably substituted
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
private boolean someArgumentHasNoType = false;
private TemporaryBindingTrace trace;
private ResolutionStatus status = UNKNOWN_STATUS;
private ResolvedCall(@NotNull D candidateDescriptor) {
this.candidateDescriptor = candidateDescriptor;
}
@NotNull
public ResolutionStatus getStatus() {
return status;
}
public void setStatus(@NotNull ResolutionStatus status) {
this.status = status;
}
@NotNull
public TemporaryBindingTrace getTrace() {
return trace;
}
public void setTrace(@NotNull TemporaryBindingTrace trace) {
this.trace = trace;
}
@NotNull
public D getCandidateDescriptor() {
return candidateDescriptor;
}
@NotNull
public D getResultingDescriptor() {
return resultingDescriptor == null ? candidateDescriptor : resultingDescriptor;
}
public ResolvedCall<D> setResultingDescriptor(@NotNull D resultingDescriptor) {
this.resultingDescriptor = resultingDescriptor;
return this;
}
public void recordTypeArgument(@NotNull TypeParameterDescriptor typeParameter, @NotNull JetType typeArgument) {
assert !typeArguments.containsKey(typeParameter);
typeArguments.put(typeParameter, typeArgument);
}
public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) {
assert !valueArguments.containsKey(valueParameter);
valueArguments.put(valueParameter, valueArgument);
}
public void autoCastValueArgument(@NotNull ValueParameterDescriptor parameter, @NotNull JetType target) {
assert !autoCasts.containsKey(parameter);
autoCasts.put(parameter, target);
}
@NotNull
public ReceiverDescriptor getReceiverArgument() {
return receiverArgument;
}
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverParameter) {
this.receiverArgument = receiverParameter;
}
@NotNull
public ReceiverDescriptor getThisObject() {
return thisObject;
}
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
this.thisObject = thisObject;
}
@NotNull
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
return valueArguments;
}
public void argumentHasNoType() {
this.someArgumentHasNoType = true;
}
public boolean isDirty() {
return someArgumentHasNoType;
}
}
@@ -0,0 +1,15 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
/**
* @author abreslav
*/
public interface ResolvedValueArgument {
@NotNull
List<JetExpression> getArgumentExpressions();
}
@@ -2,31 +2,39 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DataFlowInfo;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
import org.jetbrains.jet.lang.types.NamespaceType;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author abreslav
*/
/*package*/ abstract class TaskPrioritizer<D extends CallableDescriptor> {
public static <T extends DeclarationDescriptor> void splitLexicallyLocalDescriptors(
Collection<? extends T> allDescriptors, DeclarationDescriptor containerOfTheCurrentLocality, List<? super T> local, List<? super T> nonlocal) {
public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors(
Collection<ResolvedCall<D>> allDescriptors, DeclarationDescriptor containerOfTheCurrentLocality, Collection<ResolvedCall<D>> local, Collection<ResolvedCall<D>> nonlocal) {
for (T descriptor : allDescriptors) {
if (isLocal(containerOfTheCurrentLocality, descriptor)) {
local.add(descriptor);
for (ResolvedCall<D> resolvedCall : allDescriptors) {
if (isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) {
local.add(resolvedCall);
}
else {
nonlocal.add(descriptor);
nonlocal.add(resolvedCall);
}
}
}
@@ -43,7 +51,7 @@ import java.util.List;
*
* local extension prevail over members (and members prevail over all non-local extensions)
*/
public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
private static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
if (candidate instanceof ValueParameterDescriptor) {
return true;
}
@@ -62,67 +70,132 @@ import java.util.List;
return false;
}
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
List<ResolutionTask<D>> result = Lists.newArrayList();
doComputeTasks(scope, receiver, call, name, result);
ReceiverDescriptor explicitReceiver = call.getExplicitReceiver();
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
scope = explicitReceiver.getType().getMemberScope();
explicitReceiver = NO_RECEIVER;
}
doComputeTasks(scope, explicitReceiver, call, name, result, AutoCastService.NO_AUTO_CASTS);
ReceiverDescriptor receiverToCast = explicitReceiver.exists() ? explicitReceiver : scope.getImplicitReceiver();
if (receiverToCast.exists()) {
doComputeTasks(scope, receiverToCast, call, name, result, new AutoCastServiceImpl(dataFlowInfo, bindingContext));
}
return result;
}
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result) {
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiver != ReceiverDescriptor.NO_RECEIVER) {
Collection<D> extensionFunctions = getExtensionsByName(scope, name);
List<D> nonlocals = Lists.newArrayList();
List<D> locals = Lists.newArrayList();
if (receiver.exists()) {
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
Collection<ResolvedCall<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name));
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
List<ResolvedCall<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
Collection<D> members = getMembersByName(receiver, name);
Collection<ResolvedCall<D>> members = Lists.newArrayList();
for (ReceiverDescriptor variant : variantsForExplicitReceiver) {
Collection<D> membersForThisVariant = getMembersByName(variant.getType(), name);
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members);
}
addTask(result, receiver, call, locals);
addTask(result, ReceiverDescriptor.NO_RECEIVER, call, members);
addTask(result, call, locals, dataFlowInfo);
addTask(result, call, members, dataFlowInfo);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
addTask(result, receiver, call, memberExtensions);
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
addTask(result, call, convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver), dataFlowInfo);
}
addTask(result, receiver, call, nonlocals);
addTask(result, call, nonlocals, dataFlowInfo);
}
else {
Collection<D> functions = getNonExtensionsByName(scope, name);
Collection<ResolvedCall<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
List<D> nonlocals = Lists.newArrayList();
List<D> locals = Lists.newArrayList();
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
List<ResolvedCall<D>> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
addTask(result, receiver, call, locals);
addTask(result, call, locals, dataFlowInfo);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
doComputeTasks(scope, implicitReceiver, call, name, result);
doComputeTasks(scope, implicitReceiver, call, name, result, autoCastService);
}
addTask(result, receiver, call, nonlocals);
addTask(result, call, nonlocals, dataFlowInfo);
}
}
private Collection<ResolvedCall<D>> convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) {
Collection<ResolvedCall<D>> result = Lists.newArrayList();
convertWithReceivers(descriptors, thisObjects, receiverParameters, result);
return result;
}
private void convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolvedCall<D>> result) {
// Collection<ResolvedCall<D>> result = Lists.newArrayList();
for (ReceiverDescriptor thisObject : thisObjects) {
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D extension : descriptors) {
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
resolvedCall.setThisObject(thisObject);
resolvedCall.setReceiverArgument(receiverParameter);
result.add(resolvedCall);
}
}
}
// return result;
}
public static <D extends CallableDescriptor> Collection<ResolvedCall<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<D> descriptors) {
Collection<ResolvedCall<D>> result = Lists.newArrayList();
for (ReceiverDescriptor receiverParameter : receiverParameters) {
for (D extension : descriptors) {
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
resolvedCall.setReceiverArgument(receiverParameter);
if (setImpliedThis(scope, resolvedCall)) {
result.add(resolvedCall);
}
}
}
return result;
}
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolvedCall<D> resolvedCall) {
ReceiverDescriptor expectedThisObject = resolvedCall.getCandidateDescriptor().getExpectedThisObject();
if (!expectedThisObject.exists()) return true;
List<ReceiverDescriptor> receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers);
for (ReceiverDescriptor receiver : receivers) {
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
// TODO : Autocasts & nullability
resolvedCall.setThisObject(expectedThisObject);
return true;
}
}
return false;
}
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCall<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
if (candidates.isEmpty()) return;
result.add(new ResolutionTask<D>(candidates, call, dataFlowInfo));
}
@NotNull
protected abstract Collection<D> getNonExtensionsByName(JetScope scope, String name);
@NotNull
protected abstract Collection<D> getMembersByName(@NotNull ReceiverDescriptor receiver, String name);
protected abstract Collection<D> getMembersByName(@NotNull JetType receiver, String name);
@NotNull
protected abstract Collection<D> getExtensionsByName(JetScope scope, String name);
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull Collection<D> candidates) {
if (candidates.isEmpty()) return;
result.add(createTask(receiver, call, candidates));
}
@NotNull
protected abstract ResolutionTask<D> createTask(ReceiverDescriptor receiver, Call call, Collection<D> candidates);
}
@@ -0,0 +1,118 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
/**
* @author abreslav
*/
public class TaskPrioritizers {
/*package*/ static TaskPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer<FunctionDescriptor>() {
@NotNull
@Override
protected Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, String name) {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
if (functionDescriptor.getReceiverParameter().exists()) {
iterator.remove();
}
}
addConstructors(scope, name, functions);
addVariableAsFunction(scope, name, functions, false);
return functions;
}
@NotNull
@Override
protected Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
JetScope receiverScope = receiverType.getMemberScope();
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
addConstructors(receiverScope, name, members);
addVariableAsFunction(receiverScope, name, members, false);
return members;
}
@NotNull
@Override
protected Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) {
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next();
if (!descriptor.getReceiverParameter().exists()) {
iterator.remove();
}
}
addVariableAsFunction(scope, name, extensionFunctions, true);
return extensionFunctions;
}
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
ClassifierDescriptor classifier = scope.getClassifier(name);
if (classifier instanceof ClassDescriptor && !ErrorUtils.isError(classifier.getTypeConstructor())) {
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
functions.addAll(classDescriptor.getConstructors());
}
}
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && !variable.getReceiverParameter().exists()) {
JetType outType = variable.getOutType();
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
if ((functionDescriptor.getReceiverParameter().exists()) == receiverNeeded) {
functions.add(functionDescriptor);
}
}
}
}
};
/*package*/ static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
@NotNull
@Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && !variable.getReceiverParameter().exists()) {
return Collections.singleton(variable);
}
return Collections.emptyList();
}
@NotNull
@Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
VariableDescriptor variable = receiverType.getMemberScope().getVariable(name);
if (variable != null) {
return Collections.singleton(variable);
}
return Collections.emptyList();
}
@NotNull
@Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiverParameter().exists()) {
return Collections.singleton(variable);
}
return Collections.emptyList();
}
};
}
@@ -5,6 +5,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.Set;
@@ -15,17 +16,20 @@ import java.util.Set;
/*package*/ interface TracingStrategy {
TracingStrategy EMPTY = new TracingStrategy() {
@Override
public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {}
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall) {}
@Override
public void unresolvedReference(@NotNull BindingTrace trace) {}
@Override
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {}
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCall<D>> candidates) {}
@Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
@Override
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {}
@Override
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
@@ -36,37 +40,49 @@ import java.util.Set;
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {}
@Override
public void ambiguity(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {}
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {}
@Override
public void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors) {}
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors) {}
@Override
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {}
@Override
public void typeInferenceFailed(@NotNull BindingTrace trace) {}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
@Override
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
};
void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor);
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall);
void unresolvedReference(@NotNull BindingTrace trace);
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates);
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCall<D>> candidates);
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument);
void noReceiverAllowed(@NotNull BindingTrace trace);
void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter);
void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount);
void ambiguity(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors);
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors);
void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<? extends CallableDescriptor> descriptors);
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCall<D>> descriptors);
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
void typeInferenceFailed(@NotNull BindingTrace trace);
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
}
@@ -6,7 +6,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.CallMaker;
import java.util.List;
@@ -20,15 +21,17 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
* @author abreslav
*/
/*package*/ class ValueArgumentsToParametersMapper {
public static <Descriptor extends CallableDescriptor> boolean mapValueArgumentsToParameters(
@NotNull ResolutionTask<Descriptor> task,
public static <D extends CallableDescriptor> boolean mapValueArgumentsToParameters(
@NotNull ResolutionTask<D> task,
@NotNull TracingStrategy tracing,
@NotNull Descriptor candidate,
@NotNull BindingTrace temporaryTrace,
@NotNull Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters
@NotNull ResolvedCall<D> candidateCall
) {
TemporaryBindingTrace temporaryTrace = candidateCall.getTrace();
Map<ValueParameterDescriptor, VarargValueArgument> varargs = Maps.newHashMap();
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
D candidate = candidateCall.getCandidateDescriptor();
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
Map<String, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
@@ -36,7 +39,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
parameterByName.put(valueParameter.getName(), valueParameter);
}
List<? extends ValueArgument> valueArguments = task.getValueArguments();
List<? extends ValueArgument> valueArguments = task.getCall().getValueArguments();
boolean error = false;
boolean someNamed = false;
@@ -58,7 +61,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
temporaryTrace.report(ARGUMENT_PASSED_TWICE.on(nameReference));
}
temporaryTrace.record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
}
if (somePositioned) {
// temporaryTrace.getErrorHandler().genericError(nameNode, "Mixing named and positioned arguments in not allowed");
@@ -78,12 +81,12 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
if (i < parameterCount) {
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
usedParameters.add(valueParameterDescriptor);
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
}
else if (!valueParameters.isEmpty()) {
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
if (valueParameterDescriptor.isVararg()) {
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
usedParameters.add(valueParameterDescriptor);
}
else {
@@ -101,7 +104,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
}
}
List<JetExpression> functionLiteralArguments = task.getFunctionLiteralArguments();
List<JetExpression> functionLiteralArguments = task.getCall().getFunctionLiteralArguments();
if (!functionLiteralArguments.isEmpty()) {
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
@@ -109,7 +112,8 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
// temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), getTooManyArgumentsMessage(candidate));
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
error = true;
} else {
}
else {
JetFunctionLiteralExpression functionLiteral;
if (possiblyLabeledFunctionLiteral instanceof JetLabelQualifiedExpression) {
JetLabelQualifiedExpression labeledFunctionLiteral = (JetLabelQualifiedExpression) possiblyLabeledFunctionLiteral;
@@ -119,20 +123,20 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
functionLiteral = (JetFunctionLiteralExpression) possiblyLabeledFunctionLiteral;
}
ValueParameterDescriptor parameterDescriptor = valueParameters.get(valueParameters.size() - 1);
if (parameterDescriptor.isVararg()) {
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
if (valueParameterDescriptor.isVararg()) {
// temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), "Passing value as a vararg is only allowed inside a parenthesized argument list");
temporaryTrace.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
error = true;
}
else {
if (!usedParameters.add(parameterDescriptor)) {
if (!usedParameters.add(valueParameterDescriptor)) {
// temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), getTooManyArgumentsMessage(candidate));
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
error = true;
}
else {
argumentsToParameters.put(CallMaker.makeValueArgument(functionLiteral), parameterDescriptor);
put(candidateCall, valueParameterDescriptor, CallMaker.makeValueArgument(functionLiteral), varargs);
}
}
}
@@ -148,16 +152,52 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
for (ValueParameterDescriptor valueParameter : valueParameters) {
if (!usedParameters.contains(valueParameter)) {
if (!valueParameter.hasDefaultValue() && !valueParameter.isVararg()) {
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
if (valueParameter.hasDefaultValue()) {
candidateCall.recordValueArgument(valueParameter, DefaultValueArgument.DEFAULT);
}
else if (valueParameter.isVararg()) {
candidateCall.recordValueArgument(valueParameter, new VarargValueArgument());
}
else {
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
tracing.noValueForParameter(temporaryTrace, valueParameter);
error = true;
}
}
}
ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
if (receiverParameter.exists() &&!receiverArgument.exists()) {
tracing.missingReceiver(temporaryTrace, receiverParameter);
error = true;
}
if (!receiverParameter.exists() && receiverArgument.exists()) {
tracing.noReceiverAllowed(temporaryTrace);
error = true;
}
assert candidateCall.getThisObject().exists() == candidateCall.getResultingDescriptor().getExpectedThisObject().exists() : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
return error;
}
private static <D extends CallableDescriptor> void put(ResolvedCall<D> candidateCall, ValueParameterDescriptor valueParameterDescriptor, ValueArgument valueArgument, Map<ValueParameterDescriptor, VarargValueArgument> varargs) {
if (valueParameterDescriptor.isVararg()) {
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
if (vararg == null) {
vararg = new VarargValueArgument();
varargs.put(valueParameterDescriptor, vararg);
candidateCall.recordValueArgument(valueParameterDescriptor, vararg);
}
vararg.getArgumentExpressions().add(valueArgument.getArgumentExpression());
}
else {
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument.getArgumentExpression());
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
}
}
// private static <Descriptor extends CallableDescriptor> String getTooManyArgumentsMessage(Descriptor candidate) {
// return "Too many arguments for " + DescriptorRenderer.TEXT.render(candidate);
// }
@@ -0,0 +1,20 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
/**
* @author abreslav
*/
public class VarargValueArgument implements ResolvedValueArgument {
private final List<JetExpression> values = Lists.newArrayList();
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
return values;
}
}
@@ -21,6 +21,8 @@ public interface WritableScope extends JetScope {
void addClassifierAlias(@NotNull String name, @NotNull ClassifierDescriptor classifierDescriptor);
void addNamespaceAlias(@NotNull String name, @NotNull NamespaceDescriptor namespaceDescriptor);
void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor);
@Nullable
@@ -27,9 +27,13 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Nullable
private SetMultimap<String, FunctionDescriptor> functionGroups;
@Nullable
private Map<String, DeclarationDescriptor> variableClassOrNamespaceDescriptors;
@Nullable
private Map<String, NamespaceDescriptor> namespaceAliases;
@Nullable
private Map<String, List<DeclarationDescriptor>> labelsToDescriptors;
@@ -66,6 +70,12 @@ public class WritableScopeImpl extends WritableScopeWithImports {
super.importClassifierAlias(importedClassifierName, classifierDescriptor);
}
@Override
public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) {
allDescriptors.add(namespaceDescriptor);
super.importNamespaceAlias(aliasName, namespaceDescriptor);
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -123,6 +133,14 @@ public class WritableScopeImpl extends WritableScopeWithImports {
return variableClassOrNamespaceDescriptors;
}
@NotNull
private Map<String, NamespaceDescriptor> getNamespaceAliases() {
if (namespaceAliases == null) {
namespaceAliases = Maps.newHashMap();
}
return namespaceAliases;
}
@Override
public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) {
Map<String, DeclarationDescriptor> variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors();
@@ -189,13 +207,23 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override
public void addClassifierAlias(@NotNull String name, @NotNull ClassifierDescriptor classifierDescriptor) {
Map<String, DeclarationDescriptor> variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors();
DeclarationDescriptor originalDescriptor = variableClassOrNamespaceDescriptors.get(name);
checkForRedeclaration(name, classifierDescriptor);
getVariableClassOrNamespaceDescriptors().put(name, classifierDescriptor);
allDescriptors.add(classifierDescriptor);
}
@Override
public void addNamespaceAlias(@NotNull String name, @NotNull NamespaceDescriptor namespaceDescriptor) {
checkForRedeclaration(name, namespaceDescriptor);
getNamespaceAliases().put(name, namespaceDescriptor);
allDescriptors.add(namespaceDescriptor);
}
private void checkForRedeclaration(String name, DeclarationDescriptor classifierDescriptor) {
DeclarationDescriptor originalDescriptor = getVariableClassOrNamespaceDescriptors().get(name);
if (originalDescriptor != null) {
redeclarationHandler.handleRedeclaration(originalDescriptor, classifierDescriptor);
}
variableClassOrNamespaceDescriptors.put(name, classifierDescriptor);
allDescriptors.add(classifierDescriptor);
}
@Override
@@ -242,6 +270,9 @@ public class WritableScopeImpl extends WritableScopeWithImports {
NamespaceDescriptor declaredNamespace = getDeclaredNamespace(name);
if (declaredNamespace != null) return declaredNamespace;
NamespaceDescriptor aliased = getNamespaceAliases().get(name);
if (aliased != null) return aliased;
NamespaceDescriptor namespace = getWorkerScope().getNamespace(name);
if (namespace != null) return namespace;
return super.getNamespace(name);
@@ -97,15 +97,24 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement
return null;
}
public void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor) {
private WritableScope getCurrentIndividualImportScope() {
if (currentIndividualImportScope == null) {
WritableScopeImpl writableScope = new WritableScopeImpl(EMPTY, getContainingDeclaration(), RedeclarationHandler.DO_NOTHING).setDebugName("Individual import scope");
importScope(writableScope);
currentIndividualImportScope = writableScope;
}
currentIndividualImportScope.addClassifierAlias(importedClassifierName, classifierDescriptor);
return currentIndividualImportScope;
}
public void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor) {
getCurrentIndividualImportScope().addClassifierAlias(importedClassifierName, classifierDescriptor);
}
public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) {
getCurrentIndividualImportScope().addNamespaceAlias(aliasName, namespaceDescriptor);
}
@Override
public String toString() {
return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + " " + debugName + " for " + getContainingDeclaration();
@@ -126,6 +126,11 @@ public class WriteThroughScope extends WritableScopeWithImports {
writableWorker.addClassifierAlias(name, classifierDescriptor);
}
@Override
public void addNamespaceAlias(@NotNull String name, @NotNull NamespaceDescriptor namespaceDescriptor) {
writableWorker.addNamespaceAlias(name, namespaceDescriptor);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
writableWorker.addNamespace(namespaceDescriptor);
@@ -2,14 +2,28 @@ package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class ClassReceiver extends ImplicitReceiverDescriptor {
public class ClassReceiver implements ReceiverDescriptor {
public ClassReceiver(ClassDescriptor classDescriptor) {
super(classDescriptor, classDescriptor.getDefaultType());
private final ClassDescriptor classDescriptor;
public ClassReceiver(@NotNull ClassDescriptor classDescriptor) {
this.classDescriptor = classDescriptor;
}
@Override
public boolean exists() {
return true;
}
@NotNull
@Override
public JetType getType() {
return classDescriptor.getDefaultType();
}
@Override
@@ -20,7 +20,7 @@ public class ReceiverDescriptorVisitor<R, D> {
return null;
}
public R visitClassReceiver(ClassReceiver classReceiver, D data) {
public R visitClassReceiver(ClassReceiver receiver, D data) {
return null;
}
}
@@ -1,10 +1,12 @@
package org.jetbrains.jet.lang.types;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collections;
import java.util.List;
@@ -17,8 +19,8 @@ public class CallMaker {
private static class ExpressionValueArgument implements ValueArgument {
private final JetExpression expression;
private final PsiElement reportErrorsOn;
private final PsiElement reportErrorsOn;
private ExpressionValueArgument(@NotNull JetExpression expression) {
this(expression, expression);
}
@@ -60,18 +62,72 @@ public class CallMaker {
}
}
private static abstract class CallStub implements Call {
private static class CallImpl implements Call {
private final ASTNode callNode;
private final PsiElement callElement;
private final ReceiverDescriptor explicitReceiver;
private ASTNode callOperationNode;
private final JetExpression calleeExpression;
private final List<? extends ValueArgument> valueArguments;
protected CallImpl(@NotNull ASTNode callNode, @Nullable PsiElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments) {
this.callNode = callNode;
this.callElement = callElement;
this.explicitReceiver = explicitReceiver;
this.callOperationNode = callOperationNode;
this.calleeExpression = calleeExpression;
this.valueArguments = valueArguments;
}
protected CallImpl(@NotNull PsiElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments) {
this(callElement.getNode(), callElement, explicitReceiver, callOperationNode, calleeExpression, valueArguments);
}
@Override
public ASTNode getCallOperationNode() {
return callOperationNode;
}
@NotNull
@Override
public ReceiverDescriptor getExplicitReceiver() {
return explicitReceiver;
}
@Override
public JetExpression getCalleeExpression() {
return calleeExpression;
}
@NotNull
@Override
public List<? extends ValueArgument> getValueArguments() {
return valueArguments;
}
@NotNull
@Override
public ASTNode getCallNode() {
return callNode;
}
@Override
public PsiElement getCallElement() {
return callElement;
}
@Override
public JetValueArgumentList getValueArgumentList() {
return null;
}
@NotNull
@Override
public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList();
}
@NotNull
@Override
public List<JetTypeProjection> getTypeArguments() {
@@ -83,42 +139,36 @@ public class CallMaker {
return null;
}
}
public static Call makeCallWithArguments(final JetExpression calleeExpression, final List<? extends ValueArgument> valueArguments) {
return new CallStub() {
@Override
public JetExpression getCalleeExpression() {
return calleeExpression;
}
@NotNull
@Override
public List<? extends ValueArgument> getValueArguments() {
return valueArguments;
}
};
@Override
public String toString() {
return getCallNode().getText();
}
}
public static Call makeCall(final JetExpression calleeExpression, final List<JetExpression> argumentExpressions) {
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<JetExpression> argumentExpressions) {
List<ValueArgument> arguments = Lists.newArrayList();
for (JetExpression argumentExpression : argumentExpressions) {
arguments.add(makeValueArgument(argumentExpression, calleeExpression));
}
return makeCallWithArguments(calleeExpression, arguments);
return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments);
}
public static Call makeCall(final JetBinaryExpression expression) {
return makeCall(expression.getOperationReference(), Collections.singletonList(expression.getRight()));
public static Call makeCall(JetElement callElement, ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, JetExpression calleeExpression, List<? extends ValueArgument> arguments) {
return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments);
}
public static Call makeCall(final JetUnaryExpression expression) {
return makeCallWithArguments(expression.getOperationSign(), Collections.<ValueArgument>emptyList());
public static Call makeCall(@NotNull ReceiverDescriptor leftAsReceiver, JetBinaryExpression expression) {
return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
}
public static Call makeCall(final JetArrayAccessExpression arrayAccessExpression, final JetExpression rightHandSide) {
public static Call makeCall(@NotNull ReceiverDescriptor baseAsReceiver, JetUnaryExpression expression) {
return makeCall(expression, baseAsReceiver, null, expression.getOperationSign(), Collections.<ValueArgument>emptyList());
}
public static Call makeCall(@NotNull ReceiverDescriptor arrayAsReceiver,JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide) {
List<JetExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
arguments.add(rightHandSide);
return makeCall(arrayAccessExpression, arguments);
return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments);
}
public static ValueArgument makeValueArgument(@NotNull JetExpression expression) {
@@ -129,7 +179,68 @@ public class CallMaker {
return new ExpressionValueArgument(expression, reportErrorsOn);
}
public static Call makePropertyCall(@NotNull JetSimpleNameExpression nameExpression) {
return makeCall(nameExpression, Collections.<JetExpression>emptyList());
public static Call makePropertyCall(@NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<JetExpression>emptyList());
}
public static Call makeCall(@NotNull final ReceiverDescriptor explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final JetCallElement callElement) {
return new Call() {
@Override
public ASTNode getCallOperationNode() {
return callOperationNode;
}
@NotNull
@Override
public ReceiverDescriptor getExplicitReceiver() {
return explicitReceiver;
}
@Nullable
public JetExpression getCalleeExpression() {
return callElement.getCalleeExpression();
}
@Nullable
public JetValueArgumentList getValueArgumentList() {
return callElement.getValueArgumentList();
}
@NotNull
public List<? extends ValueArgument> getValueArguments() {
return callElement.getValueArguments();
}
@NotNull
public List<JetExpression> getFunctionLiteralArguments() {
return callElement.getFunctionLiteralArguments();
}
@NotNull
public List<JetTypeProjection> getTypeArguments() {
return callElement.getTypeArguments();
}
@Nullable
public JetTypeArgumentList getTypeArgumentList() {
return callElement.getTypeArgumentList();
}
@NotNull
@Override
public ASTNode getCallNode() {
return callElement.getNode();
}
@Override
public PsiElement getCallElement() {
return callElement;
}
@Override
public String toString() {
return callElement.toString();
}
};
}
}
@@ -4,6 +4,7 @@ import com.google.common.collect.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.util.CommonSuppliers;
import java.util.*;
@@ -14,9 +15,9 @@ import java.util.*;
public class DataFlowInfo {
public static abstract class CompositionOperator {
public abstract DataFlowInfo compose(DataFlowInfo a, DataFlowInfo b);
}
public static final CompositionOperator AND = new CompositionOperator() {
@Override
public DataFlowInfo compose(DataFlowInfo a, DataFlowInfo b) {
@@ -31,7 +32,7 @@ public class DataFlowInfo {
}
};
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<VariableDescriptor, NullabilityFlags>of(), Multimaps.newListMultimap(Collections.<VariableDescriptor, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
private static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<Object, NullabilityFlags>of(), Multimaps.newListMultimap(Collections.<Object, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
public static DataFlowInfo getEmpty() {
return EMPTY;
@@ -39,10 +40,11 @@ public class DataFlowInfo {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final ImmutableMap<VariableDescriptor, NullabilityFlags> nullabilityInfo;
private final ListMultimap<VariableDescriptor, JetType> typeInfo;
private final ImmutableMap<Object, NullabilityFlags> nullabilityInfo;
private DataFlowInfo(ImmutableMap<VariableDescriptor, NullabilityFlags> nullabilityInfo, ListMultimap<VariableDescriptor, JetType> typeInfo) {
private final ListMultimap<Object, JetType> typeInfo;
private DataFlowInfo(ImmutableMap<Object, NullabilityFlags> nullabilityInfo, ListMultimap<Object, JetType> typeInfo) {
this.nullabilityInfo = nullabilityInfo;
this.typeInfo = typeInfo;
}
@@ -60,13 +62,16 @@ public class DataFlowInfo {
}
@NotNull
public List<JetType> getPossibleTypes(VariableDescriptor variableDescriptor) {
List<JetType> types = typeInfo.get(variableDescriptor);
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
private List<JetType> getPossibleTypes(Object key, @NotNull JetType originalType) {
List<JetType> types = typeInfo.get(key);
NullabilityFlags nullabilityFlags = nullabilityInfo.get(key);
if (nullabilityFlags == null || nullabilityFlags.canBeNull()) {
return types;
}
List<JetType> enrichedTypes = Lists.newArrayListWithCapacity(types.size());
if (originalType.isNullable()) {
enrichedTypes.add(TypeUtils.makeNotNullable(originalType));
}
for (JetType type: types) {
if (type.isNullable()) {
enrichedTypes.add(TypeUtils.makeNotNullable(type));
@@ -78,21 +83,30 @@ public class DataFlowInfo {
return enrichedTypes;
}
@NotNull
public List<JetType> getPossibleTypesForVariable(@NotNull VariableDescriptor variableDescriptor) {
return getPossibleTypes(variableDescriptor, variableDescriptor.getOutType());
}
public List<JetType> getPossibleTypesForReceiver(@NotNull ReceiverDescriptor receiver) {
return getPossibleTypes(receiver, receiver.getType());
}
public DataFlowInfo equalsToNull(@NotNull VariableDescriptor variableDescriptor, boolean notNull) {
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, notNull), typeInfo);
}
private ImmutableMap<VariableDescriptor, NullabilityFlags> getEqualsToNullMap(VariableDescriptor variableDescriptor, boolean notNull) {
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
private ImmutableMap<Object, NullabilityFlags> getEqualsToNullMap(VariableDescriptor variableDescriptor, boolean notNull) {
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
boolean varNotNull = notNull || (nullabilityFlags != null && !nullabilityFlags.canBeNull);
builder.put(variableDescriptor, new NullabilityFlags(!varNotNull, varNotNull));
return ImmutableMap.copyOf(builder);
}
private ImmutableMap<VariableDescriptor, NullabilityFlags> getEqualsToNullMap(VariableDescriptor[] variableDescriptors, boolean notNull) {
private ImmutableMap<Object, NullabilityFlags> getEqualsToNullMap(VariableDescriptor[] variableDescriptors, boolean notNull) {
if (variableDescriptors.length == 0) return nullabilityInfo;
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
for (VariableDescriptor variableDescriptor : variableDescriptors) {
if (variableDescriptor != null) {
NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor);
@@ -104,14 +118,14 @@ public class DataFlowInfo {
}
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor variableDescriptor, @NotNull JetType type) {
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
newTypeInfo.put(variableDescriptor, type);
return new DataFlowInfo(getEqualsToNullMap(variableDescriptor, !type.isNullable()), newTypeInfo);
}
public DataFlowInfo isInstanceOf(@NotNull VariableDescriptor[] variableDescriptors, @NotNull JetType type) {
if (variableDescriptors.length == 0) return this;
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
for (VariableDescriptor variableDescriptor : variableDescriptors) {
if (variableDescriptor != null) {
newTypeInfo.put(variableDescriptor, type);
@@ -121,59 +135,63 @@ public class DataFlowInfo {
}
public DataFlowInfo and(DataFlowInfo other) {
Map<VariableDescriptor, NullabilityFlags> nullabilityMapBuilder = Maps.newHashMap();
Map<Object, NullabilityFlags> nullabilityMapBuilder = Maps.newHashMap();
nullabilityMapBuilder.putAll(nullabilityInfo);
for (Map.Entry<VariableDescriptor, NullabilityFlags> entry : other.nullabilityInfo.entrySet()) {
VariableDescriptor variableDescriptor = entry.getKey();
for (Map.Entry<Object, NullabilityFlags> entry : other.nullabilityInfo.entrySet()) {
Object key = entry.getKey();
NullabilityFlags otherFlags = entry.getValue();
NullabilityFlags thisFlags = nullabilityInfo.get(variableDescriptor);
NullabilityFlags thisFlags = nullabilityInfo.get(key);
if (thisFlags != null) {
nullabilityMapBuilder.put(variableDescriptor, thisFlags.and(otherFlags));
nullabilityMapBuilder.put(key, thisFlags.and(otherFlags));
}
else {
nullabilityMapBuilder.put(variableDescriptor, otherFlags);
nullabilityMapBuilder.put(key, otherFlags);
}
}
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
ListMultimap<Object, JetType> newTypeInfo = copyTypeInfo();
newTypeInfo.putAll(other.typeInfo);
return new DataFlowInfo(ImmutableMap.copyOf(nullabilityMapBuilder), newTypeInfo);
}
private ListMultimap<VariableDescriptor, JetType> copyTypeInfo() {
ListMultimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
private ListMultimap<Object, JetType> copyTypeInfo() {
ListMultimap<Object, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<Object, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
newTypeInfo.putAll(typeInfo);
return newTypeInfo;
}
public DataFlowInfo or(DataFlowInfo other) {
Map<VariableDescriptor, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
Map<Object, NullabilityFlags> builder = Maps.newHashMap(nullabilityInfo);
builder.keySet().retainAll(other.nullabilityInfo.keySet());
for (Map.Entry<VariableDescriptor, NullabilityFlags> entry : builder.entrySet()) {
VariableDescriptor variableDescriptor = entry.getKey();
for (Map.Entry<Object, NullabilityFlags> entry : builder.entrySet()) {
Object key = entry.getKey();
NullabilityFlags thisFlags = entry.getValue();
NullabilityFlags otherFlags = other.nullabilityInfo.get(variableDescriptor);
NullabilityFlags otherFlags = other.nullabilityInfo.get(key);
assert (otherFlags != null);
builder.put(variableDescriptor, thisFlags.or(otherFlags));
builder.put(key, thisFlags.or(otherFlags));
}
ListMultimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
ListMultimap<Object, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<Object, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
Set<VariableDescriptor> keys = newTypeInfo.keySet();
Set<Object> keys = newTypeInfo.keySet();
keys.retainAll(other.typeInfo.keySet());
for (VariableDescriptor variableDescriptor : keys) {
Collection<JetType> thisTypes = typeInfo.get(variableDescriptor);
Collection<JetType> otherTypes = other.typeInfo.get(variableDescriptor);
for (Object key : keys) {
Collection<JetType> thisTypes = typeInfo.get(key);
Collection<JetType> otherTypes = other.typeInfo.get(key);
Collection<JetType> newTypes = Sets.newHashSet(thisTypes);
newTypes.retainAll(otherTypes);
newTypeInfo.putAll(variableDescriptor, newTypes);
newTypeInfo.putAll(key, newTypes);
}
return new DataFlowInfo(ImmutableMap.copyOf(builder), newTypeInfo);
}
public DataFlowInfo nullabilityOnly() {
return new DataFlowInfo(nullabilityInfo, EMPTY.copyTypeInfo());
}
private static class NullabilityFlags {
private final boolean canBeNull;
@@ -105,6 +105,7 @@ public class ErrorUtils {
Visibility.INTERNAL,
true,
null,
ReceiverDescriptor.NO_RECEIVER,
"<ERROR PROPERTY>",
ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE);
@@ -112,6 +113,7 @@ public class ErrorUtils {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), "<ERROR FUNCTION>");
return functionDescriptor.initialize(
null,
ReceiverDescriptor.NO_RECEIVER,
typeParameters,
getValueParameters(functionDescriptor, positionedValueArgumentTypes),
createErrorType("<ERROR FUNCTION RETURN>"),
@@ -123,6 +125,7 @@ public class ErrorUtils {
public static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), "<ERROR FUNCTION>").initialize(
null,
ReceiverDescriptor.NO_RECEIVER,
Collections.<TypeParameterDescriptor>emptyList(), // TODO
Collections.<ValueParameterDescriptor>emptyList(), // TODO
createErrorType("<ERROR FUNCTION RETURN TYPE>"),
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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);
@@ -186,7 +186,7 @@ public class DescriptorRenderer implements Renderer {
renderModality(descriptor.getModality(), builder);
String typeString = renderPropertyPrefixAndComputeTypeString(
builder, descriptor.getTypeParameters(),
descriptor.getReceiver(),
descriptor.getReceiverParameter(),
descriptor.getOutType(),
descriptor.getInType());
renderName(descriptor, builder);
@@ -215,7 +215,7 @@ public class DescriptorRenderer implements Renderer {
builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(descriptor.getTypeParameters(), builder);
ReceiverDescriptor receiver = descriptor.getReceiver();
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
if (receiver.exists()) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
Binary file not shown.
@@ -97,6 +97,15 @@ public class JetHighlighter extends SyntaxHighlighterBase {
JET_AUTO_CAST_EXPRESSION = TextAttributesKey.createTextAttributesKey("JET.AUTO.CAST.EXPRESSION", clone);
}
public static final TextAttributesKey JET_WRAPPED_INTO_REF;
static {
TextAttributes attributes = new TextAttributes();
attributes.setEffectType(EffectType.LINE_UNDERSCORE);
attributes.setEffectColor(Color.BLACK);
JET_WRAPPED_INTO_REF = TextAttributesKey.createTextAttributesKey("JET.WRAPPED.INTO.REF", attributes);
}
public static final TextAttributesKey JET_AUTOCREATED_IT;
static {
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.AnalyzerFacade;
@@ -91,7 +92,7 @@ public class DebugInfoAnnotator implements Annotator {
target = labelTarget.getText();
}
else {
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
if (declarationDescriptors != null) {
target = "[" + declarationDescriptors.size() + " descriptors]";
}
@@ -3,6 +3,7 @@ package org.jetbrains.jet.plugin.annotations;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
@@ -117,9 +118,28 @@ public class JetPsiChecker implements Annotator {
holder.createInfoAnnotation(expression, "Automatically declared based on the expected type").setTextAttributes(JetHighlighter.JET_AUTOCREATED_IT);
}
}
markVariableAsWrappedIfNeeded(expression.getNode(), target);
super.visitSimpleNameExpression(expression);
}
private void markVariableAsWrappedIfNeeded(ASTNode node, DeclarationDescriptor target) {
if (target instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) target;
if (bindingContext.get(MUST_BE_WRAPPED_IN_A_REF, variableDescriptor)) {
holder.createInfoAnnotation(node, "Wrapped into a ref-object to be modifier when captured in a closure").setTextAttributes(JetHighlighter.JET_WRAPPED_INTO_REF);
}
}
}
@Override
public void visitProperty(JetProperty property) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
markVariableAsWrappedIfNeeded(property.getNameIdentifier().getNode(), declarationDescriptor);
super.visitProperty(property);
}
@Override
public void visitExpression(JetExpression expression) {
JetType autoCast = bindingContext.get(AUTOCAST, expression);
@@ -12,8 +12,8 @@ import org.jetbrains.jet.lang.psi.*;
/**
* @author svtk
*/
public class AddFunctionBodyFix extends JetIntentionAction<JetFunctionOrPropertyAccessor> {
public AddFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) {
public class AddFunctionBodyFix extends JetIntentionAction<JetFunction> {
public AddFunctionBodyFix(@NotNull JetFunction element) {
super(element);
}
@@ -37,7 +37,7 @@ public class AddFunctionBodyFix extends JetIntentionAction<JetFunctionOrProperty
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetFunctionOrPropertyAccessor newElement = (JetFunctionOrPropertyAccessor) element.copy();
JetFunction newElement = (JetFunction) element.copy();
JetExpression bodyExpression = newElement.getBodyExpression();
if (!(newElement.getLastChild() instanceof PsiWhiteSpace)) {
newElement.add(JetPsiFactory.createWhiteSpace(project));
@@ -48,12 +48,12 @@ public class AddFunctionBodyFix extends JetIntentionAction<JetFunctionOrProperty
element.replace(newElement);
}
public static JetIntentionActionFactory<JetFunctionOrPropertyAccessor> createFactory() {
return new JetIntentionActionFactory<JetFunctionOrPropertyAccessor>() {
public static JetIntentionActionFactory<JetFunction> createFactory() {
return new JetIntentionActionFactory<JetFunction>() {
@Override
public JetIntentionAction<JetFunctionOrPropertyAccessor> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor;
return new AddFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement());
public JetIntentionAction<JetFunction> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunction;
return new AddFunctionBodyFix((JetFunction) diagnostic.getPsiElement());
}
};
}
@@ -4,11 +4,13 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetToken;
@@ -17,19 +19,39 @@ import org.jetbrains.jet.lexer.JetTokens;
/**
* @author svtk
*/
public class AddModifierFix extends ModifierFix {
public class AddModifierFix extends JetIntentionAction<JetModifierListOwner> {
private final JetKeywordToken modifier;
private final JetToken[] modifiersThanCanBeReplaced;
private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced) {
super(element, modifier);
super(element);
this.modifier = modifier;
this.modifiersThanCanBeReplaced = modifiersThanCanBeReplaced;
}
@NotNull
/*package*/ static String getElementName(JetModifierListOwner modifierListOwner) {
String name = null;
if (modifierListOwner instanceof PsiNameIdentifierOwner) {
PsiElement nameIdentifier = ((PsiNameIdentifierOwner) modifierListOwner).getNameIdentifier();
if (nameIdentifier != null) {
name = nameIdentifier.getText();
}
}
else if (modifierListOwner instanceof JetPropertyAccessor) {
name = ((JetPropertyAccessor) modifierListOwner).getNamePlaceholder().getText();
}
if (name == null) {
name = modifierListOwner.getText();
}
return "'" + name + "'";
}
@NotNull
@Override
public String getText() {
if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) {
return "Make " + getElementName() + " " + modifier.getValue();
return "Make " + getElementName(element) + " " + modifier.getValue();
}
return "Add '" + modifier.getValue() + "' modifier";
}
@@ -0,0 +1,92 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author svtk
*/
public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
private JetType type;
public AddReturnTypeFix(@NotNull JetNamedDeclaration element, JetType type) {
super(element);
this.type = type;
}
@NotNull
@Override
public String getText() {
return "Add return type declaration";
}
@NotNull
@Override
public String getFamilyName() {
return "Add return type declaration";
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement newElement;
if (element instanceof JetProperty) {
newElement = addPropertyType(project, (JetProperty) element, type);
}
else {
assert element instanceof JetFunction;
newElement = addFunctionType(project, (JetFunction) element, type);
}
ImportClassHelper.perform(type, element, newElement);
}
@Override
public boolean startInWriteAction() {
return true;
}
public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) {
JetProperty newProperty = (JetProperty) property.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
PsiElement nameIdentifier = newProperty.getNameIdentifier();
addTypeReference(newProperty, typeReference, colon, nameIdentifier);
return newProperty;
}
public static JetFunction addFunctionType(Project project, JetFunction function, JetType type) {
JetFunction newFunction = (JetFunction) function.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
JetParameterList valueParameterList = newFunction.getValueParameterList();
addTypeReference(newFunction, typeReference, colon, valueParameterList);
return newFunction;
}
private static void addTypeReference(JetNamedDeclaration element, JetTypeReference typeReference, Pair<PsiElement, PsiElement> colon, PsiElement anchor) {
assert anchor != null;
element.addAfter(typeReference, anchor);
element.addRangeAfter(colon.getFirst(), colon.getSecond(), anchor);
}
public static JetIntentionActionFactory<JetNamedDeclaration> createFactory() {
return new JetIntentionActionFactory<JetNamedDeclaration>() {
@Override
public JetIntentionAction<JetNamedDeclaration> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetNamedDeclaration;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE);
JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE);
return new AddReturnTypeFix((JetNamedDeclaration) diagnostic.getPsiElement(), type);
}
};
}
}
@@ -1,38 +0,0 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lexer.JetKeywordToken;
/**
* @author svtk
*/
public abstract class ModifierFix extends JetIntentionAction<JetModifierListOwner> {
protected final JetKeywordToken modifier;
protected ModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier) {
super(element);
this.modifier = modifier;
}
@NotNull
protected String getElementName() {
String name = null;
if (element instanceof PsiNameIdentifierOwner) {
PsiElement nameIdentifier = ((PsiNameIdentifierOwner) element).getNameIdentifier();
if (nameIdentifier != null) {
name = nameIdentifier.getText();
}
}
else if (element instanceof JetPropertyAccessor) {
name = ((JetPropertyAccessor) element).getNamePlaceholder().getText();
}
if (name == null) {
name = element.getText();
}
return "'" + name + "'";
}
}
@@ -1,9 +1,11 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.extapi.psi.ASTDelegatePsiElement;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameter;
@@ -69,4 +71,12 @@ public class QuickFixUtil {
}
};
}
public static boolean removePossiblyWhiteSpace(ASTDelegatePsiElement element, PsiElement possiblyWhiteSpace) {
if (possiblyWhiteSpace instanceof PsiWhiteSpace) {
element.deleteChildInternal(possiblyWhiteSpace.getNode());
return true;
}
return false;
}
}
@@ -29,7 +29,7 @@ public class QuickFixes {
}
static {
JetIntentionActionFactory<JetModifierListOwner> removeAbstractModifierFactory = RemoveModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD);
JetIntentionActionFactory<JetModifierListOwner> removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD);
JetIntentionActionFactory<JetModifierListOwner> addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD});
add(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory);
@@ -53,22 +53,21 @@ public class QuickFixes {
add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
JetIntentionActionFactory<JetFunctionOrPropertyAccessor> removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory();
JetIntentionActionFactory<JetFunction> removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory();
add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory);
add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory);
JetIntentionActionFactory<JetFunctionOrPropertyAccessor> addFunctionBodyFactory = AddFunctionBodyFix.createFactory();
JetIntentionActionFactory<JetFunction> addFunctionBodyFactory = AddFunctionBodyFix.createFactory();
add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory);
add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory);
add(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory);
add(Errors.NON_MEMBER_ABSTRACT_ACCESSOR, removeAbstractModifierFactory);
add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD));
add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListFactory(JetTokens.OVERRIDE_KEYWORD));
add(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD, new JetToken[] {JetTokens.OPEN_KEYWORD}));
add(Errors.VAL_WITH_SETTER, ChangeVariableMutabilityFix.createFactory());
@@ -84,10 +83,10 @@ public class QuickFixes {
add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory());
JetIntentionActionFactory<JetModifierList> removeRedundantModifierFactory = RemoveRedundantModifierFix.createFactory();
JetIntentionActionFactory<JetModifierList> removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(true);
add(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory);
add(Errors.REDUNDANT_MODIFIER_IN_TRAIT, removeRedundantModifierFactory);
add(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createFactory(JetTokens.FINAL_KEYWORD));
add(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD));
add(Errors.PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR, RemovePartsFromPropertyFix.createRemoveInitializerFactory());
@@ -96,14 +95,15 @@ public class QuickFixes {
add(Errors.PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY, addPrimaryConstructorFactory);
JetIntentionActionFactory<JetModifierListOwner> addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD});
JetIntentionActionFactory<JetModifierListOwner> removeOpenModifierFactory = RemoveModifierFix.createFactory(JetTokens.OPEN_KEYWORD);
JetIntentionActionFactory<JetModifierListOwner> removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD);
add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, DiagnosticParameters.CLASS));
add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory);
add(Errors.NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, DiagnosticParameters.PROPERTY));
add(Errors.NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY, removeOpenModifierFactory);
add(Errors.ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, DiagnosticParameters.PROPERTY));
add(Errors.ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY, removeAbstractModifierFactory);
JetIntentionActionFactory<JetModifierList> removeModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory();
add(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
add(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
add(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
add(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
}
}
}
@@ -4,18 +4,22 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author svtk
*/
public class RemoveFunctionBodyFix extends JetIntentionAction<JetFunctionOrPropertyAccessor> {
public class RemoveFunctionBodyFix extends JetIntentionAction<JetFunction> {
public RemoveFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) {
public RemoveFunctionBodyFix(@NotNull JetFunction element) {
super(element);
}
@@ -39,25 +43,41 @@ public class RemoveFunctionBodyFix extends JetIntentionAction<JetFunctionOrPrope
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetFunctionOrPropertyAccessor newElement = (JetFunctionOrPropertyAccessor) element.copy();
JetExpression bodyExpression = newElement.getBodyExpression();
if (bodyExpression != null) {
PsiElement prevSibling = bodyExpression.getPrevSibling();
if (prevSibling instanceof PsiWhiteSpace) {
((JetElement)newElement).deleteChildInternal(prevSibling.getNode());
}
((JetElement)newElement).deleteChildInternal(bodyExpression.getNode());
JetFunction function = (JetFunction) element.copy();
JetExpression bodyExpression = function.getBodyExpression();
assert bodyExpression != null;
if (function.hasBlockBody()) {
PsiElement prevElement = bodyExpression.getPrevSibling();
QuickFixUtil.removePossiblyWhiteSpace(function, prevElement);
function.deleteChildInternal(bodyExpression.getNode());
}
element.replace(newElement);
else {
PsiElement prevElement = bodyExpression.getPrevSibling();
PsiElement prevPrevElement = prevElement.getPrevSibling();
QuickFixUtil.removePossiblyWhiteSpace(function, prevElement);
removePossiblyEquationSign(function, prevElement);
removePossiblyEquationSign(function, prevPrevElement);
function.deleteChildInternal(bodyExpression.getNode());
}
element.replace(function);
}
public static JetIntentionActionFactory<JetFunctionOrPropertyAccessor> createFactory() {
return new JetIntentionActionFactory<JetFunctionOrPropertyAccessor>() {
private static boolean removePossiblyEquationSign(@NotNull JetElement element, @Nullable PsiElement possiblyEq) {
if (possiblyEq instanceof LeafPsiElement && ((LeafPsiElement)possiblyEq).getElementType() == JetTokens.EQ) {
QuickFixUtil.removePossiblyWhiteSpace(element, possiblyEq.getNextSibling());
element.deleteChildInternal(possiblyEq.getNode());
return true;
}
return false;
}
public static JetIntentionActionFactory<JetFunction> createFactory() {
return new JetIntentionActionFactory<JetFunction>() {
@Override
public JetIntentionAction<JetFunctionOrPropertyAccessor> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor;
return new RemoveFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement());
public JetIntentionAction<JetFunction> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunction;
return new RemoveFunctionBodyFix((JetFunction) diagnostic.getPsiElement());
}
};
}
}
}
@@ -1,14 +1,15 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.extapi.psi.ASTDelegatePsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetModifierList;
@@ -20,35 +21,31 @@ import org.jetbrains.jet.lexer.JetTokens;
/**
* @author svtk
*/
public class RemoveModifierFix extends ModifierFix {
public class RemoveModifierFix {
private final JetKeywordToken modifier;
private final boolean isRedundant;
public RemoveModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier) {
super(element, modifier);
public RemoveModifierFix(JetKeywordToken modifier, boolean isRedundant) {
this.modifier = modifier;
this.isRedundant = isRedundant;
}
@NotNull
@Override
public String getText() {
if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) {
return "Make " + getElementName() + " not " + modifier.getValue();
private static String makeText(@Nullable JetModifierListOwner element, JetKeywordToken modifier, boolean isRedundant) {
if (isRedundant) {
return "Remove redundant '" + modifier.getValue() + "' modifier";
}
if (element != null && modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) {
return "Make " + AddModifierFix.getElementName(element) + " not " + modifier.getValue();
}
return "Remove '" + modifier.getValue() + "' modifier";
}
@NotNull
@Override
public String getFamilyName() {
return "Remove modifier";
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetModifierListOwner newElement = (JetModifierListOwner) element.copy();
element.replace(removeModifier(newElement, modifier));
private static String getFamilyName() {
return "Remove modifier fix";
}
@NotNull
/*package*/ static <T extends JetModifierListOwner> T removeModifier(T element, JetToken modifier) {
private static <T extends JetModifierListOwner> T removeModifier(T element, JetToken modifier) {
JetModifierList modifierList = element.getModifierList();
assert modifierList != null;
removeModifierFromList(modifierList, modifier);
@@ -56,38 +53,128 @@ public class RemoveModifierFix extends ModifierFix {
PsiElement whiteSpace = modifierList.getNextSibling();
assert element instanceof JetElement;
((JetElement) element).deleteChildInternal(modifierList.getNode());
removeWhiteSpace((JetElement) element, whiteSpace);
QuickFixUtil.removePossiblyWhiteSpace((JetElement) element, whiteSpace);
}
return element;
}
/*package*/ static JetModifierList removeModifierFromList(@NotNull JetModifierList modifierList, JetToken modifier) {
@NotNull
private static JetModifierList removeModifierFromList(@NotNull JetModifierList modifierList, JetToken modifier) {
assert modifierList.hasModifier(modifier);
ASTNode modifierNode = modifierList.getModifierNode(modifier);
PsiElement whiteSpace = modifierNode.getPsi().getNextSibling();
boolean wsRemoved = removeWhiteSpace(modifierList, whiteSpace);
boolean wsRemoved = QuickFixUtil.removePossiblyWhiteSpace(modifierList, whiteSpace);
modifierList.deleteChildInternal(modifierNode);
if (!wsRemoved) {
removeWhiteSpace(modifierList, modifierList.getLastChild());
QuickFixUtil.removePossiblyWhiteSpace(modifierList, modifierList.getLastChild());
}
return modifierList;
}
private static boolean removeWhiteSpace(ASTDelegatePsiElement element, PsiElement subElement) {
if (subElement instanceof PsiWhiteSpace) {
element.deleteChildInternal(subElement.getNode());
return true;
private class RemoveModifierFromListOwner extends JetIntentionAction<JetModifierListOwner> {
public RemoveModifierFromListOwner(@NotNull JetModifierListOwner element) {
super(element);
}
@NotNull
@Override
public String getText() {
return makeText(element, modifier, isRedundant);
}
@NotNull
@Override
public String getFamilyName() {
return RemoveModifierFix.getFamilyName();
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetModifierListOwner newElement = (JetModifierListOwner) element.copy();
element.replace(removeModifier(newElement, modifier));
}
return false;
}
public static JetIntentionActionFactory<JetModifierListOwner> createFactory(final JetKeywordToken modifier) {
private class RemoveModifierFromList extends JetIntentionAction<JetModifierList> {
public RemoveModifierFromList(@NotNull JetModifierList element) {
super(element);
}
@NotNull
@Override
public String getText() {
return makeText(null, modifier, isRedundant);
}
@NotNull
@Override
public String getFamilyName() {
return RemoveModifierFix.getFamilyName();
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetModifierList newElement = (JetModifierList) element.copy();
element.replace(RemoveModifierFix.removeModifierFromList(newElement, modifier));
}
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierListOwner>() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return new RemoveModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier);
return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement());
}
};
}
}
private static RemoveModifierFix createRemoveModifierFixFromDiagnostic(DiagnosticWithPsiElement diagnostic, boolean isRedundant) {
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER);
JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER);
return new RemoveModifierFix(modifier, isRedundant);
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierListOwner>() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierList>() {
@Override
public JetIntentionAction<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierList;
return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final JetKeywordToken modifier, final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierList>() {
@Override
public JetIntentionAction<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierList;
return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) {
return createRemoveModifierFromListOwnerFactory(modifier, false);
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory() {
return createRemoveModifierFromListFactory(false);
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final JetKeywordToken modifier) {
return createRemoveModifierFromListFactory(modifier, false);
}
}
@@ -2,7 +2,6 @@ package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
@@ -97,7 +96,7 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
newElement.deleteChildRange(nextSibling, initializer);
if (newElement.getPropertyTypeRef() == null && type != null) {
newElement = addPropertyType(project, newElement, type);
newElement = AddReturnTypeFix.addPropertyType(project, newElement, type);
needImport = true;
}
}
@@ -108,17 +107,6 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
}
}
public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) {
JetProperty newProperty = (JetProperty) property.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
PsiElement nameIdentifier = newProperty.getNameIdentifier();
assert nameIdentifier != null;
newProperty.addAfter(typeReference, nameIdentifier);
newProperty.addRangeAfter(colon.getFirst(), colon.getSecond(), nameIdentifier);
return newProperty;
}
public static JetIntentionActionFactory<JetProperty> createFactory() {
return new JetIntentionActionFactory<JetProperty>() {
@Override
@@ -1,54 +0,0 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lexer.JetKeywordToken;
/**
* @author svtk
*/
public class RemoveRedundantModifierFix extends JetIntentionAction<JetModifierList> {
private JetKeywordToken redundantModifier;
public RemoveRedundantModifierFix(@NotNull JetModifierList element, @NotNull JetKeywordToken redundantModifier) {
super(element);
this.redundantModifier = redundantModifier;
}
@NotNull
@Override
public String getText() {
return "Remove redundant '" + redundantModifier + "' modifier";
}
@NotNull
@Override
public String getFamilyName() {
return "Remove redundant modifier";
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetModifierList newElement = (JetModifierList) element.copy();
element.replace(RemoveModifierFix.removeModifierFromList(newElement, redundantModifier));
}
public static JetIntentionActionFactory<JetModifierList> createFactory() {
return new JetIntentionActionFactory<JetModifierList>() {
@Override
public JetIntentionAction<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierList;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER);
JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER);
return new RemoveRedundantModifierFix((JetModifierList) diagnostic.getPsiElement(), modifier);
}
};
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.plugin.AnalyzerFacade;
import java.util.Collection;
@@ -80,7 +81,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
if (psiElement != null) {
return psiElement;
}
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (declarationDescriptors != null) return null;
return file;
}
@@ -88,12 +89,12 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
protected ResolveResult[] doMultiResolve() {
JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY;
ResolveResult[] results = new ResolveResult[declarationDescriptors.size()];
Collection<? extends ResolvedCall<? extends DeclarationDescriptor>> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY;
ResolveResult[] results = new ResolveResult[resolvedCalls.size()];
int i = 0;
for (DeclarationDescriptor descriptor : declarationDescriptors) {
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor);
for (ResolvedCall<? extends DeclarationDescriptor> resolvedCall : resolvedCalls) {
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, resolvedCall.getResultingDescriptor());
if (element != null) {
results[i] = new PsiElementResolveResult(element, true);
i++;

Some files were not shown because too many files have changed in this diff Show More