public static boolean isLocalNamedFun(DeclarationDescriptor fd) { if (fd instanceof FunctionDescriptor) { FunctionDescriptor descriptor = (FunctionDescriptor) fd; return descriptor.getVisibility() == Visibilities.LOCAL && !descriptor.getName().isSpecial(); } return false; }
private ClassDescriptor recordClassForFunction(FunctionDescriptor funDescriptor) { ClassDescriptor classDescriptor; int arity = funDescriptor.getValueParameters().size(); classDescriptor = new ClassDescriptorImpl( funDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Name.special("<closure>")); ((ClassDescriptorImpl) classDescriptor) .initialize( false, Collections.<TypeParameterDescriptor>emptyList(), Collections.singleton( (funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)) .getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null); assert PsiCodegenPredictor.checkPredictedClassNameForFun( bindingContext, funDescriptor, classDescriptor); bindingTrace.record(CLASS_FOR_FUNCTION, funDescriptor, classDescriptor); return classDescriptor; }
@NotNull public JetTypeInfo getSimpleNameExpressionTypeInfo( @NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context) { boolean[] result = new boolean[1]; TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(context.trace, "trace to resolve as variable", nameExpression); JetType type = getVariableType( nameExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result); if (result[0]) { traceForVariable.commit(); if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) { type = null; } return JetTypeInfo.create(type, context.dataFlowInfo); } Call call = CallMaker.makeCall( nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList()); TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", nameExpression); ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction( call, nameExpression, receiver, context, ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCache.create(), result); if (result[0]) { FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; traceForFunction.commit(); boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; context.trace.report( FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters)); type = functionDescriptor != null ? functionDescriptor.getReturnType() : null; return JetTypeInfo.create(type, context.dataFlowInfo); } traceForVariable.commit(); return JetTypeInfo.create(null, context.dataFlowInfo); }
@Override public void visitNamedFunction(JetNamedFunction function) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); // working around a problem with shallow analysis if (functionDescriptor == null) return; DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); if (containingDeclaration instanceof ClassDescriptor) { nameStack.push(peekFromStack(nameStack) + '$' + function.getName()); super.visitNamedFunction(function); nameStack.pop(); } else if (containingDeclaration instanceof NamespaceDescriptor) { String peek = peekFromStack(nameStack); if (peek.isEmpty()) { peek = JvmAbi.PACKAGE_CLASS; } else { peek += "/" + JvmAbi.PACKAGE_CLASS; } nameStack.push(peek + '$' + function.getName()); super.visitNamedFunction(function); nameStack.pop(); } else { String name = inventAnonymousClassName(function); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor); recordClosure( bindingTrace, function, classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), true); classStack.push(classDescriptor); nameStack.push(name); super.visitNamedFunction(function); nameStack.pop(); classStack.pop(); } }
@NotNull public TypeInfoForCall getCallExpressionTypeInfoForCallWithoutFinalTypeCheck( @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode) { boolean[] result = new boolean[1]; Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression); TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create( context.trace, "trace to resolve as function call", callExpression); ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction( call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), resolveMode, result); if (result[0]) { FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; traceForFunction.commit(); if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) { // there are only type arguments boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; context.trace.report( FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters)); } if (functionDescriptor == null) { return TypeInfoForCall.create(null, context.dataFlowInfo); } JetType type = functionDescriptor.getReturnType(); return TypeInfoForCall.create( type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context, resolveMode); } JetExpression calleeExpression = callExpression.getCalleeExpression(); if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) { TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create( context.trace, "trace to resolve as variable with 'invoke' call", callExpression); JetType type = getVariableType( (JetSimpleNameExpression) calleeExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result); if (result[0]) { traceForVariable.commit(); context.trace.report( FUNCTION_EXPECTED.on( (JetReferenceExpression) calleeExpression, calleeExpression, type != null ? type : ErrorUtils.createErrorType(""))); return TypeInfoForCall.create(null, context.dataFlowInfo); } } traceForFunction.commit(); return TypeInfoForCall.create(null, context.dataFlowInfo); }