Beispiel #1
0
 public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors(
     @NotNull Collection<ResolutionCandidate<D>> allDescriptors,
     @NotNull DeclarationDescriptor containerOfTheCurrentLocality,
     @NotNull Collection<ResolutionCandidate<D>> local,
     @NotNull Collection<ResolutionCandidate<D>> nonlocal) {
   for (ResolutionCandidate<D> resolvedCall : allDescriptors) {
     if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
       local.add(resolvedCall);
     } else {
       nonlocal.add(resolvedCall);
     }
   }
 }
Beispiel #2
0
 private static <D extends CallableDescriptor> boolean setImpliedThis(
     @NotNull JetScope scope, ResolutionCandidate<D> candidate) {
   ReceiverDescriptor expectedThisObject = candidate.getDescriptor().getExpectedThisObject();
   if (!expectedThisObject.exists()) return true;
   List<ReceiverDescriptor> receivers = Lists.newArrayList();
   scope.getImplicitReceiversHierarchy(receivers);
   for (ReceiverDescriptor receiver : receivers) {
     if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
       // TODO : Autocasts & nullability
       candidate.setThisObject(expectedThisObject);
       return true;
     }
   }
   return false;
 }
Beispiel #3
0
  private static <D extends CallableDescriptor> void convertWithReceivers(
      Collection<? extends D> descriptors,
      Iterable<ReceiverDescriptor> thisObjects,
      Iterable<ReceiverDescriptor> receiverParameters,
      Collection<ResolutionCandidate<D>> result,
      boolean hasExplicitThisObject) {

    for (ReceiverDescriptor thisObject : thisObjects) {
      for (ReceiverDescriptor receiverParameter : receiverParameters) {
        for (D extension : descriptors) {
          ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension);
          candidate.setThisObject(thisObject);
          candidate.setReceiverArgument(receiverParameter);
          candidate.setExplicitReceiverKind(
              hasExplicitThisObject
                  ? ExplicitReceiverKind.BOTH_RECEIVERS
                  : ExplicitReceiverKind.THIS_OBJECT);
          result.add(candidate);
        }
      }
    }
  }
