@Nullable
  private JetType lookupNamespaceOrClassObject(
      @NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
    Name referencedName = expression.getReferencedNameAsName();
    final ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
    if (classifier != null) {
      JetType classObjectType = classifier.getClassObjectType();
      if (classObjectType != null) {
        context.trace.record(REFERENCE_TARGET, expression, classifier);
        JetType result =
            getExtendedClassObjectType(classObjectType, referencedName, classifier, context);
        if (result == null) {
          context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
        }
        return DataFlowUtils.checkType(result, expression, context);
      }
    }
    JetType[] result = new JetType[1];
    TemporaryBindingTrace temporaryTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace for namespace/class object lookup of name", referencedName);
    if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
      temporaryTrace.commit();
      return DataFlowUtils.checkType(result[0], expression, context);
    }
    // To report NO_CLASS_OBJECT when no namespace found
    if (classifier != null) {
      if (classifier instanceof TypeParameterDescriptor) {
        if (context.expressionPosition == ExpressionPosition.FREE) {
          context.trace.report(
              TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(
                  expression, (TypeParameterDescriptor) classifier));
        } else {
          context.trace.report(
              TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, (TypeParameterDescriptor) classifier));
        }
      } else if (context.expressionPosition == ExpressionPosition.FREE) {
        context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
      }
      context.trace.record(REFERENCE_TARGET, expression, classifier);
      JetScope scopeForStaticMembersResolution =
          classifier instanceof ClassDescriptor
              ? getStaticNestedClassesScope((ClassDescriptor) classifier)
              : new JetScopeImpl() {
                @NotNull
                @Override
                public DeclarationDescriptor getContainingDeclaration() {
                  return classifier;
                }

                @Override
                public String toString() {
                  return "Scope for the type parameter on the left hand side of dot";
                }
              };
      return new NamespaceType(referencedName, scopeForStaticMembersResolution);
    }
    temporaryTrace.commit();
    return result[0];
  }
  private boolean canImportMembersFrom(
      @NotNull Collection<? extends DeclarationDescriptor> descriptors,
      @NotNull JetSimpleNameExpression reference,
      @NotNull BindingTrace trace,
      @NotNull LookupMode lookupMode) {

    if (lookupMode == LookupMode.ONLY_CLASSES) {
      return true;
    }

    if (descriptors.size() == 1) {
      return canImportMembersFrom(descriptors.iterator().next(), reference, trace, lookupMode);
    }
    TemporaryBindingTrace temporaryTrace =
        TemporaryBindingTrace.create(
            trace, "trace to find out if members can be imported from", reference);
    boolean canImport = false;
    for (DeclarationDescriptor descriptor : descriptors) {
      canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, lookupMode);
    }
    if (!canImport) {
      temporaryTrace.commit();
    }
    return canImport;
  }
  @Override
  public JetTypeInfo visitObjectLiteralExpression(
      @NotNull final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
    DelegatingBindingTrace delegatingBindingTrace =
        context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration());
    if (delegatingBindingTrace != null) {
      delegatingBindingTrace.addAllMyDataTo(context.trace);
      JetType type = context.trace.get(EXPRESSION_TYPE, expression);
      return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo);
    }
    final JetType[] result = new JetType[1];
    final TemporaryBindingTrace temporaryTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to resolve object literal expression", expression);
    ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler =
        new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {

          @Override
          public void handleRecord(
              WritableSlice<PsiElement, ClassDescriptor> slice,
              PsiElement declaration,
              final ClassDescriptor descriptor) {
            if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
              JetType defaultType =
                  DeferredType.create(
                      context.trace,
                      createRecursionIntolerantLazyValueWithDefault(
                          ErrorUtils.createErrorType("Recursive dependency"),
                          new Function0<JetType>() {
                            @Override
                            public JetType invoke() {
                              return descriptor.getDefaultType();
                            }
                          }));
              result[0] = defaultType;
              if (!context.trace.get(PROCESSED, expression)) {
                temporaryTrace.record(EXPRESSION_TYPE, expression, defaultType);
                temporaryTrace.record(PROCESSED, expression);
              }
            }
          }
        };
    ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
    traceAdapter.addHandler(CLASS, handler);
    TopDownAnalyzer.processClassOrObject(
        context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT),
        context.scope.getContainingDeclaration(),
        expression.getObjectDeclaration());

    DelegatingBindingTrace cloneDelta =
        new DelegatingBindingTrace(
            new BindingTraceContext().getBindingContext(),
            "cached delta trace for object literal expression resolve",
            expression);
    temporaryTrace.addAllMyDataTo(cloneDelta);
    context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta);
    temporaryTrace.commit();
    return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo);
  }
 @Nullable
 private JetType lookupNamespaceOrClassObject(
     @NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
   Name referencedName = expression.getReferencedNameAsName();
   ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
   if (classifier != null) {
     JetType classObjectType = classifier.getClassObjectType();
     if (classObjectType != null) {
       context.trace.record(REFERENCE_TARGET, expression, classifier);
       JetType result;
       if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
           && classifier instanceof ClassDescriptor) {
         JetScope scope =
             new ChainedScope(
                 classifier,
                 classObjectType.getMemberScope(),
                 getStaticNestedClassesScope((ClassDescriptor) classifier));
         result = new NamespaceType(referencedName, scope);
       } else if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
           || classifier.isClassObjectAValue()) {
         result = classObjectType;
       } else {
         context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
         result = null;
       }
       return DataFlowUtils.checkType(result, expression, context);
     }
   }
   JetType[] result = new JetType[1];
   TemporaryBindingTrace temporaryTrace =
       TemporaryBindingTrace.create(
           context.trace, "trace for namespace/class object lookup of name", referencedName);
   if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
     temporaryTrace.commit();
     return DataFlowUtils.checkType(result[0], expression, context);
   }
   // To report NO_CLASS_OBJECT when no namespace found
   if (classifier != null) {
     if (context.expressionPosition == ExpressionPosition.FREE) {
       context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
     }
     context.trace.record(REFERENCE_TARGET, expression, classifier);
     JetScope scopeForStaticMembersResolution =
         classifier instanceof ClassDescriptor
             ? getStaticNestedClassesScope((ClassDescriptor) classifier)
             : JetScope.EMPTY;
     return new NamespaceType(referencedName, scopeForStaticMembersResolution);
   }
   temporaryTrace.commit();
   return result[0];
 }
