diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md index b8a6694ecd77a..0dbbcb74bef3e 100644 --- a/docs/Language Feature Status.md +++ b/docs/Language Feature Status.md @@ -17,6 +17,7 @@ efforts behind them. | [Lambda default parameters](https://github.com/dotnet/csharplang/issues/6051) | [lambda-default-parameters](https://github.com/dotnet/roslyn/tree/features/lambda-default-parameters) | [Merged into 17.5p2](https://github.com/dotnet/roslyn/issues/62485) | [adamperlin](https://github.com/adamperlin), [jjonescz](https://github.com/jjonescz) | [333fred](https://github.com/333fred), [cston](https://github.com/cston) | [captainsafia](https://github.com/captainsafia) | | [Default in deconstruction](https://github.com/dotnet/roslyn/pull/25562) | [decon-default](https://github.com/dotnet/roslyn/tree/features/decon-default) | [In Progress](https://github.com/dotnet/roslyn/issues/25559) | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) | | [Collection Literals](https://github.com/dotnet/csharplang/issues/5354) | [CollectionLiterals](https://github.com/dotnet/roslyn/tree/features/CollectionLiterals) | | [cston](https://github.com/cston) | [333fred](https://github.com/333fred), [RikkiGibson](https://github.com/RikkiGibson) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | +| [Using aliases for any type](https://github.com/dotnet/csharplang/issues/4284) | [UsingAliasTypes](https://github.com/dotnet/roslyn/tree/features/UsingAliasTypes) | [Test Plan](https://github.com/dotnet/roslyn/issues/56323) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [jcouv](https://github.com/jcouv) [cston](https://github.com/cston) | | # C# 11.0 diff --git a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs index 469e1bd3158a8..f4a4dc875446b 100644 --- a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs @@ -186,8 +186,8 @@ private static async Task ExpandUsingDirectivesAsync( private static async Task ExpandUsingDirectiveAsync(Document document, UsingDirectiveSyntax usingDirective, CancellationToken cancellationToken) { - var newName = await Simplifier.ExpandAsync(usingDirective.Name, document, cancellationToken: cancellationToken).ConfigureAwait(false); - return usingDirective.WithName(newName); + var newType = await Simplifier.ExpandAsync(usingDirective.Type, document, cancellationToken: cancellationToken).ConfigureAwait(false); + return usingDirective.WithType(newType); } private static CompilationUnitSyntax MoveUsingsInsideNamespace(CompilationUnitSyntax compilationUnit) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 11f8a5d5118a1..634cc150fb6d9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -477,10 +477,19 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS { // ref needs to be handled by the caller var refTypeSyntax = (RefTypeSyntax)syntax; - var refToken = refTypeSyntax.RefKeyword; if (!syntax.HasErrors) { - diagnostics.Add(ErrorCode.ERR_UnexpectedToken, refToken.GetLocation(), refToken.ToString()); + var refToken = refTypeSyntax.RefKeyword; + + // Specialized diagnostic if our parent is a using directive. + if (refTypeSyntax.Parent is UsingDirectiveSyntax) + { + diagnostics.Add(ErrorCode.ERR_BadRefInUsingAlias, refToken.GetLocation()); + } + else + { + diagnostics.Add(ErrorCode.ERR_UnexpectedToken, refToken.GetLocation(), refToken.ToString()); + } } return BindNamespaceOrTypeOrAliasSymbol(refTypeSyntax.Type, diagnostics, basesBeingResolved, suppressUseSiteDiagnostics); @@ -830,29 +839,6 @@ private NamespaceOrTypeOrAliasSymbolWithAnnotations BindSimpleNamespaceOrTypeOrA } } - private static bool IsViableType(LookupResult result) - { - if (!result.IsMultiViable) - { - return false; - } - - foreach (var s in result.Symbols) - { - switch (s.Kind) - { - case SymbolKind.Alias: - if (((AliasSymbol)s).Target.Kind == SymbolKind.NamedType) return true; - break; - case SymbolKind.NamedType: - case SymbolKind.TypeParameter: - return true; - } - } - - return false; - } - protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamespaceOrTypeOrAliasSymbol( IdentifierNameSyntax node, BindingDiagnosticBag diagnostics, @@ -875,7 +861,7 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp } var errorResult = CreateErrorIfLookupOnTypeParameter(node.Parent, qualifierOpt, identifierValueText, 0, diagnostics); - if ((object)errorResult != null) + if (errorResult is not null) { return TypeWithAnnotations.Create(errorResult); } @@ -891,15 +877,12 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp // If we were looking up "dynamic" or "nint" at the topmost level and didn't find anything good, // use that particular type (assuming the /langversion is supported). - if ((object)qualifierOpt == null && - !IsViableType(result)) + if (qualifierOpt is null && + !isViableType(result)) { if (node.Identifier.ValueText == "dynamic") { - if ((node.Parent == null || - node.Parent.Kind() != SyntaxKind.Attribute && // dynamic not allowed as attribute type - SyntaxFacts.IsInTypeOnlyContext(node)) && - Compilation.LanguageVersion >= MessageID.IDS_FeatureDynamic.RequiredVersion()) + if (dynamicAllowed()) { bindingResult = Compilation.DynamicType; ReportUseSiteDiagnosticForDynamic(diagnostics, node); @@ -907,7 +890,11 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp } else { - bindingResult = BindNativeIntegerSymbolIfAny(node, diagnostics); + // nint/nuint is allowed to bind to an existing namespace. + if (!isViableNamespace(result)) + { + bindingResult = BindNativeIntegerSymbolIfAny(node, diagnostics); + } } } @@ -919,15 +906,80 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp if (bindingResult.Kind == SymbolKind.Alias) { var aliasTarget = ((AliasSymbol)bindingResult).GetAliasTarget(basesBeingResolved); - if (aliasTarget.Kind == SymbolKind.NamedType && ((NamedTypeSymbol)aliasTarget).ContainsDynamic()) + if (aliasTarget is TypeSymbol type) { - ReportUseSiteDiagnosticForDynamic(diagnostics, node); + if (type.ContainsDynamic()) + { + ReportUseSiteDiagnosticForDynamic(diagnostics, node); + } + + if (type.IsUnsafe()) + { + ReportUnsafeIfNotAllowed(node, diagnostics); + } } } } result.Free(); return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(AreNullableAnnotationsEnabled(node.Identifier), bindingResult); + + bool dynamicAllowed() + { + if (Compilation.LanguageVersion < MessageID.IDS_FeatureDynamic.RequiredVersion()) + return false; + + if (node.Parent == null) + return true; + + // dynamic not allowed as attribute type + if (node.Parent.Kind() == SyntaxKind.Attribute) + return false; + + if (SyntaxFacts.IsInTypeOnlyContext(node)) + return true; + + // using X = dynamic; is legal. + if (node.Parent is UsingDirectiveSyntax { Alias: not null }) + return true; + + return false; + } + + static bool isViableType(LookupResult result) + { + if (!result.IsMultiViable) + return false; + + foreach (var s in result.Symbols) + { + switch (s.Kind) + { + case SymbolKind.Alias: + if (((AliasSymbol)s).Target.Kind == SymbolKind.NamedType) return true; + break; + case SymbolKind.NamedType: + case SymbolKind.TypeParameter: + return true; + } + } + + return false; + } + + static bool isViableNamespace(LookupResult result) + { + if (!result.IsMultiViable) + return false; + + foreach (var s in result.Symbols) + { + if (s.Kind == SymbolKind.Namespace) + return true; + } + + return false; + } } /// @@ -936,24 +988,26 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp /// private NamedTypeSymbol BindNativeIntegerSymbolIfAny(IdentifierNameSyntax node, BindingDiagnosticBag diagnostics) { - SpecialType specialType; - switch (node.Identifier.Text) - { - case "nint": - specialType = SpecialType.System_IntPtr; - break; - case "nuint": - specialType = SpecialType.System_UIntPtr; - break; - default: - return null; - } + var specialType = + node.IsNint ? SpecialType.System_IntPtr : + node.IsNuint ? SpecialType.System_UIntPtr : SpecialType.None; + + if (specialType == SpecialType.None) + return null; switch (node.Parent) { case AttributeSyntax parent when parent.Name == node: // [nint] return null; - case UsingDirectiveSyntax parent when parent.Name == node: // using nint; using A = nuint; + case UsingDirectiveSyntax usingDirective: + if (usingDirective.Alias != null && usingDirective.Type == node) + { + // legal to write `using A = nuint;` as long as using-alias-to-type is enabled (checked later). + break; + } + + // `using nint;` not legal where 'nint' has the System.IntPtr meaning. It is legal if you were to + // have `namespace nint { }` somewhere. That is handled though in our caller. return null; case ArgumentSyntax parent when // nameof(nint) (IsInsideNameof && diff --git a/src/Compilers/CSharp/Portable/Binder/ImportChain.cs b/src/Compilers/CSharp/Portable/Binder/ImportChain.cs index 895b99a5255e5..d25b20ac1a991 100644 --- a/src/Compilers/CSharp/Portable/Binder/ImportChain.cs +++ b/src/Compilers/CSharp/Portable/Binder/ImportChain.cs @@ -113,11 +113,11 @@ public Cci.IImportScope Translate(Emit.PEModuleBuilder moduleBuilder, Diagnostic var assemblyRef = TryGetAssemblyScope(ns, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns.GetCciAdapter(), assemblyRef, alias)); } - else if (!target.ContainingAssembly.IsLinked) + else if (target is TypeSymbol { ContainingAssembly.IsLinked: false } typeSymbol) { // We skip alias imports of embedded types to avoid breaking existing code that // imports types that can't be embedded but doesn't use them anywhere else in the code. - var typeRef = GetTypeReference((TypeSymbol)target, syntax, moduleBuilder, diagnostics); + var typeRef = GetTypeReference(typeSymbol, syntax, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, alias)); } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 4cff0f0425181..874e6f3ea97e2 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6847,6 +6847,18 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Do not compare function pointer values + + using type alias + + + Using alias cannot be a 'ref' type. + + + Only a using alias can be 'unsafe'. + + + Using alias cannot be a nullable reference type. + Using a function pointer type in this context is not supported. diff --git a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs index f33dccf18f017..f8363898ab861 100644 --- a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs +++ b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs @@ -292,7 +292,12 @@ private static QuickAttributes GetQuickAttributes( continue; } - result |= QuickAttributeHelpers.GetQuickAttributes(directive.Name.GetUnqualifiedName().Identifier.ValueText, inAttribute: false); + if (directive.Name is not NameSyntax name) + { + continue; + } + + result |= QuickAttributeHelpers.GetQuickAttributes(name.GetUnqualifiedName().Identifier.ValueText, inAttribute: false); } return result; diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 237a3f9d9998d..e368efb13e967 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2162,6 +2162,11 @@ internal enum ErrorCode ERR_UnscopedRefAttributeInterfaceImplementation = 9102, ERR_UnrecognizedRefSafetyRulesAttributeVersion = 9103, ERR_BadSpecialByRefUsing = 9104, + + ERR_BadRefInUsingAlias = 9105, + ERR_BadUnsafeInUsingDirective = 9106, + ERR_BadNullableReferenceTypeInUsingAlias = 9107, + #endregion // Note: you will need to do the following after adding warnings: diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index a5e81d5f2008d..0284ee922b3a9 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2279,6 +2279,9 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_UnscopedRefAttributeInterfaceImplementation: case ErrorCode.ERR_UnrecognizedRefSafetyRulesAttributeVersion: case ErrorCode.ERR_BadSpecialByRefUsing: + case ErrorCode.ERR_BadRefInUsingAlias: + case ErrorCode.ERR_BadUnsafeInUsingDirective: + case ErrorCode.ERR_BadNullableReferenceTypeInUsingAlias: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 80df92f4a05e2..27f90af28f6a0 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -262,6 +262,8 @@ internal enum MessageID IDS_Missing = MessageBase + 12830, IDS_FeatureLambdaOptionalParameters = MessageBase + 12831, IDS_FeatureLambdaParamsArray = MessageBase + 12832, + + IDS_FeatureUsingTypeAlias = MessageBase + 12833, } // Message IDs may refer to strings that need to be localized. @@ -388,6 +390,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# preview features. case MessageID.IDS_FeatureLambdaOptionalParameters: // semantic check case MessageID.IDS_FeatureLambdaParamsArray: // semantic check + case MessageID.IDS_FeatureUsingTypeAlias: // semantic check return LanguageVersion.Preview; // C# 11.0 features. diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 index 504ec0ed912d1..688e234296326 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 +++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 @@ -10,7 +10,7 @@ extern_alias_directive ; using_directive - : 'global'? 'using' ('static' | name_equals)? name ';' + : 'global'? 'using' ('static' | ('unsafe'? name_equals))? type ';' ; name_equals @@ -22,6 +22,18 @@ identifier_name | identifier_token ; +attribute_list + : '[' attribute_target_specifier? attribute (',' attribute)* ']' + ; + +attribute_target_specifier + : syntax_token ':' + ; + +attribute + : name attribute_argument_list? + ; + name : alias_qualified_name | qualified_name @@ -49,18 +61,6 @@ qualified_name : name '.' simple_name ; -attribute_list - : '[' attribute_target_specifier? attribute (',' attribute)* ']' - ; - -attribute_target_specifier - : syntax_token ':' - ; - -attribute - : name attribute_argument_list? - ; - attribute_argument_list : '(' (attribute_argument (',' attribute_argument)*)? ')' ; 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 64918ffb46658..cb68f09282757 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 @@ -19664,14 +19664,15 @@ internal sealed partial class UsingDirectiveSyntax : CSharpSyntaxNode internal readonly SyntaxToken? globalKeyword; internal readonly SyntaxToken usingKeyword; internal readonly SyntaxToken? staticKeyword; + internal readonly SyntaxToken? unsafeKeyword; internal readonly NameEqualsSyntax? alias; - internal readonly NameSyntax name; + internal readonly TypeSyntax type; internal readonly SyntaxToken semicolonToken; - internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, SyntaxToken? unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) : base(kind, diagnostics, annotations) { - this.SlotCount = 6; + this.SlotCount = 7; if (globalKeyword != null) { this.AdjustFlagsAndWidth(globalKeyword); @@ -19684,22 +19685,27 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta this.AdjustFlagsAndWidth(staticKeyword); this.staticKeyword = staticKeyword; } + if (unsafeKeyword != null) + { + this.AdjustFlagsAndWidth(unsafeKeyword); + this.unsafeKeyword = unsafeKeyword; + } if (alias != null) { this.AdjustFlagsAndWidth(alias); this.alias = alias; } - this.AdjustFlagsAndWidth(name); - this.name = name; + this.AdjustFlagsAndWidth(type); + this.type = type; this.AdjustFlagsAndWidth(semicolonToken); this.semicolonToken = semicolonToken; } - internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken, SyntaxFactoryContext context) + internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, SyntaxToken? unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken, SyntaxFactoryContext context) : base(kind) { this.SetFactoryContext(context); - this.SlotCount = 6; + this.SlotCount = 7; if (globalKeyword != null) { this.AdjustFlagsAndWidth(globalKeyword); @@ -19712,21 +19718,26 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta this.AdjustFlagsAndWidth(staticKeyword); this.staticKeyword = staticKeyword; } + if (unsafeKeyword != null) + { + this.AdjustFlagsAndWidth(unsafeKeyword); + this.unsafeKeyword = unsafeKeyword; + } if (alias != null) { this.AdjustFlagsAndWidth(alias); this.alias = alias; } - this.AdjustFlagsAndWidth(name); - this.name = name; + this.AdjustFlagsAndWidth(type); + this.type = type; this.AdjustFlagsAndWidth(semicolonToken); this.semicolonToken = semicolonToken; } - internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, SyntaxToken? unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken) : base(kind) { - this.SlotCount = 6; + this.SlotCount = 7; if (globalKeyword != null) { this.AdjustFlagsAndWidth(globalKeyword); @@ -19739,13 +19750,18 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta this.AdjustFlagsAndWidth(staticKeyword); this.staticKeyword = staticKeyword; } + if (unsafeKeyword != null) + { + this.AdjustFlagsAndWidth(unsafeKeyword); + this.unsafeKeyword = unsafeKeyword; + } if (alias != null) { this.AdjustFlagsAndWidth(alias); this.alias = alias; } - this.AdjustFlagsAndWidth(name); - this.name = name; + this.AdjustFlagsAndWidth(type); + this.type = type; this.AdjustFlagsAndWidth(semicolonToken); this.semicolonToken = semicolonToken; } @@ -19753,8 +19769,9 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta public SyntaxToken? GlobalKeyword => this.globalKeyword; public SyntaxToken UsingKeyword => this.usingKeyword; public SyntaxToken? StaticKeyword => this.staticKeyword; + public SyntaxToken? UnsafeKeyword => this.unsafeKeyword; public NameEqualsSyntax? Alias => this.alias; - public NameSyntax Name => this.name; + public TypeSyntax Type => this.type; public SyntaxToken SemicolonToken => this.semicolonToken; internal override GreenNode? GetSlot(int index) @@ -19763,9 +19780,10 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta 0 => this.globalKeyword, 1 => this.usingKeyword, 2 => this.staticKeyword, - 3 => this.alias, - 4 => this.name, - 5 => this.semicolonToken, + 3 => this.unsafeKeyword, + 4 => this.alias, + 5 => this.type, + 6 => this.semicolonToken, _ => null, }; @@ -19774,11 +19792,11 @@ internal UsingDirectiveSyntax(SyntaxKind kind, SyntaxToken? globalKeyword, Synta public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitUsingDirective(this); public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitUsingDirective(this); - public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax alias, NameSyntax name, SyntaxToken semicolonToken) + public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, SyntaxToken unsafeKeyword, NameEqualsSyntax alias, TypeSyntax type, SyntaxToken semicolonToken) { - if (globalKeyword != this.GlobalKeyword || usingKeyword != this.UsingKeyword || staticKeyword != this.StaticKeyword || alias != this.Alias || name != this.Name || semicolonToken != this.SemicolonToken) + if (globalKeyword != this.GlobalKeyword || usingKeyword != this.UsingKeyword || staticKeyword != this.StaticKeyword || unsafeKeyword != this.UnsafeKeyword || alias != this.Alias || type != this.Type || semicolonToken != this.SemicolonToken) { - var newNode = SyntaxFactory.UsingDirective(globalKeyword, usingKeyword, staticKeyword, alias, name, semicolonToken); + var newNode = SyntaxFactory.UsingDirective(globalKeyword, usingKeyword, staticKeyword, unsafeKeyword, alias, type, semicolonToken); var diags = GetDiagnostics(); if (diags?.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -19792,15 +19810,15 @@ public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingK } internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) - => new UsingDirectiveSyntax(this.Kind, this.globalKeyword, this.usingKeyword, this.staticKeyword, this.alias, this.name, this.semicolonToken, diagnostics, GetAnnotations()); + => new UsingDirectiveSyntax(this.Kind, this.globalKeyword, this.usingKeyword, this.staticKeyword, this.unsafeKeyword, this.alias, this.type, this.semicolonToken, diagnostics, GetAnnotations()); internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) - => new UsingDirectiveSyntax(this.Kind, this.globalKeyword, this.usingKeyword, this.staticKeyword, this.alias, this.name, this.semicolonToken, GetDiagnostics(), annotations); + => new UsingDirectiveSyntax(this.Kind, this.globalKeyword, this.usingKeyword, this.staticKeyword, this.unsafeKeyword, this.alias, this.type, this.semicolonToken, GetDiagnostics(), annotations); internal UsingDirectiveSyntax(ObjectReader reader) : base(reader) { - this.SlotCount = 6; + this.SlotCount = 7; var globalKeyword = (SyntaxToken?)reader.ReadValue(); if (globalKeyword != null) { @@ -19816,15 +19834,21 @@ internal UsingDirectiveSyntax(ObjectReader reader) AdjustFlagsAndWidth(staticKeyword); this.staticKeyword = staticKeyword; } + var unsafeKeyword = (SyntaxToken?)reader.ReadValue(); + if (unsafeKeyword != null) + { + AdjustFlagsAndWidth(unsafeKeyword); + this.unsafeKeyword = unsafeKeyword; + } var alias = (NameEqualsSyntax?)reader.ReadValue(); if (alias != null) { AdjustFlagsAndWidth(alias); this.alias = alias; } - var name = (NameSyntax)reader.ReadValue(); - AdjustFlagsAndWidth(name); - this.name = name; + var type = (TypeSyntax)reader.ReadValue(); + AdjustFlagsAndWidth(type); + this.type = type; var semicolonToken = (SyntaxToken)reader.ReadValue(); AdjustFlagsAndWidth(semicolonToken); this.semicolonToken = semicolonToken; @@ -19836,8 +19860,9 @@ internal override void WriteTo(ObjectWriter writer) writer.WriteValue(this.globalKeyword); writer.WriteValue(this.usingKeyword); writer.WriteValue(this.staticKeyword); + writer.WriteValue(this.unsafeKeyword); writer.WriteValue(this.alias); - writer.WriteValue(this.name); + writer.WriteValue(this.type); writer.WriteValue(this.semicolonToken); } @@ -35277,7 +35302,7 @@ public override CSharpSyntaxNode VisitExternAliasDirective(ExternAliasDirectiveS => node.Update((SyntaxToken)Visit(node.ExternKeyword), (SyntaxToken)Visit(node.AliasKeyword), (SyntaxToken)Visit(node.Identifier), (SyntaxToken)Visit(node.SemicolonToken)); public override CSharpSyntaxNode VisitUsingDirective(UsingDirectiveSyntax node) - => node.Update((SyntaxToken)Visit(node.GlobalKeyword), (SyntaxToken)Visit(node.UsingKeyword), (SyntaxToken)Visit(node.StaticKeyword), (NameEqualsSyntax)Visit(node.Alias), (NameSyntax)Visit(node.Name), (SyntaxToken)Visit(node.SemicolonToken)); + => node.Update((SyntaxToken)Visit(node.GlobalKeyword), (SyntaxToken)Visit(node.UsingKeyword), (SyntaxToken)Visit(node.StaticKeyword), (SyntaxToken)Visit(node.UnsafeKeyword), (NameEqualsSyntax)Visit(node.Alias), (TypeSyntax)Visit(node.Type), (SyntaxToken)Visit(node.SemicolonToken)); public override CSharpSyntaxNode VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), (SyntaxToken)Visit(node.NamespaceKeyword), (NameSyntax)Visit(node.Name), (SyntaxToken)Visit(node.OpenBraceToken), VisitList(node.Externs), VisitList(node.Usings), VisitList(node.Members), (SyntaxToken)Visit(node.CloseBraceToken), (SyntaxToken)Visit(node.SemicolonToken)); @@ -38699,7 +38724,7 @@ public ExternAliasDirectiveSyntax ExternAliasDirective(SyntaxToken externKeyword return new ExternAliasDirectiveSyntax(SyntaxKind.ExternAliasDirective, externKeyword, aliasKeyword, identifier, semicolonToken, this.context); } - public UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + public UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, SyntaxToken? unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken) { #if DEBUG if (globalKeyword != null) @@ -38713,12 +38738,30 @@ public UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, SyntaxTok } if (usingKeyword == null) throw new ArgumentNullException(nameof(usingKeyword)); if (usingKeyword.Kind != SyntaxKind.UsingKeyword) throw new ArgumentException(nameof(usingKeyword)); - if (name == null) throw new ArgumentNullException(nameof(name)); + if (staticKeyword != null) + { + switch (staticKeyword.Kind) + { + case SyntaxKind.StaticKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(staticKeyword)); + } + } + if (unsafeKeyword != null) + { + switch (unsafeKeyword.Kind) + { + case SyntaxKind.UnsafeKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(unsafeKeyword)); + } + } + if (type == null) throw new ArgumentNullException(nameof(type)); if (semicolonToken == null) throw new ArgumentNullException(nameof(semicolonToken)); if (semicolonToken.Kind != SyntaxKind.SemicolonToken) throw new ArgumentException(nameof(semicolonToken)); #endif - return new UsingDirectiveSyntax(SyntaxKind.UsingDirective, globalKeyword, usingKeyword, staticKeyword, alias, name, semicolonToken, this.context); + return new UsingDirectiveSyntax(SyntaxKind.UsingDirective, globalKeyword, usingKeyword, staticKeyword, unsafeKeyword, alias, type, semicolonToken, this.context); } public NamespaceDeclarationSyntax NamespaceDeclaration(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, SyntaxToken namespaceKeyword, NameSyntax name, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList externs, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList usings, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList members, SyntaxToken closeBraceToken, SyntaxToken? semicolonToken) @@ -43770,7 +43813,7 @@ public static ExternAliasDirectiveSyntax ExternAliasDirective(SyntaxToken extern return new ExternAliasDirectiveSyntax(SyntaxKind.ExternAliasDirective, externKeyword, aliasKeyword, identifier, semicolonToken); } - public static UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + public static UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, SyntaxToken usingKeyword, SyntaxToken? staticKeyword, SyntaxToken? unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken) { #if DEBUG if (globalKeyword != null) @@ -43784,12 +43827,30 @@ public static UsingDirectiveSyntax UsingDirective(SyntaxToken? globalKeyword, Sy } if (usingKeyword == null) throw new ArgumentNullException(nameof(usingKeyword)); if (usingKeyword.Kind != SyntaxKind.UsingKeyword) throw new ArgumentException(nameof(usingKeyword)); - if (name == null) throw new ArgumentNullException(nameof(name)); + if (staticKeyword != null) + { + switch (staticKeyword.Kind) + { + case SyntaxKind.StaticKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(staticKeyword)); + } + } + if (unsafeKeyword != null) + { + switch (unsafeKeyword.Kind) + { + case SyntaxKind.UnsafeKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(unsafeKeyword)); + } + } + if (type == null) throw new ArgumentNullException(nameof(type)); if (semicolonToken == null) throw new ArgumentNullException(nameof(semicolonToken)); if (semicolonToken.Kind != SyntaxKind.SemicolonToken) throw new ArgumentException(nameof(semicolonToken)); #endif - return new UsingDirectiveSyntax(SyntaxKind.UsingDirective, globalKeyword, usingKeyword, staticKeyword, alias, name, semicolonToken); + return new UsingDirectiveSyntax(SyntaxKind.UsingDirective, globalKeyword, usingKeyword, staticKeyword, unsafeKeyword, alias, type, semicolonToken); } public static NamespaceDeclarationSyntax NamespaceDeclaration(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, SyntaxToken namespaceKeyword, NameSyntax name, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList externs, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList usings, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList members, SyntaxToken closeBraceToken, SyntaxToken? semicolonToken) 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 f01225eae09f9..a3b2fb4e72933 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 @@ -1894,7 +1894,7 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor => node.Update(VisitToken(node.ExternKeyword), VisitToken(node.AliasKeyword), VisitToken(node.Identifier), VisitToken(node.SemicolonToken)); public override SyntaxNode? VisitUsingDirective(UsingDirectiveSyntax node) - => node.Update(VisitToken(node.GlobalKeyword), VisitToken(node.UsingKeyword), VisitToken(node.StaticKeyword), (NameEqualsSyntax?)Visit(node.Alias), (NameSyntax?)Visit(node.Name) ?? throw new ArgumentNullException("name"), VisitToken(node.SemicolonToken)); + => node.Update(VisitToken(node.GlobalKeyword), VisitToken(node.UsingKeyword), VisitToken(node.StaticKeyword), VisitToken(node.UnsafeKeyword), (NameEqualsSyntax?)Visit(node.Alias), (TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"), VisitToken(node.SemicolonToken)); public override SyntaxNode? VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), VisitToken(node.NamespaceKeyword), (NameSyntax?)Visit(node.Name) ?? throw new ArgumentNullException("name"), VisitToken(node.OpenBraceToken), VisitList(node.Externs), VisitList(node.Usings), VisitList(node.Members), VisitToken(node.CloseBraceToken), VisitToken(node.SemicolonToken)); @@ -4664,7 +4664,7 @@ public static ExternAliasDirectiveSyntax ExternAliasDirective(string identifier) => SyntaxFactory.ExternAliasDirective(SyntaxFactory.Token(SyntaxKind.ExternKeyword), SyntaxFactory.Token(SyntaxKind.AliasKeyword), SyntaxFactory.Identifier(identifier), SyntaxFactory.Token(SyntaxKind.SemicolonToken)); /// Creates a new UsingDirectiveSyntax instance. - public static UsingDirectiveSyntax UsingDirective(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + public static UsingDirectiveSyntax UsingDirective(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, SyntaxToken unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken) { switch (globalKeyword.Kind()) { @@ -4673,18 +4673,30 @@ public static UsingDirectiveSyntax UsingDirective(SyntaxToken globalKeyword, Syn default: throw new ArgumentException(nameof(globalKeyword)); } if (usingKeyword.Kind() != SyntaxKind.UsingKeyword) throw new ArgumentException(nameof(usingKeyword)); - if (name == null) throw new ArgumentNullException(nameof(name)); + switch (staticKeyword.Kind()) + { + case SyntaxKind.StaticKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(staticKeyword)); + } + switch (unsafeKeyword.Kind()) + { + case SyntaxKind.UnsafeKeyword: + case SyntaxKind.None: break; + default: throw new ArgumentException(nameof(unsafeKeyword)); + } + if (type == null) throw new ArgumentNullException(nameof(type)); if (semicolonToken.Kind() != SyntaxKind.SemicolonToken) throw new ArgumentException(nameof(semicolonToken)); - return (UsingDirectiveSyntax)Syntax.InternalSyntax.SyntaxFactory.UsingDirective((Syntax.InternalSyntax.SyntaxToken?)globalKeyword.Node, (Syntax.InternalSyntax.SyntaxToken)usingKeyword.Node!, (Syntax.InternalSyntax.SyntaxToken?)staticKeyword.Node, alias == null ? null : (Syntax.InternalSyntax.NameEqualsSyntax)alias.Green, (Syntax.InternalSyntax.NameSyntax)name.Green, (Syntax.InternalSyntax.SyntaxToken)semicolonToken.Node!).CreateRed(); + return (UsingDirectiveSyntax)Syntax.InternalSyntax.SyntaxFactory.UsingDirective((Syntax.InternalSyntax.SyntaxToken?)globalKeyword.Node, (Syntax.InternalSyntax.SyntaxToken)usingKeyword.Node!, (Syntax.InternalSyntax.SyntaxToken?)staticKeyword.Node, (Syntax.InternalSyntax.SyntaxToken?)unsafeKeyword.Node, alias == null ? null : (Syntax.InternalSyntax.NameEqualsSyntax)alias.Green, (Syntax.InternalSyntax.TypeSyntax)type.Green, (Syntax.InternalSyntax.SyntaxToken)semicolonToken.Node!).CreateRed(); } /// Creates a new UsingDirectiveSyntax instance. - public static UsingDirectiveSyntax UsingDirective(SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name) - => SyntaxFactory.UsingDirective(default, SyntaxFactory.Token(SyntaxKind.UsingKeyword), staticKeyword, alias, name, SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + public static UsingDirectiveSyntax UsingDirective(NameEqualsSyntax? alias, TypeSyntax type) + => SyntaxFactory.UsingDirective(default, SyntaxFactory.Token(SyntaxKind.UsingKeyword), default, default, alias, type, SyntaxFactory.Token(SyntaxKind.SemicolonToken)); /// Creates a new UsingDirectiveSyntax instance. - public static UsingDirectiveSyntax UsingDirective(NameSyntax name) - => SyntaxFactory.UsingDirective(default, SyntaxFactory.Token(SyntaxKind.UsingKeyword), default, default, name, SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + public static UsingDirectiveSyntax UsingDirective(TypeSyntax type) + => SyntaxFactory.UsingDirective(default, SyntaxFactory.Token(SyntaxKind.UsingKeyword), default, default, default, type, SyntaxFactory.Token(SyntaxKind.SemicolonToken)); /// Creates a new NamespaceDeclarationSyntax instance. public static NamespaceDeclarationSyntax NamespaceDeclaration(SyntaxList attributeLists, SyntaxTokenList modifiers, SyntaxToken namespaceKeyword, NameSyntax name, SyntaxToken openBraceToken, SyntaxList externs, SyntaxList usings, SyntaxList members, SyntaxToken closeBraceToken, SyntaxToken semicolonToken) 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 3ba605db95112..1a9dde8232c73 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 @@ -9193,7 +9193,7 @@ public ExternAliasDirectiveSyntax Update(SyntaxToken externKeyword, SyntaxToken public sealed partial class UsingDirectiveSyntax : CSharpSyntaxNode { private NameEqualsSyntax? alias; - private NameSyntax? name; + private TypeSyntax? type; internal UsingDirectiveSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) : base(green, parent, position) @@ -9220,36 +9220,45 @@ public SyntaxToken StaticKeyword } } - public NameEqualsSyntax? Alias => GetRed(ref this.alias, 3); + public SyntaxToken UnsafeKeyword + { + get + { + var slot = ((Syntax.InternalSyntax.UsingDirectiveSyntax)this.Green).unsafeKeyword; + return slot != null ? new SyntaxToken(this, slot, GetChildPosition(3), GetChildIndex(3)) : default; + } + } + + public NameEqualsSyntax? Alias => GetRed(ref this.alias, 4); - public NameSyntax Name => GetRed(ref this.name, 4)!; + public TypeSyntax Type => GetRed(ref this.type, 5)!; - public SyntaxToken SemicolonToken => new SyntaxToken(this, ((Syntax.InternalSyntax.UsingDirectiveSyntax)this.Green).semicolonToken, GetChildPosition(5), GetChildIndex(5)); + public SyntaxToken SemicolonToken => new SyntaxToken(this, ((Syntax.InternalSyntax.UsingDirectiveSyntax)this.Green).semicolonToken, GetChildPosition(6), GetChildIndex(6)); internal override SyntaxNode? GetNodeSlot(int index) => index switch { - 3 => GetRed(ref this.alias, 3), - 4 => GetRed(ref this.name, 4)!, + 4 => GetRed(ref this.alias, 4), + 5 => GetRed(ref this.type, 5)!, _ => null, }; internal override SyntaxNode? GetCachedSlot(int index) => index switch { - 3 => this.alias, - 4 => this.name, + 4 => this.alias, + 5 => this.type, _ => null, }; public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitUsingDirective(this); public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitUsingDirective(this); - public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, SyntaxToken unsafeKeyword, NameEqualsSyntax? alias, TypeSyntax type, SyntaxToken semicolonToken) { - if (globalKeyword != this.GlobalKeyword || usingKeyword != this.UsingKeyword || staticKeyword != this.StaticKeyword || alias != this.Alias || name != this.Name || semicolonToken != this.SemicolonToken) + if (globalKeyword != this.GlobalKeyword || usingKeyword != this.UsingKeyword || staticKeyword != this.StaticKeyword || unsafeKeyword != this.UnsafeKeyword || alias != this.Alias || type != this.Type || semicolonToken != this.SemicolonToken) { - var newNode = SyntaxFactory.UsingDirective(globalKeyword, usingKeyword, staticKeyword, alias, name, semicolonToken); + var newNode = SyntaxFactory.UsingDirective(globalKeyword, usingKeyword, staticKeyword, unsafeKeyword, alias, type, semicolonToken); var annotations = GetAnnotations(); return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; } @@ -9257,12 +9266,13 @@ public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingK return this; } - public UsingDirectiveSyntax WithGlobalKeyword(SyntaxToken globalKeyword) => Update(globalKeyword, this.UsingKeyword, this.StaticKeyword, this.Alias, this.Name, this.SemicolonToken); - public UsingDirectiveSyntax WithUsingKeyword(SyntaxToken usingKeyword) => Update(this.GlobalKeyword, usingKeyword, this.StaticKeyword, this.Alias, this.Name, this.SemicolonToken); - public UsingDirectiveSyntax WithStaticKeyword(SyntaxToken staticKeyword) => Update(this.GlobalKeyword, this.UsingKeyword, staticKeyword, this.Alias, this.Name, this.SemicolonToken); - public UsingDirectiveSyntax WithAlias(NameEqualsSyntax? alias) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, alias, this.Name, this.SemicolonToken); - public UsingDirectiveSyntax WithName(NameSyntax name) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, this.Alias, name, this.SemicolonToken); - public UsingDirectiveSyntax WithSemicolonToken(SyntaxToken semicolonToken) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, this.Alias, this.Name, semicolonToken); + public UsingDirectiveSyntax WithGlobalKeyword(SyntaxToken globalKeyword) => Update(globalKeyword, this.UsingKeyword, this.StaticKeyword, this.UnsafeKeyword, this.Alias, this.Type, this.SemicolonToken); + public UsingDirectiveSyntax WithUsingKeyword(SyntaxToken usingKeyword) => Update(this.GlobalKeyword, usingKeyword, this.StaticKeyword, this.UnsafeKeyword, this.Alias, this.Type, this.SemicolonToken); + public UsingDirectiveSyntax WithStaticKeyword(SyntaxToken staticKeyword) => Update(this.GlobalKeyword, this.UsingKeyword, staticKeyword, this.UnsafeKeyword, this.Alias, this.Type, this.SemicolonToken); + public UsingDirectiveSyntax WithUnsafeKeyword(SyntaxToken unsafeKeyword) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, unsafeKeyword, this.Alias, this.Type, this.SemicolonToken); + public UsingDirectiveSyntax WithAlias(NameEqualsSyntax? alias) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, this.UnsafeKeyword, alias, this.Type, this.SemicolonToken); + public UsingDirectiveSyntax WithType(TypeSyntax type) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, this.UnsafeKeyword, this.Alias, type, this.SemicolonToken); + public UsingDirectiveSyntax WithSemicolonToken(SyntaxToken semicolonToken) => Update(this.GlobalKeyword, this.UsingKeyword, this.StaticKeyword, this.UnsafeKeyword, this.Alias, this.Type, semicolonToken); } /// Member declaration syntax. diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 2ef9749a216b6..6059cdac7f981 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -788,13 +788,15 @@ private UsingDirectiveSyntax ParseUsingDirective() var usingToken = this.EatToken(SyntaxKind.UsingKeyword); var staticToken = this.TryEatToken(SyntaxKind.StaticKeyword); + var unsafeToken = this.TryEatToken(SyntaxKind.UnsafeKeyword); var alias = this.IsNamedAssignment() ? ParseNameEquals() : null; - NameSyntax name; + TypeSyntax type; SyntaxToken semicolon; - if (IsPossibleNamespaceMemberDeclaration()) + var isAliasToFunctionPointer = alias != null && this.CurrentToken.Kind == SyntaxKind.DelegateKeyword; + if (!isAliasToFunctionPointer && IsPossibleNamespaceMemberDeclaration()) { //We're worried about the case where someone already has a correct program //and they've gone back to add a using directive, but have not finished the @@ -812,23 +814,25 @@ private UsingDirectiveSyntax ParseUsingDirective() //NB: there's no way this could be true for a set of tokens that form a valid //using directive, so there's no danger in checking the error case first. - name = WithAdditionalDiagnostics(CreateMissingIdentifierName(), GetExpectedTokenError(SyntaxKind.IdentifierToken, this.CurrentToken.Kind)); + type = WithAdditionalDiagnostics(CreateMissingIdentifierName(), GetExpectedTokenError(SyntaxKind.IdentifierToken, this.CurrentToken.Kind)); semicolon = SyntaxFactory.MissingToken(SyntaxKind.SemicolonToken); } else { - name = this.ParseQualifiedName(); - if (name.IsMissing && this.PeekToken(1).Kind == SyntaxKind.SemicolonToken) - { - //if we can see a semicolon ahead, then the current token was - //probably supposed to be an identifier - name = AddTrailingSkippedSyntax(name, this.EatToken()); - } + // In the case where we don't have an alias, only parse out a name for this using-directive. This is + // worse for error recovery, but it means all code that consumes a using-directive can keep on assuming + // it has a name when there is no alias. Only code that specifically has to process aliases then has to + // deal with getting arbitrary types back. + type = alias == null ? this.ParseQualifiedName() : this.ParseType(); + + // If we can see a semicolon ahead, then the current token was probably supposed to be an identifier + if (type.IsMissing && this.PeekToken(1).Kind == SyntaxKind.SemicolonToken) + type = AddTrailingSkippedSyntax(type, this.EatToken()); semicolon = this.EatToken(SyntaxKind.SemicolonToken); } - return _syntaxFactory.UsingDirective(globalToken, usingToken, staticToken, alias, name, semicolon); + return _syntaxFactory.UsingDirective(globalToken, usingToken, staticToken, unsafeToken, alias, type, semicolon); } private bool IsPossibleGlobalAttributeDeclaration() diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 00644bd7fc75b..4ffa14f7f9a9f 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1 +1,11 @@ +*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.Name.get -> Microsoft.CodeAnalysis.CSharp.Syntax.NameSyntax! static Microsoft.CodeAnalysis.CSharpExtensions.ContainsDirective(this Microsoft.CodeAnalysis.SyntaxNode! node, Microsoft.CodeAnalysis.CSharp.SyntaxKind kind) -> bool +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.Name.get -> Microsoft.CodeAnalysis.CSharp.Syntax.NameSyntax? +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.UnsafeKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken globalKeyword, Microsoft.CodeAnalysis.SyntaxToken usingKeyword, Microsoft.CodeAnalysis.SyntaxToken staticKeyword, Microsoft.CodeAnalysis.SyntaxToken unsafeKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.NameEqualsSyntax? alias, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! +Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.WithUnsafeKeyword(Microsoft.CodeAnalysis.SyntaxToken unsafeKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UsingDirective(Microsoft.CodeAnalysis.CSharp.Syntax.NameEqualsSyntax? alias, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UsingDirective(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UsingDirective(Microsoft.CodeAnalysis.SyntaxToken globalKeyword, Microsoft.CodeAnalysis.SyntaxToken usingKeyword, Microsoft.CodeAnalysis.SyntaxToken staticKeyword, Microsoft.CodeAnalysis.SyntaxToken unsafeKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.NameEqualsSyntax? alias, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax! \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/SourceGeneration/CSharpSyntaxHelper.cs b/src/Compilers/CSharp/Portable/SourceGeneration/CSharpSyntaxHelper.cs index 89189859ceeb2..091742b2eb2f7 100644 --- a/src/Compilers/CSharp/Portable/SourceGeneration/CSharpSyntaxHelper.cs +++ b/src/Compilers/CSharp/Portable/SourceGeneration/CSharpSyntaxHelper.cs @@ -92,8 +92,13 @@ private static void AddAliases( if (global != (usingDirective.GlobalKeyword != null)) continue; + // We only care about aliases from one name to another name. e.g. `using X = A.B.C;` That's because + // the caller is only interested in finding a fully-qualified-metadata-name to an attribute. + if (usingDirective.Type is not Syntax.InternalSyntax.NameSyntax name) + continue; + var aliasName = usingDirective.Alias.Name.Identifier.ValueText; - var symbolName = GetUnqualifiedName(usingDirective.Name).Identifier.ValueText; + var symbolName = GetUnqualifiedName(name).Identifier.ValueText; aliases.Add((aliasName, symbolName)); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs index f41c719dd5d8f..ab2d9cbc18643 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs @@ -322,11 +322,11 @@ internal override NamespaceOrTypeSymbol GetAliasTarget(ConsList? bas // symbol. If it is an extern alias then find the target in the list of metadata references. var newDiagnostics = BindingDiagnosticBag.GetInstance(); - NamespaceOrTypeSymbol symbol = this.IsExtern ? - ResolveExternAliasTarget(newDiagnostics) : - ResolveAliasTarget(((UsingDirectiveSyntax)_directive.GetSyntax()).Name, newDiagnostics, basesBeingResolved); + NamespaceOrTypeSymbol symbol = this.IsExtern + ? ResolveExternAliasTarget(newDiagnostics) + : ResolveAliasTarget((UsingDirectiveSyntax)_directive.GetSyntax(), newDiagnostics, basesBeingResolved); - if ((object?)Interlocked.CompareExchange(ref _aliasTarget, symbol, null) == null) + if (Interlocked.CompareExchange(ref _aliasTarget, symbol, null) is null) { // Note: It's important that we don't call newDiagnosticsToReadOnlyAndFree here. That call // can force the prompt evaluation of lazy initialized diagnostics. That in turn can @@ -372,10 +372,52 @@ private NamespaceSymbol ResolveExternAliasTarget(BindingDiagnosticBag diagnostic return target; } - private NamespaceOrTypeSymbol ResolveAliasTarget(NameSyntax syntax, BindingDiagnosticBag diagnostics, ConsList? basesBeingResolved) + private NamespaceOrTypeSymbol ResolveAliasTarget( + UsingDirectiveSyntax usingDirective, + BindingDiagnosticBag diagnostics, + ConsList? basesBeingResolved) { - var declarationBinder = ContainingSymbol.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree).GetBinder(syntax).WithAdditionalFlags(BinderFlags.SuppressConstraintChecks | BinderFlags.SuppressObsoleteChecks); - return declarationBinder.BindNamespaceOrTypeSymbol(syntax, diagnostics, basesBeingResolved).NamespaceOrTypeSymbol; + if (usingDirective.UnsafeKeyword != default) + { + MessageID.IDS_FeatureUsingTypeAlias.CheckFeatureAvailability(diagnostics, usingDirective, usingDirective.UnsafeKeyword.GetLocation()); + } + else if (usingDirective.Type is not NameSyntax) + { + MessageID.IDS_FeatureUsingTypeAlias.CheckFeatureAvailability(diagnostics, usingDirective.Type); + } + + var syntax = usingDirective.Type; + var flags = BinderFlags.SuppressConstraintChecks | BinderFlags.SuppressObsoleteChecks; + if (usingDirective.UnsafeKeyword != default) + { + this.CheckUnsafeModifier(DeclarationModifiers.Unsafe, usingDirective.UnsafeKeyword.GetLocation(), diagnostics); + flags |= BinderFlags.UnsafeRegion; + } + + var declarationBinder = ContainingSymbol.DeclaringCompilation + .GetBinderFactory(syntax.SyntaxTree) + .GetBinder(syntax) + .WithAdditionalFlags(flags); + + var annotatedNamespaceOrType = declarationBinder.BindNamespaceOrTypeSymbol(syntax, diagnostics, basesBeingResolved); + + // `using X = RefType?;` is not legal. + if (usingDirective.Type is NullableTypeSyntax nullableType && + annotatedNamespaceOrType.TypeWithAnnotations.NullableAnnotation == NullableAnnotation.Annotated && + annotatedNamespaceOrType.TypeWithAnnotations.Type?.IsReferenceType is true) + { + diagnostics.Add(ErrorCode.ERR_BadNullableReferenceTypeInUsingAlias, nullableType.QuestionToken.GetLocation()); + } + + var namespaceOrType = annotatedNamespaceOrType.NamespaceOrTypeSymbol; + if (namespaceOrType is TypeSymbol { IsNativeIntegerWrapperType: true } && + (usingDirective.Type.IsNint || usingDirective.Type.IsNuint)) + { + // using X = nint; + MessageID.IDS_FeatureUsingTypeAlias.CheckFeatureAvailability(diagnostics, usingDirective.Type); + } + + return namespaceOrType; } internal override bool RequiresCompletion diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/QuickAttributeChecker.cs b/src/Compilers/CSharp/Portable/Symbols/Source/QuickAttributeChecker.cs index 221d50af7f060..96aeb91c91d15 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/QuickAttributeChecker.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/QuickAttributeChecker.cs @@ -93,7 +93,9 @@ internal QuickAttributeChecker AddAliasesIfAny(SyntaxList foreach (var usingDirective in usingsSyntax) { - if (usingDirective.Alias != null && (!onlyGlobalAliases || usingDirective.GlobalKeyword.IsKind(SyntaxKind.GlobalKeyword))) + if (usingDirective.Alias != null && + usingDirective.Name != null && + (!onlyGlobalAliases || usingDirective.GlobalKeyword.IsKind(SyntaxKind.GlobalKeyword))) { string name = usingDirective.Alias.Name.Identifier.ValueText; string target = usingDirective.Name.GetUnqualifiedName().Identifier.ValueText; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.AliasesAndUsings.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.AliasesAndUsings.cs index e452f0656c610..c5c45e4144a57 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.AliasesAndUsings.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.AliasesAndUsings.cs @@ -320,7 +320,7 @@ private MergedGlobalAliasesAndUsings GetMergedGlobalAliasesAndUsings(ConsList' is a '' but is used as 'type or namespace' - diagnostics.Add(ErrorCode.ERR_BadSKknown, usingDirective.Name.Location, - usingDirective.Name, + diagnostics.Add(ErrorCode.ERR_BadSKknown, usingDirective.Type.Location, + usingDirective.Type, imported.GetKindText(), MessageID.IDS_SK_TYPE_OR_NAMESPACE.Localize()); } @@ -966,7 +969,7 @@ private static void Validate(SourceNamespaceSymbol declaringSymbol, SyntaxRefere if (target.IsType) { var typeSymbol = (TypeSymbol)target; - var location = usingDirective.Name.Location; + var location = usingDirective.Type.Location; typeSymbol.CheckAllConstraints(compilation, conversions, location, diagnostics); } diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index b994af84558b8..10a892ad771e5 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -3075,10 +3075,17 @@ - - + + + + + + + + + - + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs index 547ad72f77272..b6220a0769742 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs @@ -2655,7 +2655,14 @@ public static UsingDirectiveSyntax UsingDirective(NameEqualsSyntax alias, NameSy public static UsingDirectiveSyntax UsingDirective(SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) { - return UsingDirective(globalKeyword: default(SyntaxToken), usingKeyword, staticKeyword, alias, name, semicolonToken); + return UsingDirective( + globalKeyword: default, + usingKeyword, + staticKeyword, + unsafeKeyword: default, + alias, + type: name, + semicolonToken); } /// Creates a new ClassOrStructConstraintSyntax instance. diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs index 6a6e832dfe64e..2c026feea49ba 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs @@ -237,14 +237,14 @@ public static bool IsInNamespaceOrTypeContext(ExpressionSyntax? node) { if (node != null) { - node = (ExpressionSyntax)SyntaxFactory.GetStandaloneExpression(node); + node = SyntaxFactory.GetStandaloneExpression(node); var parent = node.Parent; if (parent != null) { switch (parent.Kind()) { case UsingDirective: - return ((UsingDirectiveSyntax)parent).Name == node; + return ((UsingDirectiveSyntax)parent).Type == node; case QualifiedName: // left of QN is namespace or type. Note: when you have "a.b.c()", then diff --git a/src/Compilers/CSharp/Portable/Syntax/UsingDirectiveSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/UsingDirectiveSyntax.cs index d242ccc5da7f0..dd083ee8b3943 100644 --- a/src/Compilers/CSharp/Portable/Syntax/UsingDirectiveSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/UsingDirectiveSyntax.cs @@ -2,13 +2,47 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.CSharp.Syntax; + namespace Microsoft.CodeAnalysis.CSharp.Syntax { - partial class UsingDirectiveSyntax + public partial class UsingDirectiveSyntax { + /// + /// Returns the name this points at, or if it does not + /// point at a name. A normal using X.Y.Z; or using static X.Y.Z; will always point at a name and + /// will always return a value for this. However, a using-alias (e.g. using x = ...;) may or may not + /// point at a name and may return here. An example of when that may happen is the type + /// on the right side of the = is not a name. For example using x = (X.Y.Z, A.B.C);. Here, as + /// the type is a tuple-type there is no name to return. + /// + public NameSyntax? Name => this.Type as NameSyntax; + public UsingDirectiveSyntax Update(SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) - { - return Update(globalKeyword: GlobalKeyword, usingKeyword, staticKeyword, alias, name, semicolonToken); - } + => this.Update(this.GlobalKeyword, usingKeyword, staticKeyword, this.UnsafeKeyword, alias, type: name, semicolonToken); + + public UsingDirectiveSyntax Update(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + => this.Update(globalKeyword, usingKeyword, staticKeyword, this.UnsafeKeyword, alias, type: name, semicolonToken); + + public UsingDirectiveSyntax WithName(NameSyntax name) + => WithType(name); + } +} + +namespace Microsoft.CodeAnalysis.CSharp +{ + public partial class SyntaxFactory + { + /// Creates a new UsingDirectiveSyntax instance. + public static UsingDirectiveSyntax UsingDirective(SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name) + => UsingDirective(globalKeyword: default, usingKeyword: default, staticKeyword, unsafeKeyword: default, alias, type: name, semicolonToken: default); + + /// Creates a new UsingDirectiveSyntax instance. + public static UsingDirectiveSyntax UsingDirective(SyntaxToken globalKeyword, SyntaxToken usingKeyword, SyntaxToken staticKeyword, NameEqualsSyntax? alias, NameSyntax name, SyntaxToken semicolonToken) + => UsingDirective(globalKeyword, usingKeyword, staticKeyword, unsafeKeyword: default, alias, type: name, semicolonToken); + + /// Creates a new UsingDirectiveSyntax instance. + public static UsingDirectiveSyntax UsingDirective(NameSyntax name) + => UsingDirective(type: name); } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 3bd10c54e3428..967625b1aea88 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -197,6 +197,11 @@ Neplatná možnost {0} pro /nullable. Je třeba použít disable, enable, warnings nebo annotations. + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Operátor typeof nejde použít na typ odkazů s možnou hodnotou null. @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Chyba syntaxe příkazového řádku: {0} není platná hodnota možnosti {1}. Hodnota musí mít tvar {2}. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. Atribut AsyncMethodBuilder je u anonymních metod bez explicitního návratového typu zakázaný. @@ -1877,6 +1892,11 @@ Řetězcové literály UTF-8 + + using type alias + using type alias + + with on anonymous types s anonymními typy diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index e879ad0edaeb8..990074f6cad58 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -197,6 +197,11 @@ Ungültige Option "{0}" für "/nullable". Zulässig sind nur "disable", "enable", "warnings" oder "annotations". + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Der typeof-Operator kann nicht für einen Verweistyp verwendet werden, der NULL-Werte zulässt. @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Fehler in der Befehlszeilensyntax: "{0}" ist kein gültiger Wert für die Option "{1}". Der Wert muss im Format "{2}" vorliegen. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. Das AsyncMethodBuilder-Attribut ist für anonyme Methoden ohne expliziten Rückgabetyp unzulässig. @@ -1877,6 +1892,11 @@ UTF-8-Zeichenfolgenliterale + + using type alias + using type alias + + with on anonymous types "with" in anonymen Typen diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 756b4978c80bd..06a685d8c1eae 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -197,6 +197,11 @@ Opción no válida "{0}" para /nullable; debe ser "deshabilitar", ·"habilitar", "advertencias" o "anotaciones" + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type El operador typeof no se puede usar en un tipo de referencia que acepta valores NULL @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Error de sintaxis de la línea de comandos: "{0}" no es un valor válido para la opción "{1}". El valor debe tener el formato "{2}". + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. El atributo AsyncMethodBuilder no se permite en métodos anónimos sin un tipo de valor devuelto explícito. @@ -1877,6 +1892,11 @@ Literales de cadena UTF-8 + + using type alias + using type alias + + with on anonymous types con los tipos anónimos diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index dfc50dc623973..ad5c6810399fe 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -197,6 +197,11 @@ Option '{0}' non valide pour /nullable ; utilisez 'disable', 'enable', 'warnings' ou 'annotations' + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Impossible d'utiliser l'opérateur typeof sur un type référence Nullable @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Erreur de syntaxe de ligne de commande : '{0}' est une valeur non valide pour l'option '{1}'. La valeur doit se présenter sous la forme '{2}'. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. L'attribut AsyncMethodBuilder n'est pas autorisé pour les méthodes anonymes sans type de retour explicite. @@ -1877,6 +1892,11 @@ Littéraux de chaîne UTF-8 + + using type alias + using type alias + + with on anonymous types avec sur les types anonymes diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 5971edebb4f82..3043d5b791deb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -197,6 +197,11 @@ L'opzione '{0}' non è valida per /nullable. Deve essere 'disable', 'enable', 'warnings' o 'annotations' + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Non è possibile usare l'operatore typeof nel tipo riferimento nullable @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Errore di sintassi della riga di comando: '{0}' non è un valore valido per l'opzione '{1}'. Il valore deve essere espresso nel formato '{2}'. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. L'attributo AsyncMethodBuilder non è consentito in metodi anonimi senza un tipo restituito esplicito. @@ -1877,6 +1892,11 @@ Valori letterali stringa UTF-8 + + using type alias + using type alias + + with on anonymous types con tipi anonimi diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index b93ebdb147e8e..e2716ecc8ac48 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -197,6 +197,11 @@ /nullable のオプション '{0}' が無効です。'disable'、'enable'、'warnings'、'annotations' のいずれかにする必要があります + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type NULL 許容参照型では typeof 演算子を使用できません @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. コマンドライン構文エラー: '{0}' は、'{1}' オプションの有効な値ではありません。値は '{2}' の形式にする必要があります。 + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. AsyncMethodBuilder 属性は、明示的な戻り値の型のない匿名メソッドでは許可されていません。 @@ -1877,6 +1892,11 @@ UTF-8 文字列リテラル + + using type alias + using type alias + + with on anonymous types 匿名型の場合 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 7e408f5860340..da86f368d9fac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -197,6 +197,11 @@ /nullable의 '{0}' 옵션이 잘못되었습니다. 'disable', 'enable', 'warnings' 또는 'annotations'여야 합니다. + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type typeof 연산자는 nullable 참조 형식에 사용할 수 없습니다. @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. 명령줄 구문 오류: '{0}'은(는) '{1}' 옵션에 유효한 값이 아닙니다. 값은 '{2}' 형식이어야 합니다. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. AsyncMethodBuilder 특성은 명시적 반환 형식이 없는 익명 메서드에서 허용되지 않습니다. @@ -1877,6 +1892,11 @@ UTF-8 문자열 리터럴 + + using type alias + using type alias + + with on anonymous types 무명 형식에서 사용 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 472b92cafcbd6..b976c81b9653a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -197,6 +197,11 @@ Nieprawidłowa opcja „{0}” dla parametru /nullable; należy użyć opcji „disable”, „enable”, „warnings” lub „annotations” + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Nie można użyć operatora typeof w przypadku typu referencyjnego dopuszczającego wartość null @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Błąd składni wiersza polecenia: „{0}” nie jest prawidłową wartością dla opcji „{1}”. Wartość musi mieć postać „{2}”. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. Atrybut AsyncMethodBuilder jest niedozwolony w metodach anonimowych bez jawnego zwracanego typu. @@ -1877,6 +1892,11 @@ Literały ciągu UTF-8 + + using type alias + using type alias + + with on anonymous types przy użyciu typów anonimowych diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 986dde642519c..388faaca2cc51 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -197,6 +197,11 @@ Opção inválida '{0}' para /nullable; precisa ser 'disable', 'enable', 'safeonly', 'warnings' ou 'safeonlywarnings' + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type O operador typeof não pode ser usado em um tipo de referência anulável @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Erro de sintaxe de linha de comando: '{0}' não é um valor válido para a opção '{1}'. O valor precisa estar no formato '{2}'. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. O atributo AsyncMethodBuilder não é permitido em métodos anônimos sem um tipo de retorno explícito. @@ -1877,6 +1892,11 @@ Cadeia de caracteres UTF-8 literais + + using type alias + using type alias + + with on anonymous types com tipos anônimos diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 964de189fa622..9d0cab2dc6a16 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -197,6 +197,11 @@ Недопустимый параметр "{0}" для /nullable. Допустимые значения: "disable", "enable", "warnings" или "annotations" + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Оператор typeof невозможно использовать для ссылочного типа, допускающего значения NULL. @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Ошибка в синтаксисе командной строки: "{0}" не является допустимым значением для параметра "{1}". Значение должно иметь форму "{2}". + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. Атрибут AsyncMethodBuilder запрещен для анонимных методов без явного типа возвращаемого значения. @@ -1877,6 +1892,11 @@ Строковые литералы UTF-8 + + using type alias + using type alias + + with on anonymous types с использованием анонимных типов diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index d8d3316a1a290..2b1cee8b5a85c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -197,6 +197,11 @@ /nullable için geçersiz '{0}' seçeneği; 'disable', 'enable', 'warnings' veya 'annotations' olmalıdır + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type Boş değer atanabilir tür üzerinde typeof işleci kullanılamaz @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. Komut satırı söz dizimi hatası: '{0}', '{1}' seçeneği için geçerli bir değer değil. Değer '{2}' biçiminde olmalıdır. + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. Açık dönüş türü olmadan, anonim yöntemlerde AsyncMethodBuilder özniteliğine izin verilmez. @@ -1877,6 +1892,11 @@ UTF-8 sabit değerli dizeleri + + using type alias + using type alias + + with on anonymous types anonim türler ile diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 337b681eaddee..2e43a2af0e898 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -197,6 +197,11 @@ /nullable 的选项“{0}”无效;必须为“禁用”、“启用”、“警告”或“注释” + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type 不能在可为 null 的引用类型上使用 typeof 运算符 @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. 命令行语法错误:“{0}”不是“{1}”选项的有效值。值的格式必须为 "{2}"。 + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. 没有显式返回类型的匿名方法不允许使用 AsyncMethodBuilder 属性。 @@ -1877,6 +1892,11 @@ UTF-8 字符串文本 + + using type alias + using type alias + + with on anonymous types 在匿名类型上 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index e5f4abba7bf21..05e4e20682343 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -197,6 +197,11 @@ /nullable 的選項 '{0}' 無效; 必須為 'disable'、'enable'、'warnings' 或 'annotations' + + Using alias cannot be a nullable reference type. + Using alias cannot be a nullable reference type. + + The typeof operator cannot be used on a nullable reference type typeof 運算子不得用於可為 Null 的參考型別上 @@ -227,11 +232,21 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + + Using alias cannot be a 'ref' type. + Using alias cannot be a 'ref' type. + + Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'. 命令列語法錯誤: '{0}' 對 '{1}' 選項而言不是有效的值。此值的格式必須是 '{2}'。 + + Only a using alias can be 'unsafe'. + Only a using alias can be 'unsafe'. + + The AsyncMethodBuilder attribute is disallowed on anonymous methods without an explicit return type. 沒有明確傳回型別的匿名方法上不允許 AsyncMethodBuilder 屬性。 @@ -1877,6 +1892,11 @@ UTF-8 字串常值 + + using type alias + using type alias + + with on anonymous types 在匿名型別上 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 81a224f586df3..5998f24f35e3b 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -5400,24 +5400,22 @@ public void TupleUnsupportedInUsingStatement() var source = @" using VT2 = (int, int); "; - var comp = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics( - // (2,13): error CS1001: Identifier expected - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(2, 13), - // (2,13): error CS1002: ; expected - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(2, 13), - // (2,14): error CS1525: Invalid expression term 'int' + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9).VerifyDiagnostics( + // (2,13): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(2, 14), - // (2,19): error CS1525: Invalid expression term 'int' + Diagnostic(ErrorCode.ERR_FeatureInPreview, "(int, int)").WithArguments("using type alias").WithLocation(2, 13), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (2,1): hidden CS8019: Unnecessary using directive. // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(2, 19), + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using VT2 = (int, int);").WithLocation(2, 1)); + + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), // (2,1): hidden CS8019: Unnecessary using directive. // using VT2 = (int, int); - Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using VT2 = ").WithLocation(2, 1) - ); + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using VT2 = (int, int);").WithLocation(2, 1)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_Dynamic.cs b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_Dynamic.cs index 0c80534ca8a79..415f06c50e619 100644 --- a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_Dynamic.cs +++ b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_Dynamic.cs @@ -876,7 +876,7 @@ public void TestDynamicAttributeForScript_DynamicTypeArgument_NoCore() } [Fact] - public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget() + public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget1() { var source = "using X = Gen;" @@ -898,7 +898,29 @@ public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget() } [Fact] - public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget_NoCore() + public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget2() + { + var source = + "using X = dynamic[];" + + GetNoCS1980String(typeName: @"dynamic[]") + + "X x = null;"; + + var comp = CreateCompilationWithMscorlib45( + source: source, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Script.WithLanguageVersion(LanguageVersion.Preview), + references: new[] { SystemCoreRef }); + + CompileAndVerify(comp, symbolValidator: module => + { + var implicitField = module.GlobalNamespace.GetTypeMember("Script").GetMember("x"); + var expectedTransformsFlags = new bool[] { false, true }; + DynamicAttributeValidator.ValidateDynamicAttribute(implicitField.GetAttributes(), expectedDynamicAttribute: true, expectedTransformFlags: expectedTransformsFlags); + }); + } + + [Fact] + public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget_NoCore1() { var source = "using X = Gen;" @@ -911,6 +933,23 @@ public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget_NoCore() Diagnostic(ErrorCode.ERR_DynamicAttributeMissing, "X").WithArguments("System.Runtime.CompilerServices.DynamicAttribute").WithLocation(20, 1)); } + [Fact] + public void TestDynamicAttributeForScript_DynamicTypeInAliasTarget_NoCore2() + { + var source = + "using X = dynamic[];" + + GetNoCS1980String(typeName: @"dynamic[]") + + "X x = null;"; + + var comp = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.Script).VerifyDiagnostics( + // (1,11): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using X = dynamic[]; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "dynamic[]").WithArguments("using type alias").WithLocation(1, 11), + // (20,1): error CS1980: Cannot define a class or member that utilizes 'dynamic' because the compiler required type 'System.Runtime.CompilerServices.DynamicAttribute' cannot be found. Are you missing a reference? + // X x = null; + Diagnostic(ErrorCode.ERR_DynamicAttributeMissing, "X").WithArguments("System.Runtime.CompilerServices.DynamicAttribute").WithLocation(20, 1)); + } + [Fact, WorkItem(531108, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531108")] public void DynamicAttributeCtorCS1980BreakingChange() { @@ -1304,7 +1343,7 @@ public void TestDynamicAttributeForSubmissionGlobalStatement() [Theory] [InlineData(SourceCodeKind.Regular)] [InlineData(SourceCodeKind.Script)] - public void TestDynamicAttributeInAliasContext(SourceCodeKind sourceCodeKind) + public void TestDynamicAttributeInAliasContext1(SourceCodeKind sourceCodeKind) { string source = "using X = Gen; // No CS1980" @@ -1315,6 +1354,20 @@ public void TestDynamicAttributeInAliasContext(SourceCodeKind sourceCodeKind) parseOptions: new CSharpParseOptions(kind: sourceCodeKind, languageVersion: LanguageVersion.CSharp7_2))); } + [Theory] + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script)] + public void TestDynamicAttributeInAliasContext2(SourceCodeKind sourceCodeKind) + { + string source = + "using X = dynamic[]; // No CS1980" + + GetNoCS1980String(typeName: "X"); + + CompileAndVerify(CreateCompilationWithMscorlib45( + source: source, + parseOptions: new CSharpParseOptions(kind: sourceCodeKind, languageVersion: LanguageVersion.Preview))); + } + [Theory] [InlineData(SourceCodeKind.Regular)] [InlineData(SourceCodeKind.Script)] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs index c55f262b64ca0..ec231b00bee0b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs @@ -33,25 +33,18 @@ public void UsingAliasTest() using s = delegate*;"); comp.VerifyDiagnostics( - // (2,11): error CS1041: Identifier expected; 'delegate' is a keyword + // (2,11): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // using s = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(2, 11), - // (2,26): error CS1001: Identifier expected + Diagnostic(ErrorCode.ERR_FeatureInPreview, "delegate*").WithArguments("using type alias").WithLocation(2, 11), + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // using s = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(2, 26), + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(2, 11), // (2,7): warning CS8981: The type name 's' only contains lower-cased ascii characters. Such names may become reserved for the language. // using s = delegate*; Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "s").WithArguments("s").WithLocation(2, 7), - // (2,11): error CS8805: Program using top-level statements must be an executable. - // using s = delegate*; - Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "delegate*;").WithLocation(2, 11), - // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context - // using s = delegate*; - Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(2, 11), // (2,1): hidden CS8019: Unnecessary using directive. // using s = delegate*; - Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using s = ").WithLocation(2, 1) - ); + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using s = delegate*;").WithLocation(2, 1)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GlobalUsingDirectiveTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GlobalUsingDirectiveTests.cs index 56c1d8f28a0e0..2dbb4f39dcb0e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GlobalUsingDirectiveTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GlobalUsingDirectiveTests.cs @@ -5011,5 +5011,121 @@ class C2 {} Assert.Equal("alias1=C1", model.GetSpeculativeAliasInfo(tree.GetRoot().Span.End, alias1, SpeculativeBindingOption.BindAsExpression).ToTestDisplayString()); Assert.Equal("alias1=C1", model.GetSpeculativeAliasInfo(tree.GetRoot().Span.End, alias1, SpeculativeBindingOption.BindAsTypeOrNamespace).ToTestDisplayString()); } + + [Fact] + public void GlobalAliasToType1() + { + var source1 = @" +global using X = int; +"; + var source2 = @" +class C +{ + X Goo(int i) => i; +} +"; + + CreateCompilation(new[] { source1, source2 }, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (2,18): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // global using X = int; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "int").WithArguments("using type alias").WithLocation(2, 18)); + + CreateCompilation(new[] { source1, source2 }, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + + [Fact] + public void GlobalAliasToUnsafeType_CompilationOptionOff() + { + var source1 = @" +global using unsafe X = int*; +"; + var source2 = @" +class C +{ + unsafe X Goo() => default; +} +"; + + CreateCompilation(new[] { source1, source2 }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,14): error CS0227: Unsafe code may only appear if compiling with /unsafe + // global using unsafe X = int*; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 14), + // (4,14): error CS0227: Unsafe code may only appear if compiling with /unsafe + // unsafe X Goo() => default; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "Goo").WithLocation(4, 14)); + } + + [Fact] + public void GlobalAliasToUnsafeType_CompilationOptionOn_CSharp11() + { + var source1 = @" +global using unsafe X = int*; +"; + var source2 = @" +class C +{ + unsafe X Goo() => default; +} +"; + + CreateCompilation(new[] { source1, source2 }, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (2,14): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // global using unsafe X = int*; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 14)); + } + + [Fact] + public void GlobalAliasToUnsafeType1() + { + var source1 = @" +global using unsafe X = int*; +"; + var source2 = @" +class C +{ + X Goo() => default; +} +"; + + CreateCompilation(new[] { source1, source2 }, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (4,5): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // X Goo() => default; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(4, 5)); + } + + [Fact] + public void GlobalAliasToUnsafeType2() + { + var source1 = @" +global using X = int*; +"; + var source2 = @" +class C +{ + unsafe X Goo() => default; +} +"; + + CreateCompilation(new[] { source1, source2 }, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,18): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // global using X = int*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 18)); + } + + [Fact] + public void GlobalAliasToUnsafeType3() + { + var source1 = @" +global using unsafe X = int*; +"; + var source2 = @" +class C +{ + unsafe X Goo(int* p) => p; +} +"; + + CreateCompilation(new[] { source1, source2 }, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs index 0f148eb6d69aa..4fff2d22294c0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs @@ -3750,8 +3750,7 @@ static void verify(CSharpCompilation comp) } } - [WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] - [Fact] + [Fact, WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] public void AliasName_04() { var source = @@ -3762,25 +3761,33 @@ class Program A1 F1() => default; A2 F2() => default; }"; - var expectedDiagnostics = new[] - { - // (1,12): error CS0246: The type or namespace name 'nint' could not be found (are you missing a using directive or an assembly reference?) + + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8).VerifyDiagnostics( + // (1,12): error CS8400: Feature 'native-sized integers' is not available in C# 8.0. Please use language version 9.0 or greater. + // using A1 = nint; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "nint").WithArguments("native-sized integers", "9.0").WithLocation(1, 12), + // (1,12): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // using A1 = nint; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nint").WithArguments("nint").WithLocation(1, 12), - // (2,12): error CS0246: The type or namespace name 'nuint' could not be found (are you missing a using directive or an assembly reference?) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "nint").WithArguments("using type alias").WithLocation(1, 12), + // (2,12): error CS8400: Feature 'native-sized integers' is not available in C# 8.0. Please use language version 9.0 or greater. // using A2 = nuint; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nuint").WithArguments("nuint").WithLocation(2, 12) - }; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "nuint").WithArguments("native-sized integers", "9.0").WithLocation(2, 12), + // (2,12): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using A2 = nuint; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "nuint").WithArguments("using type alias").WithLocation(2, 12)); - var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); - comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular9).VerifyDiagnostics( + // (1,12): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using A1 = nint; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "nint").WithArguments("using type alias").WithLocation(1, 12), + // (2,12): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using A2 = nuint; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "nuint").WithArguments("using type alias").WithLocation(2, 12)); - comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); } - [WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] - [Fact] + [Fact, WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] public void AliasName_05() { var source1 = @@ -3803,6 +3810,91 @@ class B { } comp = CreateCompilation(new[] { source1, source2 }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); + + comp = CreateCompilation(new[] { source1, source2 }, parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] + public void AliasName_06() + { + var source1 = +@"using A=nint; +class nint { } +"; + + var comp = CreateCompilation(source1, parseOptions: TestOptions.Regular8); + comp.VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using A=nint; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A=nint;").WithLocation(1, 1), + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7)); + + comp = CreateCompilation(source1, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using A=nint; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A=nint;").WithLocation(1, 1), + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7)); + + comp = CreateCompilation(source1, parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using A=nint; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A=nint;").WithLocation(1, 1), + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7)); + } + + [Fact, WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] + public void AliasName_07() + { + var source1 = +@"using A=nint; +class nint { } + +class C +{ + void M(A a, global::nint b, System.IntPtr c) + { + // Ensure that in all cases A binds to the class, and not System.IntPtr + System.Console.WriteLine(a == b); + System.Console.WriteLine(a == c); + } +} +"; + + var comp = CreateCompilation(source1, parseOptions: TestOptions.Regular8); + comp.VerifyDiagnostics( + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7), + // (10,34): error CS0019: Operator '==' cannot be applied to operands of type 'nint' and 'IntPtr' + // System.Console.WriteLine(a == c); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "a == c").WithArguments("==", "nint", "System.IntPtr").WithLocation(10, 34)); + + comp = CreateCompilation(source1, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics( + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7), + // (10,34): error CS0019: Operator '==' cannot be applied to operands of type 'nint' and 'IntPtr' + // System.Console.WriteLine(a == c); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "a == c").WithArguments("==", "nint", "System.IntPtr").WithLocation(10, 34)); + + comp = CreateCompilation(source1, parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics( + // (2,7): warning CS8981: The type name 'nint' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class nint { } + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "nint").WithArguments("nint").WithLocation(2, 7), + // (10,34): error CS0019: Operator '==' cannot be applied to operands of type 'nint' and 'IntPtr' + // System.Console.WriteLine(a == c); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "a == c").WithArguments("==", "nint", "System.IntPtr").WithLocation(10, 34)); } [WorkItem(42975, "https://github.com/dotnet/roslyn/issues/42975")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs index d93c5cc60a116..73ba7b40eccba 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs @@ -2132,5 +2132,76 @@ struct S Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "new S()").WithArguments("S.implicit operator bool(S)").WithLocation(6, 5) ); } + + [Fact] + public void TestIsNullable1() + { + var source = @" +class C +{ + void M(object o) + { + if (o is int? i) + { + } + } +} +"; + + CreateCompilation(source).VerifyDiagnostics( + // (6,23): error CS0103: The name 'i' does not exist in the current context + // if (o is int? i) + Diagnostic(ErrorCode.ERR_NameNotInContext, "i").WithArguments("i").WithLocation(6, 23), + // (6,24): error CS1003: Syntax error, ':' expected + // if (o is int? i) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(6, 24), + // (6,24): error CS1525: Invalid expression term ')' + // if (o is int? i) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 24)); + } + + [Fact] + public void TestIsNullable2() + { + var source = @" +using A = System.Nullable; +class C +{ + void M(object o) + { + if (o is A i) + { + } + } +} +"; + + CreateCompilation(source).VerifyDiagnostics( + // (7,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead. + // if (o is A i) + Diagnostic(ErrorCode.ERR_PatternNullableType, "A").WithArguments("int").WithLocation(7, 18)); + } + + [Fact] + public void TestIsNullable3() + { + var source = @" +using A = int?; +class C +{ + void M(object o) + { + if (o is A i) + { + } + } +} +"; + + CreateCompilation(source).VerifyDiagnostics( + // (7,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead. + // if (o is A i) + Diagnostic(ErrorCode.ERR_PatternNullableType, "A").WithArguments("int").WithLocation(7, 18)); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 65eeafb8fed44..b2146c0614c7e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -9539,5 +9539,510 @@ public unsafe struct CAPROPVARIANT var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); comp.VerifyDiagnostics(); } + + [Fact] + public void TestUnsafeAliasWithCompilationOptionOff1() + { + var csharp = @" +using unsafe X = int*; + +class C +{ +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.DebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int*;").WithLocation(2, 1), + // (2,7): error CS0227: Unsafe code may only appear if compiling with /unsafe + // using unsafe X = int*; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasWithCompilationOptionOff2() + { + var csharp = @" +using unsafe X = int; + +class C +{ +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.DebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int;").WithLocation(2, 1), + // (2,7): error CS0227: Unsafe code may only appear if compiling with /unsafe + // using unsafe X = int; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_1() + { + var csharp = @" +using unsafe X = int*; +"; + var comp = CreateCompilation(csharp, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int*;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = int*; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7), + // (2,7): error CS0227: Unsafe code may only appear if compiling with /unsafe + // using unsafe X = int*; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_2() + { + var csharp = @" +using unsafe X = int; +"; + var comp = CreateCompilation(csharp, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = int; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7), + // (2,7): error CS0227: Unsafe code may only appear if compiling with /unsafe + // using unsafe X = int; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_3() + { + var csharp = @" +using unsafe X = int*; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int*;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = int*; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_4() + { + var csharp = @" +using unsafe X = int; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = int; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_5() + { + var csharp = @" +using unsafe X = System.String; +"; + var comp = CreateCompilation(csharp, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = System.String; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = System.String;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = System.String; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7), + // (2,7): error CS0227: Unsafe code may only appear if compiling with /unsafe + // using unsafe X = System.String; + Diagnostic(ErrorCode.ERR_IllegalUnsafe, "unsafe").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAliasCSharp11_6() + { + var csharp = @" +using unsafe X = System.String; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular11); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = System.String; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = System.String;").WithLocation(2, 1), + // (2,7): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using unsafe X = System.String; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("using type alias").WithLocation(2, 7)); + } + + [Fact] + public void TestUnsafeAlias1() + { + var csharp = @" +using unsafe X = int*; +using Y = int*; + +class C +{ + void M1(X x) { } + unsafe void M2(X x) { } + + void N1(Y y) { } + unsafe void N2(Y y) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (3,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using Y = int*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(3, 11), + // (7,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X x) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(7, 13), + // (10,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void N1(Y y) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "Y").WithLocation(10, 13)); + } + + [Fact] + public void TestUnsafeAlias2() + { + var csharp = @" +using unsafe X = int*; +namespace N +{ + using Y = X; +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (5,5): hidden CS8019: Unnecessary using directive. + // using Y = X; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Y = X;").WithLocation(5, 5), + // (5,15): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using Y = X; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(5, 15)); + } + + [Fact] + public void TestUnsafeAlias3() + { + var csharp = @" +using unsafe X = int*; +namespace N +{ + using unsafe Y = X; +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (5,5): hidden CS8019: Unnecessary using directive. + // using unsafe Y = X; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe Y = X;").WithLocation(5, 5)); + } + + [Fact] + public void TestUnsafeAlias5() + { + var csharp = @" +using X = int*; + +class C +{ + void M(int* x) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using X = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = int*;").WithLocation(2, 1), + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using X = int*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 11), + // (6,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M(int* x) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(6, 12)); + } + + [Fact] + public void TestUnsafeAlias6() + { + var csharp = @" +using unsafe X = int*; + +class C +{ + unsafe void M((X x1, X x2) t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,32): error CS0306: The type 'int*' may not be used as a type argument + // unsafe void M((X x1, X x2) t) { } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("int*").WithLocation(6, 32), + // (6,32): error CS0306: The type 'int*' may not be used as a type argument + // unsafe void M((X x1, X x2) t) { } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("int*").WithLocation(6, 32)); + } + + [Fact] + public void TestUnsafeAlias7() + { + var csharp = @" +using unsafe X = int*; + +class C +{ + unsafe void M(X[] t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics(); + } + + [Fact] + public void TestUnsafeAlias8() + { + var csharp = @" +using unsafe X = int*; + +class C +{ + void M(X[] t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M(X[] t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 12)); + } + + [Fact] + public void TestUnsafeAlias9() + { + var csharp = @" +using unsafe X = int*[]; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = int*[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = int*[];").WithLocation(2, 1)); + } + + [Fact] + public void TestUnsafeAlias10() + { + var csharp = @" +using X = int*[]; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using X = int*[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = int*[];").WithLocation(2, 1), + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using X = int*[]; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 11)); + } + + [Fact] + public void TestUnsafeAlias11() + { + var csharp = @" +using unsafe X = int*[]; + +class C +{ + void M1(X t) { } + unsafe void M2(X t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } + + [Fact] + public void TestUnsafeAlias13() + { + var csharp = @" +using unsafe X = int*[][]; + +class C +{ + void M1(X t) { } + unsafe void M2(X t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } + + [Fact] + public void TestUnsafeAlias1_FP() + { + var csharp = @" +using unsafe X = delegate*; + +class C +{ + void M1(X x) { } + unsafe void M2(X x) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X x) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } + + [Fact] + public void TestUnsafeAlias3_FP() + { + var csharp = @" +using X = delegate*; + +class C +{ + void M1(X x) { } + unsafe void M2(X x) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using X = delegate*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(2, 11), + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X x) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } + + [Fact] + public void TestUnsafeAlias5_FP() + { + var csharp = @" +using X = delegate*; + +class C +{ + void M(int* x) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using X = delegate*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = delegate*;").WithLocation(2, 1), + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using X = delegate*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(2, 11), + // (6,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M(int* x) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(6, 12)); + } + + [Fact] + public void TestUnsafeAlias6_FP() + { + var csharp = @" +using unsafe X = delegate*; + +class C +{ + unsafe void M1((X x1, X x2) t) { } + unsafe void M2(X[] t) { } + void M3(X[] t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,33): error CS0306: The type 'delegate*' may not be used as a type argument + // unsafe void M1((X x1, X x2) t) { } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("delegate*").WithLocation(6, 33), + // (6,33): error CS0306: The type 'delegate*' may not be used as a type argument + // unsafe void M1((X x1, X x2) t) { } + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("delegate*").WithLocation(6, 33), + // (8,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M3(X[] t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(8, 13)); + } + + [Fact] + public void TestUnsafeAlias9_FP() + { + var csharp = @" +using unsafe X = delegate*[]; +using Y = delegate*[]; +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using unsafe X = delegate*[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe X = delegate*[];").WithLocation(2, 1), + // (3,1): hidden CS8019: Unnecessary using directive. + // using Y = delegate*[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Y = delegate*[];").WithLocation(3, 1), + // (3,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using Y = delegate*[]; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(3, 11)); + } + + [Fact] + public void TestUnsafeAlias11_FP() + { + var csharp = @" +using unsafe X = delegate*[]; + +class C +{ + void M1(X t) { } + unsafe void M2(X t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } + + [Fact] + public void TestUnsafeAlias13_FP() + { + var csharp = @" +using unsafe X = delegate*[][]; + +class C +{ + void M1(X t) { } + unsafe void M2(X t) { } +} +"; + var comp = CreateCompilation(csharp, options: TestOptions.UnsafeDebugDll); + comp.VerifyDiagnostics( + // (6,13): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M1(X t) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/UsingAliasTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/UsingAliasTests.cs index 98fb11ce1befd..813eb340ce3cd 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/UsingAliasTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/UsingAliasTests.cs @@ -4,12 +4,10 @@ #nullable disable -using Microsoft.CodeAnalysis.CSharp.Symbols; +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; -using System.Linq; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Source @@ -28,7 +26,7 @@ partial class A : System.Object {} partial class A : Object {} "; var tree = Parse(text); - var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var root = tree.GetCompilationUnitRoot(); var comp = CreateCompilation(tree); var usingAlias = root.Usings[0]; @@ -38,10 +36,67 @@ partial class A : Object {} var a3 = root.Members[2] as TypeDeclarationSyntax; var a4 = root.Members[3] as TypeDeclarationSyntax; - var base1 = a1.BaseList.Types[0].Type as TypeSyntax; - var base2 = a2.BaseList.Types[0].Type as TypeSyntax; - var base3 = a3.BaseList.Types[0].Type as TypeSyntax; - var base4 = a4.BaseList.Types[0].Type as TypeSyntax; + var base1 = a1.BaseList.Types[0].Type; + var base2 = a2.BaseList.Types[0].Type; + var base3 = a3.BaseList.Types[0].Type; + var base4 = a4.BaseList.Types[0].Type; + + var model = comp.GetSemanticModel(tree); + + var info1 = model.GetSemanticInfoSummary(base1); + Assert.NotNull(info1.Symbol); + var alias1 = model.GetAliasInfo((IdentifierNameSyntax)base1); + Assert.NotNull(alias1); + Assert.Equal(SymbolKind.Alias, alias1.Kind); + Assert.Equal("O", alias1.ToDisplayString()); + Assert.Equal("O=System.Object", alias1.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal(info1.Symbol, alias1.Target); + + var info2 = model.GetSemanticInfoSummary(base2); + Assert.NotNull(info2.Symbol); + var b2 = info2.Symbol; + Assert.Equal("System.Object", b2.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info2.Type.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + var info3 = model.GetSemanticInfoSummary(base3); + Assert.NotNull(info3.Symbol); + var b3 = info3.Symbol; + Assert.Equal("System.Object", b3.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info3.Type.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + var info4 = model.GetSemanticInfoSummary(base4); + Assert.Null(info4.Symbol); // no "using System;" + Assert.Equal(0, info4.CandidateSymbols.Length); + var alias4 = model.GetAliasInfo((IdentifierNameSyntax)base4); + Assert.Null(alias4); + } + + [Fact] + public void GetSemanticInfo_PrimitiveType() + { + var text = +@"using O = object; + +partial class A : O {} +partial class A : object {} +partial class A : System.Object {} +partial class A : Object {} +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot(); + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var a1 = root.Members[0] as TypeDeclarationSyntax; + var a2 = root.Members[1] as TypeDeclarationSyntax; + var a3 = root.Members[2] as TypeDeclarationSyntax; + var a4 = root.Members[3] as TypeDeclarationSyntax; + + var base1 = a1.BaseList.Types[0].Type; + var base2 = a2.BaseList.Types[0].Type; + var base3 = a3.BaseList.Types[0].Type; + var base4 = a4.BaseList.Types[0].Type; var model = comp.GetSemanticModel(tree); @@ -79,6 +134,61 @@ public void GetSymbolInfoInParent() var text = @"using O = System.Object; +partial class A : O {} +partial class A : object {} +partial class A : System.Object {} +partial class A : Object {} +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var a1 = root.Members[0] as TypeDeclarationSyntax; + var a2 = root.Members[1] as TypeDeclarationSyntax; + var a3 = root.Members[2] as TypeDeclarationSyntax; + var a4 = root.Members[3] as TypeDeclarationSyntax; + + var base1 = a1.BaseList.Types[0].Type as TypeSyntax; + var base2 = a2.BaseList.Types[0].Type as TypeSyntax; + var base3 = a3.BaseList.Types[0].Type as TypeSyntax; + var base4 = a4.BaseList.Types[0].Type as TypeSyntax; + + var model = comp.GetSemanticModel(tree); + + var info1 = model.GetSemanticInfoSummary(base1); + Assert.Equal("System.Object", info1.Type.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + var alias1 = model.GetAliasInfo((IdentifierNameSyntax)base1); + Assert.NotNull(alias1); + Assert.Equal(SymbolKind.Alias, alias1.Kind); + Assert.Equal("O=System.Object", alias1.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + var info2 = model.GetSemanticInfoSummary(base2); + Assert.NotNull(info2.Symbol); + var b2 = info2.Symbol; + Assert.Equal("System.Object", b2.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info2.Type.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + var info3 = model.GetSemanticInfoSummary(base3); + Assert.NotNull(info3.Symbol); + var b3 = info3.Symbol; + Assert.Equal("System.Object", b3.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info3.Type.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + var info4 = model.GetSemanticInfoSummary(base4); + Assert.Null(info4.Symbol); // no "using System;" + Assert.Equal(0, info4.CandidateSymbols.Length); + var alias4 = model.GetAliasInfo((IdentifierNameSyntax)base4); + Assert.Null(alias4); + } + + [Fact] + public void GetSymbolInfoInParent_Primitive() + { + var text = +@"using O = object; + partial class A : O {} partial class A : object {} partial class A : System.Object {} @@ -134,6 +244,52 @@ public void BindType() var text = @"using O = System.Object; +partial class A : O {} +partial class A : object {} +partial class A : System.Object {} +partial class A : Object {} +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var a1 = root.Members[0] as TypeDeclarationSyntax; + var a2 = root.Members[1] as TypeDeclarationSyntax; + var a3 = root.Members[2] as TypeDeclarationSyntax; + var a4 = root.Members[3] as TypeDeclarationSyntax; + + var base1 = a1.BaseList.Types[0].Type as TypeSyntax; + var base2 = a2.BaseList.Types[0].Type as TypeSyntax; + var base3 = a3.BaseList.Types[0].Type as TypeSyntax; + var base4 = a4.BaseList.Types[0].Type as TypeSyntax; + + var model = comp.GetSemanticModel(tree); + + var symbolInfo = model.GetSpeculativeSymbolInfo(base2.SpanStart, base2, SpeculativeBindingOption.BindAsTypeOrNamespace); + var info2 = symbolInfo.Symbol as ITypeSymbol; + Assert.NotNull(info2); + Assert.Equal("System.Object", info2.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info2.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + symbolInfo = model.GetSpeculativeSymbolInfo(base3.SpanStart, base3, SpeculativeBindingOption.BindAsTypeOrNamespace); + var info3 = symbolInfo.Symbol as ITypeSymbol; + Assert.NotNull(info3); + Assert.Equal("System.Object", info3.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + Assert.Equal("System.Object", info3.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + + symbolInfo = model.GetSpeculativeSymbolInfo(base4.SpanStart, base4, SpeculativeBindingOption.BindAsTypeOrNamespace); + var info4 = symbolInfo.Symbol as ITypeSymbol; + Assert.Null(info4); // no "using System;" + } + + [Fact] + public void BindType_Primitive() + { + var text = +@"using O = object; + partial class A : O {} partial class A : object {} partial class A : System.Object {} @@ -195,6 +351,27 @@ public void GetDeclaredSymbol01() Assert.Equal(NamespaceKind.Module, global.NamespaceKind); } + [Fact] + public void GetDeclaredSymbol01_Primitive() + { + var text = +@"using O = object; +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var model = comp.GetSemanticModel(tree); + + var alias = model.GetDeclaredSymbol(usingAlias); + Assert.Equal("O", alias.ToDisplayString()); + Assert.Equal("O=System.Object", alias.ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + var global = (INamespaceSymbol)alias.ContainingSymbol; + Assert.Equal(NamespaceKind.Module, global.NamespaceKind); + } + [Fact] public void GetDeclaredSymbol02() { @@ -230,6 +407,25 @@ class C {} Assert.Contains("O", names); } + [Fact] + public void LookupNames_Primitive() + { + var text = +@"using O = object; +class C {} +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var model = comp.GetSemanticModel(tree); + + var names = model.LookupNames(root.Members[0].SpanStart); + Assert.Contains("O", names); + } + [Fact] public void LookupSymbols() { @@ -251,6 +447,27 @@ class C {} Assert.Equal("O=System.Object", symbols[0].ToDisplayString(format: SymbolDisplayFormat.TestFormat)); } + [Fact] + public void LookupSymbols_Primitive() + { + var text = +@"using O = object; +class C {} +"; + var tree = Parse(text); + var root = tree.GetCompilationUnitRoot() as CompilationUnitSyntax; + var comp = CreateCompilation(tree); + + var usingAlias = root.Usings[0]; + + var model = comp.GetSemanticModel(tree); + + var symbols = model.LookupSymbols(root.Members[0].SpanStart, name: "O"); + Assert.Equal(1, symbols.Length); + Assert.Equal(SymbolKind.Alias, symbols[0].Kind); + Assert.Equal("O=System.Object", symbols[0].ToDisplayString(format: SymbolDisplayFormat.TestFormat)); + } + [WorkItem(537401, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537401")] [Fact] public void EventEscapedIdentifier() @@ -287,6 +504,66 @@ static void Main() Assert.Equal(SymbolKind.Alias, model.GetAliasInfo(exprSyntaxToBind).Kind); } + [WorkItem(541937, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541937")] + [Fact] + public void LocalDeclaration_Primitive() + { + var text = @" +using GIBBERISH = int; +class Program +{ + static void Main() + { + /**/GIBBERISH/**/ x; + } +}"; + SyntaxTree syntaxTree = Parse(text); + CSharpCompilation comp = CreateCompilation(syntaxTree); + var model = comp.GetSemanticModel(syntaxTree); + IdentifierNameSyntax exprSyntaxToBind = (IdentifierNameSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(syntaxTree)); + Assert.Equal(SymbolKind.Alias, model.GetAliasInfo(exprSyntaxToBind).Kind); + } + + [Fact, WorkItem(541937, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541937")] + public void LocalDeclaration_Array() + { + var text = @" +using GIBBERISH = int[]; +class Program +{ + static void Main() + { + /**/GIBBERISH/**/ x; + } +}"; + SyntaxTree syntaxTree = Parse(text); + CSharpCompilation comp = CreateCompilation(syntaxTree); + var model = comp.GetSemanticModel(syntaxTree); + IdentifierNameSyntax exprSyntaxToBind = (IdentifierNameSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(syntaxTree)); + Assert.Equal(SymbolKind.Alias, model.GetAliasInfo(exprSyntaxToBind).Kind); + Assert.Equal("System.Int32[]", model.GetAliasInfo(exprSyntaxToBind).Target.ToTestDisplayString()); + } + + [Fact, WorkItem(541937, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541937")] + public void LocalDeclaration_Tuple() + { + var text = @" +using GIBBERISH = (int, int); +class Program +{ + static void Main() + { + /**/GIBBERISH/**/ x; + } +}"; + SyntaxTree syntaxTree = Parse(text); + CSharpCompilation comp = CreateCompilation(syntaxTree); + var model = comp.GetSemanticModel(syntaxTree); + IdentifierNameSyntax exprSyntaxToBind = (IdentifierNameSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(syntaxTree)); + Assert.Equal(SymbolKind.Alias, model.GetAliasInfo(exprSyntaxToBind).Kind); + Assert.Equal("(System.Int32, System.Int32)", model.GetAliasInfo(exprSyntaxToBind).Target.ToTestDisplayString()); + } + [WorkItem(576809, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/576809")] [Fact] public void AsClause() @@ -294,6 +571,29 @@ public void AsClause() var text = @" using N = System.Nullable; +class Program +{ + static void Main() + { + object x = 1; + var y = x as /**/N/**/ + 1; + } +} +"; + SyntaxTree syntaxTree = Parse(text); + CSharpCompilation comp = CreateCompilation(syntaxTree); + var model = comp.GetSemanticModel(syntaxTree); + IdentifierNameSyntax exprSyntaxToBind = (IdentifierNameSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(syntaxTree)); + Assert.Equal("System.Int32?", model.GetAliasInfo(exprSyntaxToBind).Target.ToTestDisplayString()); + } + + [WorkItem(576809, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/576809")] + [Fact] + public void AsClause_Nullable() + { + var text = @" +using N = int?; + class Program { static void Main() 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 f931cdc30f3ce..ad886fc180cc6 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 @@ -455,7 +455,7 @@ private static Syntax.InternalSyntax.ExternAliasDirectiveSyntax GenerateExternAl => InternalSyntaxFactory.ExternAliasDirective(InternalSyntaxFactory.Token(SyntaxKind.ExternKeyword), InternalSyntaxFactory.Token(SyntaxKind.AliasKeyword), InternalSyntaxFactory.Identifier("Identifier"), InternalSyntaxFactory.Token(SyntaxKind.SemicolonToken)); private static Syntax.InternalSyntax.UsingDirectiveSyntax GenerateUsingDirective() - => InternalSyntaxFactory.UsingDirective(null, InternalSyntaxFactory.Token(SyntaxKind.UsingKeyword), null, null, GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.SemicolonToken)); + => InternalSyntaxFactory.UsingDirective(null, InternalSyntaxFactory.Token(SyntaxKind.UsingKeyword), null, null, null, GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.SemicolonToken)); private static Syntax.InternalSyntax.NamespaceDeclarationSyntax GenerateNamespaceDeclaration() => InternalSyntaxFactory.NamespaceDeclaration(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.NamespaceKeyword), GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken), null); @@ -2558,8 +2558,9 @@ public void TestUsingDirectiveFactoryAndProperties() Assert.Null(node.GlobalKeyword); Assert.Equal(SyntaxKind.UsingKeyword, node.UsingKeyword.Kind); Assert.Null(node.StaticKeyword); + Assert.Null(node.UnsafeKeyword); Assert.Null(node.Alias); - Assert.NotNull(node.Name); + Assert.NotNull(node.Type); Assert.Equal(SyntaxKind.SemicolonToken, node.SemicolonToken.Kind); AttachAndCheckDiagnostics(node); @@ -10427,7 +10428,7 @@ private static ExternAliasDirectiveSyntax GenerateExternAliasDirective() => SyntaxFactory.ExternAliasDirective(SyntaxFactory.Token(SyntaxKind.ExternKeyword), SyntaxFactory.Token(SyntaxKind.AliasKeyword), SyntaxFactory.Identifier("Identifier"), SyntaxFactory.Token(SyntaxKind.SemicolonToken)); private static UsingDirectiveSyntax GenerateUsingDirective() - => SyntaxFactory.UsingDirective(default(SyntaxToken), SyntaxFactory.Token(SyntaxKind.UsingKeyword), default(SyntaxToken), default(NameEqualsSyntax), GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + => SyntaxFactory.UsingDirective(default(SyntaxToken), SyntaxFactory.Token(SyntaxKind.UsingKeyword), default(SyntaxToken), default(SyntaxToken), default(NameEqualsSyntax), GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.SemicolonToken)); private static NamespaceDeclarationSyntax GenerateNamespaceDeclaration() => SyntaxFactory.NamespaceDeclaration(new SyntaxList(), new SyntaxTokenList(), SyntaxFactory.Token(SyntaxKind.NamespaceKeyword), GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SyntaxList(), new SyntaxList(), new SyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken), default(SyntaxToken)); @@ -12530,10 +12531,11 @@ public void TestUsingDirectiveFactoryAndProperties() Assert.Equal(SyntaxKind.None, node.GlobalKeyword.Kind()); Assert.Equal(SyntaxKind.UsingKeyword, node.UsingKeyword.Kind()); Assert.Equal(SyntaxKind.None, node.StaticKeyword.Kind()); + Assert.Equal(SyntaxKind.None, node.UnsafeKeyword.Kind()); Assert.Null(node.Alias); - Assert.NotNull(node.Name); + Assert.NotNull(node.Type); Assert.Equal(SyntaxKind.SemicolonToken, node.SemicolonToken.Kind()); - var newNode = node.WithGlobalKeyword(node.GlobalKeyword).WithUsingKeyword(node.UsingKeyword).WithStaticKeyword(node.StaticKeyword).WithAlias(node.Alias).WithName(node.Name).WithSemicolonToken(node.SemicolonToken); + var newNode = node.WithGlobalKeyword(node.GlobalKeyword).WithUsingKeyword(node.UsingKeyword).WithStaticKeyword(node.StaticKeyword).WithUnsafeKeyword(node.UnsafeKeyword).WithAlias(node.Alias).WithType(node.Type).WithSemicolonToken(node.SemicolonToken); Assert.Equal(node, newNode); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs index a34aba8e00807..5558cd2837d5a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs @@ -4126,14 +4126,7 @@ public void FunctionPointerArrayInTypeArgument() [Fact] public void UsingAlias() { - UsingNode("using t = delegate*;", options: TestOptions.Regular9, - // (1,11): error CS1041: Identifier expected; 'delegate' is a keyword - // using t = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(1, 11), - // (1,26): error CS1001: Identifier expected - // using t = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 26) - ); + UsingNode("using t = delegate*;", options: TestOptions.Regular9); N(SyntaxKind.CompilationUnit); { @@ -4148,42 +4141,24 @@ public void UsingAlias() } N(SyntaxKind.EqualsToken); } - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.SemicolonToken); - } - N(SyntaxKind.GlobalStatement); - { - N(SyntaxKind.LocalDeclarationStatement); + N(SyntaxKind.FunctionPointerType); { - N(SyntaxKind.VariableDeclaration); + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); { - N(SyntaxKind.FunctionPointerType); + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); { - N(SyntaxKind.DelegateKeyword); - N(SyntaxKind.AsteriskToken); - N(SyntaxKind.FunctionPointerParameterList); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.LessThanToken); - N(SyntaxKind.FunctionPointerParameter); - { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - } - N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.VoidKeyword); } } - M(SyntaxKind.VariableDeclarator); - { - M(SyntaxKind.IdentifierToken); - } + N(SyntaxKind.GreaterThanToken); } - N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.SemicolonToken); } N(SyntaxKind.EndOfFileToken); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs index 3ed4678713b75..521fd20434c66 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; using Xunit.Abstractions; +using Xunit.Sdk; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { @@ -41,7 +42,7 @@ private void VerifyEnumeratorConsumed() if (hasNext) { DumpAndCleanup(); - Assert.False(hasNext, "Test contains unconsumed syntax left over from UsingNode()"); + Assert.False(hasNext, $"Test contains unconsumed syntax left over from UsingNode()\r\n{(this._output as TestOutputHelper)?.Output}"); } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs index e7f4ad2b133ae..d7632bf04728d 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs @@ -1609,27 +1609,19 @@ public void NewKeyword() EOF(); } - [Fact] - public void TupleUnsupportedInUsingStatement() + [Theory] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.Preview)] + public void TupleUnsupportedInUsingStatement(LanguageVersion version) { var test = @" using VT2 = (int, int); "; - UsingTree(test, - // (2,13): error CS1001: Identifier expected - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(2, 13), - // (2,13): error CS1002: ; expected - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(2, 13), - // (2,14): error CS1525: Invalid expression term 'int' - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(2, 14), - // (2,19): error CS1525: Invalid expression term 'int' - // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(2, 19) - ); + var tree = UsingTree(test, TestOptions.RegularPreview.WithLanguageVersion(version)); + + // No parse errors here regardless of version. Errors are just semantic. + tree.GetDiagnostics().Verify(); N(SyntaxKind.CompilationUnit); { @@ -1644,38 +1636,27 @@ public void TupleUnsupportedInUsingStatement() } N(SyntaxKind.EqualsToken); } - M(SyntaxKind.IdentifierName); + N(SyntaxKind.TupleType); { - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.SemicolonToken); - } - N(SyntaxKind.GlobalStatement); - { - N(SyntaxKind.ExpressionStatement); - { - N(SyntaxKind.TupleExpression); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } + N(SyntaxKind.IntKeyword); } - N(SyntaxKind.CommaToken); - N(SyntaxKind.Argument); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } + N(SyntaxKind.IntKeyword); } - N(SyntaxKind.CloseParenToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); } + N(SyntaxKind.SemicolonToken); } N(SyntaxKind.EndOfFileToken); } @@ -2686,14 +2667,7 @@ public void UsingAliasTest() { var test = @"using s = delegate*;"; - UsingTree(test, - // (1,11): error CS1041: Identifier expected; 'delegate' is a keyword - // using s = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(1, 11), - // (1,26): error CS1001: Identifier expected - // using s = delegate*; - Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 26) - ); + UsingTree(test); N(SyntaxKind.CompilationUnit); { @@ -2708,42 +2682,24 @@ public void UsingAliasTest() } N(SyntaxKind.EqualsToken); } - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.SemicolonToken); - } - N(SyntaxKind.GlobalStatement); - { - N(SyntaxKind.LocalDeclarationStatement); + N(SyntaxKind.FunctionPointerType); { - N(SyntaxKind.VariableDeclaration); + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); { - N(SyntaxKind.FunctionPointerType); + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); { - N(SyntaxKind.DelegateKeyword); - N(SyntaxKind.AsteriskToken); - N(SyntaxKind.FunctionPointerParameterList); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.LessThanToken); - N(SyntaxKind.FunctionPointerParameter); - { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - } - N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.VoidKeyword); } } - M(SyntaxKind.VariableDeclarator); - { - M(SyntaxKind.IdentifierToken); - } + N(SyntaxKind.GreaterThanToken); } - N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.SemicolonToken); } N(SyntaxKind.EndOfFileToken); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/UsingDirectiveParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/UsingDirectiveParsingTests.cs new file mode 100644 index 0000000000000..da9e6f8b8e3ed --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/UsingDirectiveParsingTests.cs @@ -0,0 +1,2500 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests; + +public sealed class UsingDirectiveParsingTests : ParsingTests +{ + public UsingDirectiveParsingTests(ITestOutputHelper output) : base(output) { } + + protected override SyntaxTree ParseTree(string text, CSharpParseOptions? options) + { + return SyntaxFactory.ParseSyntaxTree(text, options: options ?? TestOptions.RegularPreview); + } + + [Fact] + public void SimpleUsingDirectiveNamePointer() + { + UsingTree( +@"using A*;", + // (1,8): error CS1002: ; expected + // using A*; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "*").WithLocation(1, 8), + // (1,9): error CS1525: Invalid expression term ';' + // using A*; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(1, 9)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.PointerIndirectionExpression); + { + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SimpleUsingDirectiveRefType() + { + UsingTree( +@"using ref int;", + // (1,14): error CS1001: Identifier expected + // using ref int; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SimpleUsingDirectiveFunctionPointer() + { + UsingTree( +@"using delegate*;", + // (1,27): error CS1001: Identifier expected + // using delegate*; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 27)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SimpleUsingDirectivePredefinedType() + { + UsingTree( +@"using int;", + // (1,10): error CS1001: Identifier expected + // using int; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 10)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SimpleUsingDirectivePredefinedTypePointer() + { + UsingTree( +@"using int*;", + // (1,11): error CS1001: Identifier expected + // using int*; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SimpleUsingDirectiveTuple() + { + UsingTree( +@"using (int, int);", + // (1,11): error CS1001: Identifier expected + // using (int, int); + Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 11), + // (1,13): error CS1001: Identifier expected + // using (int, int); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "int").WithLocation(1, 13), + // (1,13): error CS1026: ) expected + // using (int, int); + Diagnostic(ErrorCode.ERR_CloseParenExpected, "int").WithLocation(1, 13), + // (1,16): error CS1001: Identifier expected + // using (int, int); + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 16), + // (1,16): error CS1002: ; expected + // using (int, int); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(1, 16), + // (1,16): error CS1022: Type or namespace definition, or end-of-file expected + // using (int, int); + Diagnostic(ErrorCode.ERR_EOFExpected, ")").WithLocation(1, 16)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.UsingStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CloseParenToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectiveNamePointer() + { + UsingTree( +@"using static A*;", + // (1,15): error CS1002: ; expected + // using static A*; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "*").WithLocation(1, 15), + // (1,16): error CS1525: Invalid expression term ';' + // using static A*; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(1, 16)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.PointerIndirectionExpression); + { + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectiveRefType() + { + var text = @"using static x = ref int;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using static x = ref int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static x = ref int;").WithLocation(1, 1), + // (1,14): error CS8085: A 'using static' directive cannot be used to declare an alias + // using static x = ref int; + Diagnostic(ErrorCode.ERR_NoAliasHere, "x").WithLocation(1, 14), + // (1,14): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using static x = ref int; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 14), + // (1,18): error CS9105: Using alias cannot be a 'ref' type. + // using static x = ref int; + Diagnostic(ErrorCode.ERR_BadRefInUsingAlias, "ref").WithLocation(1, 18)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectiveFunctionPointer() + { + UsingTree( +@"using static delegate*;", + // (1,7): error CS0106: The modifier 'static' is not valid for this item + // using static delegate*; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(1, 7), + // (1,34): error CS1001: Identifier expected + // using static delegate*; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 34)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectivePredefinedType() + { + UsingTree( +@"using static int;", + // (1,7): error CS0106: The modifier 'static' is not valid for this item + // using static int; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(1, 7), + // (1,17): error CS1001: Identifier expected + // using static int; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectivePredefinedTypePointer() + { + UsingTree( +@"using static int*;", + // (1,7): error CS0106: The modifier 'static' is not valid for this item + // using static int*; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(1, 7), + // (1,18): error CS1001: Identifier expected + // using static int*; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 18)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void StaticUsingDirectiveTuple() + { + UsingTree( +@"using static (int, int);", + // (1,14): error CS1001: Identifier expected + // using static (int, int); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 14), + // (1,14): error CS1002: ; expected + // using static (int, int); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(1, 14), + // (1,15): error CS1525: Invalid expression term 'int' + // using static (int, int); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(1, 15), + // (1,20): error CS1525: Invalid expression term 'int' + // using static (int, int); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(1, 20)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.TupleExpression); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveNamePointer1() + { + var text = +@"using x = A*; + +struct A { }"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = A*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = A*;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = A*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using x = A*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "A*").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveNamePointer2() + { + var text = +@"using unsafe x = A*; + +struct A { }"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using unsafe x = A*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe x = A*;").WithLocation(1, 1), + // (1,14): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using unsafe x = A*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveFunctionPointer1() + { + var text = @"using x = delegate*;"; + + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = delegate*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = delegate*;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = delegate*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using x = delegate*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveFunctionPointer2() + { + var text = @"using unsafe x = delegate*;"; + + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using unsafe x = delegate*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe x = delegate*;").WithLocation(1, 1), + // (1,14): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using unsafe x = delegate*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingUnsafeNonAlias() + { + var text = @"using unsafe System;"; + + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using unsafe System; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe System;").WithLocation(1, 1), + // (1,7): error CS9106: Only a using alias can be 'unsafe'. + // using unsafe System; + Diagnostic(ErrorCode.ERR_BadUnsafeInUsingDirective, "unsafe").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingStaticUnsafeNonAlias() + { + var text = @"using static unsafe System.Console;"; + + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using static unsafe System.Console; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static unsafe System.Console;").WithLocation(1, 1), + // (1,14): error CS9106: Only a using alias can be 'unsafe'. + // using static unsafe System.Console; + Diagnostic(ErrorCode.ERR_BadUnsafeInUsingDirective, "unsafe").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Console"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedType_CSharp11() + { + var text = @"using x = int;"; + UsingTree(text); + CreateCompilation(text, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = int;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = int; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,11): error CS8652: The feature 'using type alias' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // using x = int; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "int").WithArguments("using type alias").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedType() + { + var text = @"using x = int;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = int;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = int; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveRefType() + { + var text = @"using x = ref int;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = ref int; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = ref int;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = ref int; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,11): error CS9105: Using alias cannot be a 'ref' type. + // using x = ref int; + Diagnostic(ErrorCode.ERR_BadRefInUsingAlias, "ref").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer1() + { + var text = @"using x = int*;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = int*;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = int*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using x = int*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer2() + { + var text = @"using unsafe x = int*;"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using unsafe x = int*; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe x = int*;").WithLocation(1, 1), + // (1,14): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using unsafe x = int*; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer3() + { + var text = @" +using unsafe X = int*; + +namespace N +{ + using Y = X; +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,5): hidden CS8019: Unnecessary using directive. + // using Y = X; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Y = X;").WithLocation(6, 5), + // (6,15): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using Y = X; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 15)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "N"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer4() + { + var text = @" +using unsafe X = int*; + +namespace N +{ + using unsafe Y = X; +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,5): hidden CS8019: Unnecessary using directive. + // using unsafe Y = X; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe Y = X;").WithLocation(6, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "N"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer5() + { + var text = @" +using X = int*; + +namespace N +{ + using unsafe Y = X; +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using X = int*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 11), + // (6,5): hidden CS8019: Unnecessary using directive. + // using unsafe Y = X; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe Y = X;").WithLocation(6, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "N"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer6() + { + var text = @" +using unsafe X = int*; + +namespace N +{ + using Y = X[]; +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,5): hidden CS8019: Unnecessary using directive. + // using Y = X[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Y = X[];").WithLocation(6, 5), + // (6,15): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using Y = X[]; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 15)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "N"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectivePredefinedTypePointer7() + { + var text = @" +using unsafe X = int*; + +namespace N +{ + using unsafe Y = X[]; +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,5): hidden CS8019: Unnecessary using directive. + // using unsafe Y = X[]; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using unsafe Y = X[];").WithLocation(6, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "N"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveTuple() + { + var text = @"using x = (int, int);"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = (int, int); + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = (int, int);").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = (int, int); + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingNullableValueType() + { + var text = @"using x = int?;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = int?; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = int?;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = int?; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingNullableReferenceType() + { + var text = @"using x = string?;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using x = string?; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using x = string?;").WithLocation(1, 1), + // (1,7): warning CS8981: The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. + // using x = string?; + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "x").WithArguments("x").WithLocation(1, 7), + // (1,17): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // using x = string?; + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(1, 17), + // (1,17): error CS9107: Using alias cannot be a nullable reference type. + // using x = string?; + Diagnostic(ErrorCode.ERR_BadNullableReferenceTypeInUsingAlias, "?").WithLocation(1, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoidPointer1() + { + var text = @"using unsafe VP = void*; + +class C +{ + void M(VP vp) { } +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (5,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // void M(VP vp) { } + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "VP").WithLocation(5, 12)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.IdentifierToken, "vp"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoidPointer2() + { + var text = @"using unsafe VP = void*; + +class C +{ + unsafe void M(VP vp) { } +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics(); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.IdentifierToken, "vp"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoidPointer3() + { + var text = @"using VP = void*; + +class C +{ + unsafe void M(VP vp) { } +}"; + UsingTree(text); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using VP = void*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "void*").WithLocation(1, 12)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.UnsafeKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VP"); + } + N(SyntaxKind.IdentifierToken, "vp"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoid1() + { + var text = @"using V = void; + +class C +{ + void M(V v) { } +}"; + UsingTree(text, + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11)); + + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.IdentifierToken, "v"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoid2() + { + var text = @"using V = void; + +class C +{ + V M() { } +}"; + UsingTree(text, + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11)); + + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingVoid3() + { + var text = @"using V = void[]; + +class C +{ + V M() { } +}"; + UsingTree(text, + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11)); + + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (1,11): error CS1547: Keyword 'void' cannot be used in this context + // using V = void[]; + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(1, 11), + // (5,7): error CS0161: 'C.M()': not all code paths return a value + // V M() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "M").WithArguments("C.M()").WithLocation(5, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "V"); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirectiveDynamic1() + { + var text = @" +using dynamic;"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using dynamic; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using dynamic;").WithLocation(2, 1), + // (2,7): error CS0246: The type or namespace name 'dynamic' could not be found (are you missing a using directive or an assembly reference?) + // using dynamic; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "dynamic").WithArguments("dynamic").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dynamic"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveDynamic1() + { + var text = @" +using D = dynamic; + +class C +{ + void M(D d) + { + d.Goo(); + } +}"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics(); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dynamic"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveDynamic2() + { + var text = @" +using D = System.Collections.Generic.List; + +class C +{ + void M(D d) + { + d[0].Goo(); + } +}"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics(); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Collections"); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Generic"); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "List"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dynamic"); + } + N(SyntaxKind.GreaterThanToken); + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void AliasUsingDirectiveDynamic3() + { + var text = @" +using D = dynamic[]; + +class C +{ + void M(D d) + { + d[0].Goo(); + } +}"; + UsingTree(text); + CreateCompilation(text).VerifyDiagnostics(); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dynamic"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "d"); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } +} diff --git a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs index 35a61805d82a5..ccf7391ee54b8 100644 --- a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs +++ b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs @@ -223,7 +223,7 @@ private static bool CheckLocation(SourceText text, int position, SyntaxNode owni } // check whether using has contents - if (owningNode is UsingDirectiveSyntax u && u.Name.IsMissing) + if (owningNode is UsingDirectiveSyntax u && u.Type.IsMissing) { return false; } diff --git a/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs b/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs index bb1fd9307cdd8..d9a0fdbb842c0 100644 --- a/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs +++ b/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs @@ -119,7 +119,7 @@ private void AddAliasedNames(CompilationUnitSyntax compilationUnit) void AddAliasedName(UsingDirectiveSyntax usingDirective) { if (usingDirective.Alias is not null && - usingDirective.Name.GetRightmostName() is IdentifierNameSyntax identifierName) + usingDirective.Name?.GetRightmostName() is IdentifierNameSyntax identifierName) { var identifierAlias = identifierName.Identifier.ValueText; if (!string.IsNullOrEmpty(identifierAlias)) diff --git a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.cs b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.cs index f7f062a863672..0879b75f5c555 100644 --- a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.cs +++ b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.cs @@ -1557,7 +1557,7 @@ public override bool TryGetImportNode(SyntaxNode parentNode, string dottedName, { foreach (UsingDirectiveSyntax usingDirective in GetImportNodes(parentNode)) { - if (usingDirective.Name.ToString() == dottedName) + if (usingDirective.Name?.ToString() == dottedName) { importNode = usingDirective; return true; @@ -1838,7 +1838,7 @@ public override string GetImportNamespaceOrType(SyntaxNode importNode) { if (importNode is UsingDirectiveSyntax usingDirective) { - return usingDirective.Name.ToString(); + return usingDirective.Type.ToString(); } throw new InvalidOperationException(); @@ -1852,7 +1852,7 @@ public override void GetImportParentAndName(SyntaxNode importNode, out SyntaxNod ? null : usingDirective.Parent; - name = usingDirective.Name.ToString(); + name = usingDirective.Type.ToString(); return; } diff --git a/src/VisualStudio/CSharp/Impl/Snippets/SnippetExpansionClient.cs b/src/VisualStudio/CSharp/Impl/Snippets/SnippetExpansionClient.cs index a2b2be8eddeed..e31f7dea9d69d 100644 --- a/src/VisualStudio/CSharp/Impl/Snippets/SnippetExpansionClient.cs +++ b/src/VisualStudio/CSharp/Impl/Snippets/SnippetExpansionClient.cs @@ -113,7 +113,7 @@ internal override Document AddImports( // In Venus/Razor, inserting imports statements into the subject buffer does not work. // Instead, we add the imports through the contained language host. - if (TryAddImportsToContainedDocument(document, newUsingDirectives.Where(u => u.Alias == null).Select(u => u.Name.ToString()))) + if (TryAddImportsToContainedDocument(document, newUsingDirectives.Where(u => u.Alias == null).Select(u => u.Name!.ToString()))) { return document; } diff --git a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/UsingDirectiveSyntaxClassifier.cs b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/UsingDirectiveSyntaxClassifier.cs index 427209e1f237a..6cbc8a663d0eb 100644 --- a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/UsingDirectiveSyntaxClassifier.cs +++ b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/UsingDirectiveSyntaxClassifier.cs @@ -41,7 +41,7 @@ private static void ClassifyUsingDirectiveSyntax( { var token = usingDirective.Alias.Name; - var symbolInfo = semanticModel.GetSymbolInfo(usingDirective.Name, cancellationToken); + var symbolInfo = semanticModel.GetSymbolInfo(usingDirective.Type, cancellationToken); if (symbolInfo.Symbol is ITypeSymbol typeSymbol) { var classification = GetClassificationForType(typeSymbol); diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index bd80205536106..582c4f7a4dfa3 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -1899,7 +1899,7 @@ public override string GetName(SyntaxNode declaration) EnumMemberDeclarationSyntax enumMemberDeclaration => enumMemberDeclaration.Identifier.ValueText, EventDeclarationSyntax eventDeclaration => eventDeclaration.Identifier.ValueText, BaseNamespaceDeclarationSyntax namespaceDeclaration => namespaceDeclaration.Name.ToString(), - UsingDirectiveSyntax usingDirective => usingDirective.Name.ToString(), + UsingDirectiveSyntax usingDirective => usingDirective.Name?.ToString() ?? string.Empty, ParameterSyntax parameter => parameter.Identifier.ValueText, LocalDeclarationStatementSyntax localDeclaration => this.GetName(localDeclaration.Declaration), VariableDeclarationSyntax variableDeclaration when variableDeclaration.Variables.Count == 1 => variableDeclaration.Variables[0].Identifier.ValueText, @@ -1929,7 +1929,7 @@ private SyntaxNode WithNameInternal(SyntaxNode declaration, string name) EnumMemberDeclarationSyntax enumMemberDeclaration => ReplaceWithTrivia(declaration, enumMemberDeclaration.Identifier, id), EventDeclarationSyntax eventDeclaration => ReplaceWithTrivia(declaration, eventDeclaration.Identifier, id), BaseNamespaceDeclarationSyntax namespaceDeclaration => ReplaceWithTrivia(declaration, namespaceDeclaration.Name, this.DottedName(name)), - UsingDirectiveSyntax usingDeclaration => ReplaceWithTrivia(declaration, usingDeclaration.Name, this.DottedName(name)), + UsingDirectiveSyntax usingDeclaration => ReplaceWithTrivia(declaration, usingDeclaration.Type, this.DottedName(name)), ParameterSyntax parameter => ReplaceWithTrivia(declaration, parameter.Identifier, id), LocalDeclarationStatementSyntax localDeclaration when localDeclaration.Declaration.Variables.Count == 1 => diff --git a/src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs b/src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs index bf89d661d7bb3..f086b80d3ec87 100644 --- a/src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs +++ b/src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs @@ -674,7 +674,7 @@ protected override bool TryGetAliasesFromUsingDirective( if (usingDirectiveNode.Alias != null) { if (TryGetSimpleTypeName(usingDirectiveNode.Alias.Name, typeParameterNames: null, out var aliasName, out _) && - TryGetSimpleTypeName(usingDirectiveNode.Name, typeParameterNames: null, out var name, out _)) + TryGetSimpleTypeName(usingDirectiveNode.Type, typeParameterNames: null, out var name, out _)) { aliases = ImmutableArray.Create<(string, string)>((aliasName, name)); return true; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs index 0b5e5fe257aee..b4721e6cad96f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs @@ -165,7 +165,8 @@ public static ISet GetUsingNamespacesInScope(this SemanticMode { if (@using.Alias == null) { - var symbolInfo = semanticModel.GetSymbolInfo(@using.Name); + Contract.ThrowIfNull(@using.Type); + var symbolInfo = semanticModel.GetSymbolInfo(@using.Type); if (symbolInfo.Symbol != null && symbolInfo.Symbol.Kind == SymbolKind.Namespace) { result ??= new HashSet(); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs index ae114ae74942d..dd09e876f0086 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs @@ -191,7 +191,7 @@ public bool IsParameterList([NotNullWhen(true)] SyntaxNode? node) public bool IsUsingDirectiveName([NotNullWhen(true)] SyntaxNode? node) => node?.Parent is UsingDirectiveSyntax usingDirective && - usingDirective.Name == node; + usingDirective.Type == node; public bool IsUsingAliasDirective([NotNullWhen(true)] SyntaxNode? node) => node is UsingDirectiveSyntax usingDirectiveNode && usingDirectiveNode.Alias != null; @@ -201,7 +201,7 @@ public void GetPartsOfUsingAliasDirective(SyntaxNode node, out SyntaxToken globa var usingDirective = (UsingDirectiveSyntax)node; globalKeyword = usingDirective.GlobalKeyword; alias = usingDirective.Alias!.Name.Identifier; - name = usingDirective.Name; + name = usingDirective.Type; } public bool IsDeconstructionForEachStatement([NotNullWhen(true)] SyntaxNode? node) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesDirectiveComparer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesDirectiveComparer.cs index c676afc63beda..f2fb03e3645e4 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesDirectiveComparer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesDirectiveComparer.cs @@ -116,7 +116,7 @@ public int Compare(SyntaxNode? directive1, SyntaxNode? directive2) case UsingKind.Alias: var aliasComparisonResult = _tokenComparer.Compare(using1!.Alias!.Name.Identifier, using2!.Alias!.Name.Identifier); - if (aliasComparisonResult == 0) + if (aliasComparisonResult == 0 && using1.Name != null && using2.Name != null) { // They both use the same alias, so compare the names. return _nameComparer.Compare(using1.Name, using2.Name); @@ -125,6 +125,8 @@ public int Compare(SyntaxNode? directive1, SyntaxNode? directive2) return aliasComparisonResult; default: + Contract.ThrowIfNull(using1!.Name); + Contract.ThrowIfNull(using2!.Name); return _nameComparer.Compare(using1!.Name, using2!.Name); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesOrganizer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesOrganizer.cs index 9a1788f5d1680..5d622ff72dc3c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesOrganizer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/UsingsAndExternAliasesOrganizer.cs @@ -81,6 +81,8 @@ public static bool NeedsGrouping( { // Both normal usings. Place them in groups if their first namespace // component differs. + Contract.ThrowIfNull(using1.Name); + Contract.ThrowIfNull(using2.Name); var name1 = using1.Name.GetFirstToken().ValueText; var name2 = using2.Name.GetFirstToken().ValueText; return name1 != name2;