Exemplo n.º 1
0
  public void rememberClosure(JetExpression expression, Type type) {
    JetExpression lambda = JetPsiUtil.deparenthesize(expression);
    assert isInlinableParameterExpression(lambda)
        : "Couldn't find inline expression in " + expression.getText();

    LambdaInfo info = new LambdaInfo(lambda, typeMapper);

    ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null);
    closureInfo.setLambda(info);
    expressionMap.put(closureInfo.getIndex(), info);
  }
 @NotNull
 private JetTypeInfo getSelectorReturnTypeInfo(
     @NotNull ReceiverValue receiver,
     @Nullable ASTNode callOperationNode,
     @NotNull JetExpression selectorExpression,
     @NotNull ResolutionContext context,
     @NotNull ResolveMode resolveMode,
     @NotNull ResolutionResultsCache resolutionResultsCache) {
   if (selectorExpression instanceof JetCallExpression) {
     return getCallExpressionTypeInfoWithoutFinalTypeCheck(
         (JetCallExpression) selectorExpression,
         receiver,
         callOperationNode,
         context,
         resolveMode,
         resolutionResultsCache);
   } else if (selectorExpression instanceof JetSimpleNameExpression) {
     return getSimpleNameExpressionTypeInfo(
         (JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
   } else if (selectorExpression instanceof JetQualifiedExpression) {
     JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression;
     JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression();
     JetTypeInfo newReceiverTypeInfo =
         getSelectorReturnTypeInfo(
             receiver,
             callOperationNode,
             newReceiverExpression,
             context.replaceExpectedType(NO_EXPECTED_TYPE),
             resolveMode,
             resolutionResultsCache);
     JetType newReceiverType = newReceiverTypeInfo.getType();
     DataFlowInfo newReceiverDataFlowInfo = newReceiverTypeInfo.getDataFlowInfo();
     JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression();
     if (newReceiverType != null && newSelectorExpression != null) {
       ExpressionReceiver expressionReceiver =
           new ExpressionReceiver(newReceiverExpression, newReceiverType);
       return getSelectorReturnTypeInfo(
           expressionReceiver,
           qualifiedExpression.getOperationTokenNode(),
           newSelectorExpression,
           context.replaceDataFlowInfo(newReceiverDataFlowInfo),
           resolveMode,
           resolutionResultsCache);
     }
   } else {
     context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
   }
   return JetTypeInfo.create(null, context.dataFlowInfo);
 }
  private static String getDefaultExpressionString(@Nullable PsiElement parameterDeclaration) {
    if (parameterDeclaration instanceof JetParameter) {
      JetExpression defaultValue = ((JetParameter) parameterDeclaration).getDefaultValue();
      if (defaultValue != null) {
        String defaultExpression = defaultValue.getText();
        if (defaultExpression.length() <= 32) {
          return defaultExpression;
        }

        if (defaultValue instanceof JetConstantExpression
            || defaultValue instanceof JetStringTemplateExpression) {
          if (defaultExpression.startsWith("\"")) {
            return "\"...\"";
          } else if (defaultExpression.startsWith("\'")) {
            return "\'...\'";
          }
        }
      }
    }
    return "...";
  }
  @NotNull
  @Override
  protected List<IntentionAction> doCreateActions(@NotNull Diagnostic diagnostic) {
    List<IntentionAction> actions = new LinkedList<IntentionAction>();

    BindingContext context = ResolutionUtils.analyzeFully((JetFile) diagnostic.getPsiFile());

    PsiElement diagnosticElement = diagnostic.getPsiElement();
    if (!(diagnosticElement instanceof JetExpression)) {
      LOG.error("Unexpected element: " + diagnosticElement.getText());
      return Collections.emptyList();
    }

    JetExpression expression = (JetExpression) diagnosticElement;

    JetType expectedType;
    JetType expressionType;
    if (diagnostic.getFactory() == Errors.TYPE_MISMATCH) {
      DiagnosticWithParameters2<JetExpression, JetType, JetType> diagnosticWithParameters =
          Errors.TYPE_MISMATCH.cast(diagnostic);
      expectedType = diagnosticWithParameters.getA();
      expressionType = diagnosticWithParameters.getB();
    } else if (diagnostic.getFactory() == Errors.NULL_FOR_NONNULL_TYPE) {
      DiagnosticWithParameters1<JetConstantExpression, JetType> diagnosticWithParameters =
          Errors.NULL_FOR_NONNULL_TYPE.cast(diagnostic);
      expectedType = diagnosticWithParameters.getA();
      expressionType = TypeUtilsKt.makeNullable(expectedType);
    } else if (diagnostic.getFactory() == Errors.CONSTANT_EXPECTED_TYPE_MISMATCH) {
      DiagnosticWithParameters2<JetConstantExpression, String, JetType> diagnosticWithParameters =
          Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic);
      expectedType = diagnosticWithParameters.getB();
      expressionType = context.getType(expression);
      if (expressionType == null) {
        LOG.error("No type inferred: " + expression.getText());
        return Collections.emptyList();
      }
    } else {
      LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic));
      return Collections.emptyList();
    }

    // We don't want to cast a cast or type-asserted expression:
    if (!(expression instanceof JetBinaryExpressionWithTypeRHS)
        && !(expression.getParent() instanceof JetBinaryExpressionWithTypeRHS)) {
      actions.add(new CastExpressionFix(expression, expectedType));
    }

    // Property initializer type mismatch property type:
    JetProperty property = PsiTreeUtil.getParentOfType(expression, JetProperty.class);
    if (property != null) {
      JetPropertyAccessor getter = property.getGetter();
      JetExpression initializer = property.getInitializer();
      if (QuickFixUtil.canEvaluateTo(initializer, expression)
          || (getter != null
              && QuickFixUtil.canFunctionOrGetterReturnExpression(
                  property.getGetter(), expression))) {
        LexicalScope scope =
            CorePackage.getResolutionScope(
                property, context, ResolutionUtils.getResolutionFacade(property));
        JetType typeToInsert =
            TypeUtils.approximateWithResolvableType(expressionType, scope, false);
        actions.add(new ChangeVariableTypeFix(property, typeToInsert));
      }
    }

    PsiElement expressionParent = expression.getParent();

    // Mismatch in returned expression:

    JetCallableDeclaration function =
        expressionParent instanceof JetReturnExpression
            ? BindingContextUtilPackage.getTargetFunction(
                (JetReturnExpression) expressionParent, context)
            : PsiTreeUtil.getParentOfType(expression, JetFunction.class, true);
    if (function instanceof JetFunction
        && QuickFixUtil.canFunctionOrGetterReturnExpression(function, expression)) {
      LexicalScope scope =
          CorePackage.getResolutionScope(
              function, context, ResolutionUtils.getResolutionFacade(function));
      JetType typeToInsert = TypeUtils.approximateWithResolvableType(expressionType, scope, false);
      actions.add(new ChangeFunctionReturnTypeFix((JetFunction) function, typeToInsert));
    }

    // Fixing overloaded operators:
    if (expression instanceof JetOperationExpression) {
      ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
      if (resolvedCall != null) {
        JetFunction declaration = getFunctionDeclaration(resolvedCall);
        if (declaration != null) {
          actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType));
        }
      }
    }

    // Change function return type when TYPE_MISMATCH is reported on call expression:
    if (expression instanceof JetCallExpression) {
      ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
      if (resolvedCall != null) {
        JetFunction declaration = getFunctionDeclaration(resolvedCall);
        if (declaration != null) {
          actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType));
        }
      }
    }

    ResolvedCall<? extends CallableDescriptor> resolvedCall =
        CallUtilPackage.getParentResolvedCall(expression, context, true);
    if (resolvedCall != null) {
      // to fix 'type mismatch' on 'if' branches
      // todo: the same with 'when'
      JetExpression parentIf = QuickFixUtil.getParentIfForBranch(expression);
      JetExpression argumentExpression = (parentIf != null) ? parentIf : expression;
      ValueArgument valueArgument =
          CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), argumentExpression);
      if (valueArgument != null) {
        JetParameter correspondingParameter =
            QuickFixUtil.getParameterDeclarationForValueArgument(resolvedCall, valueArgument);
        JetType valueArgumentType =
            diagnostic.getFactory() == Errors.NULL_FOR_NONNULL_TYPE
                ? expressionType
                : context.getType(valueArgument.getArgumentExpression());
        if (correspondingParameter != null && valueArgumentType != null) {
          JetCallableDeclaration callable =
              PsiTreeUtil.getParentOfType(
                  correspondingParameter, JetCallableDeclaration.class, true);
          LexicalScope scope =
              callable != null
                  ? CorePackage.getResolutionScope(
                      callable, context, ResolutionUtils.getResolutionFacade(callable))
                  : null;
          JetType typeToInsert =
              TypeUtils.approximateWithResolvableType(valueArgumentType, scope, true);
          actions.add(new ChangeParameterTypeFix(correspondingParameter, typeToInsert));
        }
      }
    }
    return actions;
  }
Exemplo n.º 5
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);
  }
Exemplo n.º 6
0
 private static boolean checkEquivalence(JetExpression e1, JetExpression e2) {
   return e1.getText().equals(e2.getText());
 }