Esempio n. 5
0
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
          @NotNull ResolutionResultsCache.MemberType<F> memberType,
          @NotNull BasicCallResolutionContext context,
          @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
          @NotNull CallTransformer<D, F> callTransformer,
          @NotNull JetReferenceExpression reference) {
    OverloadResolutionResultsImpl<F> results = null;
    TracingStrategy tracing =
        prioritizedTasks.isEmpty()
            ? TracingStrategy.EMPTY
            : prioritizedTasks.iterator().next().tracing;
    TemporaryBindingTrace traceToResolveCall =
        TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
    CallKey callKey = CallResolverUtil.createCallKey(context);
    if (callKey != null) {
      OverloadResolutionResultsImpl<F> cachedResults =
          context.resolutionResultsCache.getResolutionResults(callKey, memberType);
      if (cachedResults != null) {
        DelegatingBindingTrace deltasTraceForResolve =
            context.resolutionResultsCache.getResolutionTrace(callKey);
        assert deltasTraceForResolve != null;
        deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
        results = cachedResults;
      }
    }
    if (results == null) {
      BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
      results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
      DelegatingBindingTrace deltasTraceForTypeInference =
          ((OverloadResolutionResultsImpl) results).getTrace();
      if (deltasTraceForTypeInference != null) {
        deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
      }
      completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
      cacheResults(memberType, context, results, traceToResolveCall, tracing);
    }
    traceToResolveCall.commit();

    if (!prioritizedTasks.isEmpty() && context.contextDependency == ContextDependency.INDEPENDENT) {
      results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
    }

    if (extension != null) {
      extension.run(results, context);
    }

    return results;
  }
  @NotNull
  public JetTypeInfo getSimpleNameExpressionTypeInfo(
      @NotNull JetSimpleNameExpression nameExpression,
      @NotNull ReceiverValue receiver,
      @Nullable ASTNode callOperationNode,
      @NotNull ResolutionContext context) {
    boolean[] result = new boolean[1];

    TemporaryBindingTrace traceForVariable =
        TemporaryBindingTrace.create(context.trace, "trace to resolve as variable", nameExpression);
    JetType type =
        getVariableType(
            nameExpression,
            receiver,
            callOperationNode,
            context.replaceBindingTrace(traceForVariable),
            result);
    if (result[0]) {
      traceForVariable.commit();
      if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) {
        type = null;
      }
      return JetTypeInfo.create(type, context.dataFlowInfo);
    }

    Call call =
        CallMaker.makeCall(
            nameExpression,
            receiver,
            callOperationNode,
            nameExpression,
            Collections.<ValueArgument>emptyList());
    TemporaryBindingTrace traceForFunction =
        TemporaryBindingTrace.create(context.trace, "trace to resolve as function", nameExpression);
    ResolvedCall<FunctionDescriptor> resolvedCall =
        getResolvedCallForFunction(
            call,
            nameExpression,
            receiver,
            context,
            ResolveMode.TOP_LEVEL_CALL,
            ResolutionResultsCache.create(),
            result);
    if (result[0]) {
      FunctionDescriptor functionDescriptor =
          resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
      traceForFunction.commit();
      boolean hasValueParameters =
          functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
      context.trace.report(
          FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
      type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
      return JetTypeInfo.create(type, context.dataFlowInfo);
    }

    traceForVariable.commit();
    return JetTypeInfo.create(null, context.dataFlowInfo);
  }
