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); }
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 @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; }
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; }