/// <summary> /// Returns a bag of applied custom attributes and data decoded from well-known attributes. Returns null if there are no attributes applied on the symbol. /// </summary> /// <remarks> /// Forces binding and decoding of attributes. /// </remarks> internal sealed override CustomAttributesBag <CSharpAttributeData> GetAttributesBag() { if (lazyCustomAttributesBag == null || !lazyCustomAttributesBag.IsSealed) { SourceParameterSymbol copyFrom = this.BoundAttributesSource; // prevent infinite recursion: Debug.Assert(!ReferenceEquals(copyFrom, this)); bool bagCreatedOnThisThread; if ((object)copyFrom != null) { var attributesBag = copyFrom.GetAttributesBag(); bagCreatedOnThisThread = Interlocked.CompareExchange(ref lazyCustomAttributesBag, attributesBag, null) == null; } else { var attributeSyntax = this.GetAttributeDeclarations(); bagCreatedOnThisThread = LoadAndValidateAttributes(attributeSyntax, ref lazyCustomAttributesBag); } if (bagCreatedOnThisThread) { state.NotePartComplete(CompletionPart.Attributes); } } return(lazyCustomAttributesBag); }
public SynthesizedRecordPropertySymbol( SourceMemberContainerTypeSymbol containingType, CSharpSyntaxNode syntax, ParameterSymbol backingParameter, bool isOverride, BindingDiagnosticBag diagnostics) : base( containingType, syntax: syntax, hasGetAccessor: true, hasSetAccessor: true, isExplicitInterfaceImplementation: false, explicitInterfaceType: null, aliasQualifierOpt: null, modifiers: DeclarationModifiers.Public | (isOverride ? DeclarationModifiers.Override : DeclarationModifiers.None), hasInitializer: true, // Synthesized record properties always have a synthesized initializer isAutoProperty: true, isExpressionBodied: false, isInitOnly: ShouldUseInit(containingType), RefKind.None, backingParameter.Name, indexerNameAttributeLists: new SyntaxList <AttributeListSyntax>(), backingParameter.Locations[0], diagnostics) { BackingParameter = (SourceParameterSymbol)backingParameter; }
internal SourceClonedParameterSymbol(SourceParameterSymbol originalParam, Symbol newOwner, int newOrdinal, bool suppressOptional) : base(newOwner, newOrdinal) { Debug.Assert((object)originalParam != null); _suppressOptional = suppressOptional; _originalParam = originalParam; }
public SynthesizedRecordPropertySymbol( SourceMemberContainerTypeSymbol containingType, CSharpSyntaxNode syntax, ParameterSymbol backingParameter, bool isOverride, DiagnosticBag diagnostics) : base( containingType, binder: null, syntax: syntax, getSyntax: syntax, setSyntax: syntax, arrowExpression: null, interfaceSpecifier: null, modifiers: DeclarationModifiers.Public | (isOverride ? DeclarationModifiers.Override : DeclarationModifiers.None), isIndexer: false, hasInitializer: true, // Synthesized record properties always have a synthesized initializer isAutoProperty: true, hasAccessorList: false, isInitOnly: true, RefKind.None, backingParameter.Name, backingParameter.Locations[0], typeOpt: backingParameter.TypeWithAnnotations, hasParameters: false, diagnostics) { BackingParameter = (SourceParameterSymbol)backingParameter; }
public static ImmutableArray <ParameterSymbol> MakeParameters( Binder binder, Symbol owner, BaseParameterListSyntax syntax, out SyntaxToken arglistToken, BindingDiagnosticBag diagnostics, bool allowRefOrOut, bool allowThis, bool addRefReadOnlyModifier ) { return(MakeParameters <ParameterSyntax, ParameterSymbol, Symbol>( binder, owner, syntax.Parameters, out arglistToken, diagnostics, allowRefOrOut, allowThis, addRefReadOnlyModifier, suppressUseSiteDiagnostics: false, lastIndex: syntax.Parameters.Count - 1, parameterCreationFunc: ( Binder context, Symbol owner, TypeWithAnnotations parameterType, ParameterSyntax syntax, RefKind refKind, int ordinal, SyntaxToken paramsKeyword, SyntaxToken thisKeyword, bool addRefReadOnlyModifier, BindingDiagnosticBag declarationDiagnostics ) => { return SourceParameterSymbol.Create( context, owner, parameterType, syntax, refKind, syntax.Identifier, ordinal, isParams: paramsKeyword.Kind() != SyntaxKind.None, isExtensionMethodThis: ordinal == 0 && thisKeyword.Kind() != SyntaxKind.None, addRefReadOnlyModifier, declarationDiagnostics ); } )); }
private static void ReportParameterErrors( Symbol owner, ParameterSyntax parameterSyntax, SourceParameterSymbol parameter, SyntaxToken thisKeyword, SyntaxToken paramsKeyword, int firstDefault, DiagnosticBag diagnostics) { TypeSymbol parameterType = parameter.Type; int parameterIndex = parameter.Ordinal; bool isDefault = parameterSyntax.Default != null; if (thisKeyword.Kind() == SyntaxKind.ThisKeyword && parameterIndex != 0) { // Report CS1100 on "this". Note that is a change from Dev10 // which reports the error on the type following "this". // error CS1100: Method '{0}' has a parameter modifier 'this' which is not on the first parameter diagnostics.Add(ErrorCode.ERR_BadThisParam, thisKeyword.GetLocation(), owner.Name); } else if (parameter.IsParams && owner.IsOperator()) { // error CS1670: params is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalParams, paramsKeyword.GetLocation()); } else if (parameter.IsParams && !parameterType.IsSZArray()) { // error CS0225: The params parameter must be a single dimensional array diagnostics.Add(ErrorCode.ERR_ParamsMustBeArray, paramsKeyword.GetLocation()); } else if (parameter.Type.IsStatic && !parameter.ContainingSymbol.ContainingType.IsInterfaceType()) { // error CS0721: '{0}': static types cannot be used as parameters diagnostics.Add(ErrorCode.ERR_ParameterIsStaticClass, owner.Locations[0], parameter.Type); } else if (firstDefault != -1 && parameterIndex > firstDefault && !isDefault && !parameter.IsParams) { // error CS1737: Optional parameters must appear after all required parameters Location loc = parameterSyntax.Identifier.GetNextToken(includeZeroWidth: true).GetLocation(); //could be missing diagnostics.Add(ErrorCode.ERR_DefaultValueBeforeRequiredValue, loc); } else if (parameter.RefKind != RefKind.None && parameter.Type.IsRestrictedType(ignoreSpanLikeTypes: true)) { // CS1601: Cannot make reference to variable of type 'System.TypedReference' diagnostics.Add(ErrorCode.ERR_MethodArgCantBeRefAny, parameterSyntax.Location, parameter.Type); } }
internal BackingField( SourceParameterSymbol parameterSymbol, DeclarationModifiers modifiers, bool modifierErrors, DiagnosticBag diagnostics) : base((SourceMemberContainerTypeSymbol)parameterSymbol.ContainingType) { this.parameterSymbol = parameterSymbol; this.modifiers = modifiers; this.CheckAccessibility(diagnostics); if (!modifierErrors) { this.ReportModifiersDiagnostics(diagnostics); } }
internal static bool ReportDefaultParameterErrors( Binder binder, Symbol owner, ParameterSyntax parameterSyntax, SourceParameterSymbol parameter, BoundExpression defaultExpression, DiagnosticBag diagnostics) { bool hasErrors = false; // SPEC VIOLATION: The spec says that the conversion from the initializer to the // parameter type is required to be either an identity or a nullable conversion, but // that is not right: // // void M(short myShort = 10) {} // * not an identity or nullable conversion but should be legal // // void M(object obj = (dynamic)null) {} // * an identity conversion, but should be illegal // // void M(MyStruct? myStruct = default(MyStruct)) {} // * a nullable conversion, but must be illegal because we cannot generate metadata for it // // Even if the expression is thoroughly illegal, we still want to bind it and // stick it in the parameter because we want to be able to analyze it for // IntelliSense purposes. TypeSymbol parameterType = parameter.Type; HashSet <DiagnosticInfo> useSiteDiagnostics = null; Conversion conversion = binder.Conversions.ClassifyImplicitConversionFromExpression(defaultExpression, parameterType, ref useSiteDiagnostics); diagnostics.Add(defaultExpression.Syntax, useSiteDiagnostics); SyntaxToken outKeyword; SyntaxToken refKeyword; SyntaxToken paramsKeyword; SyntaxToken thisKeyword; GetModifiers(parameterSyntax.Modifiers, out outKeyword, out refKeyword, out paramsKeyword, out thisKeyword); // CONSIDER: We are inconsistent here regarding where the error is reported; is it // CONSIDER: reported on the parameter name, or on the value of the initializer? // CONSIDER: Consider making this consistent. if (outKeyword.Kind() == SyntaxKind.OutKeyword) { // error CS1741: A ref or out parameter cannot have a default value diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, outKeyword.GetLocation()); hasErrors = true; } else if (refKeyword.Kind() == SyntaxKind.RefKeyword) { // error CS1741: A ref or out parameter cannot have a default value diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, refKeyword.GetLocation()); hasErrors = true; } else if (paramsKeyword.Kind() == SyntaxKind.ParamsKeyword) { // error CS1751: Cannot specify a default value for a parameter array diagnostics.Add(ErrorCode.ERR_DefaultValueForParamsParameter, paramsKeyword.GetLocation()); hasErrors = true; } else if (thisKeyword.Kind() == SyntaxKind.ThisKeyword) { // Only need to report CS1743 for the first parameter. The caller will // have reported CS1100 if 'this' appeared on another parameter. if (parameter.Ordinal == 0) { // error CS1743: Cannot specify a default value for the 'this' parameter diagnostics.Add(ErrorCode.ERR_DefaultValueForExtensionParameter, thisKeyword.GetLocation()); hasErrors = true; } } else if (!defaultExpression.HasAnyErrors && !IsValidDefaultValue(defaultExpression)) { // error CS1736: Default parameter value for '{0}' must be a compile-time constant diagnostics.Add(ErrorCode.ERR_DefaultValueMustBeConstant, parameterSyntax.Default.Value.Location, parameterSyntax.Identifier.ValueText); hasErrors = true; } else if (!conversion.Exists || conversion.IsUserDefined || conversion.IsIdentity && parameterType.SpecialType == SpecialType.System_Object && defaultExpression.Type.IsDynamic()) { // If we had no implicit conversion, or a user-defined conversion, report an error. // // Even though "object x = (dynamic)null" is a legal identity conversion, we do not allow it. // CONSIDER: We could. Doesn't hurt anything. // error CS1750: A value of type '{0}' cannot be used as a default parameter because there are no standard conversions to type '{1}' diagnostics.Add(ErrorCode.ERR_NoConversionForDefaultParam, parameterSyntax.Identifier.GetLocation(), defaultExpression.Type ?? defaultExpression.Display, parameterType); hasErrors = true; } else if (conversion.IsReference && (parameterType.SpecialType == SpecialType.System_Object || parameterType.Kind == SymbolKind.DynamicType) && (object)defaultExpression.Type != null && defaultExpression.Type.SpecialType == SpecialType.System_String || conversion.IsBoxing) { // We don't allow object x = "hello", object x = 123, dynamic x = "hello", etc. // error CS1763: '{0}' is of type '{1}'. A default parameter value of a reference type other than string can only be initialized with null diagnostics.Add(ErrorCode.ERR_NotNullRefDefaultParameter, parameterSyntax.Identifier.GetLocation(), parameterSyntax.Identifier.ValueText, parameterType); hasErrors = true; } else if (conversion.IsNullable && !defaultExpression.Type.IsNullableType() && !(parameterType.GetNullableUnderlyingType().IsEnumType() || parameterType.GetNullableUnderlyingType().IsIntrinsicType())) { // We can do: // M(int? x = default(int)) // M(int? x = default(int?)) // M(MyEnum? e = default(enum)) // M(MyEnum? e = default(enum?)) // M(MyStruct? s = default(MyStruct?)) // // but we cannot do: // // M(MyStruct? s = default(MyStruct)) // error CS1770: // A value of type '{0}' cannot be used as default parameter for nullable parameter '{1}' because '{0}' is not a simple type diagnostics.Add(ErrorCode.ERR_NoConversionForNubDefaultParam, parameterSyntax.Identifier.GetLocation(), defaultExpression.Type, parameterSyntax.Identifier.ValueText); hasErrors = true; } // Certain contexts allow default parameter values syntactically but they are ignored during // semantic analysis. They are: // 1. Explicitly implemented interface methods; since the method will always be called // via the interface, the defaults declared on the implementation will not // be seen at the call site. // // UNDONE: 2. The "actual" side of a partial method; the default values are taken from the // UNDONE: "declaring" side of the method. // // UNDONE: 3. An indexer with only one formal parameter; it is illegal to omit every argument // UNDONE: to an indexer. // // 4. A user-defined operator; it is syntactically impossible to omit the argument. if (owner.IsExplicitInterfaceImplementation() || owner.IsPartialImplementation() || owner.IsOperator()) { // CS1066: The default value specified for parameter '{0}' will have no effect because it applies to a // member that is used in contexts that do not allow optional arguments diagnostics.Add(ErrorCode.WRN_DefaultValueForUnconsumedLocation, parameterSyntax.Identifier.GetLocation(), parameterSyntax.Identifier.ValueText); } return(hasErrors); }
public static ImmutableArray <ParameterSymbol> MakeParameters( Binder binder, Symbol owner, BaseParameterListSyntax syntax, bool allowRefOrOut, out SyntaxToken arglistToken, DiagnosticBag diagnostics, bool beStrict) { arglistToken = default(SyntaxToken); int parameterIndex = 0; int firstDefault = -1; var builder = ArrayBuilder <ParameterSymbol> .GetInstance(); ImmutableArray <ParameterSymbol> parameters; foreach (var parameterSyntax in syntax.Parameters) { SyntaxToken outKeyword; SyntaxToken refKeyword; SyntaxToken paramsKeyword; SyntaxToken thisKeyword; var refKind = GetModifiers(parameterSyntax.Modifiers, out outKeyword, out refKeyword, out paramsKeyword, out thisKeyword); if (parameterSyntax.IsArgList) { arglistToken = parameterSyntax.Identifier; // The native compiler produces "Expected type" here, in the parser. Roslyn produces // the somewhat more informative "arglist not valid" error. if (paramsKeyword.Kind() != SyntaxKind.None || outKeyword.Kind() != SyntaxKind.None || refKeyword.Kind() != SyntaxKind.None || thisKeyword.Kind() != SyntaxKind.None) { // CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation()); } continue; } if (parameterSyntax.Default != null && firstDefault == -1) { firstDefault = parameterIndex; } Debug.Assert(parameterSyntax.Type != null); var parameterType = binder.BindType(parameterSyntax.Type, diagnostics); if (!allowRefOrOut && (refKind != RefKind.None)) { var outOrRefKeyword = (outKeyword.Kind() != SyntaxKind.None) ? outKeyword : refKeyword; Debug.Assert(outOrRefKeyword.Kind() != SyntaxKind.None); // error CS0631: ref and out are not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalRefParam, outOrRefKeyword.GetLocation()); } var parameter = SourceParameterSymbol.Create( binder, owner, parameterType, parameterSyntax, refKind, parameterSyntax.Identifier, parameterIndex, (paramsKeyword.Kind() != SyntaxKind.None), parameterIndex == 0 && thisKeyword.Kind() != SyntaxKind.None, diagnostics, beStrict); ReportParameterErrors(owner, parameterSyntax, parameter, firstDefault, diagnostics); builder.Add(parameter); ++parameterIndex; } parameters = builder.ToImmutableAndFree(); var methodOwner = owner as MethodSymbol; var typeParameters = (object)methodOwner != null ? methodOwner.TypeParameters : default(ImmutableArray <TypeParameterSymbol>); binder.ValidateParameterNameConflicts(typeParameters, parameters, diagnostics); return(parameters); }
private static void ReportParameterErrors( Symbol owner, ParameterSyntax parameterSyntax, SourceParameterSymbol parameter, int firstDefault, DiagnosticBag diagnostics) { TypeSymbol parameterType = parameter.Type; int parameterIndex = parameter.Ordinal; bool isDefault = parameterSyntax.Default != null; SyntaxToken thisKeyword = parameterSyntax.Modifiers.FirstOrDefault(SyntaxKind.ThisKeyword); if (thisKeyword.Kind() == SyntaxKind.ThisKeyword && parameterIndex != 0) { // Report CS1100 on "this". Note that is a change from Dev10 // which reports the error on the type following "this". // error CS1100: Method '{0}' has a parameter modifier 'this' which is not on the first parameter diagnostics.Add(ErrorCode.ERR_BadThisParam, thisKeyword.GetLocation(), owner.Name); } else if (parameter.IsParams && owner.IsOperator()) { // error CS1670: params is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalParams, parameterSyntax.Modifiers.First(t => t.Kind() == SyntaxKind.ParamsKeyword).GetLocation()); } else if (parameter.IsParams && !parameterType.IsSingleDimensionalArray()) { // error CS0225: The params parameter must be a single dimensional array diagnostics.Add(ErrorCode.ERR_ParamsMustBeArray, parameterSyntax.Modifiers.First(t => t.Kind() == SyntaxKind.ParamsKeyword).GetLocation()); } else if (parameter.Type.IsStatic && !parameter.ContainingSymbol.ContainingType.IsInterfaceType()) { // error CS0721: '{0}': static types cannot be used as parameters diagnostics.Add(ErrorCode.ERR_ParameterIsStaticClass, owner.Locations[0], parameter.Type); } else if (firstDefault != -1 && parameterIndex > firstDefault && !isDefault && !parameter.IsParams) { // error CS1737: Optional parameters must appear after all required parameters Location loc = parameterSyntax.Identifier.GetNextToken(includeZeroWidth: true).GetLocation(); //could be missing diagnostics.Add(ErrorCode.ERR_DefaultValueBeforeRequiredValue, loc); } else if (parameter.RefKind != RefKind.None && parameter.Type.IsRestrictedType()) { // CS1601: Cannot make reference to variable of type 'System.TypedReference' diagnostics.Add(ErrorCode.ERR_MethodArgCantBeRefAny, parameterSyntax.Location, parameter.Type); } }
internal static bool ReportDefaultParameterErrors( Binder binder, Symbol owner, ParameterSyntax parameterSyntax, SourceParameterSymbol parameter, BoundExpression defaultExpression, DiagnosticBag diagnostics) { bool hasErrors = false; // SPEC VIOLATION: The spec says that the conversion from the initializer to the // parameter type is required to be either an identity or a nullable conversion, but // that is not right: // // void M(short myShort = 10) {} // * not an identity or nullable conversion but should be legal // // void M(object obj = (dynamic)null) {} // * an identity conversion, but should be illegal // // void M(MyStruct? myStruct = default(MyStruct)) {} // * a nullable conversion, but must be illegal because we cannot generate metadata for it // // Even if the expression is thoroughly illegal, we still want to bind it and // stick it in the parameter because we want to be able to analyze it for // IntelliSense purposes. TypeSymbol parameterType = parameter.Type; HashSet<DiagnosticInfo> useSiteDiagnostics = null; Conversion conversion = binder.Conversions.ClassifyImplicitConversionFromExpression(defaultExpression, parameterType, ref useSiteDiagnostics); diagnostics.Add(defaultExpression.Syntax, useSiteDiagnostics); // SPEC VIOLATION: // By the spec an optional parameter initializer is required to be either: // * a constant, // * new S() where S is a value type // * default(S) where S is a value type. // // The native compiler considers default(T) to be a valid // initializer regardless of whether T is a value type // reference type, type parameter type, and so on. // We should consider simply allowing this in the spec. // // Also when valuetype S has a parameterless constructor, // new S() is clearly not a constant expression and should produce an error bool isValidDefaultValue = (defaultExpression.ConstantValue != null) || (defaultExpression.Kind == BoundKind.DefaultOperator) || (defaultExpression.Kind == BoundKind.ObjectCreationExpression && ((BoundObjectCreationExpression)defaultExpression).Constructor.IsDefaultValueTypeConstructor()); SyntaxToken outKeyword; SyntaxToken refKeyword; SyntaxToken paramsKeyword; SyntaxToken thisKeyword; GetModifiers(parameterSyntax.Modifiers, out outKeyword, out refKeyword, out paramsKeyword, out thisKeyword); // CONSIDER: We are inconsistent here regarding where the error is reported; is it // CONSIDER: reported on the parameter name, or on the value of the initializer? // CONSIDER: Consider making this consistent. if (outKeyword.Kind() == SyntaxKind.OutKeyword) { // error CS1741: A ref or out parameter cannot have a default value diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, outKeyword.GetLocation()); hasErrors = true; } else if (refKeyword.Kind() == SyntaxKind.RefKeyword) { // error CS1741: A ref or out parameter cannot have a default value diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, refKeyword.GetLocation()); hasErrors = true; } else if (paramsKeyword.Kind() == SyntaxKind.ParamsKeyword) { // error CS1751: Cannot specify a default value for a parameter array diagnostics.Add(ErrorCode.ERR_DefaultValueForParamsParameter, paramsKeyword.GetLocation()); hasErrors = true; } else if (thisKeyword.Kind() == SyntaxKind.ThisKeyword) { // Only need to report CS1743 for the first parameter. The caller will // have reported CS1100 if 'this' appeared on another parameter. if (parameter.Ordinal == 0) { // error CS1743: Cannot specify a default value for the 'this' parameter diagnostics.Add(ErrorCode.ERR_DefaultValueForExtensionParameter, thisKeyword.GetLocation()); hasErrors = true; } } else if (!defaultExpression.HasAnyErrors && !isValidDefaultValue) { // error CS1736: Default parameter value for '{0}' must be a compile-time constant diagnostics.Add(ErrorCode.ERR_DefaultValueMustBeConstant, parameterSyntax.Default.Value.Location, parameterSyntax.Identifier.ValueText); hasErrors = true; } else if (!conversion.Exists || conversion.IsUserDefined || conversion.IsIdentity && parameterType.SpecialType == SpecialType.System_Object && defaultExpression.Type.IsDynamic()) { // If we had no implicit conversion, or a user-defined conversion, report an error. // // Even though "object x = (dynamic)null" is a legal identity conversion, we do not allow it. // CONSIDER: We could. Doesn't hurt anything. // error CS1750: A value of type '{0}' cannot be used as a default parameter because there are no standard conversions to type '{1}' diagnostics.Add(ErrorCode.ERR_NoConversionForDefaultParam, parameterSyntax.Identifier.GetLocation(), defaultExpression.Type ?? defaultExpression.Display, parameterType); hasErrors = true; } else if (conversion.IsReference && (parameterType.SpecialType == SpecialType.System_Object || parameterType.Kind == SymbolKind.DynamicType) && (object)defaultExpression.Type != null && defaultExpression.Type.SpecialType == SpecialType.System_String || conversion.IsBoxing) { // We don't allow object x = "hello", object x = 123, dynamic x = "hello", etc. // error CS1763: '{0}' is of type '{1}'. A default parameter value of a reference type other than string can only be initialized with null diagnostics.Add(ErrorCode.ERR_NotNullRefDefaultParameter, parameterSyntax.Identifier.GetLocation(), parameterSyntax.Identifier.ValueText, parameterType); hasErrors = true; } else if (conversion.IsNullable && defaultExpression.Kind == BoundKind.DefaultOperator && !defaultExpression.Type.IsNullableType() && !(parameterType.GetNullableUnderlyingType().IsEnumType() || parameterType.GetNullableUnderlyingType().IsIntrinsicType())) { // We can do: // M(int? x = default(int)) // M(int? x = default(int?)) // M(MyEnum? e = default(enum)) // M(MyEnum? e = default(enum?)) // M(MyStruct? s = default(MyStruct?)) // // but we cannot do: // // M(MyStruct? s = default(MyStruct)) // error CS1770: // A value of type '{0}' cannot be used as default parameter for nullable parameter '{1}' because '{0}' is not a simple type diagnostics.Add(ErrorCode.ERR_NoConversionForNubDefaultParam, parameterSyntax.Identifier.GetLocation(), defaultExpression.Type, parameterSyntax.Identifier.ValueText); hasErrors = true; } // Certain contexts allow default parameter values syntactically but they are ignored during // semantic analysis. They are: // 1. Explicitly implemented interface methods; since the method will always be called // via the interface, the defaults declared on the implementation will not // be seen at the call site. // // UNDONE: 2. The "actual" side of a partial method; the default values are taken from the // UNDONE: "declaring" side of the method. // // UNDONE: 3. An indexer with only one formal parameter; it is illegal to omit every argument // UNDONE: to an indexer. // // 4. A user-defined operator; it is syntactically impossible to omit the argument. if (owner.IsExplicitInterfaceImplementation() || owner.IsPartialImplementation() || owner.IsOperator()) { // CS1066: The default value specified for parameter '{0}' will have no effect because it applies to a // member that is used in contexts that do not allow optional arguments diagnostics.Add(ErrorCode.WRN_DefaultValueForUnconsumedLocation, parameterSyntax.Identifier.GetLocation(), parameterSyntax.Identifier.ValueText); } return hasErrors; }
public static ImmutableArray <ParameterSymbol> MakeParameters( Binder binder, Symbol owner, BaseParameterListSyntax syntax, out SyntaxToken arglistToken, DiagnosticBag diagnostics, bool allowRefOrOut, bool allowThis, bool addRefReadOnlyModifier) { arglistToken = default(SyntaxToken); int parameterIndex = 0; int firstDefault = -1; var builder = ArrayBuilder <ParameterSymbol> .GetInstance(); var mustBeLastParameter = (ParameterSyntax)null; foreach (var parameterSyntax in syntax.Parameters) { if (mustBeLastParameter == null) { if (parameterSyntax.Modifiers.Any(SyntaxKind.ParamsKeyword) || parameterSyntax.Identifier.Kind() == SyntaxKind.ArgListKeyword) { mustBeLastParameter = parameterSyntax; } } CheckParameterModifiers(parameterSyntax, diagnostics); var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword); if (thisKeyword.Kind() != SyntaxKind.None && !allowThis) { diagnostics.Add(ErrorCode.ERR_ThisInBadContext, thisKeyword.GetLocation()); } if (parameterSyntax.IsArgList) { arglistToken = parameterSyntax.Identifier; // The native compiler produces "Expected type" here, in the parser. Roslyn produces // the somewhat more informative "arglist not valid" error. if (paramsKeyword.Kind() != SyntaxKind.None || refnessKeyword.Kind() != SyntaxKind.None || thisKeyword.Kind() != SyntaxKind.None) { // CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation()); } continue; } if (parameterSyntax.Default != null && firstDefault == -1) { firstDefault = parameterIndex; } Debug.Assert(parameterSyntax.Type != null); var parameterType = binder.BindType(parameterSyntax.Type, diagnostics); if (!allowRefOrOut && (refKind == RefKind.Ref || refKind == RefKind.Out)) { Debug.Assert(refnessKeyword.Kind() != SyntaxKind.None); // error CS0631: ref and out are not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalRefParam, refnessKeyword.GetLocation()); } var parameter = SourceParameterSymbol.Create( binder, owner, parameterType, parameterSyntax, refKind, parameterSyntax.Identifier, parameterIndex, (paramsKeyword.Kind() != SyntaxKind.None), parameterIndex == 0 && thisKeyword.Kind() != SyntaxKind.None, addRefReadOnlyModifier, diagnostics); ReportParameterErrors(owner, parameterSyntax, parameter, thisKeyword, paramsKeyword, firstDefault, diagnostics); builder.Add(parameter); ++parameterIndex; } if (mustBeLastParameter != null && mustBeLastParameter != syntax.Parameters.Last()) { diagnostics.Add( mustBeLastParameter.Identifier.Kind() == SyntaxKind.ArgListKeyword ? ErrorCode.ERR_VarargsLast : ErrorCode.ERR_ParamsLast, mustBeLastParameter.GetLocation()); } ImmutableArray <ParameterSymbol> parameters = builder.ToImmutableAndFree(); var methodOwner = owner as MethodSymbol; var typeParameters = (object)methodOwner != null ? methodOwner.TypeParameters : default(ImmutableArray <TypeParameterSymbol>); binder.ValidateParameterNameConflicts(typeParameters, parameters, diagnostics); return(parameters); }
internal SourcePropertyClonedParameterSymbolForAccessors(SourceParameterSymbol originalParam, Symbol newOwner) : base(originalParam, newOwner, originalParam.Ordinal, suppressOptional: false) { }
internal SourceDelegateClonedParameterSymbolForBeginAndEndInvoke(SourceParameterSymbol originalParam, SourceDelegateMethodSymbol newOwner, int newOrdinal) : base(originalParam, newOwner, newOrdinal, suppressOptional: true) { }