Esempio n. 7
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
          @NotNull ResolutionTask<D, F> task, @NotNull CallTransformer<D, F> callTransformer) {
    OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);

    // If resolution fails, we should check for some of the following situations:
    //   class A {
    //     val foo = Bar() // The following is intended to be an anonymous initializer,
    //                     // but is treated as a function literal argument
    //     {
    //       ...
    //     }
    //  }
    //
    //  fun foo() {
    //    bar {
    //      buzz()
    //      {...} // intended to be a returned from the outer literal
    //    }
    //  }
    ImmutableSet<OverloadResolutionResults.Code> someFailed =
        ImmutableSet.of(MANY_FAILED_CANDIDATES, SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
    if (someFailed.contains(results.getResultCode())
        && !task.call.getFunctionLiteralArguments().isEmpty()
        && task.contextDependency
            == ContextDependency.INDEPENDENT) { // For nested calls there are no such cases
      // We have some candidates that failed for some reason
      // And we have a suspect: the function literal argument
      // Now, we try to remove this argument and see if it helps
      DelegatingCall callWithoutFLArgs =
          new DelegatingCall(task.call) {
            @NotNull
            @Override
            public List<JetExpression> getFunctionLiteralArguments() {
              return Collections.emptyList();
            }
          };
      TemporaryBindingTrace temporaryTrace =
          TemporaryBindingTrace.create(
              task.trace, "trace for resolution guarded for extra function literal arguments");
      ResolutionTask<D, F> newTask =
          task.replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);

      OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped =
          performResolution(newTask, callTransformer);
      if (resultsWithFunctionLiteralsStripped.isSuccess()
          || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
        task.tracing.danglingFunctionLiteralArgumentSuspected(
            task.trace, task.call.getFunctionLiteralArguments());
      }
    }

    return results;
  }
  @Nullable
  private JetType getVariableType(
      @NotNull JetSimpleNameExpression nameExpression,
      @NotNull ReceiverValue receiver,
      @Nullable ASTNode callOperationNode,
      @NotNull ResolutionContext context,
      @NotNull boolean[] result) {
    TemporaryBindingTrace traceForVariable =
        TemporaryBindingTrace.create(
            context.trace, "trace to resolve as local variable or property", nameExpression);
    CallResolver callResolver = expressionTypingServices.getCallResolver();
    Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
    OverloadResolutionResults<VariableDescriptor> resolutionResult =
        callResolver.resolveSimpleProperty(
            BasicCallResolutionContext.create(
                context.replaceBindingTrace(traceForVariable),
                call,
                ResolveMode.TOP_LEVEL_CALL,
                ResolutionResultsCache.create()));
    if (!resolutionResult.isNothing()) {
      traceForVariable.commit();
      checkSuper(receiver, resolutionResult, context.trace, nameExpression);
      result[0] = true;
      return resolutionResult.isSingleResult()
          ? resolutionResult.getResultingDescriptor().getReturnType()
          : null;
    }

    ResolutionContext newContext =
        receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context;
    TemporaryBindingTrace traceForNamespaceOrClassObject =
        TemporaryBindingTrace.create(
            context.trace, "trace to resolve as namespace or class object", nameExpression);
    JetType jetType =
        lookupNamespaceOrClassObject(
            nameExpression, newContext.replaceBindingTrace(traceForNamespaceOrClassObject));
    if (jetType != null) {
      traceForNamespaceOrClassObject.commit();

      // Uncommitted changes in temp context
      context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
      if (context.dataFlowInfo.hasTypeInfoConstraints()) {
        context.trace.record(
            NON_DEFAULT_EXPRESSION_DATA_FLOW, nameExpression, context.dataFlowInfo);
      }
      result[0] = true;
      return jetType;
    }
    result[0] = false;
    return null;
  }
