@NotNull @Override public LightClassConstructionContext getContextForClassOrObject( @NotNull JetClassOrObject classOrObject) { ResolveSessionForBodies session = KotlinCacheService.getInstance(classOrObject.getProject()) .getLazyResolveSession(classOrObject); if (classOrObject.isLocal()) { BindingContext bindingContext = session.resolveToElement(classOrObject, BodyResolveMode.FULL); ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject); if (descriptor == null) { LOG.warn( "No class descriptor in context for class: " + PsiUtilPackage.getElementTextWithContext(classOrObject)); return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor()); } ForceResolveUtil.forceResolveAllContents(descriptor); return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor()); } ForceResolveUtil.forceResolveAllContents(session.getClassDescriptor(classOrObject)); return new LightClassConstructionContext( session.getBindingContext(), session.getModuleDescriptor()); }
@NotNull private static KotlinType getPropertyType(@NotNull KtProperty property) { BindingContext bindingContext = ResolutionUtils.analyze(property, BodyResolveMode.PARTIAL); VariableDescriptor propertyDescriptor = bindingContext.get(BindingContext.VARIABLE, property); assert propertyDescriptor != null : "Couldn't resolve property to property descriptor " + property.getText(); return propertyDescriptor.getType(); }
private static Map<DeclarationDescriptor, List<String>> getActualLoadErrors( @NotNull BindingContext bindingContext) { Map<DeclarationDescriptor, List<String>> result = new HashMap<DeclarationDescriptor, List<String>>(); Collection<DeclarationDescriptor> descriptors = bindingContext.getKeys(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS); for (DeclarationDescriptor descriptor : descriptors) { List<String> errors = bindingContext.get(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor); result.put(descriptor, errors); } return result; }
public LambdaInfo( @NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline, boolean isBoundCallableReference) { this.isCrossInline = isCrossInline; this.expression = expression instanceof KtLambdaExpression ? ((KtLambdaExpression) expression).getFunctionLiteral() : expression; this.typeMapper = typeMapper; this.isBoundCallableReference = isBoundCallableReference; BindingContext bindingContext = typeMapper.getBindingContext(); FunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, this.expression); if (function == null && expression instanceof KtCallableReferenceExpression) { VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, this.expression); assert variableDescriptor instanceof VariableDescriptorWithAccessors : "Reference expression not resolved to variable descriptor with accessors: " + expression.getText(); classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor); closureClassType = typeMapper.mapClass(classDescriptor); SimpleFunctionDescriptor getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor); functionDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor); ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert( ((KtCallableReferenceExpression) expression).getCallableReference(), bindingContext); propertyReferenceInfo = new PropertyReferenceInfo( (VariableDescriptor) resolvedCall.getResultingDescriptor(), getFunction); } else { propertyReferenceInfo = null; functionDescriptor = function; assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText(); classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor); closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor); } closure = bindingContext.get(CLOSURE, classDescriptor); assert closure != null : "Closure for lambda should be not null " + expression.getText(); labels = InlineCodegen.getDeclarationLabels(expression, functionDescriptor); }
private void generateCopyFunctionForDataClasses(List<JetParameter> constructorParameters) { FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, classDescriptor); if (copyFunction != null) { generateCopyFunction(copyFunction, constructorParameters); } }
public void gen(@NotNull KtNamedFunction function) { SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, function); assert functionDescriptor != null : "No descriptor for function " + function.getText() + "\n" + "in " + function.getContainingFile().getVirtualFile(); if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) { generateMethod( JvmDeclarationOriginKt.OtherOrigin(function, functionDescriptor), functionDescriptor, new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function)); } generateDefaultIfNeeded( owner.intoFunction(functionDescriptor), functionDescriptor, owner.getContextKind(), DefaultParameterValueLoader.DEFAULT, function); generateOverloadsWithDefaultValues(function, functionDescriptor, functionDescriptor); }
private List<PropertyDescriptor> getDataProperties() { List<PropertyDescriptor> result = Lists.newArrayList(); for (JetParameter parameter : getPrimaryConstructorParameters()) { if (parameter.hasValOrVar()) { result.add(bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)); } } return result; }
private static boolean isArgumentTypeValid( BindingContext bindingContext, JetValueArgument argument, ValueParameterDescriptor param) { if (argument.getArgumentExpression() != null) { JetType paramType = getActualParameterType(param); JetType exprType = bindingContext.getType(argument.getArgumentExpression()); return exprType == null || JetTypeChecker.DEFAULT.isSubtypeOf(exprType, paramType); } return false; }
@Nullable private static PsiNamedElement[] getSupertypes(Expression[] params, ExpressionContext context) { if (params.length != 0) return null; Project project = context.getProject(); PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument()); if (!(psiFile instanceof JetFile)) return null; JetExpression expression = PsiTreeUtil.getParentOfType( psiFile.findElementAt(context.getStartOffset()), JetExpression.class); if (expression == null) return null; BindingContext bc = ResolutionUtils.analyze(expression, BodyResolveMode.FULL); JetScope scope = bc.get(BindingContext.RESOLUTION_SCOPE, expression); if (scope == null) return null; List<PsiNamedElement> result = new ArrayList<PsiNamedElement>(); for (DeclarationDescriptor descriptor : scope.getDescriptors( DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, JetScope.Companion.getALL_NAME_FILTER())) { if (!(descriptor instanceof ClassDescriptor)) continue; ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; if (!classDescriptor.getModality().isOverridable()) continue; ClassKind kind = classDescriptor.getKind(); if (kind == ClassKind.INTERFACE || kind == ClassKind.CLASS) { PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); if (declaration != null) { result.add((PsiNamedElement) declaration); } } } return result.toArray(new PsiNamedElement[result.size()]); }
private void generateComponentFunctionsForDataClasses() { ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); // primary constructor should exist for data classes // but when generating light-classes still need to check we have one if (constructor == null) return; for (ValueParameterDescriptor parameter : constructor.getValueParameters()) { FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter); if (function != null) { generateComponentFunction(function, parameter); } } }
public void testNoWarningsOnJavaKotlinInheritance() throws Exception { // This test checks that there are no PARAMETER_NAME_CHANGED_ON_OVERRIDE or // DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES // warnings when subclassing in Kotlin from Java binaries (in case when no parameter names are // available for Java classes) KotlinTestUtils.compileJavaFiles( Collections.singletonList(getTestDataFileWithExtension("java")), Arrays.asList("-d", tmpdir.getPath())); Project project = createEnvironment(Collections.singletonList(tmpdir)).getProject(); AnalysisResult result = JvmResolveUtil.analyzeOneFileWithJavaIntegration( KotlinTestUtils.loadJetFile(project, getTestDataFileWithExtension("kt"))); result.throwIfError(); BindingContext bindingContext = result.getBindingContext(); AnalyzerWithCompilerReport.Companion.reportDiagnostics( bindingContext.getDiagnostics(), PrintingMessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR); assertEquals( "There should be no diagnostics", 0, Iterables.size(bindingContext.getDiagnostics())); }
private static Boolean isResolvedToDescriptor( JetValueArgumentList argumentList, FunctionDescriptor functionDescriptor, BindingContext bindingContext) { JetSimpleNameExpression callNameExpression = getCallSimpleNameExpression(argumentList); if (callNameExpression != null) { DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, callNameExpression); if (declarationDescriptor != null) { if (declarationDescriptor == functionDescriptor) { return true; } } } return false; }
@NotNull public static List<Diagnostic> getDiagnosticsIncludingSyntaxErrors( @NotNull BindingContext bindingContext, @NotNull final PsiElement root, boolean markDynamicCalls, @Nullable List<DeclarationDescriptor> dynamicCallDescriptors) { List<Diagnostic> diagnostics = new ArrayList<Diagnostic>(); diagnostics.addAll( Collections2.filter( bindingContext.getDiagnostics().all(), new Predicate<Diagnostic>() { @Override public boolean apply(Diagnostic diagnostic) { return PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false); } })); for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) { diagnostics.add(new SyntaxErrorDiagnostic(errorElement)); } List<Diagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors); diagnostics.addAll(debugAnnotations); return diagnostics; }
private static JetValueArgumentList findCall(CreateParameterInfoContext context) { // todo: calls to this constructors, when we will have auxiliary constructors PsiFile file = context.getFile(); if (!(file instanceof JetFile)) { return null; } JetValueArgumentList argumentList = PsiTreeUtil.getParentOfType( file.findElementAt(context.getOffset()), JetValueArgumentList.class); if (argumentList == null) { return null; } final JetSimpleNameExpression callNameExpression = getCallSimpleNameExpression(argumentList); if (callNameExpression == null) { return null; } PsiReference[] references = callNameExpression.getReferences(); if (references.length == 0) { return null; } ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(callNameExpression.getContainingJetFile()); final BindingContext bindingContext = resolutionFacade.analyze(callNameExpression, BodyResolveMode.FULL); ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(callNameExpression); JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, callNameExpression); final DeclarationDescriptor placeDescriptor; if (scope != null) { placeDescriptor = scope.getContainingDeclaration(); } else { placeDescriptor = null; } Function1<DeclarationDescriptor, Boolean> visibilityFilter = new Function1<DeclarationDescriptor, Boolean>() { @Override public Boolean invoke(DeclarationDescriptor descriptor) { if (placeDescriptor == null) return true; if (!(descriptor instanceof DeclarationDescriptorWithVisibility)) return true; return CorePackage.isVisible( (DeclarationDescriptorWithVisibility) descriptor, placeDescriptor, bindingContext, callNameExpression); } }; final Name refName = callNameExpression.getReferencedNameAsName(); Function1<Name, Boolean> nameFilter = new Function1<Name, Boolean>() { @Override public Boolean invoke(Name name) { return name.equals(refName); } }; Collection<DeclarationDescriptor> variants = new ReferenceVariantsHelper( bindingContext, moduleDescriptor, file.getProject(), visibilityFilter) .getReferenceVariants( callNameExpression, new DescriptorKindFilter( DescriptorKindFilter.FUNCTIONS_MASK | DescriptorKindFilter.CLASSIFIERS_MASK, Collections.<DescriptorKindExclude>emptyList()), nameFilter, false, false); Collection<Pair<? extends DeclarationDescriptor, ResolutionFacade>> itemsToShow = new ArrayList<Pair<? extends DeclarationDescriptor, ResolutionFacade>>(); for (DeclarationDescriptor variant : variants) { if (variant instanceof FunctionDescriptor) { // todo: renamed functions? itemsToShow.add(Pair.create((FunctionDescriptor) variant, resolutionFacade)); } else if (variant instanceof ClassDescriptor) { // todo: renamed classes? for (ConstructorDescriptor constructorDescriptor : ((ClassDescriptor) variant).getConstructors()) { itemsToShow.add(Pair.create(constructorDescriptor, resolutionFacade)); } } } context.setItemsToShow(ArrayUtil.toObjectArray(itemsToShow)); return argumentList; }
@SuppressWarnings("TestOnlyProblems") @NotNull private static List<Diagnostic> getDebugInfoDiagnostics( @NotNull PsiElement root, @NotNull BindingContext bindingContext, final boolean markDynamicCalls, @Nullable final List<DeclarationDescriptor> dynamicCallDescriptors) { final List<Diagnostic> debugAnnotations = Lists.newArrayList(); DebugInfoUtil.markDebugAnnotations( root, bindingContext, new DebugInfoUtil.DebugInfoReporter() { @Override public void reportElementWithErrorType(@NotNull KtReferenceExpression expression) { newDiagnostic(expression, DebugInfoDiagnosticFactory.ELEMENT_WITH_ERROR_TYPE); } @Override public void reportMissingUnresolved(@NotNull KtReferenceExpression expression) { newDiagnostic(expression, DebugInfoDiagnosticFactory.MISSING_UNRESOLVED); } @Override public void reportUnresolvedWithTarget( @NotNull KtReferenceExpression expression, @NotNull String target) { newDiagnostic(expression, DebugInfoDiagnosticFactory.UNRESOLVED_WITH_TARGET); } @Override public void reportDynamicCall( @NotNull KtElement element, DeclarationDescriptor declarationDescriptor) { if (dynamicCallDescriptors != null) { dynamicCallDescriptors.add(declarationDescriptor); } if (markDynamicCalls) { newDiagnostic(element, DebugInfoDiagnosticFactory.DYNAMIC); } } private void newDiagnostic(KtElement element, DebugInfoDiagnosticFactory factory) { debugAnnotations.add(new DebugInfoDiagnostic(element, factory)); } }); // this code is used in tests and in internal action 'copy current file as diagnostic test' for (KtExpression expression : bindingContext.getSliceContents(BindingContext.SMARTCAST).keySet()) { if (PsiTreeUtil.isAncestor(root, expression, false)) { debugAnnotations.add( new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.SMARTCAST)); } } for (KtExpression expression : bindingContext.getSliceContents(BindingContext.IMPLICIT_RECEIVER_SMARTCAST).keySet()) { if (PsiTreeUtil.isAncestor(root, expression, false)) { debugAnnotations.add( new DebugInfoDiagnostic( expression, DebugInfoDiagnosticFactory.IMPLICIT_RECEIVER_SMARTCAST)); } } for (KtExpression expression : bindingContext.getSliceContents(BindingContext.SMARTCAST_NULL).keySet()) { if (PsiTreeUtil.isAncestor(root, expression, false)) { debugAnnotations.add( new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.CONSTANT)); } } for (KtExpression expression : bindingContext.getSliceContents(BindingContext.LEAKING_THIS).keySet()) { if (PsiTreeUtil.isAncestor(root, expression, false)) { debugAnnotations.add( new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.LEAKING_THIS)); } } for (KtWhenExpression expression : bindingContext.getSliceContents(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN).keySet()) { if (PsiTreeUtil.isAncestor(root, expression, false)) { debugAnnotations.add( new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.IMPLICIT_EXHAUSTIVE)); } } return debugAnnotations; }
@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; }