private SourceMemberMethodSymbol( NamedTypeSymbol containingType, TypeSymbol explicitInterfaceType, string name, Location location, MethodDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), // Prefer a block body if both exist syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location) { _name = name; _explicitInterfaceType = explicitInterfaceType; SyntaxTokenList modifiers = syntax.Modifiers; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; var firstParam = syntax.ParameterList.Parameters.FirstOrDefault(); bool isExtensionMethod = firstParam != null && !firstParam.IsArgList && firstParam.Modifiers.Any(SyntaxKind.ThisKeyword); bool modifierErrors; var declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors); var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers); _typeParameters = (syntax.Arity == 0) ? ImmutableArray<TypeParameterSymbol>.Empty : MakeTypeParameters(syntax, diagnostics); bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; if (hasBlockBody || _isExpressionBodied) { CheckModifiersForBody(location, diagnostics); } _refKind = syntax.RefKeyword.Kind().GetRefKind(); var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } }
private SourceMemberMethodSymbol( NamedTypeSymbol containingType, TypeSymbol explicitInterfaceType, string name, Location location, Binder bodyBinder, MethodDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), // Prefer a block body if both exist syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location) { _name = name; _explicitInterfaceType = explicitInterfaceType; SyntaxTokenList modifiers = syntax.Modifiers; // The following two values are used to compute and store the initial value of the flags // However, these two components are placeholders; the correct value will be // computed lazily later and then the flags will be fixed up. const bool returnsVoid = false; var firstParam = syntax.ParameterList.Parameters.FirstOrDefault(); bool isExtensionMethod = firstParam != null && !firstParam.IsArgList && firstParam.Modifiers.Any(SyntaxKind.ThisKeyword); bool modifierErrors; var declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors); var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers); // NOTE: by creating a WithMethodTypeParametersBinder, we are effectively duplicating the // functionality of the BinderFactory. Unfortunately, we cannot use the BinderFactory // because it depends on having access to the member list of our containing type and // that list cannot be complete because we're not finished constructing this member. // TODO: at least keep this in sync with BinderFactory.VisitMethodDeclaration. bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers); Binder withTypeParamsBinder; if (syntax.Arity == 0) { withTypeParamsBinder = bodyBinder; _typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } else { var parameterBinder = new WithMethodTypeParametersBinder(this, bodyBinder); withTypeParamsBinder = parameterBinder; _typeParameters = MakeTypeParameters(syntax, diagnostics); } bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; if (hasBlockBody || _isExpressionBodied) { CheckModifiersForBody(location, diagnostics); } var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers); if (info != null) { diagnostics.Add(info, location); } if (this.IsPartial) { // Partial methods must be completed early because they are matched up // by signature while producing the enclosing type's member list. However, // that means any type parameter constraints will be bound before the method // is added to the containing type. To enable binding of constraints before the // .ctor completes we hold on to the current binder while the .ctor is executing. // If we change the handling of partial methods, so that partial methods are // completed lazily, the 'constraintClauseBinder' field should be removed. _constraintClauseBinder = withTypeParamsBinder; state.NotePartComplete(CompletionPart.StartMethodChecks); MethodChecks(syntax, withTypeParamsBinder, diagnostics); state.NotePartComplete(CompletionPart.FinishMethodChecks); _constraintClauseBinder = null; } }