Esempio n. 9
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);
 }
Esempio n. 10
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> performResolution(
          @NotNull ResolutionTask<D, F> task, @NotNull CallTransformer<D, F> callTransformer) {

    for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
      TemporaryBindingTrace candidateTrace =
          TemporaryBindingTrace.create(task.trace, "trace to resolve candidate");
      Collection<CallCandidateResolutionContext<D>> contexts =
          callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
      for (CallCandidateResolutionContext<D> context : contexts) {

        candidateResolver.performResolutionForCandidateCall(context, task);

        /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
        to have a binding to variable while 'invoke' call resolve */
        task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);

        Collection<ResolvedCallWithTrace<F>> calls =
            callTransformer.transformCall(context, this, task);

        for (ResolvedCallWithTrace<F> call : calls) {
          task.tracing.bindReference(call.getTrace(), call);
          task.tracing.bindResolvedCall(call.getTrace(), call);
          task.getResolvedCalls().add(call);
        }
      }
    }

    OverloadResolutionResultsImpl<F> results =
        ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
            task.trace, task.tracing, task.getResolvedCalls());
    if (!results.isSingleResult() && !results.isIncomplete()) {
      argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
    }
    return results;
  }
  @NotNull
  public TypeInfoForCall getCallExpressionTypeInfoForCallWithoutFinalTypeCheck(
      @NotNull JetCallExpression callExpression,
      @NotNull ReceiverValue receiver,
      @Nullable ASTNode callOperationNode,
      @NotNull ResolutionContext context,
      @NotNull ResolveMode resolveMode) {
    boolean[] result = new boolean[1];
    Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);

    TemporaryBindingTrace traceForFunction =
        TemporaryBindingTrace.create(
            context.trace, "trace to resolve as function call", callExpression);
    ResolvedCall<FunctionDescriptor> resolvedCall =
        getResolvedCallForFunction(
            call,
            callExpression,
            receiver,
            context.replaceBindingTrace(traceForFunction),
            resolveMode,
            result);
    if (result[0]) {
      FunctionDescriptor functionDescriptor =
          resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
      traceForFunction.commit();
      if (callExpression.getValueArgumentList() == null
          && callExpression.getFunctionLiteralArguments().isEmpty()) {
        // there are only type arguments
        boolean hasValueParameters =
            functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
        context.trace.report(
            FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
      }
      if (functionDescriptor == null) {
        return TypeInfoForCall.create(null, context.dataFlowInfo);
      }
      JetType type = functionDescriptor.getReturnType();

      return TypeInfoForCall.create(
          type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context, resolveMode);
    }

    JetExpression calleeExpression = callExpression.getCalleeExpression();
    if (calleeExpression instanceof JetSimpleNameExpression
        && callExpression.getTypeArgumentList() == null) {
      TemporaryBindingTrace traceForVariable =
          TemporaryBindingTrace.create(
              context.trace, "trace to resolve as variable with 'invoke' call", callExpression);
      JetType type =
          getVariableType(
              (JetSimpleNameExpression) calleeExpression,
              receiver,
              callOperationNode,
              context.replaceBindingTrace(traceForVariable),
              result);
      if (result[0]) {
        traceForVariable.commit();
        context.trace.report(
            FUNCTION_EXPECTED.on(
                (JetReferenceExpression) calleeExpression,
                calleeExpression,
                type != null ? type : ErrorUtils.createErrorType("")));
        return TypeInfoForCall.create(null, context.dataFlowInfo);
      }
    }
    traceForFunction.commit();
    return TypeInfoForCall.create(null, context.dataFlowInfo);
  }
