diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs index 016c4f2a3539..8758bf909e6f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs @@ -35,6 +35,7 @@ private ImmutableArray BindCrefInternal(CrefSyntax syntax, out Symbol? a case SyntaxKind.IndexerMemberCref: case SyntaxKind.OperatorMemberCref: case SyntaxKind.ConversionOperatorMemberCref: + case SyntaxKind.ExtensionMemberCref: return BindMemberCref((MemberCrefSyntax)syntax, containerOpt: null, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics); default: throw ExceptionUtilities.UnexpectedValue(syntax.Kind()); @@ -125,6 +126,9 @@ private ImmutableArray BindMemberCref(MemberCrefSyntax syntax, Namespace case SyntaxKind.ConversionOperatorMemberCref: result = BindConversionOperatorMemberCref((ConversionOperatorMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); break; + case SyntaxKind.ExtensionMemberCref: + result = BindExtensionMemberCref((ExtensionMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); + break; default: throw ExceptionUtilities.UnexpectedValue(syntax.Kind()); } @@ -216,6 +220,142 @@ private ImmutableArray BindIndexerMemberCref(IndexerMemberCrefSyntax syn diagnostics: diagnostics); } + private ImmutableArray BindExtensionMemberCref(ExtensionMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, BindingDiagnosticBag diagnostics) + { + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle extension operators + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureExtensions, diagnostics); + + if (containerOpt is not NamedTypeSymbol namedContainer) + { + ambiguityWinner = null; + return ImmutableArray.Empty; + } + + ImmutableArray sortedSymbols = default; + int arity = 0; + TypeArgumentListSyntax? typeArgumentListSyntax = null; + CrefParameterListSyntax? parameters = null; + + if (syntax.Member is NameMemberCrefSyntax { Name: SimpleNameSyntax simpleName } nameMember) + { + arity = simpleName.Arity; + typeArgumentListSyntax = simpleName is GenericNameSyntax genericName ? genericName.TypeArgumentList : null; + parameters = nameMember.Parameters; + + TypeArgumentListSyntax? extensionTypeArguments = syntax.TypeArgumentList; + int extensionArity = extensionTypeArguments?.Arguments.Count ?? 0; + sortedSymbols = computeSortedAndFilteredCrefExtensionMembers(namedContainer, simpleName.Identifier.ValueText, extensionArity, arity, extensionTypeArguments, diagnostics, syntax); + } + + if (sortedSymbols.IsDefaultOrEmpty) + { + ambiguityWinner = null; + return []; + } + + Debug.Assert(sortedSymbols.All(s => s.GetIsNewExtensionMember())); + + return ProcessCrefMemberLookupResults(sortedSymbols, arity, syntax, typeArgumentListSyntax, parameters, out ambiguityWinner, diagnostics); + + ImmutableArray computeSortedAndFilteredCrefExtensionMembers(NamedTypeSymbol container, string name, int extensionArity, int arity, TypeArgumentListSyntax? extensionTypeArguments, BindingDiagnosticBag diagnostics, ExtensionMemberCrefSyntax syntax) + { + Debug.Assert(name is not null); + + Debug.Assert(syntax.Parameters is not null); + ImmutableArray extensionParameterSymbols = BindCrefParameters(syntax.Parameters, diagnostics); + + // Use signature method symbols to match extension blocks + var providedExtensionSignature = new SignatureOnlyMethodSymbol( + methodKind: MethodKind.Ordinary, + typeParameters: IndexedTypeParameterSymbol.TakeSymbols(extensionArity), + parameters: extensionParameterSymbols, + callingConvention: Cci.CallingConvention.Default, + // These are ignored by this specific MemberSignatureComparer. + containingType: null, + name: null, + refKind: RefKind.None, + isInitOnly: false, + isStatic: false, + returnType: default, + refCustomModifiers: [], + explicitInterfaceImplementations: []); + + LookupOptions options = LookupOptions.AllMethodsOnArityZero | LookupOptions.MustNotBeParameter; + CompoundUseSiteInfo useSiteInfo = this.GetNewCompoundUseSiteInfo(diagnostics); + ArrayBuilder? sortedSymbolsBuilder = null; + + foreach (var nested in container.GetTypeMembers()) + { + if (!nested.IsExtension || nested.Arity != extensionArity || nested.ExtensionParameter is null) + { + continue; + } + + var constructedNested = (NamedTypeSymbol)ConstructWithCrefTypeParameters(extensionArity, extensionTypeArguments, nested); + + var candidateExtensionSignature = new SignatureOnlyMethodSymbol( + methodKind: MethodKind.Ordinary, + typeParameters: IndexedTypeParameterSymbol.TakeSymbols(constructedNested.Arity), + parameters: [constructedNested.ExtensionParameter], + callingConvention: Cci.CallingConvention.Default, + // These are ignored by this specific MemberSignatureComparer. + containingType: null, + name: null, + refKind: RefKind.None, + isInitOnly: false, + isStatic: false, + returnType: default, + refCustomModifiers: [], + explicitInterfaceImplementations: []); + + if (!MemberSignatureComparer.CrefComparer.Equals(candidateExtensionSignature, providedExtensionSignature)) + { + continue; + } + + var candidates = constructedNested.GetMembers(name); + + foreach (var candidate in candidates) + { + if (!SourceMemberContainerTypeSymbol.IsAllowedExtensionMember(candidate)) + { + continue; + } + + if (arity != 0 && candidate.GetArity() != arity) + { + continue; + } + + // Note: we bypass the arity check here, as it would check for total arity (extension + member arity) + SingleLookupResult result = this.CheckViability(candidate, arity: 0, options, accessThroughType: null, diagnose: true, useSiteInfo: ref useSiteInfo); + + if (result.Kind == LookupResultKind.Viable) + { + sortedSymbolsBuilder ??= ArrayBuilder.GetInstance(); + sortedSymbolsBuilder.Add(result.Symbol); + } + } + } + + diagnostics.Add(syntax, useSiteInfo); + + if (sortedSymbolsBuilder is null) + { + return ImmutableArray.Empty; + } + + // Since we resolve ambiguities by just picking the first symbol we encounter, + // the order of the symbols matters for repeatability. + if (sortedSymbolsBuilder.Count > 1) + { + sortedSymbolsBuilder.Sort(ConsistentSymbolOrder.Instance); + } + + return sortedSymbolsBuilder.ToImmutableAndFree(); + } + } + // NOTE: not guaranteed to be a method (e.g. class op_Addition) // NOTE: constructor fallback logic applies private ImmutableArray BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, BindingDiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs b/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs index 92a84b73a5f3..556e32c56212 100644 --- a/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs @@ -90,7 +90,7 @@ private void AddTypeParameters(TypeSyntax typeSyntax, MultiDictionary map) { // Other members have arity 0. - if (memberSyntax.Kind() == SyntaxKind.NameMemberCref) + if (memberSyntax is NameMemberCrefSyntax nameMemberCref) { - AddTypeParameters(((NameMemberCrefSyntax)memberSyntax).Name, map); + AddTypeParameters(nameMemberCref.Name, map); + } + else if (memberSyntax is ExtensionMemberCrefSyntax extensionCref) + { + if (extensionCref.TypeArgumentList is { } extensionTypeArguments) + { + AddTypeParameters(extensionTypeArguments.Arguments, map); + } + + AddTypeParameters(extensionCref.Member, map); } } - private static void AddTypeParameters(GenericNameSyntax genericNameSyntax, MultiDictionary map) + private static void AddTypeParameters(SeparatedSyntaxList typeArguments, MultiDictionary map) { // NOTE: Dev11 does not warn about duplication, it just matches parameter types to the // *last* type parameter with the same name. That's why we're iterating backwards and // skipping subsequent symbols with the same name. This can result in some surprising // behavior. For example, both 'T's in "A.B" bind to the second implicitly // declared type parameter. - SeparatedSyntaxList typeArguments = genericNameSyntax.TypeArgumentList.Arguments; for (int i = typeArguments.Count - 1; i >= 0; i--) { // Other types (non-identifiers) are allowed in error scenarios, but they do not introduce new diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 97469f1d42c3..ced190df6106 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8096,7 +8096,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Extension declarations may not have a name. - Extension declarations can include only methods or properties + This member is not allowed in an extension block Extensions must be declared in a top-level, non-generic, static class @@ -8185,4 +8185,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ '#!' directives can be only used in scripts or file-based programs + + An extension member syntax is disallowed in nested position within an extension member syntax + diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 43c04974b81e..dcdc84c7f670 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -357,6 +357,8 @@ internal static bool HasParameterList(CrefSyntax crefSyntax) return ((OperatorMemberCrefSyntax)crefSyntax).Parameters != null; case SyntaxKind.ConversionOperatorMemberCref: return ((ConversionOperatorMemberCrefSyntax)crefSyntax).Parameters != null; + case SyntaxKind.ExtensionMemberCref: + return HasParameterList(((ExtensionMemberCrefSyntax)crefSyntax).Member); } return false; @@ -379,7 +381,7 @@ private static SymbolInfo GetCrefSymbolInfo(OneOrMany symbols, SymbolInf LookupResultKind resultKind = LookupResultKind.Ambiguous; - // The boundary between Ambiguous and OverloadResolutionFailure is let clear-cut for crefs. + // The boundary between Ambiguous and OverloadResolutionFailure is less clear-cut for crefs. // We'll say that overload resolution failed if the syntax has a parameter list and if // all of the candidates have the same kind. SymbolKind firstCandidateKind = symbols[0].Kind; diff --git a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.DocumentationCommentWalker.cs b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.DocumentationCommentWalker.cs index aec71992eb36..ee86d7b37e3b 100644 --- a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.DocumentationCommentWalker.cs +++ b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.DocumentationCommentWalker.cs @@ -151,7 +151,7 @@ public override void DefaultVisit(SyntaxNode node) // Do this for the diagnostics, even if it won't be written. BindingDiagnosticBag diagnostics = diagnose ? _diagnostics : BindingDiagnosticBag.GetInstance(withDiagnostics: false, withDependencies: _diagnostics.AccumulatesDependencies); - string docCommentId = GetDocumentationCommentId(cref, binder, diagnostics); + string docCommentId = GetEscapedDocumentationCommentId(cref, binder, diagnostics); if (!diagnose) { diff --git a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.IncludeElementExpander.cs b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.IncludeElementExpander.cs index 0b080f41b9b4..7ff296cff9a5 100644 --- a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.IncludeElementExpander.cs +++ b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.IncludeElementExpander.cs @@ -516,7 +516,7 @@ private void BindAndReplaceCref(XAttribute attribute, CSharpSyntaxNode originati Binder binder = BinderFactory.MakeCrefBinder(crefSyntax, memberDeclSyntax, _compilation.GetBinderFactory(memberDeclSyntax.SyntaxTree)); var crefDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics); - attribute.Value = GetDocumentationCommentId(crefSyntax, binder, crefDiagnostics); // NOTE: mutation (element must be a copy) + attribute.Value = GetEscapedDocumentationCommentId(crefSyntax, binder, crefDiagnostics); // NOTE: mutation (element must be a copy) RecordBindingDiagnostics(crefDiagnostics, sourceLocation); // Respects DocumentationMode. crefDiagnostics.Free(); } diff --git a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs index 826201c5177f..2d408b4c095e 100644 --- a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs @@ -251,9 +251,9 @@ public override void VisitMethod(MethodSymbol symbol) return; } - WriteLine("", symbol.GetDocumentationCommentId()); + WriteLine("", symbol.GetEscapedDocumentationCommentId()); Indent(); - WriteLine("", symbolForDocComment.GetDocumentationCommentId()); + WriteLine("", symbolForDocComment.GetEscapedDocumentationCommentId()); Unindent(); WriteLine(""); return; @@ -331,7 +331,7 @@ public override void DefaultVisit(Symbol symbol) // If the XML in any of the doc comments is invalid, skip all further processing (for this symbol) and // just write a comment saying that info was lost for this symbol. string message = ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED, CultureInfo.CurrentUICulture); - WriteLine(string.Format(CultureInfo.CurrentUICulture, message, symbol.GetDocumentationCommentId())); + WriteLine(string.Format(CultureInfo.CurrentUICulture, message, symbol.GetEscapedDocumentationCommentId())); return; } @@ -381,7 +381,7 @@ public override void DefaultVisit(Symbol symbol) // If the XML in any of the doc comments is invalid, skip all further processing (for this symbol) and // just write a comment saying that info was lost for this symbol. string message = ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED, CultureInfo.CurrentUICulture); - WriteLine(string.Format(CultureInfo.CurrentUICulture, message, symbol.GetDocumentationCommentId())); + WriteLine(string.Format(CultureInfo.CurrentUICulture, message, symbol.GetEscapedDocumentationCommentId())); return; } @@ -467,7 +467,7 @@ private bool TryProcessRecordPropertyDocumentation( Debug.Assert(paramTags.Count > 0); BeginTemporaryString(); - WriteLine("", recordPropertySymbol.GetDocumentationCommentId()); + WriteLine("", recordPropertySymbol.GetEscapedDocumentationCommentId()); Indent(); var substitutedTextBuilder = PooledStringBuilder.GetInstance(); var includeElementNodesBuilder = _processIncludes ? ArrayBuilder.GetInstance() : null; @@ -573,7 +573,7 @@ private bool TryProcessDocumentationCommentTriviaNodes( // because we need to have XML to process. if (!shouldSkipPartialDefinitionComments || _processIncludes) { - WriteLine("", symbol.GetDocumentationCommentId()); + WriteLine("", symbol.GetEscapedDocumentationCommentId()); Indent(); } @@ -1096,7 +1096,7 @@ private static string LongestCommonPrefix(string str1, string str2) /// /// Does not respect DocumentationMode, so use a temporary bag if diagnostics are not desired. /// - private static string GetDocumentationCommentId(CrefSyntax crefSyntax, Binder binder, BindingDiagnosticBag diagnostics) + private static string GetEscapedDocumentationCommentId(CrefSyntax crefSyntax, Binder binder, BindingDiagnosticBag diagnostics) { if (crefSyntax.ContainsDiagnostics) { @@ -1135,7 +1135,7 @@ private static string GetDocumentationCommentId(CrefSyntax crefSyntax, Binder bi diagnostics.AddDependencies(symbol as TypeSymbol ?? symbol.ContainingType); } - return symbol.OriginalDefinition.GetDocumentationCommentId(); + return symbol.OriginalDefinition.GetEscapedDocumentationCommentId(); } /// diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7211e43d60c8..3db0d158c3a6 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2400,7 +2400,7 @@ internal enum ErrorCode ERR_ExpressionTreeContainsNamedArgumentOutOfPosition = 9307, ERR_OperatorsMustBePublic = 9308, - // available 9309, + ERR_MisplacedExtension = 9309, ERR_OperatorMustReturnVoid = 9310, ERR_CloseUnimplementedInterfaceMemberOperatorMismatch = 9311, ERR_OperatorMismatchOnOverride = 9312, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 278cbd4318a8..3b7d348d0663 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -830,6 +830,7 @@ or ErrorCode.ERR_PartialWrongTypeParams or ErrorCode.ERR_PartialWrongConstraints or ErrorCode.ERR_NoImplicitConvCast or ErrorCode.ERR_PartialMisplaced + or ErrorCode.ERR_MisplacedExtension or ErrorCode.ERR_ImportedCircularBase or ErrorCode.ERR_UseDefViolationOut or ErrorCode.ERR_ArraySizeInDeclaration diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 index 400f6265ade9..bb1e25cc3677 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 +++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 @@ -1198,6 +1198,7 @@ cref member_cref : conversion_operator_member_cref + | extension_member_cref | indexer_member_cref | name_member_cref | operator_member_cref @@ -1218,6 +1219,10 @@ cref_parameter | 'ref'? 'readonly'? type ; +extension_member_cref + : 'extension' type_argument_list? cref_parameter_list '.' member_cref + ; + indexer_member_cref : 'this' cref_bracketed_parameter_list? ; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index c6b5f5f828db..9c702233d40a 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -22659,6 +22659,118 @@ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) => new NameMemberCrefSyntax(this.Kind, this.name, this.parameters, GetDiagnostics(), annotations); } +internal sealed partial class ExtensionMemberCrefSyntax : MemberCrefSyntax +{ + internal readonly SyntaxToken extensionKeyword; + internal readonly TypeArgumentListSyntax? typeArgumentList; + internal readonly CrefParameterListSyntax parameters; + internal readonly SyntaxToken dotToken; + internal readonly MemberCrefSyntax member; + + internal ExtensionMemberCrefSyntax(SyntaxKind kind, SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + : base(kind, diagnostics, annotations) + { + this.SlotCount = 5; + this.AdjustFlagsAndWidth(extensionKeyword); + this.extensionKeyword = extensionKeyword; + if (typeArgumentList != null) + { + this.AdjustFlagsAndWidth(typeArgumentList); + this.typeArgumentList = typeArgumentList; + } + this.AdjustFlagsAndWidth(parameters); + this.parameters = parameters; + this.AdjustFlagsAndWidth(dotToken); + this.dotToken = dotToken; + this.AdjustFlagsAndWidth(member); + this.member = member; + } + + internal ExtensionMemberCrefSyntax(SyntaxKind kind, SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member, SyntaxFactoryContext context) + : base(kind) + { + this.SetFactoryContext(context); + this.SlotCount = 5; + this.AdjustFlagsAndWidth(extensionKeyword); + this.extensionKeyword = extensionKeyword; + if (typeArgumentList != null) + { + this.AdjustFlagsAndWidth(typeArgumentList); + this.typeArgumentList = typeArgumentList; + } + this.AdjustFlagsAndWidth(parameters); + this.parameters = parameters; + this.AdjustFlagsAndWidth(dotToken); + this.dotToken = dotToken; + this.AdjustFlagsAndWidth(member); + this.member = member; + } + + internal ExtensionMemberCrefSyntax(SyntaxKind kind, SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + : base(kind) + { + this.SlotCount = 5; + this.AdjustFlagsAndWidth(extensionKeyword); + this.extensionKeyword = extensionKeyword; + if (typeArgumentList != null) + { + this.AdjustFlagsAndWidth(typeArgumentList); + this.typeArgumentList = typeArgumentList; + } + this.AdjustFlagsAndWidth(parameters); + this.parameters = parameters; + this.AdjustFlagsAndWidth(dotToken); + this.dotToken = dotToken; + this.AdjustFlagsAndWidth(member); + this.member = member; + } + + public SyntaxToken ExtensionKeyword => this.extensionKeyword; + public TypeArgumentListSyntax? TypeArgumentList => this.typeArgumentList; + public CrefParameterListSyntax Parameters => this.parameters; + public SyntaxToken DotToken => this.dotToken; + public MemberCrefSyntax Member => this.member; + + internal override GreenNode? GetSlot(int index) + => index switch + { + 0 => this.extensionKeyword, + 1 => this.typeArgumentList, + 2 => this.parameters, + 3 => this.dotToken, + 4 => this.member, + _ => null, + }; + + internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.ExtensionMemberCrefSyntax(this, parent, position); + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitExtensionMemberCref(this); + public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitExtensionMemberCref(this); + + public ExtensionMemberCrefSyntax Update(SyntaxToken extensionKeyword, TypeArgumentListSyntax typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + { + if (extensionKeyword != this.ExtensionKeyword || typeArgumentList != this.TypeArgumentList || parameters != this.Parameters || dotToken != this.DotToken || member != this.Member) + { + var newNode = SyntaxFactory.ExtensionMemberCref(extensionKeyword, typeArgumentList, parameters, dotToken, member); + var diags = GetDiagnostics(); + if (diags?.Length > 0) + newNode = newNode.WithDiagnosticsGreen(diags); + var annotations = GetAnnotations(); + if (annotations?.Length > 0) + newNode = newNode.WithAnnotationsGreen(annotations); + return newNode; + } + + return this; + } + + internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) + => new ExtensionMemberCrefSyntax(this.Kind, this.extensionKeyword, this.typeArgumentList, this.parameters, this.dotToken, this.member, diagnostics, GetAnnotations()); + + internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) + => new ExtensionMemberCrefSyntax(this.Kind, this.extensionKeyword, this.typeArgumentList, this.parameters, this.dotToken, this.member, GetDiagnostics(), annotations); +} + /// /// A MemberCrefSyntax specified by a this keyword and an optional parameter list. /// For example, "this" or "this[int]". @@ -27037,6 +27149,7 @@ internal partial class CSharpSyntaxVisitor public virtual TResult VisitTypeCref(TypeCrefSyntax node) => this.DefaultVisit(node); public virtual TResult VisitQualifiedCref(QualifiedCrefSyntax node) => this.DefaultVisit(node); public virtual TResult VisitNameMemberCref(NameMemberCrefSyntax node) => this.DefaultVisit(node); + public virtual TResult VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) => this.DefaultVisit(node); public virtual TResult VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => this.DefaultVisit(node); public virtual TResult VisitOperatorMemberCref(OperatorMemberCrefSyntax node) => this.DefaultVisit(node); public virtual TResult VisitConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax node) => this.DefaultVisit(node); @@ -27287,6 +27400,7 @@ internal partial class CSharpSyntaxVisitor public virtual void VisitTypeCref(TypeCrefSyntax node) => this.DefaultVisit(node); public virtual void VisitQualifiedCref(QualifiedCrefSyntax node) => this.DefaultVisit(node); public virtual void VisitNameMemberCref(NameMemberCrefSyntax node) => this.DefaultVisit(node); + public virtual void VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) => this.DefaultVisit(node); public virtual void VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => this.DefaultVisit(node); public virtual void VisitOperatorMemberCref(OperatorMemberCrefSyntax node) => this.DefaultVisit(node); public virtual void VisitConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax node) => this.DefaultVisit(node); @@ -27949,6 +28063,9 @@ public override CSharpSyntaxNode VisitQualifiedCref(QualifiedCrefSyntax node) public override CSharpSyntaxNode VisitNameMemberCref(NameMemberCrefSyntax node) => node.Update((TypeSyntax)Visit(node.Name), (CrefParameterListSyntax)Visit(node.Parameters)); + public override CSharpSyntaxNode VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) + => node.Update((SyntaxToken)Visit(node.ExtensionKeyword), (TypeArgumentListSyntax)Visit(node.TypeArgumentList), (CrefParameterListSyntax)Visit(node.Parameters), (SyntaxToken)Visit(node.DotToken), (MemberCrefSyntax)Visit(node.Member)); + public override CSharpSyntaxNode VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => node.Update((SyntaxToken)Visit(node.ThisKeyword), (CrefBracketedParameterListSyntax)Visit(node.Parameters)); @@ -32593,6 +32710,20 @@ public NameMemberCrefSyntax NameMemberCref(TypeSyntax name, CrefParameterListSyn return result; } + public ExtensionMemberCrefSyntax ExtensionMemberCref(SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + { +#if DEBUG + if (extensionKeyword == null) throw new ArgumentNullException(nameof(extensionKeyword)); + if (extensionKeyword.Kind != SyntaxKind.ExtensionKeyword) throw new ArgumentException(nameof(extensionKeyword)); + if (parameters == null) throw new ArgumentNullException(nameof(parameters)); + if (dotToken == null) throw new ArgumentNullException(nameof(dotToken)); + if (dotToken.Kind != SyntaxKind.DotToken) throw new ArgumentException(nameof(dotToken)); + if (member == null) throw new ArgumentNullException(nameof(member)); +#endif + + return new ExtensionMemberCrefSyntax(SyntaxKind.ExtensionMemberCref, extensionKeyword, typeArgumentList, parameters, dotToken, member, this.context); + } + public IndexerMemberCrefSyntax IndexerMemberCref(SyntaxToken thisKeyword, CrefBracketedParameterListSyntax? parameters) { #if DEBUG @@ -37946,6 +38077,20 @@ public static NameMemberCrefSyntax NameMemberCref(TypeSyntax name, CrefParameter return result; } + public static ExtensionMemberCrefSyntax ExtensionMemberCref(SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + { +#if DEBUG + if (extensionKeyword == null) throw new ArgumentNullException(nameof(extensionKeyword)); + if (extensionKeyword.Kind != SyntaxKind.ExtensionKeyword) throw new ArgumentException(nameof(extensionKeyword)); + if (parameters == null) throw new ArgumentNullException(nameof(parameters)); + if (dotToken == null) throw new ArgumentNullException(nameof(dotToken)); + if (dotToken.Kind != SyntaxKind.DotToken) throw new ArgumentException(nameof(dotToken)); + if (member == null) throw new ArgumentNullException(nameof(member)); +#endif + + return new ExtensionMemberCrefSyntax(SyntaxKind.ExtensionMemberCref, extensionKeyword, typeArgumentList, parameters, dotToken, member); + } + public static IndexerMemberCrefSyntax IndexerMemberCref(SyntaxToken thisKeyword, CrefBracketedParameterListSyntax? parameters) { #if DEBUG diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 4ebe1affaa52..2b899f831891 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -633,6 +633,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a NameMemberCrefSyntax node. public virtual TResult? VisitNameMemberCref(NameMemberCrefSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ExtensionMemberCrefSyntax node. + public virtual TResult? VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a IndexerMemberCrefSyntax node. public virtual TResult? VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => this.DefaultVisit(node); @@ -1374,6 +1377,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a NameMemberCrefSyntax node. public virtual void VisitNameMemberCref(NameMemberCrefSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a ExtensionMemberCrefSyntax node. + public virtual void VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a IndexerMemberCrefSyntax node. public virtual void VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => this.DefaultVisit(node); @@ -2115,6 +2121,9 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor public override SyntaxNode? VisitNameMemberCref(NameMemberCrefSyntax node) => node.Update((TypeSyntax?)Visit(node.Name) ?? throw new ArgumentNullException("name"), (CrefParameterListSyntax?)Visit(node.Parameters)); + public override SyntaxNode? VisitExtensionMemberCref(ExtensionMemberCrefSyntax node) + => node.Update(VisitToken(node.ExtensionKeyword), (TypeArgumentListSyntax?)Visit(node.TypeArgumentList), (CrefParameterListSyntax?)Visit(node.Parameters) ?? throw new ArgumentNullException("parameters"), VisitToken(node.DotToken), (MemberCrefSyntax?)Visit(node.Member) ?? throw new ArgumentNullException("member")); + public override SyntaxNode? VisitIndexerMemberCref(IndexerMemberCrefSyntax node) => node.Update(VisitToken(node.ThisKeyword), (CrefBracketedParameterListSyntax?)Visit(node.Parameters)); @@ -5860,6 +5869,24 @@ public static NameMemberCrefSyntax NameMemberCref(TypeSyntax name, CrefParameter public static NameMemberCrefSyntax NameMemberCref(TypeSyntax name) => SyntaxFactory.NameMemberCref(name, default); + /// Creates a new ExtensionMemberCrefSyntax instance. + public static ExtensionMemberCrefSyntax ExtensionMemberCref(SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + { + if (extensionKeyword.Kind() != SyntaxKind.ExtensionKeyword) throw new ArgumentException(nameof(extensionKeyword)); + if (parameters == null) throw new ArgumentNullException(nameof(parameters)); + if (dotToken.Kind() != SyntaxKind.DotToken) throw new ArgumentException(nameof(dotToken)); + if (member == null) throw new ArgumentNullException(nameof(member)); + return (ExtensionMemberCrefSyntax)Syntax.InternalSyntax.SyntaxFactory.ExtensionMemberCref((Syntax.InternalSyntax.SyntaxToken)extensionKeyword.Node!, typeArgumentList == null ? null : (Syntax.InternalSyntax.TypeArgumentListSyntax)typeArgumentList.Green, (Syntax.InternalSyntax.CrefParameterListSyntax)parameters.Green, (Syntax.InternalSyntax.SyntaxToken)dotToken.Node!, (Syntax.InternalSyntax.MemberCrefSyntax)member.Green).CreateRed(); + } + + /// Creates a new ExtensionMemberCrefSyntax instance. + public static ExtensionMemberCrefSyntax ExtensionMemberCref(TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, MemberCrefSyntax member) + => SyntaxFactory.ExtensionMemberCref(SyntaxFactory.Token(SyntaxKind.ExtensionKeyword), typeArgumentList, parameters, SyntaxFactory.Token(SyntaxKind.DotToken), member); + + /// Creates a new ExtensionMemberCrefSyntax instance. + public static ExtensionMemberCrefSyntax ExtensionMemberCref(MemberCrefSyntax member) + => SyntaxFactory.ExtensionMemberCref(SyntaxFactory.Token(SyntaxKind.ExtensionKeyword), default, SyntaxFactory.CrefParameterList(), SyntaxFactory.Token(SyntaxKind.DotToken), member); + /// Creates a new IndexerMemberCrefSyntax instance. public static IndexerMemberCrefSyntax IndexerMemberCref(SyntaxToken thisKeyword, CrefBracketedParameterListSyntax? parameters) { diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index c5074d1c316d..3f8e74385bdf 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -14288,6 +14288,80 @@ public NameMemberCrefSyntax AddParametersParameters(params CrefParameterSyntax[] } } +/// +/// This node is associated with the following syntax kinds: +/// +/// +/// +/// +public sealed partial class ExtensionMemberCrefSyntax : MemberCrefSyntax +{ + private TypeArgumentListSyntax? typeArgumentList; + private CrefParameterListSyntax? parameters; + private MemberCrefSyntax? member; + + internal ExtensionMemberCrefSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) + : base(green, parent, position) + { + } + + public SyntaxToken ExtensionKeyword => new SyntaxToken(this, ((InternalSyntax.ExtensionMemberCrefSyntax)this.Green).extensionKeyword, Position, 0); + + public TypeArgumentListSyntax? TypeArgumentList => GetRed(ref this.typeArgumentList, 1); + + public CrefParameterListSyntax Parameters => GetRed(ref this.parameters, 2)!; + + public SyntaxToken DotToken => new SyntaxToken(this, ((InternalSyntax.ExtensionMemberCrefSyntax)this.Green).dotToken, GetChildPosition(3), GetChildIndex(3)); + + public MemberCrefSyntax Member => GetRed(ref this.member, 4)!; + + internal override SyntaxNode? GetNodeSlot(int index) + => index switch + { + 1 => GetRed(ref this.typeArgumentList, 1), + 2 => GetRed(ref this.parameters, 2)!, + 4 => GetRed(ref this.member, 4)!, + _ => null, + }; + + internal override SyntaxNode? GetCachedSlot(int index) + => index switch + { + 1 => this.typeArgumentList, + 2 => this.parameters, + 4 => this.member, + _ => null, + }; + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitExtensionMemberCref(this); + public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitExtensionMemberCref(this); + + public ExtensionMemberCrefSyntax Update(SyntaxToken extensionKeyword, TypeArgumentListSyntax? typeArgumentList, CrefParameterListSyntax parameters, SyntaxToken dotToken, MemberCrefSyntax member) + { + if (extensionKeyword != this.ExtensionKeyword || typeArgumentList != this.TypeArgumentList || parameters != this.Parameters || dotToken != this.DotToken || member != this.Member) + { + var newNode = SyntaxFactory.ExtensionMemberCref(extensionKeyword, typeArgumentList, parameters, dotToken, member); + var annotations = GetAnnotations(); + return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; + } + + return this; + } + + public ExtensionMemberCrefSyntax WithExtensionKeyword(SyntaxToken extensionKeyword) => Update(extensionKeyword, this.TypeArgumentList, this.Parameters, this.DotToken, this.Member); + public ExtensionMemberCrefSyntax WithTypeArgumentList(TypeArgumentListSyntax? typeArgumentList) => Update(this.ExtensionKeyword, typeArgumentList, this.Parameters, this.DotToken, this.Member); + public ExtensionMemberCrefSyntax WithParameters(CrefParameterListSyntax parameters) => Update(this.ExtensionKeyword, this.TypeArgumentList, parameters, this.DotToken, this.Member); + public ExtensionMemberCrefSyntax WithDotToken(SyntaxToken dotToken) => Update(this.ExtensionKeyword, this.TypeArgumentList, this.Parameters, dotToken, this.Member); + public ExtensionMemberCrefSyntax WithMember(MemberCrefSyntax member) => Update(this.ExtensionKeyword, this.TypeArgumentList, this.Parameters, this.DotToken, member); + + public ExtensionMemberCrefSyntax AddTypeArgumentListArguments(params TypeSyntax[] items) + { + var typeArgumentList = this.TypeArgumentList ?? SyntaxFactory.TypeArgumentList(); + return WithTypeArgumentList(typeArgumentList.WithArguments(typeArgumentList.Arguments.AddRange(items))); + } + public ExtensionMemberCrefSyntax AddParametersParameters(params CrefParameterSyntax[] items) => WithParameters(this.Parameters.WithParameters(this.Parameters.Parameters.AddRange(items))); +} + /// /// A MemberCrefSyntax specified by a this keyword and an optional parameter list. /// For example, "this" or "this[int]". diff --git a/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs b/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs index e058696bd3cb..e5417a5f08f5 100644 --- a/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs @@ -946,6 +946,8 @@ private MemberCrefSyntax ParseMemberCref() case SyntaxKind.ExplicitKeyword: case SyntaxKind.ImplicitKeyword: return ParseConversionOperatorMemberCref(); + case SyntaxKind.IdentifierToken when CurrentToken.ContextualKind == SyntaxKind.ExtensionKeyword: + return ParsePossibleExtensionMemberCref(); default: return ParseNameMemberCref(); } @@ -975,6 +977,39 @@ private IndexerMemberCrefSyntax ParseIndexerMemberCref() return SyntaxFactory.IndexerMemberCref(thisKeyword, parameters); } +#nullable enable + /// + /// If we have `extension` (with optional type arguments) and parameter list and a dot, then we have an extension member cref. + /// Otherwise, we fall back to producing the same result as + /// + private MemberCrefSyntax ParsePossibleExtensionMemberCref() + { + Debug.Assert(CurrentToken.ContextualKind == SyntaxKind.ExtensionKeyword); + + SyntaxToken identifierToken = EatToken(); + TypeArgumentListSyntax? typeArguments = (CurrentToken.Kind == SyntaxKind.LessThanToken) ? ParseTypeArguments(typeArgumentsMustBeIdentifiers: true) : null; + CrefParameterListSyntax? parameters = (CurrentToken.Kind == SyntaxKind.OpenParenToken) ? ParseCrefParameterList() : null; + + if (parameters is null || CurrentToken.Kind != SyntaxKind.DotToken) + { + SimpleNameSyntax name = typeArguments is not null + ? SyntaxFactory.GenericName(identifierToken, typeArguments) + : SyntaxFactory.IdentifierName(identifierToken); + + return SyntaxFactory.NameMemberCref(name, parameters); + } + + SyntaxToken dotToken = EatToken(SyntaxKind.DotToken); + MemberCrefSyntax member = ParseMemberCref(); + if (member is ExtensionMemberCrefSyntax) + { + member = AddErrorAsWarning(member, ErrorCode.ERR_MisplacedExtension); + } + + return SyntaxFactory.ExtensionMemberCref(ConvertToKeyword(identifierToken), typeArguments, parameters, dotToken, member); + } +#nullable disable + /// /// Parse an overloadable operator, with optional parameters. /// @@ -1323,6 +1358,12 @@ private SimpleNameSyntax ParseCrefName(bool typeArgumentsMustBeIdentifiers) return SyntaxFactory.IdentifierName(identifierToken); } + return SyntaxFactory.GenericName(identifierToken, ParseTypeArguments(typeArgumentsMustBeIdentifiers)); + } + + private TypeArgumentListSyntax ParseTypeArguments(bool typeArgumentsMustBeIdentifiers) + { + Debug.Assert(CurrentToken.Kind == SyntaxKind.LessThanToken); var open = EatToken(); var list = _pool.AllocateSeparated(); @@ -1358,7 +1399,7 @@ private SimpleNameSyntax ParseCrefName(bool typeArgumentsMustBeIdentifiers) open = CheckFeatureAvailability(open, MessageID.IDS_FeatureGenerics, forceWarning: true); - return SyntaxFactory.GenericName(identifierToken, SyntaxFactory.TypeArgumentList(open, list, close)); + return SyntaxFactory.TypeArgumentList(open, list, close); } finally { diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 64da552a8136..dcac09b3296c 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -17,9 +17,25 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.WithOpenBra Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.WithParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax? parameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.WithSemicolonToken(Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.WithTypeParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax? typeParameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.AddParametersParameters(params Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax![]! items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.AddTypeArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax![]! items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.DotToken.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.ExtensionKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Member.get -> Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Parameters.get -> Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.TypeArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax? +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken extensionKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax? typeArgumentList, Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax! parameters, Microsoft.CodeAnalysis.SyntaxToken dotToken, Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! member) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithDotToken(Microsoft.CodeAnalysis.SyntaxToken dotToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithExtensionKeyword(Microsoft.CodeAnalysis.SyntaxToken extensionKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithMember(Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! member) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithParameters(Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax! parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithTypeArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax? typeArgumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionBlockDeclaration = 9079 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionKeyword = 8451 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionMemberCref = 8607 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! node) -> Microsoft.CodeAnalysis.SyntaxNode? +override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! node) -> Microsoft.CodeAnalysis.SyntaxNode? override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> TResult? override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList @@ -34,10 +50,16 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.Op override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.ParameterList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax? override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.SemicolonToken.get -> Microsoft.CodeAnalysis.SyntaxToken override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.TypeParameterList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax? +override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> void +override Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> TResult? static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration() -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax? typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax? parameterList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.SyntaxList members) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax? typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax? parameterList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SyntaxList members, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! member) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax? typeArgumentList, Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax! parameters, Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! member) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.SyntaxToken extensionKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax? typeArgumentList, Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax! parameters, Microsoft.CodeAnalysis.SyntaxToken dotToken, Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax! member) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! node) -> void +virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax! node) -> TResult? Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax.ColonToken.get -> Microsoft.CodeAnalysis.SyntaxToken @@ -61,5 +83,6 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.IgnoredDirectiveTrivia(bool i static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.IgnoredDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken content, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax! static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.IgnoredDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken hashToken, Microsoft.CodeAnalysis.SyntaxToken colonToken, Microsoft.CodeAnalysis.SyntaxToken content, Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax! virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitIgnoredDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax! node) -> void +virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax! node) -> TResult? virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitIgnoredDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.IgnoredDirectiveTriviaSyntax! node) -> TResult? static Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsOverloadableCompoundAssignmentOperator(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind) -> bool diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 567bfe7aeb75..c6a185b77d2c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -4618,53 +4618,56 @@ private static void CheckExtensionMembers(ImmutableArray members, Bindin static void checkExtensionMember(Symbol member, BindingDiagnosticBag diagnostics) { - switch (member.Kind) + if (!IsAllowedExtensionMember(member)) { - case SymbolKind.Method: - var meth = (MethodSymbol)member; - switch (meth.MethodKind) - { - case MethodKind.Constructor: - case MethodKind.Conversion: - case MethodKind.UserDefinedOperator: - case MethodKind.Destructor: - case MethodKind.EventAdd: - case MethodKind.EventRemove: - case MethodKind.StaticConstructor: - break; - case MethodKind.ExplicitInterfaceImplementation: - // error, but reported elsewhere - return; - case MethodKind.Ordinary: - case MethodKind.PropertyGet: - case MethodKind.PropertySet: - return; - default: - throw ExceptionUtilities.UnexpectedValue(meth.MethodKind); - } - break; + diagnostics.Add(ErrorCode.ERR_ExtensionDisallowsMember, member.GetFirstLocation()); + } + } + } - case SymbolKind.Property: - if (!((PropertySymbol)member).IsIndexer) - { - return; - } - else - { + internal static bool IsAllowedExtensionMember(Symbol member) + { + switch (member.Kind) + { + case SymbolKind.Method: + var meth = (MethodSymbol)member; + switch (meth.MethodKind) + { + case MethodKind.Constructor: + case MethodKind.Conversion: + case MethodKind.UserDefinedOperator: + case MethodKind.Destructor: + case MethodKind.EventAdd: + case MethodKind.EventRemove: + case MethodKind.StaticConstructor: + case MethodKind.ExplicitInterfaceImplementation: break; - } + case MethodKind.Ordinary: + case MethodKind.PropertyGet: + case MethodKind.PropertySet: + return true; + default: + throw ExceptionUtilities.UnexpectedValue(meth.MethodKind); + } + break; - case SymbolKind.Field: - case SymbolKind.Event: - case SymbolKind.NamedType: - break; + case SymbolKind.Property: + if (!((PropertySymbol)member).IsIndexer) + { + return true; + } + break; - default: - throw ExceptionUtilities.UnexpectedValue(member.Kind); - } + case SymbolKind.Field: + case SymbolKind.Event: + case SymbolKind.NamedType: + break; - diagnostics.Add(ErrorCode.ERR_ExtensionDisallowsMember, member.GetFirstLocation()); + default: + throw ExceptionUtilities.UnexpectedValue(member.Kind); } + + return false; } private static void CheckForStructDefaultConstructors( diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 1b843d8c13d8..8c3bf4bd9154 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -991,6 +991,17 @@ public virtual string GetDocumentationCommentId() } #nullable enable + public string GetEscapedDocumentationCommentId() + { + return escape(GetDocumentationCommentId()); + + static string escape(string s) + { + Debug.Assert(!s.Contains("&")); + return s.Replace("<", "<").Replace(">", ">"); + } + } + /// /// Fetches the documentation comment for this element with a cancellation token. /// diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 6caf07de98cb..ee5d7ede378e 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -4473,6 +4473,20 @@ + + + + + + + + + + + + + + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 673f89780865..171871cfaa20 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -585,6 +585,7 @@ public enum SyntaxKind : ushort CrefParameterList = 8603, CrefBracketedParameterList = 8604, CrefParameter = 8605, + ExtensionMemberCref = 8607, // names & type-names IdentifierName = 8616, diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index ef8eeac93bcc..8c739fc5d1b4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Žádná přetížená metoda {0} neodpovídá ukazateli na funkci {1}. + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Neočekávané klíčové slovo record. Měli jste na mysli record struct nebo record class? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 8a8a359a7690..687feee638db 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Keine Überladung für "{0}" stimmt mit dem Funktionszeiger "{1}" überein. + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Unerwartetes Schlüsselwort „Datensatz“. Meinten Sie „Datensatzstruktur“ oder „Datensatzklasse“? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 7c67b650310d..20ee0d17e885 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Ninguna sobrecarga correspondiente a "{0}" coincide con el puntero de función "{1}". + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Palabra clave \"record\" inesperada. ¿Quería decir \"record struct\" o \"record class\"? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index c80735d09850..120060b6aa3f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Aucune surcharge pour '{0}' ne correspond au pointeur de fonction '{1}' + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Mot clé 'record' inattendu. Vouliez-vous dire « struct d’enregistrement » ou « classe d’enregistrement » ? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index b2555f67e6e6..44e10a1c36ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Nessun overload per '{0}' corrisponde al puntatore a funzione '{1}' + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Parola chiave 'record' imprevista. Si intendeva 'struct record' o 'classe record'? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 838efdc373b5..a24d8c00b293 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ 関数ポインター '{1}' に一致する '{0}' のオーバーロードはありません + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? 予期しないキーワード 'record' です。'record struct' または 'record class' のつもりでしたか? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 5eee4a498b18..85abbd7b4331 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ 함수 포인터 '{1}'과(와) 일치하는 '{0}'에 대한 오버로드가 없습니다. + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? 예기치 않은 'record' 키워드가 있습니다. 'record struct' 또는 'record class'를 사용할까요? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 15367b128777..7808486f9b30 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Żadne z przeciążeń dla elementu „{0}” nie pasuje do wskaźnika funkcji „{1}” + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Nieoczekiwane słowo kluczowe „record”. Czy chodziło o „record struct” lub „record class”? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 424b87b0ae15..3d7f1b33a89f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Nenhuma sobrecarga de '{0}' corresponde ao ponteiro de função '{1}' + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Palavra-chave inesperada “record”. Você quis dizer “record struct” or “record class”? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index fb63eefd3075..3bdbf01e5b6f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ Нет перегруженного метода для "{0}", который соответствует указателю на функцию "{1}". + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Непредвиденное ключевое слово \"record\". Возможно, вы имели в виду \"record struct\" или \"record class\"? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index d6f3bdf30522..94b142d48f3c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ '{0}' için aşırı yüklemelerin hiçbiri '{1}' işlev işaretçisiyle eşleşmiyor + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? Beklenmeyen 'record' anahtar sözcüğü. 'record struct' veya 'record class' mi demek istediniz? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 5f63ff0de05c..5517f41b8100 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ “{0}”没有与函数指针“{1}”匹配的重载 + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? 意外的关键字 \"record\"。你的意思是 \"record struct\" 还是 \"record class\"? diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index f6a111f09f68..44853d257d6f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -788,8 +788,8 @@ - Extension declarations can include only methods or properties - Extension declarations can include only methods or properties + This member is not allowed in an extension block + This member is not allowed in an extension block @@ -1472,6 +1472,11 @@ '{0}' 沒有任何多載符合函式指標 '{1}' + + An extension member syntax is disallowed in nested position within an extension member syntax + An extension member syntax is disallowed in nested position within an extension member syntax + + Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? 未預期的關鍵字 'record'。您是指 'record struct' 或 'record class'? diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 0d564cb1a311..5424ae1691dc 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -727,7 +727,7 @@ static void Method() // (14,20): error CS0117: 'string' does not contain a definition for 'M' // string.M(); Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("string", "M").WithLocation(14, 20), - // (17,9): error CS9282: Extension declarations can include only methods or properties + // (17,9): error CS9282: This member is not allowed in an extension block // extension(string) { public static void M() { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "extension").WithLocation(17, 9)); @@ -1904,7 +1904,10 @@ void I.M() { } comp.VerifyEmitDiagnostics( // (10,16): error CS0541: 'Extensions.extension(object).M()': explicit interface declaration can only be declared in a class, record, struct or interface // void I.M() { } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("Extensions.extension(object).M()").WithLocation(10, 16)); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("Extensions.extension(object).M()").WithLocation(10, 16), + // (10,16): error CS9282: This member is not allowed in an extension block + // void I.M() { } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "M").WithLocation(10, 16)); } [Fact] @@ -2056,7 +2059,7 @@ public static class Extensions """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,13): error CS9282: Extension declarations can include only methods or properties + // (5,13): error CS9282: This member is not allowed in an extension block // int Property { get; set; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Property").WithLocation(5, 13)); @@ -2215,7 +2218,7 @@ public static class Extensions """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,20): error CS9282: Extension declarations can include only methods or properties + // (5,20): error CS9282: This member is not allowed in an extension block // static int Property { get; set; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Property").WithLocation(5, 20)); @@ -2250,7 +2253,7 @@ public static class Extensions """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,13): error CS9282: Extension declarations can include only methods or properties + // (5,13): error CS9282: This member is not allowed in an extension block // int this[int i] { get => 42; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(5, 13)); @@ -2275,7 +2278,7 @@ public static class Extensions // (3,5): error CS1110: Cannot define a new extension because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll? // extension(object o) Diagnostic(ErrorCode.ERR_ExtensionAttrNotFound, "extension").WithArguments("System.Runtime.CompilerServices.ExtensionAttribute").WithLocation(3, 5), - // (5,13): error CS9282: Extension declarations can include only methods or properties + // (5,13): error CS9282: This member is not allowed in an extension block // int this[int i] { get => 42; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(5, 13) ); @@ -2302,14 +2305,14 @@ public static class Extensions // (5,20): error CS0106: The modifier 'static' is not valid for this item // static int this[int i] { get => 42; set { } } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(5, 20), - // (5,20): error CS9282: Extension declarations can include only methods or properties + // (5,20): error CS9282: This member is not allowed in an extension block // static int this[int i] { get => 42; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(5, 20) ); } [Fact] - public void Member_Type() + public void Member_Type_01() { var src = """ public static class Extensions @@ -2322,7 +2325,7 @@ class Nested { } """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,15): error CS9282: Extension declarations can include only methods or properties + // (5,15): error CS9282: This member is not allowed in an extension block // class Nested { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(5, 15)); @@ -2337,6 +2340,66 @@ class Nested { } Assert.Equal("Extensions.<>E__0.Nested", symbol.GetTypeMember("Nested").ToTestDisplayString()); } + [Fact] + public void Member_Type_02() + { + var src = """ +C.Nested x = null; + +public static class Extensions +{ + extension(C) + { + class Nested { } + } +} +class C { } +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,3): error CS0426: The type name 'Nested' does not exist in the type 'C' + // C.Nested x = null; + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "Nested").WithArguments("Nested", "C").WithLocation(1, 3), + // (7,15): error CS9282: This member is not allowed in an extension block + // class Nested { } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(7, 15)); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + var syntax = GetSyntax(tree, "C.Nested"); + Assert.Null(model.GetSymbolInfo(syntax).Symbol); + } + + [Fact] + public void Member_Type_03() + { + var src = """ +object.Nested x = null; + +public static class Extensions +{ + extension(object) + { + class Nested { } + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (1,8): error CS0117: 'object' does not contain a definition for 'Nested' + // object.Nested x = null; + Diagnostic(ErrorCode.ERR_NoSuchMember, "Nested").WithArguments("object", "Nested").WithLocation(1, 8), + // (1,15): error CS1002: ; expected + // object.Nested x = null; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "x").WithLocation(1, 15), + // (1,15): error CS0103: The name 'x' does not exist in the current context + // object.Nested x = null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(1, 15), + // (7,15): error CS9282: This member is not allowed in an extension block + // class Nested { } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(7, 15)); + } + [Fact] public void Member_Constructor() { @@ -2351,7 +2414,7 @@ public static class Extensions // (3,25): error CS1520: Method must have a return type // extension(object) { Extensions() { } } Diagnostic(ErrorCode.ERR_MemberNeedsType, "Extensions").WithLocation(3, 25), - // (3,25): error CS9282: Extension declarations can include only methods or properties + // (3,25): error CS9282: This member is not allowed in an extension block // extension(object) { Extensions() { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Extensions").WithLocation(3, 25)); @@ -2379,7 +2442,7 @@ public static class Extensions """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (3,26): error CS9282: Extension declarations can include only methods or properties + // (3,26): error CS9282: This member is not allowed in an extension block // extension(object) { ~Extensions() { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Extensions").WithLocation(3, 26)); @@ -2410,7 +2473,7 @@ public static class Extensions // (1,18): error CS1061: 'object' does not contain a definition for 'field' and no accessible extension method 'field' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?) // _ = new object().field; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "field").WithArguments("object", "field").WithLocation(1, 18), - // (5,31): error CS9282: Extension declarations can include only methods or properties + // (5,31): error CS9282: This member is not allowed in an extension block // extension(object o) { int field = 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "field").WithLocation(5, 31), // (5,31): warning CS0169: The field 'Extensions.extension(object).field' is never used @@ -2439,7 +2502,7 @@ public static class Extensions """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (3,35): error CS9282: Extension declarations can include only methods or properties + // (3,35): error CS9282: This member is not allowed in an extension block // extension(object) { const int i = 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "i").WithLocation(3, 35)); @@ -2475,13 +2538,13 @@ event System.Action I.E { add { } remove { } } // (9,31): error CS0541: 'Extensions.extension(object).E': explicit interface declaration can only be declared in a class, record, struct or interface // event System.Action I.E { add { } remove { } } Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "E").WithArguments("Extensions.extension(object).E").WithLocation(9, 31), - // (9,31): error CS9282: Extension declarations can include only methods or properties + // (9,31): error CS9282: This member is not allowed in an extension block // event System.Action I.E { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "E").WithLocation(9, 31), - // (9,35): error CS9282: Extension declarations can include only methods or properties + // (9,35): error CS9282: This member is not allowed in an extension block // event System.Action I.E { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "add").WithLocation(9, 35), - // (9,43): error CS9282: Extension declarations can include only methods or properties + // (9,43): error CS9282: This member is not allowed in an extension block // event System.Action I.E { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "remove").WithLocation(9, 43)); } @@ -4196,16 +4259,16 @@ class C {} // (6,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer or property 'Extensions.extension(C).P' // public int P { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(C).P", "C").WithLocation(6, 20), - // (7,20): error CS9282: Extension declarations can include only methods or properties + // (7,20): error CS9282: This member is not allowed in an extension block // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 20), // (7,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer or property 'Extensions.extension(C).this[int]' // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(C).this[int]", "C").WithLocation(7, 20), - // (11,21): error CS9282: Extension declarations can include only methods or properties + // (11,21): error CS9282: This member is not allowed in an extension block // private int this[long i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(11, 21), - // (15,22): error CS9282: Extension declarations can include only methods or properties + // (15,22): error CS9282: This member is not allowed in an extension block // internal int this[byte i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(15, 22) ); @@ -4262,13 +4325,13 @@ private class C {} // (6,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).P' // public int P { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(Extensions.C).P", "Extensions.C").WithLocation(6, 20), - // (7,20): error CS9282: Extension declarations can include only methods or properties + // (7,20): error CS9282: This member is not allowed in an extension block // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 20), // (7,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).this[int]' // public int this[int i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(Extensions.C).this[int]", "Extensions.C").WithLocation(7, 20), - // (11,21): error CS9282: Extension declarations can include only methods or properties + // (11,21): error CS9282: This member is not allowed in an extension block // private int this[long i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(11, 21), // (13,23): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).M2()' @@ -4277,7 +4340,7 @@ private class C {} // (14,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).P2' // internal int P2 { get => 0; set {}} Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P2").WithArguments("Extensions.extension(Extensions.C).P2", "Extensions.C").WithLocation(14, 22), - // (15,22): error CS9282: Extension declarations can include only methods or properties + // (15,22): error CS9282: This member is not allowed in an extension block // internal int this[byte i] { get => 0; set {}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(15, 22), // (15,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer or property 'Extensions.extension(Extensions.C).this[byte]' @@ -4478,7 +4541,7 @@ private static void M3(this C x) {} var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (9,20): error CS9282: Extension declarations can include only methods or properties + // (9,20): error CS9282: This member is not allowed in an extension block // public int this[int i] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 20)); } @@ -4505,10 +4568,10 @@ public static void M2(this int x, C c) {} var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (9,18): error CS9282: Extension declarations can include only methods or properties + // (9,18): error CS9282: This member is not allowed in an extension block // public C this[int y] => null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 18), - // (10,20): error CS9282: Extension declarations can include only methods or properties + // (10,20): error CS9282: This member is not allowed in an extension block // public int this[C y] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20)); } @@ -13732,7 +13795,7 @@ public static class StaticType { } // (1,14): error CS1061: 'C' does not contain a definition for 'StaticType' and no accessible extension method 'StaticType' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // new C().StaticType(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "StaticType").WithArguments("C", "StaticType").WithLocation(1, 14), - // (9,29): error CS9282: Extension declarations can include only methods or properties + // (9,29): error CS9282: This member is not allowed in an extension block // public static class StaticType { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "StaticType").WithLocation(9, 29)); @@ -22066,7 +22129,7 @@ static class E // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' // _ = c[^1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[^1]").WithArguments("C").WithLocation(2, 5), - // (13,20): error CS9282: Extension declarations can include only methods or properties + // (13,20): error CS9282: This member is not allowed in an extension block // public int this[int i] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(13, 20)); } @@ -22097,7 +22160,7 @@ static class E // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' // _ = c[^1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[^1]").WithArguments("C").WithLocation(2, 5), - // (13,20): error CS9282: Extension declarations can include only methods or properties + // (13,20): error CS9282: This member is not allowed in an extension block // public int this[System.Index i] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(13, 20)); @@ -22239,7 +22302,7 @@ static class E // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'C' // _ = c[1..^1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "c[1..^1]").WithArguments("C").WithLocation(2, 5), - // (13,20): error CS9282: Extension declarations can include only methods or properties + // (13,20): error CS9282: This member is not allowed in an extension block // public int this[System.Range r] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(13, 20)); @@ -22324,7 +22387,7 @@ static class E // (1,16): error CS0021: Cannot apply indexing with [] to an expression of type 'C' // _ = new C() is [1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "[1]").WithArguments("C").WithLocation(1, 16), - // (12,20): error CS9282: Extension declarations can include only methods or properties + // (12,20): error CS9282: This member is not allowed in an extension block // public int this[int i] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(12, 20)); } @@ -22355,7 +22418,7 @@ static class E // (1,16): error CS0021: Cannot apply indexing with [] to an expression of type 'C' // _ = new C() is [1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "[1]").WithArguments("C").WithLocation(1, 16), - // (12,20): error CS9282: Extension declarations can include only methods or properties + // (12,20): error CS9282: This member is not allowed in an extension block // public int this[System.Index i] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(12, 20)); @@ -22471,7 +22534,7 @@ static class E // (1,20): error CS1503: Argument 1: cannot convert from 'System.Range' to 'System.Index' // _ = new C() is [_, .. var x]; Diagnostic(ErrorCode.ERR_BadArgType, ".. var x").WithArguments("1", "System.Range", "System.Index").WithLocation(1, 20), - // (13,20): error CS9282: Extension declarations can include only methods or properties + // (13,20): error CS9282: This member is not allowed in an extension block // public int this[System.Range r] => throw null; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(13, 20)); @@ -24730,7 +24793,7 @@ static void M3(int T){} // (15,28): error CS9288: 'T': a parameter, local variable, or local function cannot have the same name as an extension container type parameter // static void M3(int T){} Diagnostic(ErrorCode.ERR_LocalSameNameAsExtensionTypeParameter, "T").WithArguments("T").WithLocation(15, 28), - // (16,13): error CS9282: Extension declarations can include only methods or properties + // (16,13): error CS9282: This member is not allowed in an extension block // int this[int T] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(16, 13), // (16,22): error CS9288: 'T': a parameter, local variable, or local function cannot have the same name as an extension container type parameter @@ -24787,13 +24850,13 @@ int this[int i] {set{}} // (4,15): warning CS8981: The type name 'value' only contains lower-cased ascii characters. Such names may become reserved for the language. // extension(value[] p) Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "value").WithArguments("value").WithLocation(4, 15), - // (6,13): error CS9282: Extension declarations can include only methods or properties + // (6,13): error CS9282: This member is not allowed in an extension block // int this[int i] {set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(6, 13), // (6,26): error CS9294: 'value': an automatically-generated parameter name conflicts with an extension type parameter name // int this[int i] {set{}} Diagnostic(ErrorCode.ERR_ValueParameterSameNameAsExtensionTypeParameter, "set").WithLocation(6, 26), - // (7,13): error CS9282: Extension declarations can include only methods or properties + // (7,13): error CS9282: This member is not allowed in an extension block // int this[long i] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 13) ); @@ -25264,7 +25327,7 @@ class C8 {} // (13,18): error CS0119: 'T' is a type, which is not valid in the given context // int T => T; Diagnostic(ErrorCode.ERR_BadSKunknown, "T").WithArguments("T", "type").WithLocation(13, 18), - // (19,13): error CS9282: Extension declarations can include only methods or properties + // (19,13): error CS9282: This member is not allowed in an extension block // int this[int x] => T; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(19, 13), // (19,28): error CS0119: 'T' is a type, which is not valid in the given context @@ -25276,10 +25339,10 @@ class C8 {} // (32,25): error CS0119: 'T' is a type, which is not valid in the given context // static int T => T; Diagnostic(ErrorCode.ERR_BadSKunknown, "T").WithArguments("T", "type").WithLocation(32, 25), - // (43,13): error CS9282: Extension declarations can include only methods or properties + // (43,13): error CS9282: This member is not allowed in an extension block // int this[int x] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(43, 13), - // (48,13): error CS9282: Extension declarations can include only methods or properties + // (48,13): error CS9282: This member is not allowed in an extension block // int this[int x] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(48, 13) ); @@ -25366,7 +25429,7 @@ static int P1 """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (27,13): error CS9282: Extension declarations can include only methods or properties + // (27,13): error CS9282: This member is not allowed in an extension block // int this[int y] Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(27, 13), // (42,23): error CS9293: Cannot use extension parameter 'short M1' in this context. @@ -25375,10 +25438,10 @@ static int P1 // (53,17): error CS9293: Cannot use extension parameter 'string P1' in this context. // P1 = "val"; Diagnostic(ErrorCode.ERR_InvalidExtensionParameterReference, "P1").WithArguments("string P1").WithLocation(53, 17), - // (67,13): error CS9282: Extension declarations can include only methods or properties + // (67,13): error CS9282: This member is not allowed in an extension block // int this[int x] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(67, 13), - // (72,13): error CS9282: Extension declarations can include only methods or properties + // (72,13): error CS9282: This member is not allowed in an extension block // int this[int x] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(72, 13) ); @@ -25500,7 +25563,7 @@ void M3(int p2, int p2) {} // (6,28): error CS9290: 'p': a parameter, local variable, or local function cannot have the same name as an extension parameter // static void M3(int p){} Diagnostic(ErrorCode.ERR_LocalSameNameAsExtensionParameter, "p").WithArguments("p").WithLocation(6, 28), - // (7,13): error CS9282: Extension declarations can include only methods or properties + // (7,13): error CS9282: This member is not allowed in an extension block // int this[int p] => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 13), // (7,22): error CS9290: 'p': a parameter, local variable, or local function cannot have the same name as an extension parameter @@ -25536,16 +25599,16 @@ static int P7 {set{}} // (6,17): error CS9291: 'value': an automatically-generated parameter name conflicts with an extension parameter name // int P2 {set{}} Diagnostic(ErrorCode.ERR_ValueParameterSameNameAsExtensionParameter, "set").WithLocation(6, 17), - // (7,13): error CS9282: Extension declarations can include only methods or properties + // (7,13): error CS9282: This member is not allowed in an extension block // int this[int x] {get=>0;} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 13), - // (8,13): error CS9282: Extension declarations can include only methods or properties + // (8,13): error CS9282: This member is not allowed in an extension block // int this[long x] {set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 13), // (8,27): error CS9291: 'value': an automatically-generated parameter name conflicts with an extension parameter name // int this[long x] {set{}} Diagnostic(ErrorCode.ERR_ValueParameterSameNameAsExtensionParameter, "set").WithLocation(8, 27), - // (9,13): error CS9282: Extension declarations can include only methods or properties + // (9,13): error CS9282: This member is not allowed in an extension block // int this[long x, int value] {set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 13), // (9,30): error CS9290: 'value': a parameter, local variable, or local function cannot have the same name as an extension parameter @@ -26195,7 +26258,7 @@ public MyAttr(string p) {} var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (7,13): error CS9282: Extension declarations can include only methods or properties + // (7,13): error CS9282: This member is not allowed in an extension block // int this[int y] Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 13)); } @@ -26228,7 +26291,7 @@ int this[int y] // (6,54): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [System.Runtime.CompilerServices.IndexerName(p)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "p").WithLocation(6, 54), - // (7,13): error CS9282: Extension declarations can include only methods or properties + // (7,13): error CS9282: This member is not allowed in an extension block // int this[int y] Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 13) ); @@ -26320,7 +26383,7 @@ string M3() var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (6,15): error CS9282: Extension declarations can include only methods or properties + // (6,15): error CS9282: This member is not allowed in an extension block // class Nested Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(6, 15), // (11,24): error CS9293: Cannot use extension parameter 'int p' in this context. @@ -26356,7 +26419,7 @@ int this[int y] // (7,54): error CS8078: An expression is too long or complex to compile // [System.Runtime.CompilerServices.IndexerName(Str)] Diagnostic(ErrorCode.ERR_InsufficientStack, "Str").WithLocation(7, 54), - // (8,13): error CS9282: Extension declarations can include only methods or properties + // (8,13): error CS9282: This member is not allowed in an extension block // int this[int y] Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 13) ); @@ -26886,19 +26949,19 @@ static class Extensions6 // (49,20): error CS0082: Type 'Extensions4' already reserves a member called 'set_P4' with the same parameter types // public int P4 => 4; Diagnostic(ErrorCode.ERR_MemberReserved, "P4").WithArguments("set_P4", "Extensions4").WithLocation(49, 20), - // (57,20): error CS9282: Extension declarations can include only methods or properties + // (57,20): error CS9282: This member is not allowed in an extension block // public int this[int x] => 1; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(57, 20), // (57,35): error CS0082: Type 'Extensions5' already reserves a member called 'get_Item' with the same parameter types // public int this[int x] => 1; Diagnostic(ErrorCode.ERR_MemberReserved, "1").WithArguments("get_Item", "Extensions5").WithLocation(57, 35), - // (64,20): error CS9282: Extension declarations can include only methods or properties + // (64,20): error CS9282: This member is not allowed in an extension block // public int this[long b] => 4; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(64, 20), // (64,36): error CS0082: Type 'Extensions5' already reserves a member called 'get_Item' with the same parameter types // public int this[long b] => 4; Diagnostic(ErrorCode.ERR_MemberReserved, "4").WithArguments("get_Item", "Extensions5").WithLocation(64, 36), - // (73,20): error CS9282: Extension declarations can include only methods or properties + // (73,20): error CS9282: This member is not allowed in an extension block // public int this[int x] => 1; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(73, 20), // (73,35): error CS0082: Type 'Extensions6' already reserves a member called 'get_Indexer' with the same parameter types @@ -26943,13 +27006,13 @@ public int this[int y] {set{}} // (10,20): error CS0102: The type 'Extensions1' already contains a definition for 'P1' // public int P1 {set{}} Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P1").WithArguments("Extensions1", "P1").WithLocation(10, 20), - // (18,20): error CS9282: Extension declarations can include only methods or properties + // (18,20): error CS9282: This member is not allowed in an extension block // public int this[int x] => 1; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(18, 20), // (23,20): error CS0111: Type 'Extensions2' already defines a member called 'this' with the same parameter types // public int this[int y] {set{}} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Extensions2").WithLocation(23, 20), - // (23,20): error CS9282: Extension declarations can include only methods or properties + // (23,20): error CS9282: This member is not allowed in an extension block // public int this[int y] {set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(23, 20) ); @@ -28024,7 +28087,7 @@ void Item(U x) {} // (8,13): error CS0102: The type 'Extensions' already contains a definition for 'Item' // int this[T x] => default; Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "this").WithArguments("Extensions", "Item").WithLocation(8, 13), - // (8,13): error CS9282: Extension declarations can include only methods or properties + // (8,13): error CS9282: This member is not allowed in an extension block // int this[T x] => default; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 13) ); @@ -28064,13 +28127,13 @@ int this[U x] { set{}} var comp = CreateCompilation(src); comp.VerifyDiagnostics( - // (8,13): error CS9282: Extension declarations can include only methods or properties + // (8,13): error CS9282: This member is not allowed in an extension block // int this[T x] => default; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 13), // (18,13): error CS0111: Type 'Extensions' already defines a member called 'this' with the same parameter types // int this[U x] { set{}} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Extensions").WithLocation(18, 13), - // (18,13): error CS9282: Extension declarations can include only methods or properties + // (18,13): error CS9282: This member is not allowed in an extension block // int this[U x] { set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(18, 13) ); @@ -28112,13 +28175,13 @@ int this[int x] { set{}} // Tracked by https://github.com/dotnet/roslyn/issues/78830 : diagnostic quality, the "within a type" part of the message might be somewhat misleading comp.VerifyDiagnostics( - // (8,13): error CS9282: Extension declarations can include only methods or properties + // (8,13): error CS9282: This member is not allowed in an extension block // int this[T x] => default; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 13), // (19,13): error CS0668: Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type // int this[int x] { set{}} Diagnostic(ErrorCode.ERR_InconsistentIndexerNames, "this").WithLocation(19, 13), - // (19,13): error CS9282: Extension declarations can include only methods or properties + // (19,13): error CS9282: This member is not allowed in an extension block // int this[int x] { set{}} Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(19, 13) ); @@ -31428,7 +31491,7 @@ static class E // (1,9): error CS0117: 'int' does not contain a definition for 'Const' // _ = int.Const; Diagnostic(ErrorCode.ERR_NoSuchMember, "Const").WithArguments("int", "Const").WithLocation(1, 9), - // (7,26): error CS9282: Extension declarations can include only methods or properties + // (7,26): error CS9282: This member is not allowed in an extension block // public const int Const = 42; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Const").WithLocation(7, 26)); } @@ -32163,7 +32226,7 @@ static class Nested { } var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (6,22): error CS9282: Extension declarations can include only methods or properties + // (6,22): error CS9282: This member is not allowed in an extension block // static class Nested { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(6, 22)); @@ -35135,7 +35198,7 @@ static Expression> Test() """; var comp = CreateCompilation(src, options: TestOptions.DebugExe); comp.VerifyDiagnostics( - // (8,23): error CS9282: Extension declarations can include only methods or properties + // (8,23): error CS9282: This member is not allowed in an extension block // public string this[string s] => o + s; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 23), // (24,26): error CS0021: Cannot apply indexing with [] to an expression of type 'object' @@ -35942,7 +36005,7 @@ public static void M4() { } // (14,20): error CS9303: 'P3': cannot declare instance members in an extension block with an unnamed receiver parameter // public int P3 => 0; // 2 Diagnostic(ErrorCode.ERR_InstanceMemberWithUnnamedExtensionsParameter, "P3").WithArguments("P3").WithLocation(14, 20), - // (16,20): error CS9282: Extension declarations can include only methods or properties + // (16,20): error CS9282: This member is not allowed in an extension block // public int this[int j] => 0; // 3 Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(16, 20), // (16,20): error CS9303: 'this[]': cannot declare instance members in an extension block with an unnamed receiver parameter @@ -36176,13 +36239,13 @@ static class E // (6,29): error CS0106: The modifier 'abstract' is not valid for this item // public abstract int P { get; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "P").WithArguments("abstract").WithLocation(6, 29), - // (6,29): error CS9282: Extension declarations can include only methods or properties + // (6,29): error CS9282: This member is not allowed in an extension block // public abstract int P { get; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "P").WithLocation(6, 29), // (7,29): error CS0106: The modifier 'abstract' is not valid for this item // public abstract int P2 { set; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "P2").WithArguments("abstract").WithLocation(7, 29), - // (7,29): error CS9282: Extension declarations can include only methods or properties + // (7,29): error CS9282: This member is not allowed in an extension block // public abstract int P2 { set; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "P2").WithLocation(7, 29), // (7,34): error CS8051: Auto-implemented properties must have get accessors. @@ -36191,7 +36254,7 @@ static class E // (8,29): error CS0106: The modifier 'abstract' is not valid for this item // public abstract int this[int j] { get; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("abstract").WithLocation(8, 29), - // (8,29): error CS9282: Extension declarations can include only methods or properties + // (8,29): error CS9282: This member is not allowed in an extension block // public abstract int this[int j] { get; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 29), // (8,43): error CS0501: 'E.extension(int).this[int].get' must declare a body because it is not marked abstract, extern, or partial @@ -36224,7 +36287,7 @@ static class E // (7,24): error CS0106: The modifier 'new' is not valid for this item // public new int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("new").WithLocation(7, 24), - // (7,24): error CS9282: Extension declarations can include only methods or properties + // (7,24): error CS9282: This member is not allowed in an extension block // public new int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 24)); } @@ -36254,7 +36317,7 @@ static class E // (7,29): error CS0106: The modifier 'override' is not valid for this item // public override int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(7, 29), - // (7,29): error CS9282: Extension declarations can include only methods or properties + // (7,29): error CS9282: This member is not allowed in an extension block // public override int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 29)); } @@ -36287,7 +36350,7 @@ partial void M() { } // (7,21): error CS0751: A partial member must be declared within a partial type // partial int P { get; set; } Diagnostic(ErrorCode.ERR_PartialMemberOnlyInPartialClass, "P").WithLocation(7, 21), - // (9,21): error CS9282: Extension declarations can include only methods or properties + // (9,21): error CS9282: This member is not allowed in an extension block // partial int this[int j] { get; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 21), // (9,21): error CS0751: A partial member must be declared within a partial type @@ -36320,7 +36383,7 @@ sealed void M() { } // (7,20): error CS0106: The modifier 'sealed' is not valid for this item // sealed int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("sealed").WithLocation(7, 20), - // (7,20): error CS9282: Extension declarations can include only methods or properties + // (7,20): error CS9282: This member is not allowed in an extension block // sealed int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 20)); } @@ -36357,7 +36420,7 @@ readonly void M() { } // (8,22): error CS0106: The modifier 'readonly' is not valid for this item // readonly int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("readonly").WithLocation(8, 22), - // (8,22): error CS9282: Extension declarations can include only methods or properties + // (8,22): error CS9282: This member is not allowed in an extension block // readonly int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(8, 22)); } @@ -36387,7 +36450,7 @@ required void M() { } // (7,22): error CS0106: The modifier 'required' is not valid for this item // required int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("required").WithLocation(7, 22), - // (7,22): error CS9282: Extension declarations can include only methods or properties + // (7,22): error CS9282: This member is not allowed in an extension block // required int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 22)); } @@ -36417,7 +36480,7 @@ extern void M() { } // (7,20): error CS0106: The modifier 'extern' is not valid for this item // extern int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("extern").WithLocation(7, 20), - // (7,20): error CS9282: Extension declarations can include only methods or properties + // (7,20): error CS9282: This member is not allowed in an extension block // extern int this[int j] { get => 0; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 20)); } @@ -36438,7 +36501,7 @@ static class E """; var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugDll); comp.VerifyEmitDiagnostics( - // (7,21): error CS9282: Extension declarations can include only methods or properties + // (7,21): error CS9282: This member is not allowed in an extension block // unsafe int* this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 21)); } @@ -36474,13 +36537,13 @@ protected void M() { } // (8,45): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block // public int P3 { get => 0; protected set { } } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 45), - // (9,23): error CS9282: Extension declarations can include only methods or properties + // (9,23): error CS9282: This member is not allowed in an extension block // protected int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 23), // (9,23): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block // protected int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 23), - // (10,20): error CS9282: Extension declarations can include only methods or properties + // (10,20): error CS9282: This member is not allowed in an extension block // public int this[int j, int k] { protected get => throw null; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), // (10,51): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block @@ -36519,13 +36582,13 @@ protected internal void M() { } // (8,54): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block // public int P3 { get => 0; protected internal set { } } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 54), - // (9,32): error CS9282: Extension declarations can include only methods or properties + // (9,32): error CS9282: This member is not allowed in an extension block // protected internal int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 32), // (9,32): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block // protected internal int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 32), - // (10,20): error CS9282: Extension declarations can include only methods or properties + // (10,20): error CS9282: This member is not allowed in an extension block // public int this[int j, int k] { protected internal get => throw null; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), // (10,60): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block @@ -36564,13 +36627,13 @@ private protected void M() { } // (8,53): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block // public int P3 { get => 0; private protected set { } } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 53), - // (9,31): error CS9282: Extension declarations can include only methods or properties + // (9,31): error CS9282: This member is not allowed in an extension block // private protected int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 31), // (9,31): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block // private protected int this[int j] { get => throw null; } Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 31), - // (10,20): error CS9282: Extension declarations can include only methods or properties + // (10,20): error CS9282: This member is not allowed in an extension block // public int this[int j, int k] { private protected get => throw null; set { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), // (10,59): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block @@ -40962,7 +41025,7 @@ static class E var extension = e.GetTypeMembers().Single(); Assert.Equal("T:E.<>E__0`1", extension.GetDocumentationCommentId()); AssertEx.Equal(""" - + Summary for extension block Description for T Description for t @@ -40972,7 +41035,7 @@ static class E var mSkeleton = extension.GetMember("M"); AssertEx.Equal(""" - + Summary for M Description for U Description for u @@ -40983,14 +41046,14 @@ static class E var mImplementation = e.GetMember("M"); AssertEx.Equal(""" - + """, mImplementation.GetDocumentationCommentXml()); var p = extension.GetMember("P"); AssertEx.Equal(""" - + Summary for P @@ -40999,7 +41062,7 @@ static class E var pGetImplementation = e.GetMember("get_P"); AssertEx.Equal(""" - + """, pGetImplementation.GetDocumentationCommentXml()); @@ -41014,24 +41077,24 @@ static class E Summary for E - + Summary for extension block Description for T Description for t - + Summary for M Description for U Description for u - + Summary for P - + - + @@ -41059,6 +41122,22 @@ string print(XmlNameAttributeSyntax name) } } + private static IEnumerable PrintXmlCrefSymbols(SyntaxTree tree, SemanticModel model) + { + var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType(); + var crefs = docComments.SelectMany(doc => doc.DescendantNodes().OfType()); + var result = crefs.Select(name => print(name)); + return result; + + string print(XmlCrefAttributeSyntax cref) + { + CrefSyntax crefSyntax = cref.Cref; + var symbol = model.GetSymbolInfo(crefSyntax).Symbol; + var symbolDisplay = symbol is null ? "null" : symbol.ToTestDisplayString(); + return (crefSyntax, symbolDisplay).ToString(); + } + } + [Fact] public void XmlDoc_02() { @@ -41095,7 +41174,7 @@ static class E var extension = e.GetTypeMembers().Single(); AssertEx.Equal(""" - + Summary for extension block Description for T Description for t @@ -41105,7 +41184,7 @@ static class E var mSkeleton = extension.GetMember("M"); AssertEx.Equal(""" - + Summary for M Description for U Description for u @@ -41116,14 +41195,14 @@ static class E var mImplementation = e.GetMember("M"); AssertEx.Equal(""" - + """, mImplementation.GetDocumentationCommentXml()); var p = extension.GetMember("P"); AssertEx.Equal(""" - + Summary for P @@ -41132,7 +41211,7 @@ static class E var pGetImplementation = e.GetMember("get_P"); AssertEx.Equal(""" - + """, pGetImplementation.GetDocumentationCommentXml()); @@ -41208,28 +41287,28 @@ static class E var mSkeleton = extension.GetMember("M"); AssertEx.Equal(""" - + """, mSkeleton.GetDocumentationCommentXml()); var mImplementation = e.GetMember("M"); AssertEx.Equal(""" - + """, mImplementation.GetDocumentationCommentXml()); var p = extension.GetMember("P"); AssertEx.Equal(""" - + """, p.GetDocumentationCommentXml()); var pGetImplementation = e.GetMember("get_P"); AssertEx.Equal(""" - + """, pGetImplementation.GetDocumentationCommentXml()); diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs index 83142d8c3b32..3026f4bc56e3 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs @@ -4,7 +4,9 @@ #nullable disable using System; +using System.Globalization; using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting; @@ -3714,5 +3716,1834 @@ static class E var comp = CreateCompilation(src); CompileAndVerify(comp, expectedOutput: "42"); } + + [Fact] + public void Cref_01() + { + var src = """ +/// +/// +/// +/// +static class E +{ + extension(int i) + { + /// + /// + /// + public void M(string s) => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (10,24): warning CS1574: XML comment has cref attribute 'M(string)' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "M(string)").WithArguments("M(string)").WithLocation(10, 24)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + + + +""", e.GetDocumentationCommentXml()); + + AssertEx.Equal("T:E.<>E__0", e.GetTypeMembers().Single().GetDocumentationCommentId()); + + var mSkeleton = comp.GetMember("E").GetTypeMembers().Single().GetMember("M"); + AssertEx.Equal(""" + + + + + + +""", mSkeleton.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(int).M(string), void E.<>E__0.M(System.String s))", + "(E.M(int, string), void E.M(this System.Int32 i, System.String s))", + "(E.extension(int).M, void E.<>E__0.M(System.String s))", + "(E.M, void E.M(this System.Int32 i, System.String s))", + "(M(int, string), void E.M(this System.Int32 i, System.String s))", + "(M(string), null)", + "(M, void E.M(this System.Int32 i, System.String s))"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_02() + { + var src = """ +/// +static class E +{ + extension(T t) + { + public void M(U u) => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + AssertEx.Equal("T:E.<>E__0`1", e.GetTypeMembers().Single().GetDocumentationCommentId()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension{T}(T).M{U}(U), void E.<>E__0.M(U u))"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_03() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(ref int).M()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(ref int).M()").WithArguments("extension(ref int).M()").WithLocation(1, 16)); + } + + [Fact] + public void Cref_04() + { + var src = """ +/// +/// +static class E +{ + extension(ref int i) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).M()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M()").WithArguments("extension(int).M()").WithLocation(2, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(ref int).M(), void E.<>E__0.M())", + "(E.extension(int).M(), null)"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_05() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + } + extension(string s) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M(), void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_06() + { + var src = """ +/// +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + } + extension(int) + { + public static void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M()'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M()'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M()").WithArguments("E.extension(int).M()", "E.extension(int).M()", "E.extension(int).M()").WithLocation(1, 16), + // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M()'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M()").WithLocation(2, 16), + // (11,28): error CS0111: Type 'E' already defines a member called 'M' with the same parameter types + // public static void M() => throw null!; + Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M").WithArguments("M", "E").WithLocation(11, 28)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(int).M(), null)", + "(E.extension(int).M, null)"], + PrintXmlCrefSymbols(tree, model)); + + var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType(); + var crefs = docComments.SelectMany(doc => doc.DescendantNodes().OfType()).ToArray(); + Assert.Equal(CandidateReason.OverloadResolutionFailure, model.GetSymbolInfo(crefs[0].Cref).CandidateReason); + Assert.Equal(CandidateReason.Ambiguous, model.GetSymbolInfo(crefs[1].Cref).CandidateReason); + } + + [Fact] + public void Cref_08() + { + var src = """ +/// +static class E +{ + extension(int i, int j) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (4,22): error CS9285: An extension container can have only one receiver parameter + // extension(int i, int j) + Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M(), void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_09() + { + var src = """ +/// +static class E +{ + extension(int i, int j) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int, int).M()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int, int).M()").WithArguments("extension(int, int).M()").WithLocation(1, 16), + // (4,22): error CS9285: An extension container can have only one receiver parameter + // extension(int i, int j) + Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int, int).M(), null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_10() + { + // Missing closing parens + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(.M()' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(.M()").WithArguments("E.extension(.M()").WithLocation(1, 16), + // (1,28): warning CS1658: ) expected. See also error CS1026. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, ".").WithArguments(") expected", "1026").WithLocation(1, 28)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(.M(), null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_11() + { + // Missing extension parameter + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension().M()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M()").WithArguments("extension().M()").WithLocation(1, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension().M(), null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_12() + { + // Two extension parameters + var src = """ +/// +static class E +{ + extension(int i, int j) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int, int).M()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int, int).M()").WithArguments("extension(int, int).M()").WithLocation(1, 16), + // (4,22): error CS9285: An extension container can have only one receiver parameter + // extension(int i, int j) + Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int, int).M(), null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_13() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public int P => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).P, System.Int32 E.<>E__0.P { get; })"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_14() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public int P => throw null!; + } + extension(string s) + { + public string P => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).P, System.Int32 E.<>E__0.P { get; })"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_15() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public int P => throw null!; + } + extension(string s) + { + public string P => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(string).P, System.String E.<>E__1.P { get; })"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_16() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_17() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(string).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(string).M").WithArguments("extension(string).M").WithLocation(1, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(string).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_18() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_19() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_20() + { + var src = """ +/// +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(int).M{U}, void E.<>E__0.M())", + "(E.M{U}, void E.M(this System.Int32 i))"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_21() + { + // Arity for extension in cref differs from that in declaration + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_22() + { + // Arity for extension in cref differs from that in declaration + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension{T}(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension{T}(int).M").WithArguments("extension{T}(int).M").WithLocation(1, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension{T}(int).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_23() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension{T}(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_24() + { + var src = """ +/// +static class E +{ + public static void M() => throw null; +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.M").WithArguments("M").WithLocation(1, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_25() + { + // Type argument name differs from type parameter name + var src = """ +/// +static class E +{ + extension(T t) + { + public void M() => throw null; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension{U}(U).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_26() + { + // __arglist + var src = """ +/// +static class E +{ + extension(__arglist) + { + public int P => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(string).P' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(string).P").WithArguments("extension(string).P").WithLocation(1, 16), + // (4,15): error CS1669: __arglist is not valid in this context + // extension(__arglist) + Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(4, 15)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(string).P, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_27() + { + // member named "extension" + var src = """ +/// +static class E +{ + public static void extension(string s) => throw null!; +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(string), void E.extension(System.String s))"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_28() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public int P => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(int).' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(int).").WithArguments("E.extension(int).").WithLocation(1, 16), + // (1,33): warning CS1658: Identifier expected. See also error CS1001. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, @"""").WithArguments("Identifier expected", "1001").WithLocation(1, 33)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int)., null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_29() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public class Nested { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).Nested' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).Nested").WithArguments("extension(int).Nested").WithLocation(1, 16), + // (6,22): error CS9282: This member is not allowed in an extension block + // public class Nested { } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(6, 22)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).Nested, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_30() + { + var src = """ +/// +static class E +{ + extension(int i) + { + void I.M() { } + } +} + +interface I +{ + void M(); +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16), + // (6,16): error CS0541: 'E.extension(int).M()': explicit interface declaration can only be declared in a class, record, struct or interface + // void I.M() { } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("E.extension(int).M()").WithLocation(6, 16), + // (6,16): error CS9282: This member is not allowed in an extension block + // void I.M() { } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "M").WithLocation(6, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_31() + { + var src = """ +/// +static class E +{ + extension(object) + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(missing).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(missing).M").WithArguments("extension(missing).M").WithLocation(1, 16), + // (1,28): warning CS1580: Invalid type for parameter missing in XML comment cref attribute: 'E.extension(missing).M' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefParamType, "missing").WithArguments("missing", "E.extension(missing).M").WithLocation(1, 28)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(missing).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_32() + { + // nested type named "extension" + var src = """ +/// +/// +/// +static class E +{ + class @extension + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension, E.extension)", + "(E.extension.M, void E.extension.M())", + "(E.extension.M(), void E.extension.M())"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_33() + { + // nested type named "extension", error cases + var src = """ +/// +/// +/// +static class E +{ + class @extension + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (2,16): warning CS1574: XML comment has cref attribute 'extension().M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M").WithArguments("extension().M").WithLocation(2, 16), + // (3,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(3, 16)); + } + + [Fact] + public void Cref_34() + { + // generic nested type named "extension" + var src = """ +/// +/// +static class E +{ + class @extension + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension{T}, E.extension)", + "(E.extension{T}.M, void E.extension.M())"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_35() + { + // generic nested type named "extension", error cases + var src = """ +/// +static class E +{ + class @extension + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension{T}(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension{T}(int).M").WithArguments("extension{T}(int).M").WithLocation(1, 16)); + } + + [Fact] + public void Cref_36() + { + // can refer to method named "extension", but cannot refer to extension block + var src = """ +/// +/// +static class E +{ + public static void extension() { } + public static void extension(int i) { } +} + +/// +/// +static class E2 +{ + extension(int) + { + } + + /// + /// + static void M() { } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (9,16): warning CS1574: XML comment has cref attribute 'extension()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E2.extension()").WithArguments("extension()").WithLocation(9, 16), + // (10,16): warning CS1574: XML comment has cref attribute 'extension(int)' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E2.extension(int)").WithArguments("extension(int)").WithLocation(10, 16), + // (17,20): warning CS1574: XML comment has cref attribute 'extension()' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension()").WithArguments("extension()").WithLocation(17, 20), + // (18,20): warning CS1574: XML comment has cref attribute 'extension(int)' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int)").WithArguments("extension(int)").WithLocation(18, 20)); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(), void E.extension())", + "(E.extension(int), void E.extension(System.Int32 i))", + "(E2.extension(), null)", + "(E2.extension(int), null)", + "(extension(), null)", + "(extension(int), null)"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_37() + { + // method named "extension" + var src = """ +/// +/// +static class E +{ + public static void extension() { } + public static void extension(int i) { } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(E.extension(), void E.extension())", + "(E.extension(int), void E.extension(System.Int32 i))"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_38() + { + // method named "extension", error case + var src = """ +/// +/// +static class E +{ + public static void extension() { } + public static void extension(int i) { } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension().M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M").WithArguments("extension().M").WithLocation(1, 16), + // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(2, 16)); + } + + [Fact] + public void Cref_39() + { + // nested type named "extension" + var src = """ +/// +static class E +{ + class @extension + { + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension, E.extension)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_40() + { + // inaccessible due to file accessibility on type + var src1 = """ +/// +class C { } +"""; + var src2 = """ +file static class E +{ + extension(object) + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation([(src1, "file1"), (src2, "file2")], parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // file1(1,16): warning CS1574: XML comment has cref attribute 'extension(object).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(object).M").WithArguments("extension(object).M").WithLocation(1, 16)); + + var c = comp.GetMember("C"); + AssertEx.Equal(""" + + + + +""", c.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(object).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_41() + { + // inaccessible due to internal + var src = """ +/// +class C { } +"""; + var libSrc = """ +public static class E +{ + extension(object) + { + internal static void M() { } + } +} +"""; + var libComp = CreateCompilation(libSrc); + var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()], + parseOptions: TestOptions.RegularPreviewWithDocumentationComments, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); + + comp.VerifyEmitDiagnostics(); + + var c = comp.GetMember("C"); + AssertEx.Equal(""" + + + + +""", c.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(object).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_42() + { + // inaccessible due to private + var src = """ +/// +class C { } +"""; + var libSrc = """ +public static class E +{ + extension(object) + { + private static void M() { } + } +} +"""; + var libComp = CreateCompilation(libSrc); + var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()], parseOptions: TestOptions.RegularPreviewWithDocumentationComments, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(object).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(object).M").WithArguments("extension(object).M").WithLocation(1, 16)); + + var c = comp.GetMember("C"); + AssertEx.Equal(""" + + + + +""", c.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(object).M, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_43() + { + var src = """ +/// +static class E +{ + extension(T t) + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension{int}(int).M' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension{int}(int).M").WithArguments("E.extension{int}(int).M").WithLocation(1, 16), + // (1,28): warning CS1658: Type parameter declaration must be an identifier not a type. See also error CS0081. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, "int").WithArguments("Type parameter declaration must be an identifier not a type", "0081").WithLocation(1, 28)); + } + + [Fact] + public void Cref_44() + { + var src = """ +/// +extension(int) +{ + public static void M() { } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16), + // (2,1): error CS9283: Extensions must be declared in a top-level, non-generic, static class + // extension(int) + Diagnostic(ErrorCode.ERR_BadExtensionContainingType, "extension").WithLocation(2, 1), + // (4,24): warning CS1591: Missing XML comment for publicly visible type or member 'extension(int).M()' + // public static void M() { } + Diagnostic(ErrorCode.WRN_MissingXMLComment, "M").WithArguments("extension(int).M()").WithLocation(4, 24)); + } + + [Fact] + public void Cref_45() + { + var src = """ +/// +static class E +{ + extension(int) + { + extension(string) + { + public static void M() { } + } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(int).extension(string).M' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(int).extension(string).M").WithArguments("E.extension(int).extension(string).M").WithLocation(1, 16), + // (1,33): warning CS1658: An extension member syntax is disallowed in nested position within an extension member syntax. See also error CS9309. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, "extension(string).M").WithArguments("An extension member syntax is disallowed in nested position within an extension member syntax", "9309").WithLocation(1, 33), + // (6,9): error CS9282: This member is not allowed in an extension block + // extension(string) + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "extension").WithLocation(6, 9)); + } + + [Fact] + public void Cref_46() + { + var src = """ +/// +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + public void M(int j) => throw null!; + public void M2(int j) => throw null!; + public void M2() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M(int)'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M(int)").WithLocation(1, 16), + // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M2'. Assuming 'E.extension(int).M2(int)', but could have also matched other overloads including 'E.extension(int).M2()'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M2").WithArguments("E.extension(int).M2", "E.extension(int).M2(int)", "E.extension(int).M2()").WithLocation(2, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, null)", "(E.extension(int).M2, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_47() + { + // Xml doc APIs on PE symbols + var src = """ +static class E +{ + extension(int i) + { + public void M() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var comp2 = CreateCompilation("", references: [comp.EmitToImageReference(documentation: new TestDocumentationProvider())]); + + var mSkeleton = comp2.GetMember("E").GetTypeMembers().Single().GetMember("M"); + Assert.Equal("M:E.<>E__0.M", mSkeleton.GetDocumentationCommentId()); + Assert.Equal("M:E.<>E__0.M", mSkeleton.GetDocumentationCommentXml()); + } + + private class TestDocumentationProvider : DocumentationProvider + { + protected internal override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default) + { + return documentationMemberID; + } + + public override bool Equals(object obj) => (object)this == obj; + + public override int GetHashCode() => throw new NotImplementedException(); + } + + [Fact] + public void Cref_48() + { + var libSrc = """ +public static class E +{ + extension(int i) + { + public void M() => throw null!; + } +} +"""; + var libComp = CreateCompilation(libSrc); + + var src = """ +/// +class C +{ +} +"""; + var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()], parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var c = comp.GetMember("C"); + AssertEx.Equal(""" + + + + +""", c.GetDocumentationCommentXml()); + } + + [Fact] + public void Cref_49() + { + var src = """ +/// +static class E +{ +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(missing).M' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(missing).M").WithArguments("extension(missing).M").WithLocation(1, 16), + // (1,28): warning CS1580: Invalid type for parameter missing in XML comment cref attribute: 'E.extension(missing).M' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefParamType, "missing").WithArguments("missing", "E.extension(missing).M").WithLocation(1, 28)); + } + + [Fact] + public void Cref_50() + { + var src = """ +/// +/// +static class E +{ + extension(int i) + { + public void M() => throw null!; + public void M2(int j) => throw null!; + } + extension(int i) + { + public void M(int j) => throw null!; + public void M2() => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M(int)'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M(int)").WithLocation(1, 16), + // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M2'. Assuming 'E.extension(int).M2(int)', but could have also matched other overloads including 'E.extension(int).M2()'. + // /// + Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M2").WithArguments("E.extension(int).M2", "E.extension(int).M2(int)", "E.extension(int).M2()").WithLocation(2, 16)); + + var e = comp.GetMember("E"); + AssertEx.Equal(""" + + + + + +""", e.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).M, null)", "(E.extension(int).M2, null)"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_51() + { + var src = """ +/// +static class E +{ + extension(int) + { + public static void M() { } + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal(["(E.extension(int).@M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_52() + { + // unqualified reference + var src = """ +/// +/// +static class E +{ + extension(int) + { + /// + /// + public static void M1() { } + + public static void Method() { } + public static int Property => 42; + } + + /// + /// + extension(object) + { + } + + /// + /// + public static void M2() { } +} +"""; + // Tracked by https://github.com/dotnet/roslyn/issues/76130 : cref, such unqualified references in CREF should work within context of enclosing static type + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(1, 16), + // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(2, 16), + // (7,24): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(7, 24), + // (8,24): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(8, 24), + // (15,20): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(15, 20), + // (16,20): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(16, 20), + // (21,20): warning CS1574: XML comment has cref attribute 'extension(int).M2' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).M2").WithArguments("extension(int).M2").WithLocation(21, 20), + // (22,20): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(22, 20)); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(extension(int).Method, null)", + "(extension(int).Property, null)", + "(extension(int).Method, null)", + "(extension(int).Property, null)", + "(extension(int).Method, null)", + "(extension(int).Property, null)", + "(extension(int).M2, null)", + "(extension(int).Property, null)"], + PrintXmlCrefSymbols(tree, model)); + + src = """ +/// +static class E +{ + /// + static class Nested + { + /// + public static void M() { } + + public static void Method() { } + } +} +"""; + comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void Cref_53() + { + var src = """ +static class E +{ + extension(int i) + { + /// + /// + public void M(string s) => throw null!; + } + extension(int i) + { + public void M2(string s) => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (5,24): warning CS1574: XML comment has cref attribute 'M2(string)' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "M2(string)").WithArguments("M2(string)").WithLocation(5, 24)); + + var mSkeleton = comp.GetMember("E").GetTypeMembers().First().GetMember("M"); + AssertEx.Equal(""" + + + + + +""", mSkeleton.GetDocumentationCommentXml()); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + AssertEx.Equal([ + "(M2(string), null)", + "(M2, void E.M2(this System.Int32 i, System.String s))"], + PrintXmlCrefSymbols(tree, model)); + } + + [Fact] + public void Cref_54() + { + var libSrc = """ +public static class E +{ + extension(int) + { + public static void M() { } + } +} +"""; + var libComp = CreateCompilation(libSrc); + var libRef = libComp.EmitToImageReference(); + + var src = """ +/// +class C +{ +} +"""; + var comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.Regular13.WithDocumentationMode(DocumentationMode.Diagnose)); + comp.VerifyEmitDiagnostics( + // (1,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // /// + Diagnostic(ErrorCode.ERR_FeatureInPreview, "extension(int).M").WithArguments("extensions").WithLocation(1, 18)); + + comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.RegularNext.WithDocumentationMode(DocumentationMode.Diagnose)); + comp.VerifyEmitDiagnostics(); + + comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void Cref_55() + { + var src = """ +/// +static class E +{ + extension(int i) + { + public void M(string s) => throw null!; + } +} +"""; + var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments); + comp.VerifyEmitDiagnostics( + // (1,16): warning CS1574: XML comment has cref attribute 'M(string)' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "E.M(string)").WithArguments("M(string)").WithLocation(1, 16)); + } } diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 0edf1f6e5fe4..4de4f0482aad 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -628,6 +628,9 @@ private static Syntax.InternalSyntax.QualifiedCrefSyntax GenerateQualifiedCref() private static Syntax.InternalSyntax.NameMemberCrefSyntax GenerateNameMemberCref() => InternalSyntaxFactory.NameMemberCref(GenerateIdentifierName(), null); + private static Syntax.InternalSyntax.ExtensionMemberCrefSyntax GenerateExtensionMemberCref() + => InternalSyntaxFactory.ExtensionMemberCref(InternalSyntaxFactory.Token(SyntaxKind.ExtensionKeyword), null, GenerateCrefParameterList(), InternalSyntaxFactory.Token(SyntaxKind.DotToken), GenerateNameMemberCref()); + private static Syntax.InternalSyntax.IndexerMemberCrefSyntax GenerateIndexerMemberCref() => InternalSyntaxFactory.IndexerMemberCref(InternalSyntaxFactory.Token(SyntaxKind.ThisKeyword), null); @@ -3377,6 +3380,20 @@ public void TestNameMemberCrefFactoryAndProperties() AttachAndCheckDiagnostics(node); } + [Fact] + public void TestExtensionMemberCrefFactoryAndProperties() + { + var node = GenerateExtensionMemberCref(); + + Assert.Equal(SyntaxKind.ExtensionKeyword, node.ExtensionKeyword.Kind); + Assert.Null(node.TypeArgumentList); + Assert.NotNull(node.Parameters); + Assert.Equal(SyntaxKind.DotToken, node.DotToken.Kind); + Assert.NotNull(node.Member); + + AttachAndCheckDiagnostics(node); + } + [Fact] public void TestIndexerMemberCrefFactoryAndProperties() { @@ -9272,6 +9289,32 @@ public void TestNameMemberCrefIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestExtensionMemberCrefTokenDeleteRewriter() + { + var oldNode = GenerateExtensionMemberCref(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestExtensionMemberCrefIdentityRewriter() + { + var oldNode = GenerateExtensionMemberCref(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestIndexerMemberCrefTokenDeleteRewriter() { @@ -10935,6 +10978,9 @@ private static QualifiedCrefSyntax GenerateQualifiedCref() private static NameMemberCrefSyntax GenerateNameMemberCref() => SyntaxFactory.NameMemberCref(GenerateIdentifierName(), default(CrefParameterListSyntax)); + private static ExtensionMemberCrefSyntax GenerateExtensionMemberCref() + => SyntaxFactory.ExtensionMemberCref(SyntaxFactory.Token(SyntaxKind.ExtensionKeyword), default(TypeArgumentListSyntax), GenerateCrefParameterList(), SyntaxFactory.Token(SyntaxKind.DotToken), GenerateNameMemberCref()); + private static IndexerMemberCrefSyntax GenerateIndexerMemberCref() => SyntaxFactory.IndexerMemberCref(SyntaxFactory.Token(SyntaxKind.ThisKeyword), default(CrefBracketedParameterListSyntax)); @@ -13684,6 +13730,20 @@ public void TestNameMemberCrefFactoryAndProperties() Assert.Equal(node, newNode); } + [Fact] + public void TestExtensionMemberCrefFactoryAndProperties() + { + var node = GenerateExtensionMemberCref(); + + Assert.Equal(SyntaxKind.ExtensionKeyword, node.ExtensionKeyword.Kind()); + Assert.Null(node.TypeArgumentList); + Assert.NotNull(node.Parameters); + Assert.Equal(SyntaxKind.DotToken, node.DotToken.Kind()); + Assert.NotNull(node.Member); + var newNode = node.WithExtensionKeyword(node.ExtensionKeyword).WithTypeArgumentList(node.TypeArgumentList).WithParameters(node.Parameters).WithDotToken(node.DotToken).WithMember(node.Member); + Assert.Equal(node, newNode); + } + [Fact] public void TestIndexerMemberCrefFactoryAndProperties() { @@ -19579,6 +19639,32 @@ public void TestNameMemberCrefIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestExtensionMemberCrefTokenDeleteRewriter() + { + var oldNode = GenerateExtensionMemberCref(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestExtensionMemberCrefIdentityRewriter() + { + var oldNode = GenerateExtensionMemberCref(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestIndexerMemberCrefTokenDeleteRewriter() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs index b478bdf25b92..da1e331238d5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using System; using System.Linq; @@ -3573,5 +3574,475 @@ public void AliasQualifiedGenericTypeConstructor() } #endregion Non-simple-type constructors + + #region Extension members + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_01() + { + UsingNode("extension", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken); + } + } + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_02() + { + UsingNode("E.extension", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "extension"); + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_03() + { + UsingNode("E.extension()", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "extension"); + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_04() + { + UsingNode("E.extension(int)", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "extension"); + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CrefParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_05() + { + UsingNode("E.extension{T}", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "extension"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_06() + { + UsingNode("E.extension{T}()", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "extension"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_07() + { + UsingNode("E.extension{T}(int)", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "extension"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CrefParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_08() + { + UsingNode("E.extension{T}(int).", options: TestOptions.RegularPreviewWithDocumentationComments, + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension{T}(int).' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension{T}(int).").WithArguments("E.extension{T}(int).").WithLocation(1, 16), + // (1,36): warning CS1658: Identifier expected. See also error CS1001. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, @"""").WithArguments("Identifier expected", "1001").WithLocation(1, 36)); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CrefParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + M(SyntaxKind.NameMemberCref); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_09() + { + UsingNode("E.extension{T}(int).M", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CrefParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "M"); + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_10() + { + UsingNode("E.extension{T}().M", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "M"); + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_11() + { + UsingNode("E.extension().M", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "M"); + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_12() + { + UsingNode("E.extension().extension().M", options: TestOptions.RegularPreviewWithDocumentationComments, + // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension().extension().M' + // /// + Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension().extension().M").WithArguments("E.extension().extension().M").WithLocation(1, 16), + // (1,30): warning CS1658: An extension member syntax is disallowed in nested position within an extension member syntax. See also error CS9309. + // /// + Diagnostic(ErrorCode.WRN_ErrorOverride, "extension().M").WithArguments("An extension member syntax is disallowed in nested position within an extension member syntax", "9309").WithLocation(1, 30)); + + N(SyntaxKind.QualifiedCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "M"); + } + } + } + } + } + EOF(); + } + + [Fact, CompilerTrait(CompilerFeature.Extensions)] + public void ExtensionCref_13() + { + UsingNode("extension().M", options: TestOptions.RegularPreviewWithDocumentationComments); + + N(SyntaxKind.ExtensionMemberCref); + { + N(SyntaxKind.ExtensionKeyword); + N(SyntaxKind.CrefParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.NameMemberCref); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "M"); + } + } + } + EOF(); + } + + #endregion } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs index 8e383919cef6..8d7bf2990fe4 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs @@ -1568,7 +1568,7 @@ static class C """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,9): error CS9282: Extension declarations can include only methods or properties + // (5,9): error CS9282: This member is not allowed in an extension block // extension(Type2) { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "extension").WithLocation(5, 9)); @@ -2143,7 +2143,7 @@ static class C """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,19): error CS9282: Extension declarations can include only methods or properties + // (5,19): error CS9282: This member is not allowed in an extension block // const int i = 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "i").WithLocation(5, 19)); @@ -2226,7 +2226,7 @@ static class C // (5,19): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // fixed int field[10]; Diagnostic(ErrorCode.ERR_UnsafeNeeded, "field[10]").WithLocation(5, 19), - // (5,19): error CS9282: Extension declarations can include only methods or properties + // (5,19): error CS9282: This member is not allowed in an extension block // fixed int field[10]; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "field").WithLocation(5, 19)); @@ -2308,13 +2308,13 @@ static class C """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,35): error CS9282: Extension declarations can include only methods or properties + // (5,35): error CS9282: This member is not allowed in an extension block // event System.EventHandler eventField; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35), - // (5,35): error CS9282: Extension declarations can include only methods or properties + // (5,35): error CS9282: This member is not allowed in an extension block // event System.EventHandler eventField; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35), - // (5,35): error CS9282: Extension declarations can include only methods or properties + // (5,35): error CS9282: This member is not allowed in an extension block // event System.EventHandler eventField; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35), // (5,35): warning CS0067: The event 'C.extension(object).eventField' is never used @@ -2395,13 +2395,13 @@ event System.EventHandler Event { add { } remove { } } """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,35): error CS9282: Extension declarations can include only methods or properties + // (5,35): error CS9282: This member is not allowed in an extension block // event System.EventHandler Event { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Event").WithLocation(5, 35), - // (5,43): error CS9282: Extension declarations can include only methods or properties + // (5,43): error CS9282: This member is not allowed in an extension block // event System.EventHandler Event { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "add").WithLocation(5, 43), - // (5,51): error CS9282: Extension declarations can include only methods or properties + // (5,51): error CS9282: This member is not allowed in an extension block // event System.EventHandler Event { add { } remove { } } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "remove").WithLocation(5, 51)); @@ -2583,7 +2583,7 @@ class Nested { } """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,15): error CS9282: Extension declarations can include only methods or properties + // (5,15): error CS9282: This member is not allowed in an extension block // class Nested { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(5, 15)); @@ -2646,7 +2646,7 @@ static class C // (5,9): error CS1520: Method must have a return type // Constructor() { } Diagnostic(ErrorCode.ERR_MemberNeedsType, "Constructor").WithLocation(5, 9), - // (5,9): error CS9282: Extension declarations can include only methods or properties + // (5,9): error CS9282: This member is not allowed in an extension block // Constructor() { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Constructor").WithLocation(5, 9)); @@ -2717,7 +2717,7 @@ static Constructor() { } // (5,16): error CS1520: Method must have a return type // static Constructor() { } Diagnostic(ErrorCode.ERR_MemberNeedsType, "Constructor").WithLocation(5, 16), - // (5,16): error CS9282: Extension declarations can include only methods or properties + // (5,16): error CS9282: This member is not allowed in an extension block // static Constructor() { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Constructor").WithLocation(5, 16)); @@ -2785,7 +2785,7 @@ static class C """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,10): error CS9282: Extension declarations can include only methods or properties + // (5,10): error CS9282: This member is not allowed in an extension block // ~Finalizer() { } Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Finalizer").WithLocation(5, 10)); @@ -2854,7 +2854,7 @@ static class C """; var comp = CreateCompilation(src); comp.VerifyEmitDiagnostics( - // (5,13): error CS9282: Extension declarations can include only methods or properties + // (5,13): error CS9282: This member is not allowed in an extension block // int field; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "field").WithLocation(5, 13), // (5,13): warning CS0169: The field 'C.extension(object).field' is never used @@ -3024,7 +3024,7 @@ static class C // (5,39): error CS0563: One of the parameters of a binary operator must be the containing type // public static object operator +(object a, object b) => a; Diagnostic(ErrorCode.ERR_BadBinaryOperatorSignature, "+").WithLocation(5, 39), - // (5,39): error CS9282: Extension declarations can include only methods or properties + // (5,39): error CS9282: This member is not allowed in an extension block // public static object operator +(object a, object b) => a; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "+").WithLocation(5, 39)); @@ -3121,7 +3121,7 @@ static class C // (5,41): error CS0556: User-defined conversion must convert to or from the enclosing type // public static implicit operator int(object t) => 0; Diagnostic(ErrorCode.ERR_ConversionNotInvolvingContainedType, "int").WithLocation(5, 41), - // (5,41): error CS9282: Extension declarations can include only methods or properties + // (5,41): error CS9282: This member is not allowed in an extension block // public static implicit operator int(object t) => 0; Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "int").WithLocation(5, 41)); diff --git a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs index 32f881abf5f0..d5874d984e04 100644 --- a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs +++ b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs @@ -117,23 +117,25 @@ public static MetadataReference EmitToImageReference( EmitOptions options = null, bool embedInteropTypes = false, ImmutableArray aliases = default, - DiagnosticDescription[] expectedWarnings = null) => EmitToPortableExecutableReference(comp, options, embedInteropTypes, aliases, expectedWarnings); + DiagnosticDescription[] expectedWarnings = null, + DocumentationProvider documentation = null) => EmitToPortableExecutableReference(comp, options, embedInteropTypes, aliases, expectedWarnings, documentation); public static PortableExecutableReference EmitToPortableExecutableReference( this Compilation comp, EmitOptions options = null, bool embedInteropTypes = false, ImmutableArray aliases = default, - DiagnosticDescription[] expectedWarnings = null) + DiagnosticDescription[] expectedWarnings = null, + DocumentationProvider documentation = null) { var image = comp.EmitToArray(options, expectedWarnings: expectedWarnings); if (comp.Options.OutputKind == OutputKind.NetModule) { - return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.MakeSourceModuleName()); + return ModuleMetadata.CreateFromImage(image).GetReference(documentation, display: comp.MakeSourceModuleName()); } else { - return AssemblyMetadata.CreateFromImage(image).GetReference(aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName()); + return AssemblyMetadata.CreateFromImage(image).GetReference(documentation, aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName()); } } diff --git a/src/Tools/SemanticSearch/ReferenceAssemblies/Apis/Microsoft.CodeAnalysis.CSharp.txt b/src/Tools/SemanticSearch/ReferenceAssemblies/Apis/Microsoft.CodeAnalysis.CSharp.txt index 53594c67d7a2..3eb8e1fb0791 100644 --- a/src/Tools/SemanticSearch/ReferenceAssemblies/Apis/Microsoft.CodeAnalysis.CSharp.txt +++ b/src/Tools/SemanticSearch/ReferenceAssemblies/Apis/Microsoft.CodeAnalysis.CSharp.txt @@ -408,6 +408,7 @@ Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionColon(Microsof Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionElement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionElementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionStatement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax) +Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExternAliasDirective(Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitFieldDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.FieldDeclarationSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitFieldExpression(Microsoft.CodeAnalysis.CSharp.Syntax.FieldExpressionSyntax) @@ -704,6 +705,7 @@ Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExpressionColon(Microsoft Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExpressionElement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionElementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExpressionStatement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax) +Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExternAliasDirective(Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFieldDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.FieldDeclarationSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFieldExpression(Microsoft.CodeAnalysis.CSharp.Syntax.FieldExpressionSyntax) @@ -954,6 +956,7 @@ Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExpressionColon(Microso Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExpressionElement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionElementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExpressionStatement(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExtensionBlockDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax) +Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitExternAliasDirective(Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitFieldDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.FieldDeclarationSyntax) Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitFieldExpression(Microsoft.CodeAnalysis.CSharp.Syntax.FieldExpressionSyntax) @@ -2489,6 +2492,22 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.get_OpenBra Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.get_ParameterList Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.get_SemicolonToken Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionBlockDeclarationSyntax.get_TypeParameterList +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Accept``1(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor{``0}) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.AddParametersParameters(Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax[]) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.AddTypeArgumentListArguments(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax[]) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax,Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithDotToken(Microsoft.CodeAnalysis.SyntaxToken) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithExtensionKeyword(Microsoft.CodeAnalysis.SyntaxToken) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithMember(Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithParameters(Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.WithTypeArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax) +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.get_DotToken +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.get_ExtensionKeyword +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.get_Member +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.get_Parameters +Microsoft.CodeAnalysis.CSharp.Syntax.ExtensionMemberCrefSyntax.get_TypeArgumentList Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor) Microsoft.CodeAnalysis.CSharp.Syntax.ExternAliasDirectiveSyntax.Accept``1(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor{``0}) @@ -5004,6 +5023,9 @@ Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExpressionStatement(Microsoft.CodeAn Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration(Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax},Microsoft.CodeAnalysis.SyntaxTokenList,Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax,Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax},Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.MemberDeclarationSyntax}) Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionBlockDeclaration(Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax},Microsoft.CodeAnalysis.SyntaxTokenList,Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax,Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax},Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.SyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.MemberDeclarationSyntax},Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.SyntaxToken) +Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax) +Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax) +Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExtensionMemberCref(Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.CSharp.Syntax.TypeArgumentListSyntax,Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax,Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.CSharp.Syntax.MemberCrefSyntax) Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExternAliasDirective(Microsoft.CodeAnalysis.SyntaxToken) Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExternAliasDirective(Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.SyntaxToken,Microsoft.CodeAnalysis.SyntaxToken) Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExternAliasDirective(System.String) @@ -5885,6 +5907,7 @@ Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExpressionElement Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExpressionStatement Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionBlockDeclaration Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionKeyword +Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExtensionMemberCref Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExternAliasDirective Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExternKeyword Microsoft.CodeAnalysis.CSharp.SyntaxKind.FalseKeyword