private static SMAP createSMAPWithDefaultMapping( @NotNull JetExpression declaration, @NotNull List<FileMapping> mappings) { PsiFile containingFile = declaration.getContainingFile(); Integer lineNumbers = CodegenUtil.getLineNumberForElement(containingFile, true); assert lineNumbers != null : "Couldn't extract line count in " + containingFile; return new SMAP(mappings); }
public static boolean isSelectorInQualified(@NotNull JetSimpleNameExpression nameExpression) { PsiElement nameExpressionParent = nameExpression.getParent(); if (nameExpressionParent instanceof JetUserType) { assert ((JetUserType) nameExpressionParent).getReferenceExpression() == nameExpression; return ((JetUserType) nameExpressionParent).getQualifier() != null; } JetExpression selector = nameExpression; if (nameExpressionParent instanceof JetCallExpression && ((JetCallExpression) nameExpressionParent).getCalleeExpression() == nameExpression) { selector = (JetCallExpression) nameExpressionParent; } PsiElement selectorParent = selector.getParent(); return selectorParent instanceof JetQualifiedExpression && (((JetQualifiedExpression) selectorParent).getSelectorExpression() == selector); }
private static JetScope getExpressionResolutionScope( @NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { ScopeProvider provider = resolveSession.getInjector().getScopeProvider(); JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class); if (parentDeclaration == null) { return provider.getFileScopeWithAllImported((JetFile) expression.getContainingFile()); } return provider.getResolutionScopeForDeclaration(parentDeclaration); }
public static void foldIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) { Project project = ifExpression.getProject(); JetExpression condition = ifExpression.getCondition(); JetExpression thenRoot = ifExpression.getThen(); JetExpression elseRoot = (JetExpression) JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression); assertNotNull(condition); assertNotNull(thenRoot); assertNotNull(elseRoot); //noinspection ConstantConditions JetIfExpression newIfExpression = JetPsiFactory.createIf(project, condition, thenRoot, elseRoot); JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, newIfExpression); newIfExpression = (JetIfExpression) newReturnExpression.getReturnedExpression(); assertNotNull(newIfExpression); //noinspection ConstantConditions JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen()); JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse()); assertNotNull(thenReturn); assertNotNull(elseReturn); JetExpression thenExpr = thenReturn.getReturnedExpression(); JetExpression elseExpr = elseReturn.getReturnedExpression(); assertNotNull(thenExpr); assertNotNull(elseExpr); //noinspection ConstantConditions thenReturn.replace(thenExpr); //noinspection ConstantConditions elseReturn.replace(elseExpr); elseRoot.delete(); ifExpression.replace(newReturnExpression); }
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); }
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 "..."; }
public static @NotNull BindingContext resolveToExpression( @NotNull final ResolveSession resolveSession, @NotNull JetExpression expression) { final DelegatingBindingTrace trace = new DelegatingBindingTrace( resolveSession.getBindingContext(), "trace to resolve expression", expression); JetFile file = (JetFile) expression.getContainingFile(); @SuppressWarnings("unchecked") PsiElement topmostCandidateForAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes( expression, JetNamedFunction.class, JetClassInitializer.class, JetProperty.class, JetDelegationSpecifierList.class); if (topmostCandidateForAdditionalResolve != null) { if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) { functionAdditionalResolve( resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) { initializerAdditionalResolve( resolveSession, (JetClassInitializer) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetProperty) { propertyAdditionalResolve( resolveSession, (JetProperty) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetDelegationSpecifierList) { delegationSpecifierAdditionalResolve( resolveSession, (JetDelegationSpecifierList) topmostCandidateForAdditionalResolve, trace, file); } else { assert false : "Invalid type of the topmost parent"; } return trace.getBindingContext(); } // Setup resolution scope explicitly if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) { JetScope scope = getExpressionMemberScope(resolveSession, expression); if (scope != null) { trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope); } } return trace.getBindingContext(); }
@Nullable private static Name getName(@Nullable JetExpression expression) { if (expression == null) { return null; } if (expression instanceof JetSimpleNameExpression) { return ((JetSimpleNameExpression) expression).getReferencedNameAsName(); } else { throw new IllegalArgumentException( "Can't construct name for: " + expression.getClass().toString()); } }
/** * Name suggestion types: 1. According to type: 1a. Primitive types to some short name 1b. Class * types according to class name camel humps: (AbCd => {abCd, cd}) 1c. Arrays => arrayOfInnerType * 2. Reference expressions according to reference name camel humps 3. Method call expression * according to method callee expression * * @param expression to suggest name for variable * @param validator to check scope for such names * @return possible names */ public static String[] suggestNames(JetExpression expression, JetNameValidator validator) { ArrayList<String> result = new ArrayList<String>(); BindingContext bindingContext = AnalyzeSingleFileUtil.getContextForSingleFile((JetFile) expression.getContainingFile()); JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); if (jetType != null) { addNamesForType(result, jetType, validator); } addNamesForExpression(result, expression, validator); if (result.isEmpty()) addName(result, "value", validator); return ArrayUtil.toStringArray(result); }
public static Collection<JetReturnExpression> collectReturns(@NotNull JetExpression expression) { Collection<JetReturnExpression> result = Lists.newArrayList(); expression.accept( new JetTreeVisitor<Collection<JetReturnExpression>>() { @Override public Void visitReturnExpression( @NotNull JetReturnExpression expression, Collection<JetReturnExpression> data) { data.add(expression); return null; } }, result); return result; }
@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); }
@Nullable private static FqName getFQName(@Nullable JetExpression expression) { if (expression == null) { return null; } if (expression instanceof JetDotQualifiedExpression) { JetDotQualifiedExpression dotQualifiedExpression = (JetDotQualifiedExpression) expression; FqName parentFqn = getFQName(dotQualifiedExpression.getReceiverExpression()); Name child = getName(dotQualifiedExpression.getSelectorExpression()); return parentFqn != null && child != null ? parentFqn.child(child) : null; } else if (expression instanceof JetSimpleNameExpression) { JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression; return FqName.topLevel(simpleNameExpression.getReferencedNameAsName()); } else { throw new IllegalArgumentException( "Can't construct fqn for: " + expression.getClass().toString()); } }
public static boolean isLHSOfDot(@NotNull JetExpression expression) { PsiElement parent = expression.getParent(); if (!(parent instanceof JetQualifiedExpression)) return false; JetQualifiedExpression qualifiedParent = (JetQualifiedExpression) parent; return qualifiedParent.getReceiverExpression() == expression || isLHSOfDot(qualifiedParent); }
@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); }
public static boolean areParenthesesNecessary( @NotNull JetExpression innerExpression, @NotNull JetExpression currentInner, @NotNull JetExpression parentExpression) { if (parentExpression instanceof JetParenthesizedExpression || innerExpression instanceof JetParenthesizedExpression) { return false; } if (parentExpression instanceof JetWhenExpression || innerExpression instanceof JetWhenExpression) { return false; } if (innerExpression instanceof JetIfExpression) { PsiElement current = parentExpression; while (!(current instanceof JetBlockExpression || current instanceof JetDeclaration || current instanceof JetStatementExpression)) { if (current.getTextRange().getEndOffset() != currentInner.getTextRange().getEndOffset()) { return current.getText().charAt(current.getTextLength() - 1) != ')'; // if current expression is "guarded" by parenthesis, no extra parenthesis is // necessary } current = current.getParent(); } } IElementType innerOperation = getOperation(innerExpression); IElementType parentOperation = getOperation(parentExpression); // 'return (@label{...})' case if (parentExpression instanceof JetReturnExpression && innerOperation == JetTokens.LABEL_IDENTIFIER) { return true; } // '(x: Int) < y' case if (innerExpression instanceof JetBinaryExpressionWithTypeRHS && parentOperation == JetTokens.LT) { return true; } int innerPriority = getPriority(innerExpression); int parentPriority = getPriority(parentExpression); if (innerPriority == parentPriority) { if (parentExpression instanceof JetBinaryExpression) { if (innerOperation == JetTokens.ANDAND || innerOperation == JetTokens.OROR) { return false; } return ((JetBinaryExpression) parentExpression).getRight() == currentInner; } // '-(-x)' case if (parentExpression instanceof JetPrefixExpression && innerExpression instanceof JetPrefixExpression) { return innerOperation == parentOperation && (innerOperation == JetTokens.PLUS || innerOperation == JetTokens.MINUS); } return false; } return innerPriority < parentPriority; }
public static boolean isNullConstant(@NotNull JetExpression expression) { JetExpression deparenthesized = deparenthesize(expression); return deparenthesized instanceof JetConstantExpression && deparenthesized.getNode().getElementType() == JetNodeTypes.NULL; }
private static boolean checkEquivalence(JetExpression e1, JetExpression e2) { return e1.getText().equals(e2.getText()); }
public static JetScope getExpressionMemberScope( @NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { DelegatingBindingTrace trace = new DelegatingBindingTrace( resolveSession.getBindingContext(), "trace to resolve a member scope of expression", expression); if (expression instanceof JetReferenceExpression) { QualifiedExpressionResolver qualifiedExpressionResolver = resolveSession.getInjector().getQualifiedExpressionResolver(); // In some type declaration if (expression.getParent() instanceof JetUserType) { JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier(); if (qualifier != null) { Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver.lookupDescriptorsForUserType( qualifier, getExpressionResolutionScope(resolveSession, expression), trace); for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof LazyPackageDescriptor) { return ((LazyPackageDescriptor) descriptor).getMemberScope(); } } } } // Inside import if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class, false) != null) { NamespaceDescriptor rootPackage = resolveSession.getPackageDescriptorByFqName(FqName.ROOT); assert rootPackage != null; if (expression.getParent() instanceof JetDotQualifiedExpression) { JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression(); String name = ((JetFile) expression.getContainingFile()).getPackageName(); NamespaceDescriptor filePackage = name != null ? resolveSession.getPackageDescriptorByFqName(new FqName(name)) : rootPackage; assert filePackage != null : "File package should be already resolved and be found"; JetScope scope = filePackage.getMemberScope(); Collection<? extends DeclarationDescriptor> descriptors; if (element instanceof JetDotQualifiedExpression) { descriptors = qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression( (JetDotQualifiedExpression) element, rootPackage.getMemberScope(), scope, trace, false, false); } else { descriptors = qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference( (JetSimpleNameExpression) element, rootPackage.getMemberScope(), scope, trace, false, false, false); } for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof NamespaceDescriptor) { return ((NamespaceDescriptor) descriptor).getMemberScope(); } } } else { return rootPackage.getMemberScope(); } } // Inside package declaration JetNamespaceHeader namespaceHeader = PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class, false); if (namespaceHeader != null) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName( namespaceHeader.getParentFqName((JetReferenceExpression) expression)); if (packageDescriptor != null) { return packageDescriptor.getMemberScope(); } } } return null; }
public static boolean isTypeFlexible(@Nullable JetExpression expression) { if (expression == null) return false; return TokenSet.create(JetNodeTypes.INTEGER_CONSTANT, JetNodeTypes.FLOAT_CONSTANT) .contains(expression.getNode().getElementType()); }
@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; }