Esempio n. 12
0
 public void commit() {
   trace.commit();
   cache.commit();
 }
Esempio n. 13
0
 public TemporaryTraceAndCache(
     ResolutionContext context, String debugName, JetExpression expression) {
   trace = TemporaryBindingTrace.create(context.trace, debugName, expression);
   cache = new TemporaryResolutionResultsCache(context.resolutionResultsCache);
 }
  @NotNull
  protected JetTypeInfo visitAssignmentOperation(
      JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
    // There is a temporary binding trace for an opportunity to resolve set method for array if
    // needed (the initial trace should be used there)
    TemporaryBindingTrace temporaryBindingTrace =
        TemporaryBindingTrace.create(
            contextWithExpectedType.trace,
            "trace to resolve array set method for binary expression",
            expression);
    ExpressionTypingContext context =
        contextWithExpectedType
            .replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
            .replaceBindingTrace(temporaryBindingTrace);

    JetSimpleNameExpression operationSign = expression.getOperationReference();
    IElementType operationType = operationSign.getReferencedNameElementType();
    JetTypeInfo leftInfo = facade.getTypeInfo(expression.getLeft(), context);
    JetType leftType = leftInfo.getType();
    DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();

    JetExpression right = expression.getRight();
    JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft());
    if (right == null || left == null) {
      temporaryBindingTrace.commit();
      return JetTypeInfo.create(null, dataFlowInfo);
    }

    if (leftType == null) {
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
      context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
      temporaryBindingTrace.commit();
      return JetTypeInfo.create(null, dataFlowInfo);
    }
    ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);

    // We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we
    // then also assign)
    // Check for '+='
    Name name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
    TemporaryBindingTrace assignmentOperationTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to check assignment operation like '+=' for", expression);
    OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors =
        basic.getResolutionResultsForBinaryCall(
            scope,
            name,
            context.replaceBindingTrace(assignmentOperationTrace),
            expression,
            receiver);
    JetType assignmentOperationType =
        OverloadResolutionResultsUtil.getResultType(assignmentOperationDescriptors);

    // Check for '+'
    Name counterpartName =
        OperatorConventions.BINARY_OPERATION_NAMES.get(
            OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
    TemporaryBindingTrace binaryOperationTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to check binary operation like '+' for", expression);
    OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors =
        basic.getResolutionResultsForBinaryCall(
            scope,
            counterpartName,
            context.replaceBindingTrace(binaryOperationTrace),
            expression,
            receiver);
    JetType binaryOperationType =
        OverloadResolutionResultsUtil.getResultType(binaryOperationDescriptors);

    JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
    if (assignmentOperationType != null && binaryOperationType != null) {
      OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults =
          OverloadResolutionResultsUtil.ambiguity(
              assignmentOperationDescriptors, binaryOperationDescriptors);
      context.trace.report(
          ASSIGN_OPERATOR_AMBIGUITY.on(
              operationSign, ambiguityResolutionResults.getResultingCalls()));
      Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
      for (ResolvedCall<? extends FunctionDescriptor> call :
          ambiguityResolutionResults.getResultingCalls()) {
        descriptors.add(call.getResultingDescriptor());
      }
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
      context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
    } else if (assignmentOperationType != null) {
      assignmentOperationTrace.commit();
      if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
        context.trace.report(
            ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(
                operationSign,
                assignmentOperationDescriptors.getResultingDescriptor(),
                operationSign));
      }
    } else {
      binaryOperationTrace.commit();
      context.trace.record(VARIABLE_REASSIGNMENT, expression);
      if (left instanceof JetArrayAccessExpression) {
        ExpressionTypingContext contextForResolve =
            context
                .replaceScope(scope)
                .replaceBindingTrace(
                    TemporaryBindingTrace.create(
                        contextWithExpectedType.trace,
                        "trace to resolve array set method for assignment",
                        expression));
        basic.resolveArrayAccessSetMethod(
            (JetArrayAccessExpression) left, right, contextForResolve, context.trace);
      }
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
    }
    basic.checkLValue(context.trace, expression.getLeft());
    temporaryBindingTrace.commit();
    return JetTypeInfo.create(
        checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
  }
