Working on type inference for function literals
This commit is contained in:
@@ -29,7 +29,7 @@ public interface JetNodeTypes {
|
||||
JetNodeType DELEGATOR_BY = new JetNodeType("DELEGATOR_BY", JetDelegatorByExpressionSpecifier.class);
|
||||
JetNodeType DELEGATOR_SUPER_CALL = new JetNodeType("DELEGATOR_SUPER_CALL", JetDelegatorToSuperCall.class);
|
||||
JetNodeType DELEGATOR_SUPER_CLASS = new JetNodeType("DELEGATOR_SUPER_CLASS", JetDelegatorToSuperClass.class);
|
||||
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
|
||||
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
|
||||
JetNodeType VALUE_PARAMETER_LIST = new JetNodeType("VALUE_PARAMETER_LIST", JetParameterList.class);
|
||||
JetNodeType VALUE_PARAMETER = new JetNodeType("VALUE_PARAMETER", JetParameter.class);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<? extends FunctionDescriptor> getOverriddenFunctions() {
|
||||
return null;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -22,7 +23,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
private JetType unsubstitutedReturnType;
|
||||
private JetType receiverType;
|
||||
|
||||
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newHashSet();
|
||||
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet();
|
||||
private final FunctionDescriptor original;
|
||||
|
||||
public FunctionDescriptorImpl(
|
||||
@@ -97,12 +98,14 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FunctionDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
if (substitutor.isEmpty()) {
|
||||
public final FunctionDescriptor substitute(TypeSubstitutor originalSubstitutor) {
|
||||
if (originalSubstitutor.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
FunctionDescriptorImpl substitutedDescriptor;
|
||||
substitutedDescriptor = createSubstitutedCopy();
|
||||
FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy();
|
||||
|
||||
List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
|
||||
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
|
||||
|
||||
JetType receiverType = getReceiverType();
|
||||
JetType substitutedReceiverType = null;
|
||||
@@ -125,7 +128,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
||||
|
||||
substitutedDescriptor.initialize(
|
||||
substitutedReceiverType,
|
||||
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
|
||||
substitutedTypeParameters,
|
||||
substitutedValueParameters,
|
||||
substitutedReturnType
|
||||
);
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.TypeSubstitutor.TypeSubstitution;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
@@ -110,6 +112,59 @@ public class FunctionDescriptorUtil {
|
||||
return parameterScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FunctionDescriptor substituteBounds(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
final List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
||||
if (typeParameters.isEmpty()) return functionDescriptor;
|
||||
final Map<TypeConstructor, TypeParameterDescriptor> typeConstructors = Maps.newHashMap();
|
||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
||||
typeConstructors.put(typeParameter.getTypeConstructor(), typeParameter);
|
||||
}
|
||||
return functionDescriptor.substitute(new TypeSubstitutor(TypeSubstitution.EMPTY) {
|
||||
@Override
|
||||
public boolean inRange(@NotNull TypeConstructor typeConstructor) {
|
||||
return typeConstructors.containsKey(typeConstructor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return typeParameters.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeSubstitution getSubstitution() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType safeSubstitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) {
|
||||
JetType substituted = substitute(type, howThisTypeIsUsed);
|
||||
if (substituted == null) {
|
||||
return ErrorUtils.createErrorType("Substitution failed");
|
||||
}
|
||||
return substituted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType substitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeConstructors.get(type.getConstructor());
|
||||
if (typeParameterDescriptor != null) {
|
||||
switch (howThisTypeIsUsed) {
|
||||
case INVARIANT:
|
||||
return type;
|
||||
case IN_VARIANCE:
|
||||
throw new UnsupportedOperationException(); // TODO : lower bounds
|
||||
case OUT_VARIANCE:
|
||||
return typeParameterDescriptor.getDefaultType();
|
||||
}
|
||||
}
|
||||
return super.substitute(type, howThisTypeIsUsed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class OverrideCompatibilityInfo {
|
||||
|
||||
private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(false, "SUCCESS");
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -19,12 +16,6 @@ public interface FunctionGroup extends Named {
|
||||
return "<empty>";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
@@ -42,9 +33,6 @@ public interface FunctionGroup extends Named {
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
@NotNull
|
||||
OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -16,27 +16,40 @@ import java.util.List;
|
||||
public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
|
||||
private final ClassDescriptor original;
|
||||
private final TypeSubstitutor originalSubstitutor;
|
||||
private TypeSubstitutor newSubstitutor;
|
||||
private List<TypeParameterDescriptor> typeParameters;
|
||||
private TypeConstructor typeConstructor;
|
||||
private final TypeSubstitutor substitutor;
|
||||
|
||||
public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
|
||||
this.original = descriptor;
|
||||
this.substitutor = substitutor;
|
||||
this.originalSubstitutor = substitutor;
|
||||
}
|
||||
|
||||
private TypeSubstitutor getSubstitutor() {
|
||||
if (newSubstitutor == null) {
|
||||
if (originalSubstitutor.isEmpty()) {
|
||||
newSubstitutor = originalSubstitutor;
|
||||
}
|
||||
else {
|
||||
typeParameters = Lists.newArrayList();
|
||||
newSubstitutor = DescriptorSubstitutor.substituteTypeParameters(original.getTypeConstructor().getParameters(), originalSubstitutor, this, typeParameters);
|
||||
}
|
||||
}
|
||||
return newSubstitutor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
TypeConstructor originalTypeConstructor = original.getTypeConstructor();
|
||||
if (substitutor.isEmpty()) {
|
||||
if (originalSubstitutor.isEmpty()) {
|
||||
return originalTypeConstructor;
|
||||
}
|
||||
|
||||
if (typeConstructor == null) {
|
||||
List<TypeParameterDescriptor> parameters = Lists.newArrayList();
|
||||
for (TypeParameterDescriptor parameterDescriptor : originalTypeConstructor.getParameters()) {
|
||||
parameters.add(parameterDescriptor.substitute(substitutor));
|
||||
}
|
||||
TypeSubstitutor substitutor = getSubstitutor();
|
||||
|
||||
Collection<JetType> supertypes = Lists.newArrayList();
|
||||
for (JetType supertype : originalTypeConstructor.getSupertypes()) {
|
||||
supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
|
||||
@@ -47,7 +60,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
originalTypeConstructor.getAnnotations(),
|
||||
originalTypeConstructor.isSealed(),
|
||||
originalTypeConstructor.toString(),
|
||||
parameters,
|
||||
typeParameters,
|
||||
supertypes
|
||||
);
|
||||
}
|
||||
@@ -59,10 +72,10 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
@Override
|
||||
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
|
||||
JetScope memberScope = original.getMemberScope(typeArguments);
|
||||
if (substitutor.isEmpty()) {
|
||||
if (originalSubstitutor.isEmpty()) {
|
||||
return memberScope;
|
||||
}
|
||||
return new SubstitutingScope(memberScope, substitutor); // TODO : compose substitutors
|
||||
return new SubstitutingScope(memberScope, getSubstitutor());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -2,14 +2,9 @@ package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -31,30 +26,6 @@ public class LazySubstitutingFunctionGroup implements FunctionGroup {
|
||||
return functionGroup.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
OverloadResolutionResult resolutionResult = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||
if (resolutionResult.isNothing()) return resolutionResult;
|
||||
|
||||
Collection<FunctionDescriptor> result = new ArrayList<FunctionDescriptor>();
|
||||
for (FunctionDescriptor function : resolutionResult.getFunctionDescriptors()) {
|
||||
FunctionDescriptor functionDescriptor = substitute(function);
|
||||
if (functionDescriptor != null) {
|
||||
result.add(functionDescriptor);
|
||||
}
|
||||
}
|
||||
return resolutionResult.newContents(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor substitute(
|
||||
@NotNull FunctionDescriptor functionDescriptor) {
|
||||
if (substitutor.isEmpty()) return functionDescriptor;
|
||||
|
||||
return functionDescriptor.substitute(substitutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return functionGroup.isEmpty();
|
||||
@@ -68,13 +39,14 @@ public class LazySubstitutingFunctionGroup implements FunctionGroup {
|
||||
functionDescriptors = functionGroup.getFunctionDescriptors();
|
||||
}
|
||||
else {
|
||||
functionDescriptors = Sets.newHashSet();
|
||||
Set<FunctionDescriptor> functionDescriptorSet = Sets.newLinkedHashSet();
|
||||
for (FunctionDescriptor descriptor : functionGroup.getFunctionDescriptors()) {
|
||||
FunctionDescriptor substitute = descriptor.substitute(substitutor);
|
||||
if (substitute != null) {
|
||||
functionDescriptors.add(substitute);
|
||||
functionDescriptorSet.add(substitute);
|
||||
}
|
||||
}
|
||||
functionDescriptors = Collections.unmodifiableSet(functionDescriptorSet);
|
||||
}
|
||||
}
|
||||
return functionDescriptors;
|
||||
|
||||
@@ -103,8 +103,9 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated // Use the static method TypeParameterDescriptor.substitute()
|
||||
public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,11 +2,8 @@ package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -15,6 +12,7 @@ import java.util.Set;
|
||||
public class WritableFunctionGroup implements FunctionGroup {
|
||||
private final String name;
|
||||
private Set<FunctionDescriptor> functionDescriptors;
|
||||
private Set<FunctionDescriptor> unmodifiableFunctionDescriptors;
|
||||
|
||||
public WritableFunctionGroup(String name) {
|
||||
this.name = name;
|
||||
@@ -34,51 +32,32 @@ public class WritableFunctionGroup implements FunctionGroup {
|
||||
}
|
||||
|
||||
public void addFunction(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
getFunctionDescriptors().add(functionDescriptor);
|
||||
getWritableFunctionDescriptors().add(functionDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<FunctionDescriptor> getFunctionDescriptors() {
|
||||
if (unmodifiableFunctionDescriptors == null) {
|
||||
unmodifiableFunctionDescriptors = Collections.unmodifiableSet(getWritableFunctionDescriptors());
|
||||
}
|
||||
return unmodifiableFunctionDescriptors;
|
||||
}
|
||||
|
||||
private Set<FunctionDescriptor> getWritableFunctionDescriptors() {
|
||||
if (functionDescriptors == null) {
|
||||
functionDescriptors = Sets.newLinkedHashSet();
|
||||
}
|
||||
return functionDescriptors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
Set<FunctionDescriptor> functionDescriptors = getFunctionDescriptors();
|
||||
if (functionDescriptors.isEmpty()) return OverloadResolutionResult.nameNotFound();
|
||||
|
||||
int typeArgCount = typeArguments.size();
|
||||
int valueArgCount = positionedValueArgumentTypes.size();
|
||||
List<FunctionDescriptor> result = new ArrayList<FunctionDescriptor>();
|
||||
for (FunctionDescriptor functionDescriptor : functionDescriptors) {
|
||||
// TODO : type argument inference breaks this logic
|
||||
if (functionDescriptor.getTypeParameters().size() == typeArgCount) {
|
||||
if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount &&
|
||||
valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) {
|
||||
FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor);
|
||||
assert substitutedFunctionDescriptor != null;
|
||||
result.add(substitutedFunctionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
assert !functionDescriptors.isEmpty();
|
||||
if (functionDescriptors.size() == 1) {
|
||||
return OverloadResolutionResult.singleFunctionArgumentMismatch(functionDescriptors.iterator().next());
|
||||
}
|
||||
}
|
||||
if (result.size() == 1) {
|
||||
return OverloadResolutionResult.success(result.get(0));
|
||||
}
|
||||
return OverloadResolutionResult.ambiguity(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return functionDescriptors == null || functionDescriptors.isEmpty();
|
||||
}
|
||||
|
||||
public void addAllFunctions(@NotNull FunctionGroup functionGroup) {
|
||||
if (functionGroup.isEmpty()) return;
|
||||
getWritableFunctionDescriptors().addAll(functionGroup.getFunctionDescriptors());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,10 @@ public class JetConstructorCalleeExpression extends JetExpression {
|
||||
return null;
|
||||
}
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
assert typeElement instanceof JetUserType;
|
||||
if (typeElement == null) {
|
||||
return null;
|
||||
}
|
||||
assert typeElement instanceof JetUserType : typeElement;
|
||||
return ((JetUserType) typeElement).getReferenceExpression();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,11 +55,16 @@ public class ChainedScope implements JetScope {
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
for (JetScope jetScope : scopeChain) {
|
||||
FunctionGroup functionGroup = jetScope.getFunctionGroup(name);
|
||||
if (!functionGroup.isEmpty()) return functionGroup;
|
||||
if (scopeChain.length == 0) {
|
||||
return FunctionGroup.EMPTY;
|
||||
}
|
||||
return FunctionGroup.EMPTY;
|
||||
|
||||
WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
for (JetScope jetScope : scopeChain) {
|
||||
result.addAllFunctions(jetScope.getFunctionGroup(name));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ClassDescriptorResolver {
|
||||
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
|
||||
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
|
||||
|
||||
final WritableScope memberDeclarations = new WritableScopeImpl(parameterScope, classDescriptor, trace.getErrorHandler());
|
||||
final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, trace.getErrorHandler());
|
||||
|
||||
List<JetDeclaration> declarations = classElement.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.CollectingErrorHandler;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.JetDiagnostic;
|
||||
import org.jetbrains.jet.util.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class DelegatingBindingTrace implements BindingTrace {
|
||||
private final BindingContext parentContext;
|
||||
private final MutableManyMap map = ManyMapImpl.create();
|
||||
private final List<JetDiagnostic> diagnostics = Lists.newArrayList();
|
||||
private final ErrorHandler errorHandler = new CollectingErrorHandler(diagnostics);
|
||||
|
||||
private final BindingContext bindingContext = new BindingContext() {
|
||||
@Override
|
||||
public Collection<JetDiagnostic> getDiagnostics() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||
return DelegatingBindingTrace.this.get(slice, key);
|
||||
}
|
||||
};
|
||||
|
||||
public DelegatingBindingTrace(BindingContext parentContext) {
|
||||
this.parentContext = parentContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ErrorHandler getErrorHandler() {
|
||||
return errorHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingContext getBindingContext() {
|
||||
return bindingContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
||||
map.put(slice, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
|
||||
record(slice, key, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||
if (map.containsKey(slice, key)) {
|
||||
return map.get(slice, key);
|
||||
}
|
||||
return parentContext.get(slice, key);
|
||||
}
|
||||
|
||||
public void addAllMyDataTo(BindingTrace trace) {
|
||||
for (Map.Entry<ManyMapKey<?, ?>, ?> entry : map) {
|
||||
ManyMapKey manyMapKey = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
//noinspection unchecked
|
||||
trace.record(manyMapKey.getSlice(), manyMapKey.getKey(), value);
|
||||
}
|
||||
|
||||
AnalyzingUtils.applyHandler(trace.getErrorHandler(), diagnostics);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +1,74 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ScopeWithReceiver extends JetScopeImpl {
|
||||
|
||||
private final JetType receiverType;
|
||||
private final JetScope outerScope;
|
||||
private final JetTypeChecker typeChecker;
|
||||
|
||||
public ScopeWithReceiver(@NotNull JetScope outerScope, @NotNull JetType receiverType, @NotNull JetTypeChecker typeChecker) {
|
||||
this.outerScope = outerScope;
|
||||
this.receiverType = receiverType;
|
||||
this.typeChecker = typeChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
JetScope memberScope = receiverType.getMemberScope();
|
||||
FunctionGroup functionGroup = memberScope.getFunctionGroup(name);
|
||||
if (functionGroup.isEmpty()) {
|
||||
return outerScope.getFunctionGroup(name);
|
||||
// return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name),
|
||||
// new Function<FunctionDescriptor, Boolean>() {
|
||||
// @Override
|
||||
// public Boolean apply(@Nullable FunctionDescriptor functionDescriptor) {
|
||||
// if (functionDescriptor == null) return false;
|
||||
// JetType functionReceiverType = functionDescriptor.getReceiverType();
|
||||
// if (functionReceiverType == null) {
|
||||
// return false;
|
||||
// }
|
||||
// // TODO : in case of inferred type arguments, substitute the receiver type first
|
||||
// return typeChecker.startForPairOfTypes(receiverType, functionReceiverType);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
return functionGroup; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassifierDescriptor getClassifier(@NotNull String name) {
|
||||
return receiverType.getMemberScope().getClassifier(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VariableDescriptor getVariable(@NotNull String name) {
|
||||
VariableDescriptor variable = receiverType.getMemberScope().getVariable(name);
|
||||
if (variable != null) {
|
||||
return variable;
|
||||
}
|
||||
variable = outerScope.getVariable(name);
|
||||
if (variable instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
|
||||
JetType receiverType = propertyDescriptor.getReceiverType();
|
||||
// TODO : in case of type arguments, substitute the receiver type first
|
||||
if (receiverType != null
|
||||
&& typeChecker.isSubtypeOf(receiverType, receiverType)) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
||||
return receiverType.getMemberScope().getNamespace(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getThisType() {
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor getContainingDeclaration() {
|
||||
return outerScope.getContainingDeclaration();
|
||||
}
|
||||
}
|
||||
//package org.jetbrains.jet.lang.resolve;
|
||||
//
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.jetbrains.jet.lang.descriptors.*;
|
||||
//import org.jetbrains.jet.lang.types.JetType;
|
||||
//import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
//
|
||||
///**
|
||||
// * @author abreslav
|
||||
// */
|
||||
//public class ScopeWithReceiver extends JetScopeImpl {
|
||||
//
|
||||
// private final JetType receiverType;
|
||||
// private final JetScope outerScope;
|
||||
// private final JetTypeChecker typeChecker;
|
||||
//
|
||||
// public ScopeWithReceiver(@NotNull JetScope outerScope, @NotNull JetType receiverType, @NotNull JetTypeChecker typeChecker) {
|
||||
// this.outerScope = outerScope;
|
||||
// this.receiverType = receiverType;
|
||||
// this.typeChecker = typeChecker;
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
// WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
//
|
||||
// result.addAllFunctions(receiverType.getMemberScope().getFunctionGroup(name));
|
||||
// result.addAllFunctions(outerScope.getFunctionGroup(name));
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ClassifierDescriptor getClassifier(@NotNull String name) {
|
||||
// return receiverType.getMemberScope().getClassifier(name);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public VariableDescriptor getVariable(@NotNull String name) {
|
||||
// VariableDescriptor variable = receiverType.getMemberScope().getVariable(name);
|
||||
// if (variable != null) {
|
||||
// return variable;
|
||||
// }
|
||||
// variable = outerScope.getVariable(name);
|
||||
// if (variable instanceof PropertyDescriptor) {
|
||||
// PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
|
||||
// JetType receiverType = propertyDescriptor.getReceiverType();
|
||||
// // TODO : in case of type arguments, substitute the receiver type first
|
||||
// if (receiverType != null
|
||||
// && typeChecker.isSubtypeOf(receiverType, receiverType)) {
|
||||
// return variable;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public NamespaceDescriptor getNamespace(@NotNull String name) {
|
||||
// return receiverType.getMemberScope().getNamespace(name);
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public JetType getThisType() {
|
||||
// return receiverType;
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public DeclarationDescriptor getContainingDeclaration() {
|
||||
// return outerScope.getContainingDeclaration();
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.util.Collection;
|
||||
public class SubstitutingScope implements JetScope {
|
||||
|
||||
private final JetScope workerScope;
|
||||
// private final Map<TypeConstructor, TypeProjection> substitutionContext;
|
||||
private final TypeSubstitutor substitutor;
|
||||
private Collection<DeclarationDescriptor> allDescriptors;
|
||||
|
||||
@@ -60,7 +59,7 @@ public class SubstitutingScope implements JetScope {
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = workerScope.getFunctionGroup(name);
|
||||
if (substitutor.isEmpty()) {
|
||||
if (substitutor.isEmpty() || functionGroup.isEmpty()) {
|
||||
return functionGroup;
|
||||
}
|
||||
return new LazySubstitutingFunctionGroup(substitutor, functionGroup);
|
||||
|
||||
@@ -1,79 +1,22 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.CollectingErrorHandler;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.JetDiagnostic;
|
||||
import org.jetbrains.jet.util.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TemporaryBindingTrace implements BindingTrace {
|
||||
private final BindingContext parentContext;
|
||||
private final MutableManyMap map = ManyMapImpl.create();
|
||||
private final List<JetDiagnostic> diagnostics = Lists.newArrayList();
|
||||
private final ErrorHandler errorHandler = new CollectingErrorHandler(diagnostics);
|
||||
public class TemporaryBindingTrace extends DelegatingBindingTrace {
|
||||
|
||||
private final BindingContext bindingContext = new BindingContext() {
|
||||
@Override
|
||||
public Collection<JetDiagnostic> getDiagnostics() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||
return TemporaryBindingTrace.this.get(slice, key);
|
||||
}
|
||||
};
|
||||
|
||||
public TemporaryBindingTrace(BindingContext parentContext) {
|
||||
this.parentContext = parentContext;
|
||||
public static TemporaryBindingTrace create(BindingTrace trace) {
|
||||
return new TemporaryBindingTrace(trace);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ErrorHandler getErrorHandler() {
|
||||
return errorHandler;
|
||||
private final BindingTrace trace;
|
||||
|
||||
private TemporaryBindingTrace(BindingTrace trace) {
|
||||
super(trace.getBindingContext());
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingContext getBindingContext() {
|
||||
return bindingContext;
|
||||
public void commit() {
|
||||
addAllMyDataTo(trace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
||||
map.put(slice, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
|
||||
record(slice, key, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||
if (map.containsKey(slice, key)) {
|
||||
return map.get(slice, key);
|
||||
}
|
||||
return parentContext.get(slice, key);
|
||||
}
|
||||
|
||||
public void addAllMyDataTo(BindingTrace trace) {
|
||||
for (Map.Entry<ManyMapKey<?, ?>, ?> entry : map) {
|
||||
ManyMapKey manyMapKey = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
//noinspection unchecked
|
||||
trace.record(manyMapKey.getSlice(), manyMapKey.getKey(), value);
|
||||
}
|
||||
|
||||
AnalyzingUtils.applyHandler(trace.getErrorHandler(), diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,6 +478,8 @@ public class TopDownAnalyzer {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void resolveBehaviorDeclarationBodies() {
|
||||
bindOverrides();
|
||||
|
||||
resolveDelegationSpecifierLists();
|
||||
resolveClassAnnotations();
|
||||
|
||||
@@ -488,8 +490,6 @@ public class TopDownAnalyzer {
|
||||
resolveFunctionBodies();
|
||||
|
||||
checkIfPrimaryConstructorIsNecessary();
|
||||
|
||||
bindOverrides();
|
||||
}
|
||||
|
||||
private void bindOverrides() {
|
||||
@@ -580,7 +580,7 @@ public class TopDownAnalyzer {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
if (descriptor.getUnsubstitutedPrimaryConstructor() != null) {
|
||||
typeInferrer.getCallResolver().resolveCall(scopeForConstructor, call, NO_EXPECTED_TYPE);
|
||||
typeInferrer.getCallResolver().resolveCall(scopeForConstructor, null, call, NO_EXPECTED_TYPE);
|
||||
}
|
||||
else {
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
@@ -685,7 +685,7 @@ public class TopDownAnalyzer {
|
||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeInferrerForInitializers.getCallResolver().resolveCall(functionInnerScope, call, NO_EXPECTED_TYPE);
|
||||
typeInferrerForInitializers.getCallResolver().resolveCall(functionInnerScope, null, call, NO_EXPECTED_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,49 +196,28 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
addVariablesAsFunctions();
|
||||
|
||||
WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
|
||||
FunctionGroup functionGroup = getFunctionGroups().get(name);
|
||||
FunctionGroup constructors = null;
|
||||
ClassifierDescriptor classifier = getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
constructors = classDescriptor.getConstructors();
|
||||
}
|
||||
if (functionGroup != null && !functionGroup.isEmpty()) {
|
||||
if (constructors != null) {
|
||||
WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
for (FunctionDescriptor functionDescriptor : functionGroup.getFunctionDescriptors()) {
|
||||
result.addFunction(functionDescriptor);
|
||||
}
|
||||
for (FunctionDescriptor functionDescriptor : constructors.getFunctionDescriptors()) {
|
||||
result.addFunction(functionDescriptor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return functionGroup;
|
||||
}
|
||||
|
||||
if (constructors != null && !constructors.isEmpty()) {
|
||||
return constructors;
|
||||
if (functionGroup != null) {
|
||||
result.addAllFunctions(functionGroup);
|
||||
}
|
||||
|
||||
// ClassifierDescriptor classifier = getClassifier(name);
|
||||
// if (classifier instanceof ClassDescriptor) {
|
||||
// ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
// result.addAllFunctions(classDescriptor.getConstructors());
|
||||
// }
|
||||
|
||||
if (thisType != null) {
|
||||
functionGroup = getThisType().getMemberScope().getFunctionGroup(name);
|
||||
if (!functionGroup.isEmpty()) {
|
||||
return functionGroup;
|
||||
}
|
||||
result.addAllFunctions(getThisType().getMemberScope().getFunctionGroup(name));
|
||||
}
|
||||
|
||||
// TODO : this logic is questionable
|
||||
functionGroup = getWorkerScope().getFunctionGroup(name);
|
||||
if (!functionGroup.isEmpty()) return functionGroup;
|
||||
// for (JetScope imported : getImports()) {
|
||||
// FunctionGroup importedDescriptor = imported.getFunctionGroup(name);
|
||||
// if (!importedDescriptor.isEmpty()) {
|
||||
// return importedDescriptor;
|
||||
// }
|
||||
// }
|
||||
// return functionGroup;
|
||||
return super.getFunctionGroup(name);
|
||||
result.addAllFunctions(getWorkerScope().getFunctionGroup(name));
|
||||
|
||||
result.addAllFunctions(super.getFunctionGroup(name));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addVariablesAsFunctions() {
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.jetbrains.jet.lang.resolve;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionGroup;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -63,13 +60,17 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
if (getImports().isEmpty()) {
|
||||
return FunctionGroup.EMPTY;
|
||||
}
|
||||
WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
for (JetScope imported : getImports()) {
|
||||
FunctionGroup importedDescriptor = imported.getFunctionGroup(name);
|
||||
if (!importedDescriptor.isEmpty()) {
|
||||
return importedDescriptor;
|
||||
FunctionGroup importedFunctions = imported.getFunctionGroup(name);
|
||||
if (!importedFunctions.isEmpty()) {
|
||||
result.addAllFunctions(importedFunctions);
|
||||
}
|
||||
}
|
||||
return FunctionGroup.EMPTY;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,13 +48,15 @@ public class WriteThroughScope extends WritableScopeWithImports {
|
||||
@Override
|
||||
@NotNull
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = writableWorker.getFunctionGroup(name);
|
||||
if (!functionGroup.isEmpty()) return functionGroup; // TODO : Overloads from different places
|
||||
WritableFunctionGroup result = new WritableFunctionGroup(name);
|
||||
|
||||
functionGroup = getWorkerScope().getFunctionGroup(name);
|
||||
if (!functionGroup.isEmpty()) return functionGroup; // TODO : Overloads from different places
|
||||
result.addAllFunctions(writableWorker.getFunctionGroup(name));
|
||||
|
||||
return super.getFunctionGroup(name); // Imports
|
||||
result.addAllFunctions(getWorkerScope().getFunctionGroup(name));
|
||||
|
||||
result.addAllFunctions(super.getFunctionGroup(name)); // Imports
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,11 +32,11 @@ public class JavaPackageScope extends JetScopeImpl {
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
ClassifierDescriptor classifier = getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
return classDescriptor.getConstructors();
|
||||
}
|
||||
// ClassifierDescriptor classifier = getClassifier(name);
|
||||
// if (classifier instanceof ClassDescriptor) {
|
||||
// ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
// return classDescriptor.getConstructors();
|
||||
// }
|
||||
return FunctionGroup.EMPTY;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,9 +93,9 @@ public class CallMaker {
|
||||
}
|
||||
|
||||
public static Call makeCall(final JetExpression calleeExpression, final List<JetExpression> argumentExpressions) {
|
||||
List<ExpressionValueArgument> arguments = Lists.newArrayList();
|
||||
List<ValueArgument> arguments = Lists.newArrayList();
|
||||
for (JetExpression argumentExpression : argumentExpressions) {
|
||||
arguments.add(new ExpressionValueArgument(argumentExpression));
|
||||
arguments.add(makeValueArgument(argumentExpression));
|
||||
}
|
||||
return makeCallWithArguments(calleeExpression, arguments);
|
||||
}
|
||||
@@ -114,4 +114,7 @@ public class CallMaker {
|
||||
return makeCall(arrayAccessExpression, arguments);
|
||||
}
|
||||
|
||||
public static ValueArgument makeValueArgument(JetExpression expression) {
|
||||
return new ExpressionValueArgument(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.lang.ASTNode;
|
||||
@@ -22,21 +25,31 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
*/
|
||||
public class CallResolver {
|
||||
|
||||
private static abstract class ResolutionTask {
|
||||
private static class ResolutionTask {
|
||||
private final Collection<FunctionDescriptor> candidates;
|
||||
private final JetExpression receiver;
|
||||
private final JetType receiverType;
|
||||
private final List<JetTypeProjection> typeArguments;
|
||||
private final List<? extends ValueArgument> valueArguments;
|
||||
private final List<JetExpression> functionLiteralArguments;
|
||||
|
||||
protected ResolutionTask(
|
||||
@NotNull Collection<FunctionDescriptor> candidates,
|
||||
@Nullable JetExpression receiver,
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull List<JetTypeProjection> typeArguments,
|
||||
@NotNull List<? extends ValueArgument> valueArguments) {
|
||||
@NotNull List<? extends ValueArgument> valueArguments,
|
||||
@NotNull List<JetExpression> functionLiteralArguments) {
|
||||
this.candidates = candidates;
|
||||
this.receiver = receiver;
|
||||
this.receiverType = receiverType;
|
||||
this.typeArguments = typeArguments;
|
||||
this.valueArguments = valueArguments;
|
||||
this.functionLiteralArguments = functionLiteralArguments;
|
||||
}
|
||||
|
||||
public ResolutionTask(
|
||||
@NotNull Collection<FunctionDescriptor> candidates,
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull Call call) {
|
||||
this(candidates, receiverType, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -45,8 +58,8 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetExpression getReceiver() {
|
||||
return receiver;
|
||||
public JetType getReceiverType() {
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -59,15 +72,24 @@ public class CallResolver {
|
||||
return valueArguments;
|
||||
}
|
||||
|
||||
public abstract void bindFunctionReference(@NotNull BindingTrace trace, @NotNull FunctionDescriptor functionDescriptor);
|
||||
@NotNull
|
||||
public List<JetExpression> getFunctionLiteralArguments() {
|
||||
return functionLiteralArguments;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message);
|
||||
private interface TracingStrategy {
|
||||
void bindFunctionReference(@NotNull BindingTrace trace, @NotNull FunctionDescriptor functionDescriptor);
|
||||
|
||||
public abstract void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
public abstract void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
public abstract void reportUnresolvedFunctionReference(@NotNull BindingTrace trace);
|
||||
void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
void reportUnresolvedFunctionReference(@NotNull BindingTrace trace);
|
||||
|
||||
void reportErrorOnFunctionReference(BindingTrace trace, String message);
|
||||
}
|
||||
|
||||
private final BindingTrace trace;
|
||||
@@ -87,10 +109,11 @@ public class CallResolver {
|
||||
@Nullable
|
||||
public JetType resolveCall(
|
||||
@NotNull JetScope scope,
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull JetCallElement call,
|
||||
@NotNull JetType expectedType
|
||||
) {
|
||||
FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(scope, null, call, expectedType);
|
||||
FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(scope, receiverType, call, expectedType);
|
||||
return functionDescriptor == null ? null : functionDescriptor.getReturnType();
|
||||
}
|
||||
|
||||
@@ -100,47 +123,55 @@ public class CallResolver {
|
||||
@NotNull final Call call,
|
||||
@NotNull final JetReferenceExpression functionReference,
|
||||
@NotNull String name,
|
||||
@Nullable JetExpression receiver,
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull JetType expectedType) {
|
||||
Collection<FunctionDescriptor> candidates;
|
||||
if (receiver != null) {
|
||||
JetType type = typeInferrer.getServices(trace).getType(scope, receiver, false, NO_EXPECTED_TYPE);
|
||||
if (type == null) {
|
||||
return null; // TODO : check parameter types anyway?
|
||||
}
|
||||
// TODO : autocasts
|
||||
// TODO : nullability
|
||||
candidates = type.getMemberScope().getFunctionGroup(name).getFunctionDescriptors();
|
||||
}
|
||||
else {
|
||||
candidates = scope.getFunctionGroup(name).getFunctionDescriptors();
|
||||
}
|
||||
return resolveCallToFunctionDescriptor(scope, receiver, call, functionReference.getNode(), expectedType, candidates, functionReference);
|
||||
// TODO : autocasts
|
||||
// TODO : nullability
|
||||
List<ResolutionTask> tasks = computePrioritizedTasks(scope, receiverType, call, name);
|
||||
return resolveCallToFunctionDescriptor(scope, call, functionReference.getNode(), expectedType, tasks, functionReference);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveSimpleCallToFunctionDescriptor(
|
||||
@NotNull JetScope scope,
|
||||
@Nullable JetExpression receiver,
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull final JetCallElement call,
|
||||
@NotNull JetType expectedType
|
||||
) {
|
||||
List<ResolutionTask> prioritizedTasks;
|
||||
|
||||
JetExpression calleeExpression = call.getCalleeExpression();
|
||||
Collection<FunctionDescriptor> candidates;
|
||||
final JetReferenceExpression functionReference;
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
|
||||
functionReference = expression;
|
||||
candidates = scope.getFunctionGroup(expression.getReferencedName()).getFunctionDescriptors();
|
||||
|
||||
String name = expression.getReferencedName();
|
||||
if (name == null) return null;
|
||||
|
||||
prioritizedTasks = computePrioritizedTasks(scope, receiverType, call, name);
|
||||
}
|
||||
else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
assert receiverType == null;
|
||||
|
||||
prioritizedTasks = Lists.newArrayList();
|
||||
|
||||
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
|
||||
functionReference = expression.getConstructorReferenceExpression();
|
||||
JetType constructedType = typeResolver.resolveType(scope, expression.getTypeReference());
|
||||
if (functionReference == null) {
|
||||
return null; // No type there
|
||||
}
|
||||
JetTypeReference typeReference = expression.getTypeReference();
|
||||
JetType constructedType = typeResolver.resolveType(scope, typeReference);
|
||||
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
candidates = classDescriptor.getConstructors().getFunctionDescriptors();
|
||||
Set<FunctionDescriptor> members = classDescriptor.getConstructors().getFunctionDescriptors();
|
||||
if (members.isEmpty()) {
|
||||
trace.getErrorHandler().genericError(call.getValueArgumentList().getNode(), "This class does not have a constructor");
|
||||
return null;
|
||||
}
|
||||
addTask(prioritizedTasks, null, call, members);
|
||||
}
|
||||
else {
|
||||
trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
|
||||
@@ -148,22 +179,76 @@ public class CallResolver {
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Type argument inference not implemented");
|
||||
throw new UnsupportedOperationException("Type argument inference not implemented for " + call);
|
||||
}
|
||||
|
||||
return resolveCallToFunctionDescriptor(scope, receiver, call, call.getNode(), expectedType, candidates, functionReference);
|
||||
return resolveCallToFunctionDescriptor(scope, call, call.getNode(), expectedType, prioritizedTasks, functionReference);
|
||||
}
|
||||
|
||||
private List<ResolutionTask> computePrioritizedTasks(JetScope scope, JetType receiverType, Call call, String name) {
|
||||
List<ResolutionTask> result = Lists.newArrayList();
|
||||
if (receiverType != null) {
|
||||
Collection<FunctionDescriptor> extensionFunctions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
|
||||
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor functionDescriptor = iterator.next();
|
||||
if (functionDescriptor.getReceiverType() == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
List<FunctionDescriptor> nonlocals = Lists.newArrayList();
|
||||
List<FunctionDescriptor> locals = Lists.newArrayList();
|
||||
splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
|
||||
|
||||
Set<FunctionDescriptor> members = Sets.newHashSet(receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors());
|
||||
addConstrtuctors(receiverType.getMemberScope(), name, members);
|
||||
|
||||
addTask(result, receiverType, call, locals);
|
||||
addTask(result, null, call, members);
|
||||
addTask(result, receiverType, call, nonlocals);
|
||||
}
|
||||
else {
|
||||
Collection<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
|
||||
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
|
||||
FunctionDescriptor functionDescriptor = iterator.next();
|
||||
if (functionDescriptor.getReceiverType() != null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
addConstrtuctors(scope, name, functions);
|
||||
|
||||
List<FunctionDescriptor> nonlocals = Lists.newArrayList();
|
||||
List<FunctionDescriptor> locals = Lists.newArrayList();
|
||||
splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
|
||||
|
||||
addTask(result, receiverType, call, locals);
|
||||
|
||||
addTask(result, receiverType, call, nonlocals);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addTask(List<ResolutionTask> result, JetType receiverType, Call call, Collection<FunctionDescriptor> candidates) {
|
||||
if (candidates.isEmpty()) return;
|
||||
result.add(new ResolutionTask(candidates, receiverType, call));
|
||||
}
|
||||
|
||||
private void addConstrtuctors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
|
||||
ClassifierDescriptor classifier = scope.getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
functions.addAll(classDescriptor.getConstructors().getFunctionDescriptors());
|
||||
}
|
||||
}
|
||||
|
||||
private FunctionDescriptor resolveCallToFunctionDescriptor(
|
||||
JetScope scope,
|
||||
final JetExpression receiver,
|
||||
final Call call,
|
||||
final ASTNode callNode,
|
||||
JetType expectedType,
|
||||
final Collection<FunctionDescriptor> candidates,
|
||||
final JetReferenceExpression functionReference) {
|
||||
ResolutionTask task = new ResolutionTask(candidates, receiver, call.getTypeArguments(), call.getValueArguments()) {
|
||||
@NotNull JetScope scope,
|
||||
@NotNull final Call call,
|
||||
@NotNull final ASTNode callNode,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull final List<ResolutionTask> prioritizedTasks, // high to low priority
|
||||
@NotNull final JetReferenceExpression functionReference) {
|
||||
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
||||
TracingStrategy tracing = new TracingStrategy() {
|
||||
@Override
|
||||
public void bindFunctionReference(@NotNull BindingTrace trace, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
trace.record(BindingContext.REFERENCE_TARGET, functionReference, functionDescriptor);
|
||||
@@ -207,14 +292,38 @@ public class CallResolver {
|
||||
public void reportUnresolvedFunctionReference(@NotNull BindingTrace trace) {
|
||||
trace.getErrorHandler().unresolvedReference(functionReference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportErrorOnFunctionReference(BindingTrace trace, String message) {
|
||||
trace.getErrorHandler().genericError(functionReference.getNode(), message);
|
||||
}
|
||||
|
||||
};
|
||||
return performResolution(scope, expectedType, task);
|
||||
for (ResolutionTask task : prioritizedTasks) {
|
||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||
FunctionDescriptor functionDescriptor = performResolution(temporaryTrace, scope, expectedType, task, tracing);
|
||||
if (functionDescriptor != null) {
|
||||
temporaryTrace.commit();
|
||||
return functionDescriptor;
|
||||
}
|
||||
if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) {
|
||||
traceForFirstNonemptyCandidateSet = temporaryTrace;
|
||||
}
|
||||
}
|
||||
if (traceForFirstNonemptyCandidateSet != null) {
|
||||
traceForFirstNonemptyCandidateSet.commit();
|
||||
}
|
||||
else {
|
||||
trace.getErrorHandler().unresolvedReference(functionReference);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean mapValueArgumentsToParameters(
|
||||
@NotNull ResolutionTask task,
|
||||
@NotNull TracingStrategy tracing,
|
||||
@NotNull FunctionDescriptor candidate,
|
||||
@NotNull BindingTrace temporaryTrace,
|
||||
@NotNull Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters
|
||||
@@ -222,6 +331,7 @@ public class CallResolver {
|
||||
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
||||
|
||||
Map<String, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||
parameterByName.put(valueParameter.getName(), valueParameter);
|
||||
@@ -229,22 +339,25 @@ public class CallResolver {
|
||||
|
||||
List<? extends ValueArgument> valueArguments = task.getValueArguments();
|
||||
|
||||
boolean error = false;
|
||||
boolean someNamed = false;
|
||||
boolean somePositioned = false;
|
||||
boolean error = false;
|
||||
for (int i = 0; i < valueArguments.size(); i++) {
|
||||
ValueArgument valueArgument = valueArguments.get(i);
|
||||
if (valueArgument.isNamed()) {
|
||||
someNamed = true;
|
||||
ASTNode nameNode = valueArgument.getArgumentName().getNode();
|
||||
if (somePositioned) {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.getArgumentName().getNode(), "Mixing named and positioned arguments in not allowed");
|
||||
temporaryTrace.getErrorHandler().genericError(nameNode, "Mixing named and positioned arguments in not allowed");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(valueArgument.getArgumentName().getName());
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
if (usedParameters.add(valueParameterDescriptor)) {
|
||||
temporaryTrace.getErrorHandler().genericError(nameNode, "An argument is already passed for this parameter");
|
||||
}
|
||||
if (valueParameterDescriptor == null) {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.getArgumentName().getNode(), "Cannot find a parameter with this name");
|
||||
temporaryTrace.getErrorHandler().genericError(nameNode, "Cannot find a parameter with this name");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
@@ -260,13 +373,13 @@ public class CallResolver {
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
if (i < valueParameters.size()) {
|
||||
int parameterCount = valueParameters.size();
|
||||
if (i < parameterCount) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
|
||||
}
|
||||
else if (!valueParameters.isEmpty()) {
|
||||
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||
if (valueParameterDescriptor.isVararg()) {
|
||||
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
|
||||
@@ -285,10 +398,51 @@ public class CallResolver {
|
||||
}
|
||||
}
|
||||
|
||||
List<JetExpression> functionLiteralArguments = task.getFunctionLiteralArguments();
|
||||
if (!functionLiteralArguments.isEmpty()) {
|
||||
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
|
||||
|
||||
if (valueParameters.isEmpty()) {
|
||||
temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), "Too many arguments");
|
||||
error = true;
|
||||
} else {
|
||||
JetFunctionLiteralExpression functionLiteral;
|
||||
if (possiblyLabeledFunctionLiteral instanceof JetLabelQualifiedExpression) {
|
||||
JetLabelQualifiedExpression labeledFunctionLiteral = (JetLabelQualifiedExpression) possiblyLabeledFunctionLiteral;
|
||||
functionLiteral = (JetFunctionLiteralExpression) labeledFunctionLiteral.getLabeledExpression();
|
||||
}
|
||||
else {
|
||||
functionLiteral = (JetFunctionLiteralExpression) possiblyLabeledFunctionLiteral;
|
||||
}
|
||||
|
||||
ValueParameterDescriptor parameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||
if (parameterDescriptor.isVararg()) {
|
||||
temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), "Passing value as a vararg is only allowed inside a parenthesized argument list");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
if (!usedParameters.add(parameterDescriptor)) {
|
||||
temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), "Too many arguments");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
argumentsToParameters.put(CallMaker.makeValueArgument(functionLiteral), parameterDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < functionLiteralArguments.size(); i++) {
|
||||
JetExpression argument = functionLiteralArguments.get(i);
|
||||
temporaryTrace.getErrorHandler().genericError(argument.getNode(), "Only one function literal is allowed outside a parenthesized argument list");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||
if (!usedParameters.contains(valueParameter)) {
|
||||
if (!valueParameter.hasDefaultValue()) {
|
||||
task.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
|
||||
tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
@@ -297,58 +451,77 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor performResolution(@NotNull JetScope scope, @NotNull JetType expectedType, @NotNull ResolutionTask task) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> successfulCandidates = Maps.newHashMap();
|
||||
Set<FunctionDescriptor> failedCandidates = Sets.newHashSet();
|
||||
private FunctionDescriptor performResolution(@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull JetType expectedType, @NotNull ResolutionTask task, @NotNull TracingStrategy tracing) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> successfulCandidates = Maps.newLinkedHashMap();
|
||||
Set<FunctionDescriptor> failedCandidates = Sets.newLinkedHashSet();
|
||||
Map<FunctionDescriptor, ConstraintSystem.Solution> solutions = Maps.newHashMap();
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> traces = Maps.newHashMap();
|
||||
|
||||
for (FunctionDescriptor candidate : task.getCandidates()) {
|
||||
TemporaryBindingTrace temporaryTrace = new TemporaryBindingTrace(trace.getBindingContext());
|
||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||
traces.put(candidate, temporaryTrace);
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
|
||||
task.bindFunctionReference(temporaryTrace, candidate);
|
||||
tracing.bindFunctionReference(temporaryTrace, candidate);
|
||||
|
||||
Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters = Maps.newHashMap();
|
||||
boolean error = mapValueArgumentsToParameters(task, candidate, temporaryTrace, argumentsToParameters);
|
||||
boolean error = mapValueArgumentsToParameters(task, tracing, candidate, temporaryTrace, argumentsToParameters);
|
||||
|
||||
if (error) continue;
|
||||
|
||||
if (task.getTypeArguments().isEmpty()) {
|
||||
// Type argument inference
|
||||
|
||||
ConstraintSystem constraintSystem = new ConstraintSystem();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
||||
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
||||
}
|
||||
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
JetType type = temporaryServices.getType(scope, expression, false, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
if (candidate.getTypeParameters().isEmpty()) {
|
||||
if (checkValueArgumentTypes(scope, temporaryServices, argumentsToParameters, Functions.<ValueParameterDescriptor>identity())
|
||||
&& checkReceiver(task, tracing, candidate, temporaryTrace)) {
|
||||
successfulCandidates.put(candidate, candidate);
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedType != NO_EXPECTED_TYPE) {
|
||||
constraintSystem.addSubtypingConstraint(candidate.getReturnType(), expectedType);
|
||||
}
|
||||
|
||||
ConstraintSystem.Solution solution = constraintSystem.solve();
|
||||
solutions.put(candidate, solution);
|
||||
if (solution.isSuccessful()) {
|
||||
FunctionDescriptor substitute = candidate.substitute(solution.getSubstitutor());
|
||||
assert substitute != null;
|
||||
successfulCandidates.put(candidate, substitute);
|
||||
}
|
||||
else {
|
||||
task.reportOverallResolutionError(temporaryTrace, "Type inference failed");
|
||||
failedCandidates.add(candidate);
|
||||
// Type argument inference
|
||||
|
||||
ConstraintSystem constraintSystem = new ConstraintSystem();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
||||
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
||||
}
|
||||
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
JetType type = temporaryServices.getType(scope, expression, false, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
}
|
||||
}
|
||||
|
||||
checkReceiverAbsence(task, tracing, candidate, temporaryTrace);
|
||||
// Error is already reported if something is missing
|
||||
JetType receiverType = task.getReceiverType();
|
||||
JetType candidateReceiverType = candidate.getReceiverType();
|
||||
if (receiverType != null && candidateReceiverType != null) {
|
||||
constraintSystem.addSubtypingConstraint(receiverType, candidateReceiverType);
|
||||
}
|
||||
|
||||
if (expectedType != NO_EXPECTED_TYPE) {
|
||||
constraintSystem.addSubtypingConstraint(candidate.getReturnType(), expectedType);
|
||||
}
|
||||
|
||||
ConstraintSystem.Solution solution = constraintSystem.solve();
|
||||
solutions.put(candidate, solution);
|
||||
if (solution.isSuccessful()) {
|
||||
FunctionDescriptor substitute = candidate.substitute(solution.getSubstitutor());
|
||||
assert substitute != null;
|
||||
successfulCandidates.put(candidate, substitute);
|
||||
}
|
||||
else {
|
||||
tracing.reportOverallResolutionError(temporaryTrace, "Type inference failed");
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -362,57 +535,80 @@ public class CallResolver {
|
||||
}
|
||||
}
|
||||
|
||||
List<JetType> typeArguments = new ArrayList<JetType>();
|
||||
for (JetTypeProjection projection : jetTypeArguments) {
|
||||
// TODO : check that there's no projection
|
||||
JetTypeReference typeReference = projection.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeArguments.add(new TypeResolver(semanticServices, temporaryTrace, true).resolveType(scope, typeReference));
|
||||
if (candidate.getTypeParameters().size() == jetTypeArguments.size()) {
|
||||
List<JetType> typeArguments = new ArrayList<JetType>();
|
||||
for (JetTypeProjection projection : jetTypeArguments) {
|
||||
// TODO : check that there's no projection
|
||||
JetTypeReference typeReference = projection.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeArguments.add(new TypeResolver(semanticServices, temporaryTrace, true).resolveType(scope, typeReference));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate);
|
||||
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate);
|
||||
|
||||
int typeArgCount = typeArguments.size();
|
||||
if (candidate.getTypeParameters().size() == typeArgCount) {
|
||||
FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, candidate);
|
||||
|
||||
assert substitutedFunctionDescriptor != null;
|
||||
Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
|
||||
final Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) {
|
||||
parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
|
||||
}
|
||||
|
||||
boolean localError = false;
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
ValueParameterDescriptor substitutedParameter = parameterMap.get(valueParameterDescriptor.getOriginal());
|
||||
|
||||
assert substitutedParameter != null;
|
||||
|
||||
JetType parameterType = substitutedParameter.getOutType();
|
||||
JetType type = temporaryServices.getType(scope, valueArgument.getArgumentExpression(), false, parameterType);
|
||||
if (type == null) {
|
||||
localError = true;
|
||||
Function<ValueParameterDescriptor, ValueParameterDescriptor> mapFunction = new Function<ValueParameterDescriptor, ValueParameterDescriptor>() {
|
||||
@Override
|
||||
public ValueParameterDescriptor apply(ValueParameterDescriptor input) {
|
||||
return parameterMap.get(input.getOriginal());
|
||||
}
|
||||
}
|
||||
if (localError) {
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
else {
|
||||
};
|
||||
if (checkValueArgumentTypes(scope, temporaryServices, argumentsToParameters, mapFunction)
|
||||
&& checkReceiver(task, tracing, substitutedFunctionDescriptor, temporaryTrace)) {
|
||||
successfulCandidates.put(candidate, substitutedFunctionDescriptor);
|
||||
}
|
||||
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
task.reportWrongTypeArguments(temporaryTrace, "Number of type arguments does not match " + DescriptorRenderer.TEXT.render(candidate));
|
||||
tracing.reportWrongTypeArguments(temporaryTrace, "Number of type arguments does not match " + DescriptorRenderer.TEXT.render(candidate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates, traces);
|
||||
}
|
||||
|
||||
private boolean checkReceiver(ResolutionTask task, TracingStrategy tracing, FunctionDescriptor candidate, TemporaryBindingTrace temporaryTrace) {
|
||||
if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false;
|
||||
JetType receiverType = task.getReceiverType();
|
||||
JetType candidateReceiverType = candidate.getReceiverType();
|
||||
if (receiverType != null
|
||||
&& candidateReceiverType != null
|
||||
&& !semanticServices.getTypeChecker().isSubtypeOf(receiverType, candidateReceiverType)) {
|
||||
tracing.reportErrorOnFunctionReference(temporaryTrace, "This function requires a receiver of type " + candidateReceiverType);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkReceiverAbsence(ResolutionTask task, TracingStrategy tracing, FunctionDescriptor candidate, TemporaryBindingTrace temporaryTrace) {
|
||||
JetType receiverType = task.getReceiverType();
|
||||
JetType candidateReceiverType = candidate.getReceiverType();
|
||||
if (receiverType != null) {
|
||||
if (candidateReceiverType == null) {
|
||||
tracing.reportErrorOnFunctionReference(temporaryTrace, "This function does not admit a receiver");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (candidateReceiverType != null) {
|
||||
tracing.reportErrorOnFunctionReference(temporaryTrace, "Receiver is missing" + candidateReceiverType);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private FunctionDescriptor computeResultAndReportErrors(BindingTrace trace, TracingStrategy tracing, Map<FunctionDescriptor, FunctionDescriptor> successfulCandidates, Set<FunctionDescriptor> failedCandidates, Map<FunctionDescriptor, TemporaryBindingTrace> traces) {
|
||||
if (successfulCandidates.size() > 0) {
|
||||
if (successfulCandidates.size() == 1) {
|
||||
Map.Entry<FunctionDescriptor, FunctionDescriptor> entry = successfulCandidates.entrySet().iterator().next();
|
||||
@@ -420,25 +616,18 @@ public class CallResolver {
|
||||
FunctionDescriptor result = entry.getValue();
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.addAllMyDataTo(trace);
|
||||
temporaryTrace.commit();
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> maximallySpecific = Maps.newHashMap();
|
||||
meLoop:
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> myEntry : successfulCandidates.entrySet()) {
|
||||
FunctionDescriptor me = myEntry.getValue();
|
||||
TemporaryBindingTrace myTrace = traces.get(myEntry.getKey());
|
||||
for (FunctionDescriptor other : successfulCandidates.values()) {
|
||||
if (other == me) continue;
|
||||
if (!moreSpecific(me, other) || moreSpecific(other, me)) continue meLoop;
|
||||
}
|
||||
maximallySpecific.put(me, myTrace);
|
||||
FunctionDescriptor maximallySpecific = findMaximallySpecific(successfulCandidates, traces, false);
|
||||
if (maximallySpecific != null) {
|
||||
return maximallySpecific;
|
||||
}
|
||||
if (maximallySpecific.size() == 1) {
|
||||
Map.Entry<FunctionDescriptor, TemporaryBindingTrace> result = maximallySpecific.entrySet().iterator().next();
|
||||
result.getValue().addAllMyDataTo(trace);
|
||||
return result.getKey();
|
||||
|
||||
FunctionDescriptor maximallySpecificGenericsDiscriminated = findMaximallySpecific(successfulCandidates, traces, true);
|
||||
if (maximallySpecificGenericsDiscriminated != null) {
|
||||
return maximallySpecificGenericsDiscriminated;
|
||||
}
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
@@ -446,14 +635,14 @@ public class CallResolver {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
|
||||
task.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
||||
tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
||||
}
|
||||
}
|
||||
else if (!failedCandidates.isEmpty()) {
|
||||
if (failedCandidates.size() == 1) {
|
||||
FunctionDescriptor functionDescriptor = failedCandidates.iterator().next();
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.addAllMyDataTo(trace);
|
||||
temporaryTrace.commit();
|
||||
}
|
||||
else {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
@@ -461,16 +650,65 @@ public class CallResolver {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
|
||||
task.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder);
|
||||
tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder);
|
||||
}
|
||||
}
|
||||
else {
|
||||
task.reportUnresolvedFunctionReference(trace);
|
||||
tracing.reportUnresolvedFunctionReference(trace);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) {
|
||||
private boolean checkValueArgumentTypes(JetScope scope, JetTypeInferrer.Services temporaryServices, Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters, Function<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap) {
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
ValueParameterDescriptor substitutedParameter = parameterMap.apply(valueParameterDescriptor);
|
||||
|
||||
assert substitutedParameter != null;
|
||||
|
||||
JetType parameterType = substitutedParameter.getOutType();
|
||||
JetType type = temporaryServices.getType(scope, valueArgument.getArgumentExpression(), false, parameterType);
|
||||
if (type == null || !semanticServices.getTypeChecker().isSubtypeOf(type, parameterType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor findMaximallySpecific(Map<FunctionDescriptor, FunctionDescriptor> candidates, Map<FunctionDescriptor, TemporaryBindingTrace> traces, boolean discriminateGenericFunctions) {
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> maximallySpecific = Maps.newHashMap();
|
||||
meLoop:
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> myEntry : candidates.entrySet()) {
|
||||
FunctionDescriptor me = myEntry.getValue();
|
||||
TemporaryBindingTrace myTrace = traces.get(myEntry.getKey());
|
||||
for (FunctionDescriptor other : candidates.values()) {
|
||||
if (other == me) continue;
|
||||
if (!moreSpecific(me, other, discriminateGenericFunctions) || moreSpecific(other, me, discriminateGenericFunctions)) continue meLoop;
|
||||
}
|
||||
maximallySpecific.put(me, myTrace);
|
||||
}
|
||||
if (maximallySpecific.size() == 1) {
|
||||
Map.Entry<FunctionDescriptor, TemporaryBindingTrace> result = maximallySpecific.entrySet().iterator().next();
|
||||
result.getValue().commit();
|
||||
return result.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let < mean "more specific"
|
||||
* Subtype < supertype
|
||||
* Double < Float
|
||||
* Int < Long
|
||||
* Int < Short < Byte
|
||||
*/
|
||||
private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g, boolean discriminateGenericFunctions) {
|
||||
if (overrides(f, g)) return true;
|
||||
if (overrides(g, f)) return false;
|
||||
|
||||
List<ValueParameterDescriptor> fParams = f.getValueParameters();
|
||||
List<ValueParameterDescriptor> gParams = g.getValueParameters();
|
||||
|
||||
@@ -480,13 +718,62 @@ public class CallResolver {
|
||||
JetType fParamType = fParams.get(i).getOutType();
|
||||
JetType gParamType = gParams.get(i).getOutType();
|
||||
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(fParamType, gParamType)) {
|
||||
if (!semanticServices.getTypeChecker().isSubtypeOf(fParamType, gParamType)
|
||||
&& !numericTypeMoreSpecific(fParamType, gParamType)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (discriminateGenericFunctions && isGenericFunction(f)) {
|
||||
if (!isGenericFunction(g)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// g is generic, too
|
||||
|
||||
return moreSpecific(FunctionDescriptorUtil.substituteBounds(f), FunctionDescriptorUtil.substituteBounds(g), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isGenericFunction(FunctionDescriptor f) {
|
||||
return !f.getOriginal().getTypeParameters().isEmpty();
|
||||
}
|
||||
|
||||
private boolean numericTypeMoreSpecific(@NotNull JetType specific, @NotNull JetType general) {
|
||||
JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
|
||||
JetType _double = standardLibrary.getDoubleType();
|
||||
JetType _float = standardLibrary.getFloatType();
|
||||
JetType _long = standardLibrary.getLongType();
|
||||
JetType _int = standardLibrary.getIntType();
|
||||
JetType _byte = standardLibrary.getByteType();
|
||||
JetType _short = standardLibrary.getShortType();
|
||||
|
||||
if (eq(specific, _double) && eq(general, _float)) return true;
|
||||
if (eq(specific, _int)) {
|
||||
if (eq(general, _long)) return true;
|
||||
if (eq(general, _byte)) return true;
|
||||
if (eq(general, _short)) return true;
|
||||
}
|
||||
if (eq(specific, _short) && eq(general, _byte)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean eq(@NotNull JetType a, @NotNull JetType b) {
|
||||
return semanticServices.getTypeChecker().isSubtypeOf(a, b) && semanticServices.getTypeChecker().isSubtypeOf(b, a);
|
||||
}
|
||||
|
||||
private boolean overrides(@NotNull FunctionDescriptor f, @NotNull FunctionDescriptor g) {
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = f.getOverriddenFunctions();
|
||||
FunctionDescriptor originalG = g.getOriginal();
|
||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||
if (originalG.equals(overriddenFunction.getOriginal())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void checkGenericBoundsInAFunctionCall(List<JetTypeProjection> jetTypeArguments, List<JetType> typeArguments, FunctionDescriptor functionDescriptor) {
|
||||
Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
|
||||
|
||||
@@ -507,9 +794,126 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResult resolveExactSignature(@NotNull JetScope scope, @NotNull JetType receiver, @NotNull String name, @NotNull List<JetType> jetTypes) {
|
||||
// TODO
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
public OverloadResolutionResult resolveExactSignature(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull String name, @NotNull List<JetType> parameterTypes) {
|
||||
List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiverType, name, parameterTypes);
|
||||
return listToOverloadResolutionResult(result);
|
||||
}
|
||||
|
||||
private List<FunctionDescriptor> findCandidatesByExactSignature(JetScope scope, JetType receiverType, String name, List<JetType> parameterTypes) {
|
||||
List<FunctionDescriptor> result = Lists.newArrayList();
|
||||
if (receiverType != null) {
|
||||
Set<FunctionDescriptor> extensionFunctionDescriptors = scope.getFunctionGroup(name).getFunctionDescriptors();
|
||||
List<FunctionDescriptor> nonlocal = Lists.newArrayList();
|
||||
List<FunctionDescriptor> local = Lists.newArrayList();
|
||||
splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
|
||||
|
||||
|
||||
if (findExtensionFunctions(local, receiverType, parameterTypes, result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Set<FunctionDescriptor> functionDescriptors = receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors();
|
||||
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
|
||||
return result;
|
||||
|
||||
}
|
||||
findExtensionFunctions(nonlocal, receiverType, parameterTypes, result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
lookupExactSignature(scope.getFunctionGroup(name).getFunctionDescriptors(), parameterTypes, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean lookupExactSignature(Set<FunctionDescriptor> candidates, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
|
||||
boolean found = false;
|
||||
for (FunctionDescriptor functionDescriptor : candidates) {
|
||||
if (functionDescriptor.getReceiverType() != null) continue;
|
||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
|
||||
result.add(functionDescriptor);
|
||||
found = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private OverloadResolutionResult listToOverloadResolutionResult(List<FunctionDescriptor> result) {
|
||||
if (result.isEmpty()) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
else if (result.size() == 1) {
|
||||
return OverloadResolutionResult.success(result.get(0));
|
||||
}
|
||||
else {
|
||||
return OverloadResolutionResult.ambiguity(result);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean findExtensionFunctions(Collection<FunctionDescriptor> candidates, JetType receiverType, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
|
||||
boolean found = false;
|
||||
for (FunctionDescriptor functionDescriptor : candidates) {
|
||||
JetType functionReceiverType = functionDescriptor.getReceiverType();
|
||||
if (functionReceiverType == null) continue;
|
||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||
if (!semanticServices.getTypeChecker().isSubtypeOf(receiverType, functionReceiverType)) continue;
|
||||
if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
|
||||
result.add(functionDescriptor);
|
||||
found = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private <T extends DeclarationDescriptor> void splitLexicallyLocalDescriptors(
|
||||
Collection<? extends T> allDescriptors, DeclarationDescriptor containerOfTheCurrentLocality, List<? super T> local, List<? super T> nonlocal) {
|
||||
|
||||
for (T descriptor : allDescriptors) {
|
||||
if (isLocal(containerOfTheCurrentLocality, descriptor)) {
|
||||
local.add(descriptor);
|
||||
}
|
||||
else {
|
||||
nonlocal.add(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The primary case for local extensions is the following:
|
||||
*
|
||||
* I had a locally declared extension function or a local variable of function type called foo
|
||||
* And I called it on my x
|
||||
* Now, someone added function foo() to the class of x
|
||||
* My code should not change
|
||||
*
|
||||
* thus
|
||||
*
|
||||
* local extension prevail over members (and members prevail over all non-local extensions)
|
||||
*/
|
||||
private boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
|
||||
DeclarationDescriptor parent = candidate.getContainingDeclaration();
|
||||
if (!(parent instanceof FunctionDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
|
||||
DeclarationDescriptor current = containerOfTheCurrentLocality;
|
||||
while (current != null) {
|
||||
if (current == functionDescriptor) {
|
||||
return true;
|
||||
}
|
||||
current = current.getContainingDeclaration();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<JetType> parameterTypes) {
|
||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||
if (valueParameters.size() != parameterTypes.size()) return false;
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor valueParameter = valueParameters.get(i);
|
||||
JetType expectedType = parameterTypes.get(i);
|
||||
if (!eq(expectedType, valueParameter.getOutType())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class DescriptorSubstitutor {
|
||||
|
||||
@NotNull
|
||||
public static TypeSubstitutor substituteTypeParameters(
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull final TypeSubstitutor originalSubstitutor,
|
||||
@NotNull DeclarationDescriptor newContainingDeclaration,
|
||||
@NotNull List<TypeParameterDescriptor> result) {
|
||||
final Map<TypeConstructor, TypeProjection> mutableSubstitution = Maps.newHashMap();
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitutor.TypeSubstitution() {
|
||||
|
||||
@Override
|
||||
public TypeProjection get(TypeConstructor key) {
|
||||
if (originalSubstitutor.inRange(key)) {
|
||||
return originalSubstitutor.getSubstitution().get(key);
|
||||
}
|
||||
return mutableSubstitution.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return originalSubstitutor.isEmpty() && mutableSubstitution.isEmpty();
|
||||
}
|
||||
});
|
||||
|
||||
for (TypeParameterDescriptor descriptor : typeParameters) {
|
||||
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification(
|
||||
newContainingDeclaration,
|
||||
descriptor.getAnnotations(),
|
||||
descriptor.getVariance(),
|
||||
descriptor.getName(),
|
||||
descriptor.getIndex());
|
||||
|
||||
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjection(substituted.getDefaultType()));
|
||||
|
||||
for (JetType upperBound : descriptor.getUpperBounds()) {
|
||||
substituted.getUpperBounds().add(substitutor.substitute(upperBound, Variance.INVARIANT));
|
||||
}
|
||||
|
||||
result.add(substituted);
|
||||
}
|
||||
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ 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.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -79,13 +78,6 @@ public class ErrorUtils {
|
||||
return "<ERROR FUNCTION>";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
List<TypeParameterDescriptor> typeParameters = Collections.<TypeParameterDescriptor>emptyList();
|
||||
return OverloadResolutionResult.success(createErrorFunction(typeParameters, positionedValueArgumentTypes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
|
||||
@@ -21,10 +21,12 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ErrorValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.jetbrains.jet.util.WritableSlice;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT;
|
||||
|
||||
/**
|
||||
@@ -60,6 +62,11 @@ public class JetTypeInferrer {
|
||||
public List<AnnotationDescriptor> getAnnotations() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FORBIDDEN";
|
||||
}
|
||||
};
|
||||
public static final JetType NO_EXPECTED_TYPE = new JetType() {
|
||||
@NotNull
|
||||
@@ -89,6 +96,11 @@ public class JetTypeInferrer {
|
||||
public List<AnnotationDescriptor> getAnnotations() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NO_EXPECTED_TYPE";
|
||||
}
|
||||
};
|
||||
|
||||
private static final ImmutableMap<IElementType, String> unaryOperationNames = ImmutableMap.<IElementType, String>builder()
|
||||
@@ -180,84 +192,6 @@ public class JetTypeInferrer {
|
||||
return typeInferrerVisitorWithNamespaces.getType(expression, new TypeInferenceContext(trace, scope, preferBlock, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, NO_EXPECTED_TYPE));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private OverloadResolutionResult resolveNoParametersFunction(@NotNull JetType receiverType, @NotNull JetScope scope, @NotNull String name) {
|
||||
// OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
|
||||
// No generics. Guaranteed
|
||||
// return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), Collections.<JetType>emptyList());
|
||||
return callResolver.resolveExactSignature(scope, receiverType, name, Collections.<JetType>emptyList());
|
||||
}
|
||||
|
||||
// private OverloadDomain getOverloadDomain(
|
||||
// @Nullable final JetType receiverType,
|
||||
// @NotNull final JetScope scope,
|
||||
// @NotNull JetExpression calleeExpression,
|
||||
// @Nullable PsiElement argumentList
|
||||
// ) {
|
||||
// final OverloadDomain[] result = new OverloadDomain[1];
|
||||
// final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
|
||||
// calleeExpression.accept(new JetVisitorVoid() {
|
||||
//
|
||||
// @Override
|
||||
// public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
|
||||
// // a#b -- create a domain for all overloads of b in a
|
||||
// throw new UnsupportedOperationException(); // TODO
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitPredicateExpression(JetPredicateExpression expression) {
|
||||
// // overload lookup for checking, but the type is receiver's type + nullable
|
||||
// throw new UnsupportedOperationException(); // TODO
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitQualifiedExpression(JetQualifiedExpression expression) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]");
|
||||
//
|
||||
// // . or ?.
|
||||
// // JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
|
||||
// // checkNullSafety(receiverType, expression.getOperationTokenNode());
|
||||
// //
|
||||
// // JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
// // if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
// // JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
|
||||
// // String referencedName = referenceExpression.getReferencedName();
|
||||
// //
|
||||
// // if (receiverType != null && referencedName != null) {
|
||||
// // // No generics. Guaranteed
|
||||
// // result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
|
||||
// // reference[0] = referenceExpression;
|
||||
// // }
|
||||
// // } else {
|
||||
// // throw new UnsupportedOperationException(); // TODO
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
|
||||
// // a -- create a hierarchical lookup domain for this.a
|
||||
// String referencedName = expression.getReferencedName();
|
||||
// if (referencedName != null) {
|
||||
// // No generics. Guaranteed
|
||||
// result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
|
||||
// reference[0] = expression;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitExpression(JetExpression expression) {
|
||||
// // <e> create a dummy domain for the type of e
|
||||
// throw new UnsupportedOperationException(expression.getText()); // TODO
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitJetElement(JetElement element) {
|
||||
// trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message
|
||||
// }
|
||||
// });
|
||||
// return wrapForTracing(result[0], reference[0], argumentList, true);
|
||||
// }
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
return callResolver;
|
||||
}
|
||||
@@ -284,68 +218,6 @@ public class JetTypeInferrer {
|
||||
}
|
||||
}
|
||||
|
||||
// private OverloadDomain wrapForTracing(
|
||||
// @NotNull final OverloadDomain overloadDomain,
|
||||
// @NotNull final JetReferenceExpression referenceExpression,
|
||||
// @Nullable final PsiElement argumentList,
|
||||
// final boolean reportErrors) {
|
||||
// return new OverloadDomain() {
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
|
||||
// report(resolutionResult);
|
||||
// return resolutionResult;
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
|
||||
// report(resolutionResult);
|
||||
// return resolutionResult;
|
||||
// }
|
||||
//
|
||||
// private void report(OverloadResolutionResult resolutionResult) {
|
||||
// if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) {
|
||||
// trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, resolutionResult.getFunctionDescriptor());
|
||||
// }
|
||||
// if (reportErrors) {
|
||||
// switch (resolutionResult.getResultCode()) {
|
||||
// case NAME_NOT_FOUND:
|
||||
// trace.getErrorHandler().unresolvedReference(referenceExpression);
|
||||
// break;
|
||||
// case SINGLE_FUNCTION_ARGUMENT_MISMATCH:
|
||||
// if (argumentList != null) {
|
||||
// // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
|
||||
// trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor()));
|
||||
// }
|
||||
// else {
|
||||
// trace.getErrorHandler().unresolvedReference(referenceExpression);
|
||||
// }
|
||||
// break;
|
||||
// case AMBIGUITY:
|
||||
// if (argumentList != null) {
|
||||
// // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
|
||||
// trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]");
|
||||
// }
|
||||
// else {
|
||||
// trace.getErrorHandler().unresolvedReference(referenceExpression);
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// // Not a success
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isEmpty() {
|
||||
// return overloadDomain.isEmpty();
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.getEmpty());
|
||||
}
|
||||
@@ -520,195 +392,6 @@ public class JetTypeInferrer {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// @Nullable
|
||||
// private JetType resolveCall1(
|
||||
// @NotNull JetScope scope,
|
||||
// @NotNull OverloadDomain overloadDomain,
|
||||
// @NotNull JetCallElement call) {
|
||||
// // 1) ends with a name -> (scope, name) to look up
|
||||
// // 2) ends with something else -> just check types
|
||||
//
|
||||
// final List<JetTypeProjection> jetTypeArguments = call.getTypeArguments();
|
||||
//
|
||||
// for (JetTypeProjection typeArgument : jetTypeArguments) {
|
||||
// if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
|
||||
// trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// List<JetType> typeArguments = new ArrayList<JetType>();
|
||||
// for (JetTypeProjection projection : jetTypeArguments) {
|
||||
// // TODO : check that there's no projection
|
||||
// JetTypeReference typeReference = projection.getTypeReference();
|
||||
// if (typeReference != null) {
|
||||
// typeArguments.add(new TypeResolver(semanticServices, trace, true).resolveType(scope, typeReference));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return resolveCallWithTypeArguments(scope, overloadDomain, call, typeArguments);
|
||||
// }
|
||||
|
||||
// private JetType resolveCallWithTypeArguments(JetScope scope, OverloadDomain overloadDomain, JetCallElement call, List<JetType> typeArguments) {
|
||||
// final List<JetValueArgument> valueArguments = call.getValueArguments();
|
||||
//
|
||||
// boolean someNamed = false;
|
||||
// for (JetValueArgument argument : valueArguments) {
|
||||
// if (argument.isNamed()) {
|
||||
// someNamed = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// final List<JetExpression> functionLiteralArguments = call.getFunctionLiteralArguments();
|
||||
//
|
||||
// // TODO : must be a check
|
||||
// assert functionLiteralArguments.size() <= 1;
|
||||
//
|
||||
// if (someNamed) {
|
||||
// // TODO : check that all are named
|
||||
// trace.getErrorHandler().genericError(call.getNode(), "Named arguments are not supported"); // TODO
|
||||
//
|
||||
// } else {
|
||||
// List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
|
||||
// for (JetValueArgument argument : valueArguments) {
|
||||
// JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
// if (argumentExpression != null) {
|
||||
// positionedValueArguments.add(argumentExpression);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// positionedValueArguments.addAll(functionLiteralArguments);
|
||||
//
|
||||
// List<JetType> valueArgumentTypes = new ArrayList<JetType>();
|
||||
// for (JetExpression valueArgument : positionedValueArguments) {
|
||||
// valueArgumentTypes.add(safeGetType(scope, valueArgument, false, NO_EXPECTED_TYPE)); // TODO
|
||||
// }
|
||||
//
|
||||
// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes);
|
||||
// if (resolutionResult.isSuccess()) {
|
||||
// final FunctionDescriptor functionDescriptor = resolutionResult.getFunctionDescriptor();
|
||||
//
|
||||
// callResolver.checkGenericBoundsInAFunctionCall(call.getTypeArguments(), typeArguments, functionDescriptor);
|
||||
// return functionDescriptor.getReturnType();
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
// @Nullable
|
||||
// public JetType checkTypeInitializerCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCallElement call) {
|
||||
// JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
// if (typeElement instanceof JetUserType) {
|
||||
// JetUserType userType = (JetUserType) typeElement;
|
||||
// // TODO : to infer constructor parameters, one will need to
|
||||
// // 1) resolve a _class_ from the typeReference
|
||||
// // 2) rely on the overload domain of constructors of this class to infer type arguments
|
||||
// // For now we assume that the type arguments are provided, and thus the typeReference can be
|
||||
// // resolved into a valid type
|
||||
// JetType receiverType = typeResolver.resolveType(scope, typeReference);
|
||||
// DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
|
||||
// if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
// ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
//
|
||||
// for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
|
||||
// switch (typeProjection.getProjectionKind()) {
|
||||
// case IN:
|
||||
// case OUT:
|
||||
// case STAR:
|
||||
// // TODO : Bug in the editor
|
||||
// trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
|
||||
// break;
|
||||
// case NONE:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
|
||||
// if (referenceExpression != null) {
|
||||
// return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// else {
|
||||
// if (typeElement != null) {
|
||||
// trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// @Nullable
|
||||
// public JetType checkClassConstructorCall(
|
||||
// @NotNull JetScope scope,
|
||||
// @NotNull JetReferenceExpression referenceExpression,
|
||||
// @NotNull ClassDescriptor classDescriptor,
|
||||
// @NotNull JetType receiverType,
|
||||
// @NotNull JetCallElement call) {
|
||||
// // When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
|
||||
// // of 'Array<T>' must be created anyway.
|
||||
// // Thus, we should either prohibit projections in type arguments in such contexts,
|
||||
// // or treat them as an automatic upcast to the desired type, i.e. for the user not
|
||||
// // to be forced to write
|
||||
// // val a : Array<in T> = new Array<T>(...)
|
||||
// // NOTE: Array may be a bad example here, some classes may have substantial functionality
|
||||
// // not involving their type parameters
|
||||
// //
|
||||
// // The code below upcasts the type automatically
|
||||
//
|
||||
//
|
||||
// FunctionGroup constructors = classDescriptor.getConstructors();
|
||||
//// OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(null, constructors);
|
||||
//
|
||||
// JetType constructorReturnedType;
|
||||
// if (call instanceof JetDelegatorToThisCall) {
|
||||
// List<TypeProjection> typeArguments = receiverType.getArguments();
|
||||
//
|
||||
// List<JetType> projectionsStripped = Lists.newArrayList();
|
||||
// for (TypeProjection typeArgument : typeArguments) {
|
||||
// projectionsStripped.add(typeArgument.getType());
|
||||
// }
|
||||
//
|
||||
// constructorReturnedType = resolveCallWithTypeArguments(
|
||||
// scope,
|
||||
// wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
|
||||
// call, projectionsStripped);
|
||||
// }
|
||||
// else {
|
||||
// constructorReturnedType = callResolver.resolveCall(
|
||||
// scope, call, NO_EXPECTED_TYPE);
|
||||
//// wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
|
||||
//// call);
|
||||
// }
|
||||
// if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
|
||||
// DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
|
||||
// assert declarationDescriptor != null;
|
||||
// trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, declarationDescriptor);
|
||||
// // TODO : more helpful message
|
||||
// JetValueArgumentList argumentList = call.getValueArgumentList();
|
||||
// final String errorMessage = "Cannot find a constructor overload for class " + classDescriptor.getName() + " with these arguments";
|
||||
// if (argumentList != null) {
|
||||
// trace.getErrorHandler().genericError(argumentList.getNode(), errorMessage);
|
||||
// }
|
||||
// else {
|
||||
// trace.getErrorHandler().genericError(call.getNode(), errorMessage);
|
||||
// }
|
||||
// constructorReturnedType = receiverType;
|
||||
// }
|
||||
// // If no upcast needed:
|
||||
// return constructorReturnedType;
|
||||
//
|
||||
// // Automatic upcast:
|
||||
// // result = receiverType;
|
||||
// }
|
||||
|
||||
//TODO
|
||||
private JetType enrichOutType(JetExpression expression, JetType initialType, @NotNull TypeInferenceContext context) {
|
||||
if (expression == null) return initialType;
|
||||
@@ -736,32 +419,31 @@ public class JetTypeInferrer {
|
||||
return expressionType;
|
||||
}
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context);
|
||||
if (variableDescriptor == null) return expressionType;
|
||||
|
||||
JetType enrichedType = null;
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor));
|
||||
Collections.reverse(possibleTypes);
|
||||
for (JetType possibleType: possibleTypes) {
|
||||
if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) {
|
||||
enrichedType = possibleType;
|
||||
break;
|
||||
boolean appropriateTypeFound = false;
|
||||
if (variableDescriptor != null) {
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor));
|
||||
Collections.reverse(possibleTypes);
|
||||
for (JetType possibleType : possibleTypes) {
|
||||
if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) {
|
||||
appropriateTypeFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!appropriateTypeFound) {
|
||||
JetType notnullType = context.dataFlowInfo.getOutType(variableDescriptor);
|
||||
if (notnullType != null && semanticServices.getTypeChecker().isSubtypeOf(notnullType, context.expectedType)) {
|
||||
appropriateTypeFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enrichedType == null) {
|
||||
enrichedType = context.dataFlowInfo.getOutType(variableDescriptor);
|
||||
}
|
||||
if (enrichedType == null) {
|
||||
enrichedType = expressionType;
|
||||
}
|
||||
|
||||
if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) {
|
||||
if (!appropriateTypeFound) {
|
||||
context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType);
|
||||
} else {
|
||||
checkAutoCast(expression, context.expectedType, variableDescriptor, context.trace);
|
||||
return expressionType;
|
||||
}
|
||||
return enrichedType;
|
||||
checkAutoCast(expression, context.expectedType, variableDescriptor, context.trace);
|
||||
return context.expectedType;
|
||||
}
|
||||
|
||||
|
||||
private void checkAutoCast(JetExpression expression, JetType type, VariableDescriptor variableDescriptor, BindingTrace trace) {
|
||||
if (variableDescriptor.isVar()) {
|
||||
trace.getErrorHandler().genericError(expression.getNode(), "Automatic cast to " + type + " is impossible, because variable " + variableDescriptor.getName() + " is mutable");
|
||||
@@ -793,7 +475,7 @@ public class JetTypeInferrer {
|
||||
VariableDescriptor variableDescriptor = null;
|
||||
if (receiverExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression;
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, nameExpression);
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(REFERENCE_TARGET, nameExpression);
|
||||
if (declarationDescriptor instanceof VariableDescriptor) {
|
||||
variableDescriptor = (VariableDescriptor) declarationDescriptor;
|
||||
}
|
||||
@@ -956,7 +638,7 @@ public class JetTypeInferrer {
|
||||
context.trace.getErrorHandler().unresolvedReference(expression);
|
||||
}
|
||||
else {
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression, property);
|
||||
context.trace.record(REFERENCE_TARGET, expression, property);
|
||||
return context.services.checkEnrichedType(property.getOutType(), expression, context);
|
||||
}
|
||||
}
|
||||
@@ -965,7 +647,7 @@ public class JetTypeInferrer {
|
||||
if (referencedName != null) {
|
||||
VariableDescriptor variable = context.scope.getVariable(referencedName);
|
||||
if (variable != null) {
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression, variable);
|
||||
context.trace.record(REFERENCE_TARGET, expression, variable);
|
||||
JetType result = variable.getOutType();
|
||||
if (result == null) {
|
||||
context.trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
|
||||
@@ -983,7 +665,7 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
context.trace.getErrorHandler().genericError(expression.getNode(), "Classifier " + classifier.getName() + " does not have a class object");
|
||||
}
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression, classifier);
|
||||
context.trace.record(REFERENCE_TARGET, expression, classifier);
|
||||
return context.services.checkEnrichedType(result, expression, context);
|
||||
}
|
||||
else {
|
||||
@@ -1019,7 +701,7 @@ public class JetTypeInferrer {
|
||||
if (namespace == null) {
|
||||
return null;
|
||||
}
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression, namespace);
|
||||
context.trace.record(REFERENCE_TARGET, expression, namespace);
|
||||
return namespace.getNamespaceType();
|
||||
}
|
||||
|
||||
@@ -1077,6 +759,14 @@ public class JetTypeInferrer {
|
||||
List<JetType> parameterTypes = new ArrayList<JetType>();
|
||||
List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
|
||||
List<JetParameter> parameters = functionLiteral.getValueParameters();
|
||||
JetType expectedType = context.expectedType;
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = null;
|
||||
boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(expectedType);
|
||||
if (functionTypeExpected) {
|
||||
valueParameters = JetStandardClasses.getValueParameters(functionDescriptor, expectedType);
|
||||
}
|
||||
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
JetParameter parameter = parameters.get(i);
|
||||
JetTypeReference typeReference = parameter.getTypeReference();
|
||||
@@ -1086,15 +776,31 @@ public class JetTypeInferrer {
|
||||
type = context.typeResolver.resolveType(context.scope, typeReference);
|
||||
}
|
||||
else {
|
||||
context.trace.getErrorHandler().genericError(parameter.getNode(), "Type inference for parameters is not implemented yet");
|
||||
type = ErrorUtils.createErrorType("Not inferred");
|
||||
if (valueParameters != null) {
|
||||
type = valueParameters.get(i).getOutType();
|
||||
}
|
||||
else {
|
||||
context.trace.getErrorHandler().genericError(parameter.getNode(), "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation");
|
||||
type = ErrorUtils.createErrorType("Cannot be inferred");
|
||||
}
|
||||
}
|
||||
ValueParameterDescriptor valueParameterDescriptor = context.classDescriptorResolver.resolveValueParameterDescriptor(functionDescriptor, parameter, i, type);
|
||||
parameterTypes.add(valueParameterDescriptor.getOutType());
|
||||
valueParameterDescriptors.add(valueParameterDescriptor);
|
||||
}
|
||||
|
||||
JetType effectiveReceiverType = receiverTypeRef == null ? null : receiverType;
|
||||
JetType effectiveReceiverType;
|
||||
if (receiverTypeRef == null) {
|
||||
if (functionTypeExpected) {
|
||||
effectiveReceiverType = JetStandardClasses.getReceiverType(expectedType);
|
||||
}
|
||||
else {
|
||||
effectiveReceiverType = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
effectiveReceiverType = receiverType;
|
||||
}
|
||||
functionDescriptor.initialize(effectiveReceiverType, Collections.<TypeParameterDescriptor>emptyList(), valueParameterDescriptors, null);
|
||||
context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor);
|
||||
|
||||
@@ -1106,15 +812,17 @@ public class JetTypeInferrer {
|
||||
context.services.checkFunctionReturnType(functionInnerScope, expression, returnType, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
if (context.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(context.expectedType)) {
|
||||
returnType = JetStandardClasses.getReturnType(context.expectedType);
|
||||
if (functionTypeExpected) {
|
||||
returnType = JetStandardClasses.getReturnType(expectedType);
|
||||
}
|
||||
returnType = getBlockReturnedType(functionInnerScope, functionLiteral.getBodyExpression(), context.replaceExpectedType(returnType));
|
||||
}
|
||||
JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
|
||||
functionDescriptor.setReturnType(safeReturnType);
|
||||
|
||||
if (functionTypeExpected) {
|
||||
|
||||
}
|
||||
return context.services.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), effectiveReceiverType, parameterTypes, safeReturnType), expression, context);
|
||||
}
|
||||
|
||||
@@ -1293,8 +1001,8 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
else if (size == 0) {
|
||||
// This uses the info written by the control flow processor
|
||||
@@ -1307,8 +1015,8 @@ public class JetTypeInferrer {
|
||||
thisType = JetStandardClasses.getNothingType();
|
||||
}
|
||||
else {
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1328,7 +1036,7 @@ public class JetTypeInferrer {
|
||||
|
||||
DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis();
|
||||
if (declarationDescriptorForUnqualifiedThis != null) {
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getThisReference(), declarationDescriptorForUnqualifiedThis);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptorForUnqualifiedThis);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,9 +1153,10 @@ public class JetTypeInferrer {
|
||||
@Override
|
||||
public void visitWhenConditionCall(JetWhenConditionCall condition) {
|
||||
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
|
||||
JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker());
|
||||
// JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker());
|
||||
if (callSuffixExpression != null) {
|
||||
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context);
|
||||
// JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context);
|
||||
JetType selectorReturnType = getSelectorReturnType(subjectType, callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context);
|
||||
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context);
|
||||
context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context));
|
||||
}
|
||||
@@ -1923,7 +1632,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Nullable
|
||||
private JetType checkIterableConvention(@NotNull JetType type, @NotNull ASTNode reportErrorsOn, TypeInferenceContext context) {
|
||||
OverloadResolutionResult iteratorResolutionResult = context.services.resolveNoParametersFunction(type, context.scope, "iterator");
|
||||
OverloadResolutionResult iteratorResolutionResult = context.services.callResolver.resolveExactSignature(context.scope, type, "iterator", Collections.<JetType>emptyList());
|
||||
if (iteratorResolutionResult.isSuccess()) {
|
||||
JetType iteratorType = iteratorResolutionResult.getFunctionDescriptor().getReturnType();
|
||||
boolean hasNextFunctionSupported = checkHasNextFunctionSupport(reportErrorsOn, iteratorType, context);
|
||||
@@ -1936,7 +1645,7 @@ public class JetTypeInferrer {
|
||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
|
||||
}
|
||||
|
||||
OverloadResolutionResult nextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "next");
|
||||
OverloadResolutionResult nextResolutionResult = context.services.callResolver.resolveExactSignature(context.scope, iteratorType, "next", Collections.<JetType>emptyList());
|
||||
if (nextResolutionResult.isAmbiguity()) {
|
||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
|
||||
} else if (nextResolutionResult.isNothing()) {
|
||||
@@ -1956,7 +1665,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
||||
OverloadResolutionResult hasNextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "hasNext");
|
||||
OverloadResolutionResult hasNextResolutionResult = context.services.callResolver.resolveExactSignature(context.scope, iteratorType, "hasNext", Collections.<JetType>emptyList());
|
||||
if (hasNextResolutionResult.isAmbiguity()) {
|
||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
|
||||
} else if (hasNextResolutionResult.isNothing()) {
|
||||
@@ -1988,89 +1697,6 @@ public class JetTypeInferrer {
|
||||
return true;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void visitNewExpression(JetNewExpression expression) {
|
||||
// // TODO : type argument inference
|
||||
// JetTypeReference typeReference = expression.getTypeReference();
|
||||
// if (typeReference != null) {
|
||||
// result = checkTypeInitializerCall(scope, typeReference, expression);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private void resolveCallWithExplicitName(@NotNull JetScope scope, JetExpression receiver, String functionName, List<JetType> resolvedTypeArguments, List<ValueArgumentPsi> valueArguments) {
|
||||
//
|
||||
// boolean someNamed = false;
|
||||
// boolean allNamed = true;
|
||||
// for (ValueArgumentPsi valueArgument : valueArguments) {
|
||||
// if (valueArgument.isNamed()) {
|
||||
// context.trace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Named arguments are not supported");
|
||||
// someNamed = true;
|
||||
// }
|
||||
// else {
|
||||
// allNamed = false;
|
||||
// }
|
||||
// }
|
||||
// if (someNamed) {
|
||||
// return; // TODO
|
||||
// }
|
||||
// if (someNamed && !allNamed) {
|
||||
// // TODO function literals outside parentheses
|
||||
// }
|
||||
//
|
||||
// ErrorHandlerWithRegions errorHandler = context.trace.getErrorHandler();
|
||||
//
|
||||
// // 1. resolve 'receiver' in 'scope' with expected type 'NO_EXPECTED_TYPE'
|
||||
// errorHandler.openRegion();
|
||||
// JetType receiverType = JetTypeInferrer.this.getType(scope, receiver, false, NO_EXPECTED_TYPE);
|
||||
// // for each applicable function in 'receiverType'
|
||||
// Set<FunctionDescriptor> allFunctions = receiverType.getMemberScope().getFunctionGroup(functionName).getFunctionDescriptors();
|
||||
// Map<FunctionDescriptor, List<JetType>> applicableFunctions = Maps.newHashMap();
|
||||
// int typeArgCount = resolvedTypeArguments.size();
|
||||
// int valueArgCount = valueArguments.size();
|
||||
// for (FunctionDescriptor functionDescriptor : allFunctions) {
|
||||
// if (typeArgCount == 0 || functionDescriptor.getTypeParameters().size() == typeArgCount) {
|
||||
// if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount &&
|
||||
// valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) {
|
||||
// // get expected types for value parameters
|
||||
// if (typeArgCount > 0) {
|
||||
// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(resolvedTypeArguments, functionDescriptor);
|
||||
// }
|
||||
// else {
|
||||
// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(TypeUtils.getDefaultTypes(functionDescriptor.getTypeParameters()), functionDescriptor);
|
||||
// List<JetType> valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments);
|
||||
// if (valueArgumentTypes == null) {
|
||||
// Map<TypeConstructor, TypeProjection> noExpectedTypes = Maps.newHashMap();
|
||||
// for (TypeParameterDescriptor typeParameterDescriptor : functionDescriptor.getTypeParameters()) {
|
||||
// noExpectedTypes.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(NO_EXPECTED_TYPE));
|
||||
// }
|
||||
// substitutedFunctionDescriptor = functionDescriptor.substitute(TypeSubstitutor.create(noExpectedTypes));
|
||||
// valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments);
|
||||
// }
|
||||
// if (valueArgumentTypes != null) {
|
||||
// List<JetType> typeArguments = solveConstraintSystem(functionDescriptor, valueArgumentTypes, expectedReturnType);
|
||||
// if (typeArguments != null) {
|
||||
// applicableFunctions.put(functionDescriptor, typeArguments);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // type-check the parameters
|
||||
// // if something was found (one or many options
|
||||
// errorHandler.closeAndCommitCurrentRegion();
|
||||
// // otherwise
|
||||
// errorHandler.closeAndReturnCurrentRegion();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // get expected types for value parameters
|
||||
// // type-check the parameters
|
||||
// // if something was found (one or many options
|
||||
// errorHandler.closeAndCommitCurrentRegion();
|
||||
// // otherwise
|
||||
// errorHandler.closeAndReturnCurrentRegion();
|
||||
//
|
||||
// }
|
||||
|
||||
@Override
|
||||
public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, TypeInferenceContext context) {
|
||||
context.trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
|
||||
@@ -2087,10 +1713,8 @@ public class JetTypeInferrer {
|
||||
if (receiverType == null) return null;
|
||||
|
||||
// Clean resolution: no autocasts
|
||||
TemporaryBindingTrace cleanResolutionTrace = new TemporaryBindingTrace(context.trace.getBindingContext());
|
||||
TemporaryBindingTrace cleanResolutionTrace = TemporaryBindingTrace.create(context.trace);
|
||||
TypeInferenceContext cleanResolutionContext = context.replaceBindingTrace(cleanResolutionTrace);
|
||||
// ErrorHandler errorHandler = context.trace.getErrorHandler();
|
||||
// errorHandler.openRegion();
|
||||
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression, cleanResolutionContext);
|
||||
|
||||
//TODO move further
|
||||
@@ -2109,24 +1733,24 @@ public class JetTypeInferrer {
|
||||
List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor));
|
||||
Collections.reverse(possibleTypes);
|
||||
|
||||
TemporaryBindingTrace autocastResolutionTrace = new TemporaryBindingTrace(context.trace.getBindingContext());
|
||||
TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace);
|
||||
TypeInferenceContext autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace);
|
||||
for (JetType possibleType : possibleTypes) {
|
||||
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext);
|
||||
if (selectorReturnType != null) {
|
||||
context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace);
|
||||
autocastResolutionTrace.addAllMyDataTo(context.trace);
|
||||
autocastResolutionTrace.commit();
|
||||
somethingFound = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
autocastResolutionTrace = new TemporaryBindingTrace(context.trace.getBindingContext());
|
||||
autocastResolutionTrace = TemporaryBindingTrace.create(context.trace);
|
||||
autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!somethingFound) {
|
||||
cleanResolutionTrace.addAllMyDataTo(context.trace);
|
||||
cleanResolutionTrace.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2170,7 +1794,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(JetReferenceExpression referenceExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, referenceExpression);
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(REFERENCE_TARGET, referenceExpression);
|
||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
result[0] = (FunctionDescriptor) declarationDescriptor;
|
||||
}
|
||||
@@ -2202,24 +1826,15 @@ public class JetTypeInferrer {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression, TypeInferenceContext context) {
|
||||
// JetExpression calleeExpression = callExpression.getCalleeExpression();
|
||||
// if (calleeExpression == null) {
|
||||
// return null;
|
||||
// }
|
||||
// OverloadDomain overloadDomain = context.services.getOverloadDomain(receiverType, context.scope, calleeExpression, callExpression.getValueArgumentList());
|
||||
JetScope scope = receiverType == null ? context.scope : new ScopeWithReceiver(context.scope, receiverType, JetTypeChecker.INSTANCE);
|
||||
return context.services.callResolver.resolveCall(scope, callExpression, context.expectedType);
|
||||
// return context.services.resolveCall(context.scope, overloadDomain, callExpression);
|
||||
}
|
||||
|
||||
private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression, TypeInferenceContext context) {
|
||||
@Nullable
|
||||
private JetType getSelectorReturnType(@Nullable JetType receiverType, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) {
|
||||
if (selectorExpression instanceof JetCallExpression) {
|
||||
return getCallExpressionType(receiverType, (JetCallExpression) selectorExpression, context);
|
||||
return context.services.callResolver.resolveCall(context.scope, receiverType, (JetCallExpression) selectorExpression, context.expectedType);
|
||||
}
|
||||
else if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
JetScope compositeScope = new ScopeWithReceiver(context.scope, receiverType, semanticServices.getTypeChecker());
|
||||
return getType(compositeScope, selectorExpression, false, context);
|
||||
// JetScope compositeScope = new ScopeWithReceiver(context.scope, receiverType, semanticServices.getTypeChecker());
|
||||
JetScope scope = receiverType != null ? receiverType.getMemberScope() : context.scope;
|
||||
return getType(scope, selectorExpression, false, context);
|
||||
}
|
||||
else if (selectorExpression != null) {
|
||||
// TODO : not a simple name -> resolve in scope, expect property type or a function type
|
||||
@@ -2230,8 +1845,8 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) {
|
||||
// return context.services.checkType(context.services.resolveCall(context.scope, expression, context.expectedType), expression, context);
|
||||
return context.services.checkType(getCallExpressionType(null, expression, context), expression, context);
|
||||
JetType expressionType = context.services.callResolver.resolveCall(context.scope, null, expression, context.expectedType);
|
||||
return context.services.checkType(expressionType, expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2271,7 +1886,7 @@ public class JetTypeInferrer {
|
||||
CallMaker.makeCall(expression),
|
||||
expression.getOperationSign(),
|
||||
name,
|
||||
baseExpression,
|
||||
receiverType,
|
||||
context.expectedType);
|
||||
|
||||
if (functionDescriptor == null) return null;
|
||||
@@ -2346,21 +1961,24 @@ public class JetTypeInferrer {
|
||||
OverloadResolutionResult resolutionResult = context.services.callResolver.resolveExactSignature(
|
||||
context.scope, leftType, "equals",
|
||||
Collections.singletonList(JetStandardClasses.getNullableAnyType()));
|
||||
FunctionDescriptor equals;
|
||||
if (resolutionResult.isSuccess()) {
|
||||
equals = resolutionResult.getFunctionDescriptor();
|
||||
}
|
||||
else {
|
||||
// TODO : Report ambiguous equals
|
||||
equals = null;
|
||||
}
|
||||
if (equals != null) {
|
||||
FunctionDescriptor equals = resolutionResult.getFunctionDescriptor();
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, equals);
|
||||
if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) {
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
|
||||
if (resolutionResult.isAmbiguity()) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (FunctionDescriptor functionDescriptor : resolutionResult.getFunctionDescriptors()) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
context.trace.getErrorHandler().genericError(operationSign.getNode(), "Ambiguous function: " + stringBuilder);
|
||||
}
|
||||
else {
|
||||
context.trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2416,11 +2034,12 @@ public class JetTypeInferrer {
|
||||
|
||||
private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) {
|
||||
String name = "contains";
|
||||
JetType receiverType = context.services.safeGetType(context.scope, right, false, NO_EXPECTED_TYPE);
|
||||
FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName(
|
||||
context.scope,
|
||||
CallMaker.makeCall(operationSign, Collections.singletonList(left)),
|
||||
operationSign,
|
||||
name, right, context.expectedType);
|
||||
name, receiverType, context.expectedType);
|
||||
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
||||
ensureBooleanResult(operationSign, name, containsType, context);
|
||||
}
|
||||
@@ -2496,9 +2115,6 @@ public class JetTypeInferrer {
|
||||
TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
JetExpression arrayExpression = expression.getArrayExpression();
|
||||
JetType receiverType = getType(context.scope, arrayExpression, false, context);
|
||||
// List<JetValueArgument> indexArguments = expression.getIndexArguments();
|
||||
// List<JetType> argumentTypes = getTypes(context.scope, indexArguments, context);
|
||||
// if (argumentTypes == null) return null;
|
||||
|
||||
if (receiverType != null) {
|
||||
FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName(
|
||||
@@ -2506,10 +2122,9 @@ public class JetTypeInferrer {
|
||||
CallMaker.makeCall(expression, expression.getIndexExpressions()),
|
||||
expression,
|
||||
"get",
|
||||
arrayExpression,
|
||||
receiverType,
|
||||
context.expectedType);
|
||||
if (functionDescriptor != null) {
|
||||
// checkNullSafety(receiverType, expression.getIndexArguments().get(0).getNode(), functionDescriptor);
|
||||
return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
|
||||
}
|
||||
}
|
||||
@@ -2518,17 +2133,13 @@ public class JetTypeInferrer {
|
||||
|
||||
@Nullable
|
||||
protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) {
|
||||
// JetType leftType = getType(scope, left, false, context);
|
||||
// JetType rightType = getType(scope, right, false, context);
|
||||
// if (leftType == null || rightType == null) {
|
||||
// return null;
|
||||
// }
|
||||
JetType leftType = getType(scope, binaryExpression.getLeft(), false, context);
|
||||
FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName(
|
||||
scope,
|
||||
CallMaker.makeCall(binaryExpression),
|
||||
binaryExpression.getOperationReference(),
|
||||
name,
|
||||
binaryExpression.getLeft(),
|
||||
leftType,
|
||||
context.expectedType);
|
||||
if (functionDescriptor != null) {
|
||||
// if (leftType.isNullable()) {
|
||||
@@ -2636,12 +2247,6 @@ public class JetTypeInferrer {
|
||||
public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
// public TypeInferrerVisitorWithWritableScope(@NotNull BindingTrace trace, @NotNull JetScope scope) {
|
||||
// super(trace);
|
||||
// this.scope = newWritableScopeImpl(scope, trace).setDebugName("Block scope");
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public JetType visitObjectDeclaration(JetObjectDeclaration declaration, TypeInferenceContext context) {
|
||||
@@ -2715,7 +2320,9 @@ public class JetTypeInferrer {
|
||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, TypeInferenceContext context) {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
String name = assignmentOperationNames.get(operationType);
|
||||
JetType assignmentOperationType = getTypeForBinaryCall(scope, name, context, expression);
|
||||
|
||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
|
||||
JetType assignmentOperationType = getTypeForBinaryCall(scope, name, context.replaceBindingTrace(temporaryBindingTrace), expression);
|
||||
|
||||
if (assignmentOperationType == null) {
|
||||
String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType));
|
||||
@@ -2725,6 +2332,9 @@ public class JetTypeInferrer {
|
||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryBindingTrace.commit();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2750,15 +2360,8 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) {
|
||||
// TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
// List<JetType> argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions(), context);
|
||||
// if (argumentTypes == null) return null;
|
||||
// JetType rhsType = getType(scope, rightHandSide, false, context);
|
||||
// if (rhsType == null) return null;
|
||||
// argumentTypes.add(rhsType);
|
||||
//
|
||||
// JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false, context);
|
||||
// if (receiverType == null) return null;
|
||||
JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false, context);
|
||||
if (receiverType == null) return null;
|
||||
//
|
||||
Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide);
|
||||
// // TODO : nasty hack: effort is duplicated
|
||||
@@ -2771,7 +2374,7 @@ public class JetTypeInferrer {
|
||||
scope,
|
||||
call,
|
||||
operationSign,
|
||||
"set", arrayAccessExpression.getArrayExpression(), NO_EXPECTED_TYPE);
|
||||
"set", receiverType, NO_EXPECTED_TYPE);
|
||||
if (functionDescriptor == null) return null;
|
||||
return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -16,6 +15,18 @@ import java.util.Map;
|
||||
public class TypeSubstitutor {
|
||||
|
||||
public interface TypeSubstitution {
|
||||
TypeSubstitution EMPTY = new TypeSubstitution() {
|
||||
@Override
|
||||
public TypeProjection get(TypeConstructor key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
TypeProjection get(TypeConstructor key);
|
||||
boolean isEmpty();
|
||||
@@ -39,7 +50,7 @@ public class TypeSubstitutor {
|
||||
}
|
||||
}
|
||||
|
||||
public static final TypeSubstitutor EMPTY = create(Collections.<TypeConstructor, TypeProjection>emptyMap());
|
||||
public static final TypeSubstitutor EMPTY = create(TypeSubstitution.EMPTY);
|
||||
|
||||
public static final class SubstitutionException extends Exception {
|
||||
public SubstitutionException(String message) {
|
||||
@@ -61,14 +72,23 @@ public class TypeSubstitutor {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final @NotNull TypeSubstitution substitutionContext;
|
||||
private final @NotNull TypeSubstitution substitution;
|
||||
|
||||
private TypeSubstitutor(@NotNull TypeSubstitution substitutionContext) {
|
||||
this.substitutionContext = substitutionContext;
|
||||
protected TypeSubstitutor(@NotNull TypeSubstitution substitution) {
|
||||
this.substitution = substitution;
|
||||
}
|
||||
|
||||
public boolean inRange(@NotNull TypeConstructor typeConstructor) {
|
||||
return substitution.get(typeConstructor) != null;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return substitutionContext.isEmpty();
|
||||
return substitution.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TypeSubstitution getSubstitution() {
|
||||
return substitution;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -100,7 +120,7 @@ public class TypeSubstitutor {
|
||||
@NotNull
|
||||
private JetType unsafeSubstitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) throws SubstitutionException {
|
||||
TypeConstructor constructor = type.getConstructor();
|
||||
TypeProjection value = substitutionContext.get(constructor);
|
||||
TypeProjection value = substitution.get(constructor);
|
||||
if (value != null) {
|
||||
assert constructor.getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||
|
||||
@@ -122,7 +142,7 @@ public class TypeSubstitutor {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
TypeParameterDescriptor parameterDescriptor = subjectType.getConstructor().getParameters().get(i);
|
||||
newArguments.add(substituteInProjection(
|
||||
substitutionContext,
|
||||
substitution,
|
||||
argument,
|
||||
parameterDescriptor,
|
||||
callSiteVariance));
|
||||
|
||||
@@ -102,7 +102,7 @@ public class ConstraintSystem {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
|
||||
println("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
|
||||
value = new KnownType(commonSupertype);
|
||||
}
|
||||
else {
|
||||
@@ -121,7 +121,7 @@ public class ConstraintSystem {
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
private Set<JetType> getTypes(Set<TypeValue> lowerBounds) {
|
||||
Set<JetType> types = Sets.newHashSet();
|
||||
for (TypeValue lowerBound : lowerBounds) {
|
||||
@@ -206,7 +206,7 @@ public class ConstraintSystem {
|
||||
}
|
||||
|
||||
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
|
||||
System.out.println(typeValueForLower + " :< " + typeValueForUpper);
|
||||
println(typeValueForLower + " :< " + typeValueForUpper);
|
||||
typeValueForLower.getUpperBounds().add(typeValueForUpper);
|
||||
typeValueForUpper.getLowerBounds().add(typeValueForLower);
|
||||
}
|
||||
@@ -271,14 +271,14 @@ public class ConstraintSystem {
|
||||
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
|
||||
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
|
||||
solution.registerError();
|
||||
System.out.println("Constraint violation: " + type + " :< " + boundingType);
|
||||
println("Constraint violation: " + type + " :< " + boundingType);
|
||||
}
|
||||
}
|
||||
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
|
||||
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
|
||||
if (!typeChecker.isSubtypeOf(boundingType, type)) {
|
||||
solution.registerError();
|
||||
System.out.println("Constraint violation: " + boundingType + " :< " + type);
|
||||
println("Constraint violation: " + boundingType + " :< " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ public class ConstraintSystem {
|
||||
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||
System.out.println(descriptor + " |-> " + getValue(descriptor));
|
||||
println(descriptor + " |-> " + getValue(descriptor));
|
||||
return new TypeProjection(getValue(descriptor));
|
||||
}
|
||||
return null;
|
||||
@@ -368,12 +368,6 @@ public class ConstraintSystem {
|
||||
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
|
||||
}
|
||||
return StatusAction.PROCEED;
|
||||
|
||||
// // both types are known
|
||||
// if (typeChecker.isSubtypeOf(subtype, supertype)) {
|
||||
// return StatusAction.PROCEED;
|
||||
// }
|
||||
// return fail();
|
||||
}
|
||||
|
||||
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
|
||||
@@ -412,4 +406,8 @@ public class ConstraintSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private static void println(String message) {
|
||||
// System.out.println(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -183,8 +183,7 @@ public class DescriptorRenderer {
|
||||
@Override
|
||||
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
|
||||
builder.append(renderKeyword("fun")).append(" ");
|
||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
|
||||
renderTypeParameters(typeParameters, builder);
|
||||
renderTypeParameters(descriptor.getTypeParameters(), builder);
|
||||
|
||||
JetType receiverType = descriptor.getReceiverType();
|
||||
if (receiverType != null) {
|
||||
@@ -192,6 +191,12 @@ public class DescriptorRenderer {
|
||||
}
|
||||
|
||||
renderName(descriptor, builder);
|
||||
renderValueParameters(descriptor, builder);
|
||||
builder.append(" : ").append(escape(renderType(descriptor.getReturnType())));
|
||||
return super.visitFunctionDescriptor(descriptor, builder);
|
||||
}
|
||||
|
||||
private void renderValueParameters(FunctionDescriptor descriptor, StringBuilder builder) {
|
||||
builder.append("(");
|
||||
for (Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator(); iterator.hasNext(); ) {
|
||||
ValueParameterDescriptor parameterDescriptor = iterator.next();
|
||||
@@ -200,8 +205,19 @@ public class DescriptorRenderer {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
builder.append(") : ").append(escape(renderType(descriptor.getReturnType())));
|
||||
return super.visitFunctionDescriptor(descriptor, builder);
|
||||
builder.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, StringBuilder builder) {
|
||||
builder.append(renderKeyword("ctor")).append(" ");
|
||||
|
||||
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
|
||||
builder.append(classDescriptor.getName());
|
||||
|
||||
renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder);
|
||||
renderValueParameters(constructorDescriptor, builder);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderTypeParameters(List<TypeParameterDescriptor> typeParameters, StringBuilder builder) {
|
||||
|
||||
@@ -19,7 +19,7 @@ fun test(l : java.util.List<Int>) {
|
||||
Collections.<error>emptyList</error>
|
||||
Collections.emptyList<Int>
|
||||
Collections.emptyList<Int>()
|
||||
Collections.emptyList<error>()</error>
|
||||
Collections.emptyList()
|
||||
|
||||
Collections.singleton<Int>(1) : Set<Int>?
|
||||
Collections.singleton<Int><error>(1.0)</error>
|
||||
@@ -43,7 +43,7 @@ fun test(l : java.util.List<Int>) {
|
||||
c : java.lang.Comparable<Int>?
|
||||
|
||||
// Collections.sort<Integer>(ArrayList<Integer>())
|
||||
xxx.Class<error>()</error>
|
||||
xxx.<error>Class</error>()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// One of the two passes is making a scope and turning vals into functions
|
||||
// See KT-76
|
||||
|
||||
namespace x
|
||||
|
||||
val b : Foo
|
||||
val a1 = b.compareTo(2)
|
||||
|
||||
class Foo() {
|
||||
fun compareTo(other : Byte) : Int
|
||||
fun compareTo(other : Char) : Int
|
||||
}
|
||||
@@ -298,7 +298,7 @@ JetFile: FunctionLiterals_ERR.jet
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('T')
|
||||
PsiElement(DOT)('.')
|
||||
PsiErrorElement:To specify a receiver type, use the full notation: {ReceiverType.(parameters) [: ReturnType] => ...}
|
||||
PsiErrorElement:To specify a receiverType type, use the full notation: {ReceiverType.(parameters) [: ReturnType] => ...}
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(COLON)(':')
|
||||
|
||||
@@ -3,7 +3,7 @@ JetFile: Properties_ERR.jet
|
||||
PROPERTY
|
||||
PsiElement(var)('var')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Expecting property name or receiver type
|
||||
PsiErrorElement:Expecting property name or receiverType type
|
||||
PsiElement(MINUS)('-')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Property getter or setter expected
|
||||
|
||||
@@ -23,7 +23,7 @@ JetFile: With.jet
|
||||
VALUE_PARAMETER_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_PARAMETER
|
||||
PsiElement(IDENTIFIER)('receiver')
|
||||
PsiElement(IDENTIFIER)('receiverType')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
@@ -63,7 +63,7 @@ JetFile: With.jet
|
||||
PsiWhiteSpace(' ')
|
||||
DOT_QUALIFIED_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('receiver')
|
||||
PsiElement(IDENTIFIER)('receiverType')
|
||||
PsiElement(DOT)('.')
|
||||
CALL_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
|
||||
@@ -11,7 +11,10 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import junit.framework.Test;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetTestCaseBase;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
@@ -100,9 +103,10 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||
|
||||
@NotNull
|
||||
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, JetType... parameterType) {
|
||||
FunctionGroup functionGroup = classDescriptor.getMemberScope(typeArguments).getFunctionGroup(name);
|
||||
List<JetType> parameterTypeList = Arrays.asList(parameterType);
|
||||
OverloadResolutionResult functions = functionGroup.getPossiblyApplicableFunctions(Collections.<JetType>emptyList(), parameterTypeList);
|
||||
JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE);
|
||||
|
||||
OverloadResolutionResult functions = typeInferrerServices.getCallResolver().resolveExactSignature(classDescriptor.getMemberScope(typeArguments), null, name, parameterTypeList);
|
||||
for (FunctionDescriptor function : functions.getFunctionDescriptors()) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getValueParameters();
|
||||
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
|
||||
@@ -606,14 +606,15 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
ClassifierDescriptor classifier = getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
return classDescriptor.getConstructors();
|
||||
}
|
||||
WritableFunctionGroup writableFunctionGroup = new WritableFunctionGroup(name);
|
||||
// ClassifierDescriptor classifier = getClassifier(name);
|
||||
// if (classifier instanceof ClassDescriptor) {
|
||||
// ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
// writableFunctionGroup.addAllFunctions(classDescriptor.getConstructors());
|
||||
// }
|
||||
ModuleDescriptor module = new ModuleDescriptor("TypeCheckerTest");
|
||||
for (String funDecl : FUNCTION_DECLARATIONS) {
|
||||
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(JetStandardClasses.getAny(), this, JetChangeUtil.createFunction(getProject(), funDecl));
|
||||
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(module, this, JetChangeUtil.createFunction(getProject(), funDecl));
|
||||
if (name.equals(functionDescriptor.getName())) {
|
||||
writableFunctionGroup.addFunction(functionDescriptor);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user