@NotNull private MutableClassDescriptor createClassDescriptorForClass( @NotNull JetClass klass, @NotNull DeclarationDescriptor containingDeclaration) { ClassKind kind = getClassKind(klass); // Kind check is needed in order to not consider enums as inner in any case // (otherwise it would be impossible to create a class object in the enum) boolean isInner = kind == ClassKind.CLASS && klass.isInner(); MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor( containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName())); c.getClasses().put(klass, mutableClassDescriptor); trace.record( FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getUnsafeFQName(klass), mutableClassDescriptor); createClassObjectForEnumClass(mutableClassDescriptor); JetScope classScope = mutableClassDescriptor.getScopeForMemberDeclarationResolution(); prepareForDeferredCall(classScope, mutableClassDescriptor, klass); return mutableClassDescriptor; }
@Override public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) { if (declaration.isObjectLiteral()) { createClassDescriptorForSingleton( declaration, SpecialNames.NO_NAME_PROVIDED, ClassKind.CLASS); return; } MutableClassDescriptor descriptor = createClassDescriptorForSingleton( declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.OBJECT); owner.addClassifierDescriptor(descriptor); trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getUnsafeFQName(declaration), descriptor); descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor)); }
@Override public void visitEnumEntry(@NotNull JetEnumEntry declaration) { MutableClassDescriptor descriptor = createClassDescriptorForSingleton( declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.ENUM_ENTRY); owner.addClassifierDescriptor(descriptor); descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor)); }
@Override public void visitJetFile(JetFile file) { if (file.isScript()) { //noinspection ConstantConditions final ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_FUNCTION, bindingContext.get(SCRIPT, file.getScript())); classStack.push(classDescriptor); //noinspection ConstantConditions nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName()); } else { nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/')); } file.acceptChildren(this); nameStack.pop(); if (file.isScript()) { classStack.pop(); } }
@NotNull public static Collection<JetFile> allFilesInNamespaces( BindingContext bindingContext, Collection<JetFile> files) { // todo: we use Set and add given files but ignoring other scripts because something non-clear // kept in binding // for scripts especially in case of REPL HashSet<FqName> names = new HashSet<FqName>(); for (JetFile file : files) { if (!file.isScript()) { names.add(JetPsiUtil.getFQName(file)); } } HashSet<JetFile> answer = new HashSet<JetFile>(); answer.addAll(files); for (FqName name : names) { NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, name); Collection<JetFile> jetFiles = bindingContext.get(NAMESPACE_TO_FILES, namespaceDescriptor); if (jetFiles != null) answer.addAll(jetFiles); } List<JetFile> sortedAnswer = new ArrayList<JetFile>(answer); Collections.sort( sortedAnswer, new Comparator<JetFile>() { @NotNull private String path(JetFile file) { VirtualFile virtualFile = file.getVirtualFile(); assert virtualFile != null : "VirtualFile is null for JetFile: " + file.getName(); return virtualFile.getPath(); } @Override public int compare(JetFile first, JetFile second) { return path(first).compareTo(path(second)); } }); return sortedAnswer; }
@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); }