Esempio n. 15
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> doResolveCall(
          @NotNull BasicCallResolutionContext context,
          @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
          @NotNull CallTransformer<D, F> callTransformer,
          @NotNull JetReferenceExpression reference) {

    ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
    context.trace.record(
        ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
    context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);

    if (context.dataFlowInfo.hasTypeInfoConstraints()) {
      context.trace.record(
          NON_DEFAULT_EXPRESSION_DATA_FLOW,
          context.call.getCalleeExpression(),
          context.dataFlowInfo);
    }

    debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);

    if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
      argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
    }

    TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
    OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
    for (ResolutionTask<D, F> task : prioritizedTasks) {
      TemporaryBindingTrace taskTrace =
          TemporaryBindingTrace.create(
              context.trace, "trace to resolve a task for", task.reference);
      OverloadResolutionResultsImpl<F> results =
          performResolutionGuardedForExtraFunctionLiteralArguments(
              task.replaceBindingTrace(taskTrace), callTransformer);
      if (results.isSuccess() || results.isAmbiguity()) {
        taskTrace.commit();

        if (results.isSuccess()) {
          debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
        }

        resolveFunctionArguments(context, results);
        return results;
      }
      if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
        results.setTrace(taskTrace);
        return results;
      }
      boolean updateResults =
          traceForFirstNonemptyCandidateSet == null
              || (resultsForFirstNonemptyCandidateSet.getResultCode()
                      == CANDIDATES_WITH_WRONG_RECEIVER
                  && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
      if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
        traceForFirstNonemptyCandidateSet = taskTrace;
        resultsForFirstNonemptyCandidateSet = results;
      }
    }
    if (traceForFirstNonemptyCandidateSet != null) {
      traceForFirstNonemptyCandidateSet.commit();
      if (resultsForFirstNonemptyCandidateSet.isSingleResult()) {

        debugInfo.set(
            ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall());
      }
      resolveFunctionArguments(context, resultsForFirstNonemptyCandidateSet);
    } else {
      context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
      argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
    }
    return resultsForFirstNonemptyCandidateSet != null
        ? resultsForFirstNonemptyCandidateSet
        : OverloadResolutionResultsImpl.<F>nameNotFound();
  }