Beispiel #4
0
 public static <D extends CallableDescriptor>
     Collection<ResolutionCandidate<D>> convertWithImpliedThis(
         JetScope scope,
         Collection<ReceiverDescriptor> receiverParameters,
         Collection<? extends D> descriptors) {
   Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
   for (ReceiverDescriptor receiverParameter : receiverParameters) {
     for (D descriptor : descriptors) {
       ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
       candidate.setReceiverArgument(receiverParameter);
       candidate.setExplicitReceiverKind(
           receiverParameter.exists()
               ? ExplicitReceiverKind.RECEIVER_ARGUMENT
               : ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
       if (setImpliedThis(scope, candidate)) {
         result.add(candidate);
       }
     }
   }
   if (receiverParameters.size() == 1 && !receiverParameters.iterator().next().exists()) {
     for (D descriptor : descriptors) {
       if (descriptor.getExpectedThisObject().exists()
           && !descriptor.getReceiverParameter().exists()) {
         DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
         if (descriptor instanceof ConstructorDescriptor) {
           assert containingDeclaration != null;
           containingDeclaration = containingDeclaration.getContainingDeclaration();
         }
         if (containingDeclaration != null && isClassObject(containingDeclaration)) {
           ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
           candidate.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
           candidate.setExplicitReceiverKind(ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
           result.add(candidate);
         }
       }
     }
   }
   return result;
 }
Beispiel #5
0
 @NotNull
 private CallTranslator finish() {
   if (resolvedCall == null) {
     assert descriptor != null;
     resolvedCall =
         ResolvedCallImpl.create(
             ResolutionCandidate.create(
                 descriptor,
                 DescriptorUtils.safeGetValue(descriptor.getExpectedThisObject()),
                 DescriptorUtils.safeGetValue(descriptor.getReceiverParameter()),
                 ExplicitReceiverKind.THIS_OBJECT,
                 false),
             TemporaryBindingTrace.create(
                 new BindingTraceContext(), "trace to resolve call (in js)"));
   }
   if (descriptor == null) {
     descriptor = resolvedCall.getCandidateDescriptor().getOriginal();
   }
   assert resolvedCall != null;
   return new CallTranslator(receiver, callee, args, resolvedCall, descriptor, callType, context);
 }
Beispiel #6
0
  @NotNull
  /*package*/ OverloadResolutionResultsImpl<FunctionDescriptor> resolveFunctionCall(
      @NotNull BasicCallResolutionContext context) {

    ProgressIndicatorProvider.checkCanceled();

    List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;

    JetExpression calleeExpression = context.call.getCalleeExpression();
    JetReferenceExpression functionReference;
    if (calleeExpression instanceof JetSimpleNameExpression) {
      JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
      functionReference = expression;

      ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope);

      Name name = expression.getReferencedNameAsName();

      prioritizedTasks =
          TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
              context,
              name,
              functionReference,
              CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
      ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck =
          new ResolutionTask.DescriptorCheckStrategy() {
            @Override
            public <D extends CallableDescriptor> boolean performAdvancedChecks(
                D descriptor, BindingTrace trace, TracingStrategy tracing) {
              if (descriptor instanceof ConstructorDescriptor) {
                Modality modality =
                    ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
                if (modality == Modality.ABSTRACT) {
                  tracing.instantiationOfAbstractClass(trace);
                  return false;
                }
              }
              return true;
            }
          };
      for (ResolutionTask task : prioritizedTasks) {
        task.setCheckingStrategy(abstractConstructorCheck);
      }
    } else {
      JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
      PsiElement reportAbsenceOn =
          valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
      if (calleeExpression instanceof JetConstructorCalleeExpression) {
        assert !context.call.getExplicitReceiver().exists();

        JetConstructorCalleeExpression expression =
            (JetConstructorCalleeExpression) calleeExpression;
        functionReference = expression.getConstructorReferenceExpression();
        if (functionReference == null) {
          return checkArgumentTypesAndFail(context); // No type there
        }
        JetTypeReference typeReference = expression.getTypeReference();
        assert typeReference != null;
        JetType constructedType =
            typeResolver.resolveType(context.scope, typeReference, context.trace, true);

        if (constructedType.isError()) {
          return checkArgumentTypesAndFail(context);
        }

        DeclarationDescriptor declarationDescriptor =
            constructedType.getConstructor().getDeclarationDescriptor();
        if (declarationDescriptor instanceof ClassDescriptor) {
          ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
          Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
          if (constructors.isEmpty()) {
            context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
            return checkArgumentTypesAndFail(context);
          }
          Collection<ResolutionCandidate<CallableDescriptor>> candidates =
              TaskPrioritizer.<CallableDescriptor>convertWithImpliedThis(
                  context.scope,
                  Collections.<ReceiverValue>singletonList(NO_RECEIVER),
                  constructors);
          prioritizedTasks =
              TaskPrioritizer
                  .<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
                      context, functionReference, candidates, null);
        } else {
          context.trace.report(NOT_A_CLASS.on(calleeExpression));
          return checkArgumentTypesAndFail(context);
        }
      } else if (calleeExpression instanceof JetThisReferenceExpression) {
        functionReference = (JetThisReferenceExpression) calleeExpression;
        DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
        if (containingDeclaration instanceof ConstructorDescriptor) {
          containingDeclaration = containingDeclaration.getContainingDeclaration();
        }
        assert containingDeclaration instanceof ClassDescriptor;
        ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;

        Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
        if (constructors.isEmpty()) {
          context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
          return checkArgumentTypesAndFail(context);
        }
        List<ResolutionCandidate<CallableDescriptor>> candidates =
            ResolutionCandidate.<CallableDescriptor>convertCollection(
                constructors, JetPsiUtil.isSafeCall(context.call));
        prioritizedTasks =
            Collections.singletonList(
                new ResolutionTask<CallableDescriptor, FunctionDescriptor>(
                    candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
      } else if (calleeExpression != null) {
        // Here we handle the case where the callee expression must be something of type function,
        // e.g. (foo.bar())(1, 2)
        JetType calleeType =
            expressionTypingServices.safeGetType(
                context.scope,
                calleeExpression,
                NO_EXPECTED_TYPE,
                context.dataFlowInfo,
                context
                    .trace); // We are actually expecting a function, but there seems to be no easy
                             // way of expressing this

        if (!KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(calleeType)) {
          //                    checkTypesWithNoCallee(trace, scope, call);
          if (!calleeType.isError()) {
            context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
          }
          return checkArgumentTypesAndFail(context);
        }

        FunctionDescriptorImpl functionDescriptor =
            new ExpressionAsFunctionDescriptor(
                context.scope.getContainingDeclaration(),
                Name.special("<for expression " + calleeExpression.getText() + ">"),
                calleeExpression);
        FunctionDescriptorUtil.initializeFromFunctionType(
            functionDescriptor,
            calleeType,
            NO_RECEIVER_PARAMETER,
            Modality.FINAL,
            Visibilities.LOCAL);
        ResolutionCandidate<CallableDescriptor> resolutionCandidate =
            ResolutionCandidate.<CallableDescriptor>create(
                functionDescriptor, JetPsiUtil.isSafeCall(context.call));
        resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
        resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT);

        // strictly speaking, this is a hack:
        // we need to pass a reference, but there's no reference in the PSI,
        // so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
        functionReference = new JetFakeReference(calleeExpression);

        prioritizedTasks =
            Collections.singletonList(
                new ResolutionTask<CallableDescriptor, FunctionDescriptor>(
                    Collections.singleton(resolutionCandidate), functionReference, context));
      } else {
        //                checkTypesWithNoCallee(trace, scope, call);
        return checkArgumentTypesAndFail(context);
      }
    }

    return doResolveCallOrGetCachedResults(
        ResolutionResultsCache.FUNCTION_MEMBER_TYPE,
        context,
        prioritizedTasks,
        CallTransformer.FUNCTION_CALL_TRANSFORMER,
        functionReference);
  }