diff --git a/docs/features/TopLevelStatements.md b/docs/features/TopLevelStatements.md new file mode 100644 index 0000000000000..9e87bd77602d7 --- /dev/null +++ b/docs/features/TopLevelStatements.md @@ -0,0 +1,21 @@ +Top-level statements +========================= + +Allow a sequence of *statements* to occur right before the *namespace_member_declaration*s of a *compilation_unit* (i.e. source file). + +The semantics are that if such a sequence of *statements* is present, the following type declaration, modulo the actual type name and the method name, would be emitted: + +``` c# +static class Program +{ + static async Task Main() + { + // statements + } +} +``` + +Proposal: https://github.com/dotnet/csharplang/blob/master/proposals/top-level-statements.md +Open issues and TODOs are tracked at https://github.com/dotnet/roslyn/issues/41704. +Test plan: https://github.com/dotnet/roslyn/issues/43563. +See also https://github.com/dotnet/csharplang/issues/3117. diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionCodeFixProvider.cs index 86a21f66cd777..9fbd93e9e3113 100644 --- a/src/Analyzers/CSharp/CodeFixes/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionCodeFixProvider.cs @@ -81,7 +81,7 @@ protected override async Task FixAllAsync( declaratorToRemoveTypeOpt = semanticModel.GetDeclaredSymbol(declaratorToRemoveNodeOpt).GetSymbolType(); } - var switchStatement = (SwitchStatementSyntax)switchLocation.FindNode(cancellationToken); + var switchStatement = (SwitchStatementSyntax)switchLocation.FindNode(getInnermostNodeForTie: true, cancellationToken); var switchExpression = Rewriter.Rewrite( switchStatement, declaratorToRemoveTypeOpt, nodeToGenerate, shouldMoveNextStatementToSwitchExpression: shouldRemoveNextStatement, @@ -97,9 +97,9 @@ protected override async Task FixAllAsync( if (shouldRemoveNextStatement) { // Already morphed into the top-level switch expression. - var nextStatement = switchStatement.GetNextStatement(); + SyntaxNode nextStatement = switchStatement.GetNextStatement(); Debug.Assert(nextStatement.IsKind(SyntaxKind.ThrowStatement, SyntaxKind.ReturnStatement)); - editor.RemoveNode(nextStatement); + editor.RemoveNode(nextStatement.IsParentKind(SyntaxKind.GlobalStatement) ? nextStatement.Parent : nextStatement); } } } diff --git a/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionTests.cs b/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionTests.cs index f0044d1be1c68..09bf671150364 100644 --- a/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionTests.cs +++ b/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionTests.cs @@ -1890,5 +1890,86 @@ static void GetRef(int[] mem, int addr, int mode) } }"); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertSwitchStatementToExpression)] + public async Task TopLevelStatement() + { + var source = @" +int i = 0; +[|switch|] (i) +{ + case 1: + return 4; + default: + return 7; +}"; + + var fixedSource = @" +int i = 0; +return i switch +{ + 1 => 4, + _ => 7, +}; +"; + + var test = new VerifyCS.Test + { + TestCode = source, + FixedCode = fixedSource, + LanguageVersion = LanguageVersion.Preview, + }; + + test.ExpectedDiagnostics.Add( + // error CS9004: Program using top-level statements must be an executable. + DiagnosticResult.CompilerError("CS9004")); + + await test.RunAsync(); + } + + [WorkItem(44449, "https://github.com/dotnet/roslyn/issues/44449")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertSwitchStatementToExpression)] + public async Task TopLevelStatement_FollowedWithThrow() + { + // We should be rewriting the declaration for 'j' to get 'var j = i switch ...' + var source = @" +int i = 0; +int j; +[|switch|] (i) +{ + case 1: + j = 4; + break; + case 2: + j = 5; + break; +} +throw null; +"; + + var fixedSource = @" +int i = 0; +int j; +j = i switch +{ + 1 => 4, + 2 => 5, + _ => throw null, +}; +"; + + var test = new VerifyCS.Test + { + TestCode = source, + FixedCode = fixedSource, + LanguageVersion = LanguageVersion.Preview, + }; + + test.ExpectedDiagnostics.Add( + // error CS9004: Program using top-level statements must be an executable. + DiagnosticResult.CompilerError("CS9004")); + + await test.RunAsync(); + } } } diff --git a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs index 40b83bafd91fa..c030113ccc88b 100644 --- a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs +++ b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.InlineDeclaration; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UseImplicitType; @@ -2280,5 +2281,16 @@ void M(out C c2) } }"); } + + [WorkItem(44429, "https://github.com/dotnet/roslyn/issues/44429")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)] + public async Task TopLevelStatement() + { + await TestMissingAsync(@" +[|int|] i; +if (int.TryParse(v, out i)) +{ +}", new TestParameters(TestOptions.Regular)); + } } } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 7beab9248929b..bd0fe7c742194 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -142,7 +142,8 @@ static void Main() } [WorkItem(545138, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545138")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] + [WorkItem(44422, "https://github.com/dotnet/roslyn/issues/44422")] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44422"), Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] public async Task DontRemoveTypeParameterCastToObject() { var source = @@ -173,7 +174,8 @@ await VerifyCS.VerifyCodeFixAsync( } [WorkItem(545139, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545139")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] + [WorkItem(44422, "https://github.com/dotnet/roslyn/issues/44422")] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44422"), Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)] public async Task DontRemoveCastInIsTest() { var source = diff --git a/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests.cs b/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests.cs index aa0b889307868..9c6f5fe9483bc 100644 --- a/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests.cs +++ b/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests.cs @@ -5,6 +5,8 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UseThrowExpression; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; @@ -541,5 +543,24 @@ public A(T? t) } }"); } + + [WorkItem(44454, "https://github.com/dotnet/roslyn/issues/44454")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseThrowExpression)] + public async Task TopLevelStatement() + { + await TestAsync( +@"using System; +string s = null; +string x = null; +if (s == null) [|throw|] new ArgumentNullException(); +x = s; +", +@"using System; +string s = null; +string x = null; + +x = s ?? throw new ArgumentNullException(); +", TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } } } diff --git a/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs index fa16fed2e5161..d780a016822d4 100644 --- a/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs @@ -102,7 +102,7 @@ private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol return; } - if (!(semanticModel.GetOperation(ifOperation.Syntax.Parent, cancellationToken) is IBlockOperation containingBlock)) + if (!(ifOperation.Parent is IBlockOperation containingBlock)) { return; } diff --git a/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs b/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs index 369a958180fc9..948b502060a90 100644 --- a/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs +++ b/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs @@ -23,20 +23,21 @@ public static void ComputeDeclarationsInSpan( ArrayBuilder builder, CancellationToken cancellationToken) { - ComputeDeclarations(model, model.SyntaxTree.GetRoot(cancellationToken), + ComputeDeclarations(model, associatedSymbol: null, model.SyntaxTree.GetRoot(cancellationToken), (node, level) => !node.Span.OverlapsWith(span) || InvalidLevel(level), getSymbol, builder, null, cancellationToken); } public static void ComputeDeclarationsInNode( SemanticModel model, + ISymbol associatedSymbol, SyntaxNode node, bool getSymbol, ArrayBuilder builder, CancellationToken cancellationToken, int? levelsToCompute = null) { - ComputeDeclarations(model, node, (n, level) => InvalidLevel(level), getSymbol, builder, levelsToCompute, cancellationToken); + ComputeDeclarations(model, associatedSymbol, node, (n, level) => InvalidLevel(level), getSymbol, builder, levelsToCompute, cancellationToken); } private static bool InvalidLevel(int? level) @@ -51,6 +52,7 @@ private static bool InvalidLevel(int? level) private static void ComputeDeclarations( SemanticModel model, + ISymbol associatedSymbol, SyntaxNode node, Func shouldSkip, bool getSymbol, @@ -74,7 +76,7 @@ private static void ComputeDeclarations( var ns = (NamespaceDeclarationSyntax)node; foreach (var decl in ns.Members) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } var declInfo = GetDeclarationInfo(model, node, getSymbol, cancellationToken); @@ -100,7 +102,7 @@ private static void ComputeDeclarations( var t = (TypeDeclarationSyntax)node; foreach (var decl in t.Members) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } var attributes = GetAttributes(t.AttributeLists).Concat(GetTypeParameterListAttributes(t.TypeParameterList)); @@ -113,7 +115,7 @@ private static void ComputeDeclarations( var t = (EnumDeclarationSyntax)node; foreach (var decl in t.Members) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } var attributes = GetAttributes(t.AttributeLists); @@ -147,7 +149,7 @@ private static void ComputeDeclarations( { foreach (var decl in t.AccessorList.Accessors) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } } var attributes = GetAttributes(t.AttributeLists); @@ -187,13 +189,13 @@ private static void ComputeDeclarations( { foreach (var decl in t.AccessorList.Accessors) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } } if (t.ExpressionBody != null) { - ComputeDeclarations(model, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); } var attributes = GetAttributes(t.AttributeLists); @@ -209,13 +211,13 @@ private static void ComputeDeclarations( { foreach (var decl in t.AccessorList.Accessors) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } } if (t.ExpressionBody != null) { - ComputeDeclarations(model, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); + ComputeDeclarations(model, associatedSymbol: null, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); } var codeBlocks = GetParameterListInitializersAndAttributes(t.ParameterList); @@ -277,16 +279,25 @@ private static void ComputeDeclarations( case SyntaxKind.CompilationUnit: { var t = (CompilationUnitSyntax)node; - foreach (var decl in t.Members) + + if (associatedSymbol is IMethodSymbol) { - ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + builder.Add(GetDeclarationInfo(model, node, getSymbol, new[] { t }, cancellationToken)); } - - if (t.AttributeLists.Any()) + else { - var attributes = GetAttributes(t.AttributeLists); - builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken)); + foreach (var decl in t.Members) + { + ComputeDeclarations(model, associatedSymbol: null, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } + + if (t.AttributeLists.Any()) + { + var attributes = GetAttributes(t.AttributeLists); + builder.Add(GetDeclarationInfo(model, node, getSymbol: false, attributes, cancellationToken)); + } } + return; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs index 9929962600221..ad4c9fe52ccc8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs @@ -387,7 +387,7 @@ internal virtual QuickAttributeChecker QuickAttributeChecker } } - internal virtual Imports GetImports(ConsList basesBeingResolved) + internal virtual Imports GetImports(ConsList? basesBeingResolved) { RoslynDebug.Assert(Next is object); return Next.GetImports(basesBeingResolved); diff --git a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs index 3946fc491adb3..4f61be271c40e 100644 --- a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs +++ b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs @@ -94,6 +94,35 @@ private Binder VisitCore(SyntaxNode node) return ((CSharpSyntaxNode)node).Accept(this); } + public override Binder VisitGlobalStatement(GlobalStatementSyntax node) + { + if (SyntaxFacts.IsSimpleProgramTopLevelStatement(node)) + { + var compilationUnit = (CompilationUnitSyntax)node.Parent; + + if (compilationUnit != syntaxTree.GetRoot()) + { + throw new ArgumentOutOfRangeException(nameof(node), "node not part of tree"); + } + + var key = CreateBinderCacheKey(compilationUnit, NodeUsage.MethodBody); + + Binder result; + if (!binderCache.TryGetValue(key, out result)) + { + SynthesizedSimpleProgramEntryPointSymbol simpleProgram = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(compilation, (CompilationUnitSyntax)node.Parent, fallbackToMainEntryPoint: false); + ExecutableCodeBinder bodyBinder = simpleProgram.GetBodyBinder(_factory._ignoreAccessibility); + result = bodyBinder.GetBinder(compilationUnit); + + binderCache.TryAdd(key, result); + } + + return result; + } + + return base.VisitGlobalStatement(node); + } + // This is used mainly by the method body binder. During construction of the method symbol, // the contexts are built "by hand" rather than by this builder (see // MethodMemberBuilder.EnsureDeclarationBound). @@ -385,17 +414,18 @@ private Binder VisitPropertyOrIndexerExpressionBody(BasePropertyDeclarationSynta private NamedTypeSymbol GetContainerType(Binder binder, CSharpSyntaxNode node) { - var container = binder.ContainingMemberOrLambda as NamedTypeSymbol; + Symbol containingSymbol = binder.ContainingMemberOrLambda; + var container = containingSymbol as NamedTypeSymbol; if ((object)container == null) { - Debug.Assert(binder.ContainingMemberOrLambda is NamespaceSymbol); + Debug.Assert(containingSymbol is NamespaceSymbol); if (node.Parent.Kind() == SyntaxKind.CompilationUnit && syntaxTree.Options.Kind != SourceCodeKind.Regular) { container = compilation.ScriptClass; } else { - container = ((NamespaceSymbol)binder.ContainingMemberOrLambda).ImplicitType; + container = ((NamespaceSymbol)containingSymbol).ImplicitType; } } @@ -737,7 +767,7 @@ public override Binder VisitNamespaceDeclaration(NamespaceDeclarationSyntax pare return VisitNamespaceDeclaration(parent, _position, inBody, inUsing); } - internal InContainerBinder VisitNamespaceDeclaration(NamespaceDeclarationSyntax parent, int position, bool inBody, bool inUsing) + internal Binder VisitNamespaceDeclaration(NamespaceDeclarationSyntax parent, int position, bool inBody, bool inUsing) { Debug.Assert(!inUsing || inBody, "inUsing => inBody"); @@ -747,7 +777,7 @@ internal InContainerBinder VisitNamespaceDeclaration(NamespaceDeclarationSyntax Binder result; if (!binderCache.TryGetValue(key, out result)) { - InContainerBinder outer; + Binder outer; var container = parent.Parent; if (InScript && container.Kind() == SyntaxKind.CompilationUnit) @@ -759,7 +789,7 @@ internal InContainerBinder VisitNamespaceDeclaration(NamespaceDeclarationSyntax } else { - outer = (InContainerBinder)_factory.GetBinder(parent.Parent, position); + outer = _factory.GetBinder(parent.Parent, position); } if (!inBody) @@ -776,10 +806,10 @@ internal InContainerBinder VisitNamespaceDeclaration(NamespaceDeclarationSyntax binderCache.TryAdd(key, result); } - return (InContainerBinder)result; + return result; } - private InContainerBinder MakeNamespaceBinder(CSharpSyntaxNode node, NameSyntax name, InContainerBinder outer, bool inUsing) + private Binder MakeNamespaceBinder(CSharpSyntaxNode node, NameSyntax name, Binder outer, bool inUsing) { QualifiedNameSyntax dotted; while ((dotted = name as QualifiedNameSyntax) != null) @@ -788,7 +818,18 @@ private InContainerBinder MakeNamespaceBinder(CSharpSyntaxNode node, NameSyntax name = dotted.Right; } - NamespaceOrTypeSymbol container = outer.Container; + NamespaceOrTypeSymbol container; + + if (outer is InContainerBinder inContainerBinder) + { + container = inContainerBinder.Container; + } + else + { + Debug.Assert(outer is SimpleProgramUnitBinder); + container = outer.Compilation.GlobalNamespace; + } + NamespaceSymbol ns = ((NamespaceSymbol)container).GetNestedNamespace(name); if ((object)ns == null) return outer; return new InContainerBinder(ns, outer, node, inUsing: inUsing); @@ -802,7 +843,7 @@ public override Binder VisitCompilationUnit(CompilationUnitSyntax parent) inScript: InScript); } - internal InContainerBinder VisitCompilationUnit(CompilationUnitSyntax compilationUnit, bool inUsing, bool inScript) + internal Binder VisitCompilationUnit(CompilationUnitSyntax compilationUnit, bool inUsing, bool inScript) { if (compilationUnit != syntaxTree.GetRoot()) { @@ -878,12 +919,19 @@ internal InContainerBinder VisitCompilationUnit(CompilationUnitSyntax compilatio // + global namespace with top-level imports // result = new InContainerBinder(compilation.GlobalNamespace, result, compilationUnit, inUsing: inUsing); + + if (!inUsing && + SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(compilation, compilationUnit, fallbackToMainEntryPoint: true) is SynthesizedSimpleProgramEntryPointSymbol simpleProgram) + { + ExecutableCodeBinder bodyBinder = simpleProgram.GetBodyBinder(_factory._ignoreAccessibility); + result = new SimpleProgramUnitBinder(result, (SimpleProgramBinder)bodyBinder.GetBinder(simpleProgram.SyntaxNode)); + } } binderCache.TryAdd(key, result); } - return (InContainerBinder)result; + return result; } private static BinderCacheKey CreateBinderCacheKey(CSharpSyntaxNode node, NodeUsage usage) diff --git a/src/Compilers/CSharp/Portable/Binder/BinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/BinderFactory.cs index 2fc0399f5671f..f34600e85cc8b 100644 --- a/src/Compilers/CSharp/Portable/Binder/BinderFactory.cs +++ b/src/Compilers/CSharp/Portable/Binder/BinderFactory.cs @@ -48,16 +48,18 @@ public override bool Equals(object obj) private readonly CSharpCompilation _compilation; private readonly SyntaxTree _syntaxTree; private readonly BuckStopsHereBinder _buckStopsHereBinder; + private readonly bool _ignoreAccessibility; // In a typing scenario, GetBinder is regularly called with a non-zero position. // This results in a lot of allocations of BinderFactoryVisitors. Pooling them // reduces this churn to almost nothing. private readonly ObjectPool _binderFactoryVisitorPool; - internal BinderFactory(CSharpCompilation compilation, SyntaxTree syntaxTree) + internal BinderFactory(CSharpCompilation compilation, SyntaxTree syntaxTree, bool ignoreAccessibility) { _compilation = compilation; _syntaxTree = syntaxTree; + _ignoreAccessibility = ignoreAccessibility; _binderFactoryVisitorPool = new ObjectPool(() => new BinderFactoryVisitor(this), 64); @@ -135,7 +137,7 @@ internal Binder GetBinder(SyntaxNode node, int position, CSharpSyntaxNode member /// for top-level imports. /// /// True if the binder will be used to bind a using directive. - internal InContainerBinder GetImportsBinder(CSharpSyntaxNode unit, bool inUsing = false) + internal Binder GetImportsBinder(CSharpSyntaxNode unit, bool inUsing = false) { switch (unit.Kind()) { @@ -143,7 +145,7 @@ internal InContainerBinder GetImportsBinder(CSharpSyntaxNode unit, bool inUsing { BinderFactoryVisitor visitor = _binderFactoryVisitorPool.Allocate(); visitor.Initialize(0, null, null); - InContainerBinder result = visitor.VisitNamespaceDeclaration((NamespaceDeclarationSyntax)unit, unit.SpanStart, inBody: true, inUsing: inUsing); + Binder result = visitor.VisitNamespaceDeclaration((NamespaceDeclarationSyntax)unit, unit.SpanStart, inBody: true, inUsing: inUsing); _binderFactoryVisitorPool.Free(visitor); return result; } @@ -153,7 +155,7 @@ internal InContainerBinder GetImportsBinder(CSharpSyntaxNode unit, bool inUsing { BinderFactoryVisitor visitor = _binderFactoryVisitorPool.Allocate(); visitor.Initialize(0, null, null); - InContainerBinder result = visitor.VisitCompilationUnit((CompilationUnitSyntax)unit, inUsing: inUsing, inScript: InScript); + Binder result = visitor.VisitCompilationUnit((CompilationUnitSyntax)unit, inUsing: inUsing, inScript: InScript); _binderFactoryVisitorPool.Free(visitor); return result; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 2726305bd248b..a114890de1ace 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1404,6 +1404,8 @@ private BoundExpression BindIdentifier( receiver != null ? BoundMethodGroupFlags.HasImplicitReceiver : BoundMethodGroupFlags.None, isError, diagnostics); + + ReportSimpleProgramLocalReferencedOutsideOfTopLevelStatement(node, members[0], diagnostics); } else { @@ -1626,12 +1628,16 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag case SymbolKind.Local: { var localSymbol = (LocalSymbol)symbol; - Location localSymbolLocation = localSymbol.Locations[0]; TypeSymbol type; bool isNullableUnknown; - if (node.SyntaxTree == localSymbolLocation.SourceTree && - node.SpanStart < localSymbolLocation.SourceSpan.Start) + if (ReportSimpleProgramLocalReferencedOutsideOfTopLevelStatement(node, localSymbol, diagnostics)) + { + type = new ExtendedErrorTypeSymbol( + this.Compilation, name: "var", arity: 0, errorInfo: null, variableUsedBeforeDeclaration: true); + isNullableUnknown = true; + } + else if (isUsedBeforeDeclaration(node, localSymbol)) { // Here we report a local variable being used before its declaration // @@ -1787,6 +1793,32 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } + + bool isUsedBeforeDeclaration(SimpleNameSyntax node, LocalSymbol localSymbol) + { + Location localSymbolLocation = localSymbol.Locations[0]; + + if (node.SyntaxTree == localSymbolLocation.SourceTree) + { + return node.SpanStart < localSymbolLocation.SourceSpan.Start; + } + + return false; + } + } + + private static bool ReportSimpleProgramLocalReferencedOutsideOfTopLevelStatement(SimpleNameSyntax node, Symbol symbol, DiagnosticBag diagnostics) + { + if (symbol.ContainingSymbol is SynthesizedSimpleProgramEntryPointSymbol) + { + if (!SyntaxFacts.IsTopLevelStatement(node.Ancestors(ascendOutOfTrivia: false).OfType().FirstOrDefault())) + { + Error(diagnostics, ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, node, node); + return true; + } + } + + return false; } protected virtual BoundExpression BindRangeVariable(SimpleNameSyntax node, RangeVariableSymbol qv, DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index 609228d5a6d7c..b9fc656abad4d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -99,6 +99,12 @@ private Binder LookupSymbolsInternal( binder = scope; } } + + if ((options & LookupOptions.LabelsOnly) != 0 && scope.IsLastBinderWithinMember()) + { + // Labels declared outside of a member are not visible inside. + break; + } } return binder; } @@ -1648,6 +1654,12 @@ internal void AddLookupSymbolsInfo(LookupSymbolsInfo result, LookupOptions optio for (var scope = this; scope != null; scope = scope.Next) { scope.AddLookupSymbolsInfoInSingleBinder(result, options, originalBinder: this); + + if ((options & LookupOptions.LabelsOnly) != 0 && scope.IsLastBinderWithinMember()) + { + // Labels declared outside of a member are not visible inside. + break; + } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs b/src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs index e8d83a4c7fb3f..8c544bf18d291 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_NameConflicts.cs @@ -122,9 +122,31 @@ private bool ValidateNameConflictsInScope(Symbol? symbol, Location location, str { return false; } + + if (binder.IsLastBinderWithinMember()) + { + // Declarations within a member do not conflict with declarations outside. + return false; + } } return false; } + + private bool IsLastBinderWithinMember() + { + var containingMemberOrLambda = this.ContainingMemberOrLambda; + + switch (containingMemberOrLambda?.Kind) + { + case null: + case SymbolKind.NamedType: + case SymbolKind.Namespace: + return true; + default: + return containingMemberOrLambda.ContainingSymbol?.Kind == SymbolKind.NamedType && + this.Next?.ContainingMemberOrLambda != containingMemberOrLambda; + } + } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 6dd63e065e78e..02d21c58d4546 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1734,6 +1734,11 @@ private BoundBlock BindBlockParts(BlockSyntax node, DiagnosticBag diagnostics) boundStatements.Add(boundStatement); } + return FinishBindBlockParts(node, boundStatements.ToImmutableAndFree(), diagnostics); + } + + private BoundBlock FinishBindBlockParts(CSharpSyntaxNode node, ImmutableArray boundStatements, DiagnosticBag diagnostics) + { ImmutableArray locals = GetDeclaredLocalsForScope(node); if (IsDirectlyInIterator) @@ -1753,7 +1758,7 @@ private BoundBlock BindBlockParts(BlockSyntax node, DiagnosticBag diagnostics) node, locals, GetDeclaredLocalFunctionsForScope(node), - boundStatements.ToImmutableAndFree()); + boundStatements); } internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType, BoundExpression expression, DiagnosticBag diagnostics, bool isDefaultParameter = false, bool isRefAssignment = false) @@ -3241,11 +3246,38 @@ public virtual BoundNode BindMethodBody(CSharpSyntaxNode syntax, DiagnosticBag d case ArrowExpressionClauseSyntax arrowExpression: return BindExpressionBodyAsBlock(arrowExpression, diagnostics); + case CompilationUnitSyntax compilationUnit: + return BindSimpleProgram(compilationUnit, diagnostics); + default: throw ExceptionUtilities.UnexpectedValue(syntax.Kind()); } } + private BoundNode BindSimpleProgram(CompilationUnitSyntax compilationUnit, DiagnosticBag diagnostics) + { + var simpleProgram = (SynthesizedSimpleProgramEntryPointSymbol)ContainingMemberOrLambda; + + return GetBinder(compilationUnit).BindSimpleProgramCompilationUnit(compilationUnit, simpleProgram, diagnostics); + } + + private BoundNode BindSimpleProgramCompilationUnit(CompilationUnitSyntax compilationUnit, SynthesizedSimpleProgramEntryPointSymbol simpleProgram, DiagnosticBag diagnostics) + { + ArrayBuilder boundStatements = ArrayBuilder.GetInstance(); + foreach (var statement in compilationUnit.Members) + { + if (statement is GlobalStatementSyntax topLevelStatement) + { + var boundStatement = BindStatement(topLevelStatement.Statement, diagnostics); + boundStatements.Add(boundStatement); + } + } + + return new BoundNonConstructorMethodBody(compilationUnit, + FinishBindBlockParts(compilationUnit, boundStatements.ToImmutableAndFree(), diagnostics).MakeCompilerGenerated(), + expressionBody: null); + } + private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor, DiagnosticBag diagnostics) { if (constructor.Initializer == null && constructor.Body == null && constructor.ExpressionBody == null) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 907c48e3632a4..a9eb313184dad 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1379,6 +1379,14 @@ internal static NamedTypeSymbol GetSpecialType(CSharpCompilation compilation, Sp return typeSymbol; } + internal static NamedTypeSymbol GetSpecialType(CSharpCompilation compilation, SpecialType typeId, Location location, DiagnosticBag diagnostics) + { + NamedTypeSymbol typeSymbol = compilation.GetSpecialType(typeId); + Debug.Assert((object)typeSymbol != null, "Expect an error type if special type isn't found"); + ReportUseSiteDiagnostics(typeSymbol, diagnostics, location); + return typeSymbol; + } + /// /// This is a layer on top of the Compilation version that generates a diagnostic if the special /// member isn't found. @@ -1447,12 +1455,25 @@ internal static bool ReportUseSiteDiagnostics(Symbol symbol, DiagnosticBag diagn /// internal NamedTypeSymbol GetWellKnownType(WellKnownType type, DiagnosticBag diagnostics, SyntaxNode node) { - NamedTypeSymbol typeSymbol = this.Compilation.GetWellKnownType(type); + return GetWellKnownType(this.Compilation, type, diagnostics, node); + } + + internal static NamedTypeSymbol GetWellKnownType(CSharpCompilation compilation, WellKnownType type, DiagnosticBag diagnostics, SyntaxNode node) + { + NamedTypeSymbol typeSymbol = compilation.GetWellKnownType(type); Debug.Assert((object)typeSymbol != null, "Expect an error type if well-known type isn't found"); ReportUseSiteDiagnostics(typeSymbol, diagnostics, node); return typeSymbol; } + internal static NamedTypeSymbol GetWellKnownType(CSharpCompilation compilation, WellKnownType type, DiagnosticBag diagnostics, Location location) + { + NamedTypeSymbol typeSymbol = compilation.GetWellKnownType(type); + Debug.Assert((object)typeSymbol != null, "Expect an error type if well-known type isn't found"); + ReportUseSiteDiagnostics(typeSymbol, diagnostics, location); + return typeSymbol; + } + /// /// This is a layer on top of the Compilation version that generates a diagnostic if the well-known /// type isn't found. diff --git a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs index 71f53de062e55..9ef2df737f746 100644 --- a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs @@ -41,7 +41,7 @@ internal override QuickAttributeChecker QuickAttributeChecker } } - internal override Imports GetImports(ConsList basesBeingResolved) + internal override Imports GetImports(ConsList? basesBeingResolved) { return Imports.Empty; } diff --git a/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs index e12480d39a879..4856fa2f47dfd 100644 --- a/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs @@ -17,23 +17,27 @@ namespace Microsoft.CodeAnalysis.CSharp /// internal sealed class EmbeddedStatementBinder : LocalScopeBinder { - private readonly SyntaxList _statements; + private readonly StatementSyntax _statement; public EmbeddedStatementBinder(Binder enclosing, StatementSyntax statement) : base(enclosing, enclosing.Flags) { Debug.Assert(statement != null); - _statements = new SyntaxList(statement); + _statement = statement; } protected override ImmutableArray BuildLocals() { - return BuildLocals(_statements, this); + ArrayBuilder locals = ArrayBuilder.GetInstance(); + BuildLocals(this, _statement, locals); + return locals.ToImmutableAndFree(); } protected override ImmutableArray BuildLocalFunctions() { - return BuildLocalFunctions(_statements); + ArrayBuilder locals = null; + BuildLocalFunctions(_statement, ref locals); + return locals?.ToImmutableAndFree() ?? ImmutableArray.Empty; } internal override bool IsLocalFunctionsScopeBinder @@ -47,8 +51,9 @@ internal override bool IsLocalFunctionsScopeBinder protected override ImmutableArray BuildLabels() { ArrayBuilder labels = null; - base.BuildLabels(_statements, ref labels); - return (labels != null) ? labels.ToImmutableAndFree() : ImmutableArray.Empty; + var containingMethod = (MethodSymbol)this.ContainingMemberOrLambda; + BuildLabels(containingMethod, _statement, ref labels); + return labels?.ToImmutableAndFree() ?? ImmutableArray.Empty; } internal override bool IsLabelsScopeBinder @@ -73,7 +78,7 @@ internal override SyntaxNode ScopeDesignator { get { - return _statements.First(); + return _statement; } } diff --git a/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs b/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs index c98bbbcf18e62..bca68e76cdce4 100644 --- a/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ExecutableCodeBinder.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; using System; using System.Collections.Immutable; using System.Diagnostics; @@ -25,7 +26,6 @@ internal sealed class ExecutableCodeBinder : Binder private readonly SyntaxNode _root; private readonly Action _binderUpdatedHandler; private SmallDictionary _lazyBinderMap; - private ImmutableArray _methodSymbolsWithYield; internal ExecutableCodeBinder(SyntaxNode root, Symbol memberSymbol, Binder next, Action binderUpdatedHandler = null) : this(root, memberSymbol, next, next.Flags) @@ -62,57 +62,27 @@ internal override Binder GetBinder(SyntaxNode node) private void ComputeBinderMap() { SmallDictionary map; - ImmutableArray methodSymbolsWithYield; - // Ensure that the member symbol is a method symbol. - if ((object)_memberSymbol != null && _root != null) + if (_memberSymbol is SynthesizedSimpleProgramEntryPointSymbol entryPoint && _root == entryPoint.SyntaxNode) { - var methodsWithYield = ArrayBuilder.GetInstance(); - var symbolsWithYield = ArrayBuilder.GetInstance(); - map = LocalBinderFactory.BuildMap(_memberSymbol, _root, this, methodsWithYield, _binderUpdatedHandler); - foreach (var methodWithYield in methodsWithYield) - { - Binder binder = this; - if (methodWithYield.Kind() != SyntaxKind.GlobalStatement && - (methodWithYield == _root || map.TryGetValue(methodWithYield, out binder))) - { - Symbol containing = binder.ContainingMemberOrLambda; - - // get the closest enclosing InMethodBinder and make it an iterator - InMethodBinder inMethod = null; - while (binder != null) - { - inMethod = binder as InMethodBinder; - if (inMethod != null) - break; - binder = binder.Next; - } - if (inMethod != null && (object)inMethod.ContainingMemberOrLambda == containing) - { - inMethod.MakeIterator(); - symbolsWithYield.Add((MethodSymbol)inMethod.ContainingMemberOrLambda); - } - else - { - Debug.Assert(methodWithYield == _root && methodWithYield is ExpressionSyntax); - } - } - else - { - // skip over it, this is an error - } - } - methodsWithYield.Free(); - methodSymbolsWithYield = symbolsWithYield.ToImmutableAndFree(); + var scopeOwner = new SimpleProgramBinder(this, entryPoint); + map = LocalBinderFactory.BuildMap(_memberSymbol, _root, scopeOwner, _binderUpdatedHandler); + map.Add(_root, scopeOwner); } else { - map = SmallDictionary.Empty; - methodSymbolsWithYield = ImmutableArray.Empty; + // Ensure that the member symbol is a method symbol. + if ((object)_memberSymbol != null && _root != null) + { + map = LocalBinderFactory.BuildMap(_memberSymbol, _root, this, _binderUpdatedHandler); + } + else + { + map = SmallDictionary.Empty; + } } Interlocked.CompareExchange(ref _lazyBinderMap, map, null); - ImmutableInterlocked.InterlockedCompareExchange(ref _methodSymbolsWithYield, methodSymbolsWithYield, default(ImmutableArray)); } private SmallDictionary BinderMap @@ -128,70 +98,59 @@ private SmallDictionary BinderMap } } - private ImmutableArray MethodSymbolsWithYield + public static void ValidateIteratorMethod(CSharpCompilation compilation, MethodSymbol iterator, DiagnosticBag diagnostics) { - get + if (!iterator.IsIterator) { - if (_methodSymbolsWithYield.IsDefault) - { - ComputeBinderMap(); - } - - return _methodSymbolsWithYield; + return; } - } - public void ValidateIteratorMethods(DiagnosticBag diagnostics) - { - foreach (var iterator in MethodSymbolsWithYield) + foreach (var parameter in iterator.Parameters) { - foreach (var parameter in iterator.Parameters) + if (parameter.RefKind != RefKind.None) { - if (parameter.RefKind != RefKind.None) - { - diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]); - } - else if (parameter.Type.IsUnsafe()) - { - diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]); - } + diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]); } - - Location errorLocation = iterator.Locations[0]; - if (iterator.IsVararg) + else if (parameter.Type.IsUnsafe()) { - // error CS1636: __arglist is not allowed in the parameter list of iterators - diagnostics.Add(ErrorCode.ERR_VarargsIterator, errorLocation); + diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]); } + } - if (((iterator as SourceMemberMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true) - && Compilation.Options.AllowUnsafe) // Don't cascade - { - diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, errorLocation); - } + Location errorLocation = (iterator as SynthesizedSimpleProgramEntryPointSymbol)?.ReturnTypeSyntax.GetLocation() ?? iterator.Locations[0]; + if (iterator.IsVararg) + { + // error CS1636: __arglist is not allowed in the parameter list of iterators + diagnostics.Add(ErrorCode.ERR_VarargsIterator, errorLocation); + } - var returnType = iterator.ReturnType; - RefKind refKind = iterator.RefKind; - TypeWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation, diagnostics); + if (((iterator as SourceMemberMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true) + && compilation.Options.AllowUnsafe) // Don't cascade + { + diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, errorLocation); + } - if (elementType.IsDefault) + var returnType = iterator.ReturnType; + RefKind refKind = iterator.RefKind; + TypeWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(compilation, refKind, returnType, errorLocation, diagnostics); + + if (elementType.IsDefault) + { + if (refKind != RefKind.None) { - if (refKind != RefKind.None) - { - Error(diagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, iterator); - } - else if (!returnType.IsErrorType()) - { - Error(diagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, iterator, returnType); - } + Error(diagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, iterator); } - - bool asyncInterface = InMethodBinder.IsAsyncStreamInterface(Compilation, refKind, returnType); - if (asyncInterface && !iterator.IsAsync) + else if (!returnType.IsErrorType()) { - diagnostics.Add(ErrorCode.ERR_IteratorMustBeAsync, errorLocation, iterator, returnType); + Error(diagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, iterator, returnType); } } + + bool asyncInterface = InMethodBinder.IsAsyncStreamInterface(compilation, refKind, returnType); + if (asyncInterface && !iterator.IsAsync) + { + diagnostics.Add(ErrorCode.ERR_IteratorMustBeAsync, errorLocation, iterator, returnType); + } } } } diff --git a/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs b/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs index 5303195e9f0b9..6485e6755e960 100644 --- a/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/InMethodBinder.cs @@ -23,7 +23,6 @@ internal sealed class InMethodBinder : LocalScopeBinder private readonly MethodSymbol _methodSymbol; private SmallDictionary _lazyDefinitionMap; private TypeWithAnnotations.Boxed _iteratorElementType; - private readonly static TypeWithAnnotations.Boxed SentinelElementType = new TypeWithAnnotations.Boxed(default); public InMethodBinder(MethodSymbol owner, Binder enclosing) : base(enclosing, enclosing.Flags & ~BinderFlags.AllClearedAtExecutableCodeBoundary) @@ -76,19 +75,11 @@ internal override bool IsInMethodBody internal override bool IsNestedFunctionBinder => _methodSymbol.MethodKind == MethodKind.LocalFunction; - internal void MakeIterator() - { - if (_iteratorElementType == null) - { - _iteratorElementType = SentinelElementType; - } - } - internal override bool IsDirectlyInIterator { get { - return _iteratorElementType != null; + return _methodSymbol.IsIterator; } } @@ -137,7 +128,7 @@ internal override TypeWithAnnotations GetIteratorElementType() return !elementType.IsDefault ? elementType : TypeWithAnnotations.Create(CreateErrorType()); } - if (_iteratorElementType == SentinelElementType) + if (_iteratorElementType is null) { TypeWithAnnotations elementType = GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation: null, diagnostics: null); if (elementType.IsDefault) @@ -145,7 +136,7 @@ internal override TypeWithAnnotations GetIteratorElementType() elementType = TypeWithAnnotations.Create(CreateErrorType()); } - Interlocked.CompareExchange(ref _iteratorElementType, new TypeWithAnnotations.Boxed(elementType), SentinelElementType); + Interlocked.CompareExchange(ref _iteratorElementType, new TypeWithAnnotations.Boxed(elementType), null); } return _iteratorElementType.Value; @@ -244,9 +235,13 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res private static bool ReportConflictWithParameter(Symbol parameter, Symbol newSymbol, string name, Location newLocation, DiagnosticBag diagnostics) { - var oldLocation = parameter.Locations[0]; +#if DEBUG + var locations = parameter.Locations; + Debug.Assert(!locations.IsEmpty || parameter.IsImplicitlyDeclared); + var oldLocation = locations.FirstOrNone(); Debug.Assert(oldLocation != newLocation || oldLocation == Location.None || newLocation.SourceTree?.GetRoot().ContainsDiagnostics == true, "same nonempty location refers to different symbols?"); +#endif SymbolKind parameterKind = parameter.Kind; // Quirk of the way we represent lambda parameters. diff --git a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs index 0bd8d307b991d..d6364ccdb3f05 100644 --- a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs +++ b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs @@ -28,8 +28,6 @@ namespace Microsoft.CodeAnalysis.CSharp internal sealed class LocalBinderFactory : CSharpSyntaxWalker { private readonly SmallDictionary _map; - private bool _sawYield; - private readonly ArrayBuilder _methodsWithYields; private Symbol _containingMemberOrLambda; private Binder _enclosing; private readonly SyntaxNode _root; @@ -63,7 +61,6 @@ private void VisitRankSpecifiers(TypeSyntax type, Binder enclosing) }, (localBinderFactory: this, binder: enclosing)); } - // methodsWithYields will contain all function-declaration-like CSharpSyntaxNodes with yield statements contained within them. // Currently the types of these are restricted to only be whatever the syntax parameter is, plus any LocalFunctionStatementSyntax contained within it. // This may change if the language is extended to allow iterator lambdas, in which case the lambda would also be returned. // (lambdas currently throw a diagnostic in WithLambdaParametersBinder.GetIteratorElementType when a yield is used within them) @@ -71,10 +68,9 @@ public static SmallDictionary BuildMap( Symbol containingMemberOrLambda, SyntaxNode syntax, Binder enclosing, - ArrayBuilder methodsWithYields, Action binderUpdatedHandler = null) { - var builder = new LocalBinderFactory(containingMemberOrLambda, syntax, enclosing, methodsWithYields); + var builder = new LocalBinderFactory(containingMemberOrLambda, syntax, enclosing); StatementSyntax statement; var expressionSyntax = syntax as ExpressionSyntax; @@ -117,9 +113,6 @@ public static SmallDictionary BuildMap( builder.Visit((CSharpSyntaxNode)syntax, enclosing); } - // the other place this is possible is in a local function - if (builder._sawYield) - methodsWithYields.Add(syntax); return builder._map; } @@ -134,7 +127,7 @@ public override void VisitCompilationUnit(CompilationUnitSyntax node) } } - private LocalBinderFactory(Symbol containingMemberOrLambda, SyntaxNode root, Binder enclosing, ArrayBuilder methodsWithYields) + private LocalBinderFactory(Symbol containingMemberOrLambda, SyntaxNode root, Binder enclosing) { Debug.Assert((object)containingMemberOrLambda != null); Debug.Assert(containingMemberOrLambda.Kind != SymbolKind.Local && containingMemberOrLambda.Kind != SymbolKind.RangeVariable && containingMemberOrLambda.Kind != SymbolKind.Parameter); @@ -142,7 +135,6 @@ private LocalBinderFactory(Symbol containingMemberOrLambda, SyntaxNode root, Bin _map = new SmallDictionary(ReferenceEqualityComparer.Instance); _containingMemberOrLambda = containingMemberOrLambda; _enclosing = enclosing; - _methodsWithYields = methodsWithYields; _root = root; } @@ -221,7 +213,6 @@ public override void VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpre public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { - bool oldSawYield = _sawYield; Symbol oldMethod = _containingMemberOrLambda; Binder binder = _enclosing; LocalFunctionSymbol match = FindLocalFunction(node, _enclosing); @@ -241,25 +232,16 @@ public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax no BlockSyntax blockBody = node.Body; if (blockBody != null) { - _sawYield = false; Visit(blockBody, binder); - - if (_sawYield) - { - _methodsWithYields.Add(blockBody); - } } ArrowExpressionClauseSyntax arrowBody = node.ExpressionBody; if (arrowBody != null) { - _sawYield = false; Visit(arrowBody, binder); - Debug.Assert(!_sawYield); } _containingMemberOrLambda = oldMethod; - _sawYield = oldSawYield; } private static LocalFunctionSymbol FindLocalFunction(LocalFunctionStatementSyntax node, Binder enclosing) @@ -698,8 +680,6 @@ public override void VisitYieldStatement(YieldStatementSyntax node) { Visit(node.Expression, _enclosing); } - - _sawYield = true; } public override void VisitExpressionStatement(ExpressionStatementSyntax node) diff --git a/src/Compilers/CSharp/Portable/Binder/LocalScopeBinder.cs b/src/Compilers/CSharp/Portable/Binder/LocalScopeBinder.cs index 34a19d69a0e8e..1f480fd9bdf22 100644 --- a/src/Compilers/CSharp/Portable/Binder/LocalScopeBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/LocalScopeBinder.cs @@ -191,118 +191,124 @@ protected ImmutableArray BuildLocals(SyntaxList st ArrayBuilder locals = ArrayBuilder.GetInstance(); foreach (var statement in statements) { - var innerStatement = statement; + BuildLocals(enclosingBinder, statement, locals); + } - // drill into any LabeledStatements -- atomic LabelStatements have been bound into - // wrapped LabeledStatements by this point - while (innerStatement.Kind() == SyntaxKind.LabeledStatement) - { - innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; - } + return locals.ToImmutableAndFree(); + } - switch (innerStatement.Kind()) - { - case SyntaxKind.LocalDeclarationStatement: - { - Binder localDeclarationBinder = enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder; - var decl = (LocalDeclarationStatementSyntax)innerStatement; + internal void BuildLocals(Binder enclosingBinder, StatementSyntax statement, ArrayBuilder locals) + { + var innerStatement = statement; - decl.Declaration.Type.VisitRankSpecifiers((rankSpecifier, args) => + // drill into any LabeledStatements -- atomic LabelStatements have been bound into + // wrapped LabeledStatements by this point + while (innerStatement.Kind() == SyntaxKind.LabeledStatement) + { + innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; + } + + switch (innerStatement.Kind()) + { + case SyntaxKind.LocalDeclarationStatement: + { + Binder localDeclarationBinder = enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder; + var decl = (LocalDeclarationStatementSyntax)innerStatement; + + decl.Declaration.Type.VisitRankSpecifiers((rankSpecifier, args) => + { + foreach (var expression in rankSpecifier.Sizes) { - foreach (var expression in rankSpecifier.Sizes) + if (expression.Kind() != SyntaxKind.OmittedArraySizeExpression) { - if (expression.Kind() != SyntaxKind.OmittedArraySizeExpression) - { - ExpressionVariableFinder.FindExpressionVariables(args.localScopeBinder, args.locals, expression, args.localDeclarationBinder); - } + ExpressionVariableFinder.FindExpressionVariables(args.localScopeBinder, args.locals, expression, args.localDeclarationBinder); } - }, (localScopeBinder: this, locals: locals, localDeclarationBinder: localDeclarationBinder)); - - LocalDeclarationKind kind; - if (decl.IsConst) - { - kind = LocalDeclarationKind.Constant; - } - else if (decl.UsingKeyword != default(SyntaxToken)) - { - kind = LocalDeclarationKind.UsingVariable; - } - else - { - kind = LocalDeclarationKind.RegularVariable; } - foreach (var vdecl in decl.Declaration.Variables) - { - var localSymbol = MakeLocal(decl.Declaration, vdecl, kind, localDeclarationBinder); - locals.Add(localSymbol); + }, (localScopeBinder: this, locals: locals, localDeclarationBinder: localDeclarationBinder)); - // also gather expression-declared variables from the bracketed argument lists and the initializers - ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl, localDeclarationBinder); - } + LocalDeclarationKind kind; + if (decl.IsConst) + { + kind = LocalDeclarationKind.Constant; } - break; + else if (decl.UsingKeyword != default(SyntaxToken)) + { + kind = LocalDeclarationKind.UsingVariable; + } + else + { + kind = LocalDeclarationKind.RegularVariable; + } + foreach (var vdecl in decl.Declaration.Variables) + { + var localSymbol = MakeLocal(decl.Declaration, vdecl, kind, localDeclarationBinder); + locals.Add(localSymbol); - case SyntaxKind.ExpressionStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.YieldReturnStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.ThrowStatement: - case SyntaxKind.GotoCaseStatement: - ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder); - break; + // also gather expression-declared variables from the bracketed argument lists and the initializers + ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl, localDeclarationBinder); + } + } + break; - case SyntaxKind.SwitchStatement: - var switchStatement = (SwitchStatementSyntax)innerStatement; - ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(switchStatement.Expression) ?? enclosingBinder); - break; + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.YieldReturnStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.GotoCaseStatement: + ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder); + break; - case SyntaxKind.LockStatement: - Binder statementBinder = enclosingBinder.GetBinder(innerStatement); - Debug.Assert(statementBinder != null); // Lock always has a binder. - ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, statementBinder); - break; + case SyntaxKind.SwitchStatement: + var switchStatement = (SwitchStatementSyntax)innerStatement; + ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(switchStatement.Expression) ?? enclosingBinder); + break; - default: - // no other statement introduces local variables into the enclosing scope - break; - } - } + case SyntaxKind.LockStatement: + Binder statementBinder = enclosingBinder.GetBinder(innerStatement); + Debug.Assert(statementBinder != null); // Lock always has a binder. + ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, statementBinder); + break; - return locals.ToImmutableAndFree(); + default: + // no other statement introduces local variables into the enclosing scope + break; + } } + protected ImmutableArray BuildLocalFunctions(SyntaxList statements) { ArrayBuilder locals = null; foreach (var statement in statements) { - var innerStatement = statement; + BuildLocalFunctions(statement, ref locals); + } - // drill into any LabeledStatements -- atomic LabelStatements have been bound into - // wrapped LabeledStatements by this point - while (innerStatement.Kind() == SyntaxKind.LabeledStatement) - { - innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; - } + return locals?.ToImmutableAndFree() ?? ImmutableArray.Empty; + } - if (innerStatement.Kind() == SyntaxKind.LocalFunctionStatement) - { - var decl = (LocalFunctionStatementSyntax)innerStatement; - if (locals == null) - { - locals = ArrayBuilder.GetInstance(); - } + internal void BuildLocalFunctions(StatementSyntax statement, ref ArrayBuilder locals) + { + var innerStatement = statement; - var localSymbol = MakeLocalFunction(decl); - locals.Add(localSymbol); - } + // drill into any LabeledStatements -- atomic LabelStatements have been bound into + // wrapped LabeledStatements by this point + while (innerStatement.Kind() == SyntaxKind.LabeledStatement) + { + innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; } - if (locals != null) + if (innerStatement.Kind() == SyntaxKind.LocalFunctionStatement) { - return locals.ToImmutableAndFree(); - } + var decl = (LocalFunctionStatementSyntax)innerStatement; + if (locals == null) + { + locals = ArrayBuilder.GetInstance(); + } - return ImmutableArray.Empty; + var localSymbol = MakeLocalFunction(decl); + locals.Add(localSymbol); + } } protected SourceLocalSymbol MakeLocal(VariableDeclarationSyntax declaration, VariableDeclaratorSyntax declarator, LocalDeclarationKind kind, Binder initializerBinderOpt = null) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs index 4554870767bef..dcd2c9a60c141 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs @@ -174,6 +174,7 @@ private static bool IsSymbolAccessibleCore( case SymbolKind.Assembly: case SymbolKind.NetModule: case SymbolKind.RangeVariable: + case SymbolKind.Method when ((MethodSymbol)symbol).MethodKind == MethodKind.LocalFunction: // These types of symbols are always accessible (if visible). return true; diff --git a/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs b/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs new file mode 100644 index 0000000000000..1f63901c7bc00 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs @@ -0,0 +1,116 @@ +// 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. +#nullable enable + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp +{ + /// + /// This binder owns the scope for Simple Program top-level statements. + /// + internal sealed class SimpleProgramBinder : LocalScopeBinder + { + private readonly SynthesizedSimpleProgramEntryPointSymbol _entryPoint; + + public SimpleProgramBinder(Binder enclosing, SynthesizedSimpleProgramEntryPointSymbol entryPoint) + : base(enclosing, enclosing.Flags) + { + _entryPoint = entryPoint; + } + + protected override ImmutableArray BuildLocals() + { + ArrayBuilder locals = ArrayBuilder.GetInstance(); + + foreach (var statement in _entryPoint.CompilationUnit.Members) + { + if (statement is GlobalStatementSyntax topLevelStatement) + { + this.BuildLocals(this, topLevelStatement.Statement, locals); + } + } + + return locals.ToImmutableAndFree(); + } + + protected override ImmutableArray BuildLocalFunctions() + { + ArrayBuilder? locals = null; + + foreach (var statement in _entryPoint.CompilationUnit.Members) + { + if (statement is GlobalStatementSyntax topLevelStatement) + { + this.BuildLocalFunctions(topLevelStatement.Statement, ref locals); + } + } + + return locals?.ToImmutableAndFree() ?? ImmutableArray.Empty; + } + + internal override bool IsLocalFunctionsScopeBinder + { + get + { + return true; + } + } + + protected override ImmutableArray BuildLabels() + { + ArrayBuilder? labels = null; + + foreach (var statement in _entryPoint.CompilationUnit.Members) + { + if (statement is GlobalStatementSyntax topLevelStatement) + { + BuildLabels(_entryPoint, topLevelStatement.Statement, ref labels); + } + } + + return labels?.ToImmutableAndFree() ?? ImmutableArray.Empty; + } + + internal override bool IsLabelsScopeBinder + { + get + { + return true; + } + } + + internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator) + { + if (ScopeDesignator == scopeDesignator) + { + return this.Locals; + } + + throw ExceptionUtilities.Unreachable; + } + + internal override SyntaxNode ScopeDesignator + { + get + { + return _entryPoint.SyntaxNode; + } + } + + internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator) + { + if (ScopeDesignator == scopeDesignator) + { + return this.LocalFunctions; + } + + throw ExceptionUtilities.Unreachable; + } + } +} diff --git a/src/Compilers/CSharp/Portable/Binder/SimpleProgramUnitBinder.cs b/src/Compilers/CSharp/Portable/Binder/SimpleProgramUnitBinder.cs new file mode 100644 index 0000000000000..d5ec7fd12f9b4 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Binder/SimpleProgramUnitBinder.cs @@ -0,0 +1,76 @@ +// 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. +#nullable enable + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp.Symbols; + +namespace Microsoft.CodeAnalysis.CSharp +{ + /// + /// This binder provides a context for binding within a specific compilation unit, but outside of top-level statements. + /// It ensures that locals are in scope, however it is not responsible + /// for creating the symbols. That task is actually owned by and + /// this binder simply delegates to it when appropriate. That ensures that the same set of symbols is + /// shared across all compilation units. + /// + internal sealed class SimpleProgramUnitBinder : LocalScopeBinder + { + private readonly SimpleProgramBinder _scope; + public SimpleProgramUnitBinder(Binder enclosing, SimpleProgramBinder scope) + : base(enclosing, enclosing.Flags) + { + _scope = scope; + } + + protected override ImmutableArray BuildLocals() + { + return _scope.Locals; + } + + protected override ImmutableArray BuildLocalFunctions() + { + return _scope.LocalFunctions; + } + + internal override bool IsLocalFunctionsScopeBinder + { + get + { + return _scope.IsLocalFunctionsScopeBinder; + } + } + + protected override ImmutableArray BuildLabels() + { + return ImmutableArray.Empty; + } + + internal override bool IsLabelsScopeBinder + { + get + { + return false; + } + } + + internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator) + { + return _scope.GetDeclaredLocalsForScope(scopeDesignator); + } + + internal override SyntaxNode? ScopeDesignator + { + get + { + return _scope.ScopeDesignator; + } + } + + internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator) + { + return _scope.GetDeclaredLocalFunctionsForScope(scopeDesignator); + } + } +} diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index 4bee7ca429f9f..e5a7b735563dd 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -615,7 +615,6 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType) ParameterHelpers.EnsureNullableAttributeExists(compilation, lambdaSymbol, lambdaParameters, diagnostics, modifyCompilation: false); // Note: we don't need to warn on annotations used in #nullable disable context for lambdas, as this is handled in binding already - ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics); ValidateUnsafeParameters(diagnostics, cacheKey.ParameterTypes); bool reachableEndpoint = ControlFlowPass.Analyze(compilation, lambdaSymbol, block, diagnostics); diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs index e2948bb1c1e74..1875ac2f36bf3 100644 --- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs +++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs @@ -1242,6 +1242,15 @@ public static Conversion ClassifyConversion(this SemanticModel? semanticModel, i return csmodel?.GetDeclaredSymbol(declarationSyntax, cancellationToken); } + /// + /// Given a compilation unit syntax, get the corresponding Simple Program entry point symbol. + /// + public static IMethodSymbol? GetDeclaredSymbol(this SemanticModel? semanticModel, CompilationUnitSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)) + { + var csmodel = semanticModel as CSharpSemanticModel; + return csmodel?.GetDeclaredSymbol(declarationSyntax, cancellationToken); + } + /// /// Given a namespace declaration syntax node, get the corresponding namespace symbol for /// the declaration assembly. diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 96766ffb9c3d1..59b36491c032e 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -3882,10 +3882,10 @@ You should consider suppressing the warning only if you're sure that you don't w Delegate '{0}' has no invoke method or an invoke method with a return type or parameter types that are not supported. - The entry point of the program is global script code; ignoring '{0}' entry point. + The entry point of the program is global code; ignoring '{0}' entry point. - The entry point of the program is global script code; ignoring entry point + The entry point of the program is global code; ignoring entry point The second operand of an 'is' or 'as' operator may not be static type '{0}' @@ -6121,4 +6121,22 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Both partial method declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers. - + + top-level statements + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + Only one compilation unit can have top-level statements. + + + Top-level statements must precede namespace and type declarations. + + + Cannot specify /main if there is a compilation unit with top-level statements. + + + Program using top-level statements must be an executable. + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 997bb6b31a945..d88fdf11ae00d 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -1537,34 +1537,62 @@ internal bool DeclaresTheObjectClass internal new MethodSymbol? GetEntryPoint(CancellationToken cancellationToken) { - EntryPoint? entryPoint = GetEntryPointAndDiagnostics(cancellationToken); - return entryPoint?.MethodSymbol; + EntryPoint entryPoint = GetEntryPointAndDiagnostics(cancellationToken); + return entryPoint.MethodSymbol; } - internal EntryPoint? GetEntryPointAndDiagnostics(CancellationToken cancellationToken) + internal EntryPoint GetEntryPointAndDiagnostics(CancellationToken cancellationToken) { - if (!this.Options.OutputKind.IsApplication() && (this.ScriptClass is null)) + if (_lazyEntryPoint == null) { - return null; - } + EntryPoint? entryPoint; + MethodSymbol? simpleProgramEntryPointSymbol = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(this); - if (this.Options.MainTypeName != null && !this.Options.MainTypeName.IsValidClrTypeName()) - { - Debug.Assert(!this.Options.Errors.IsDefaultOrEmpty); - return new EntryPoint(null, ImmutableArray.Empty); - } + if (!this.Options.OutputKind.IsApplication() && (this.ScriptClass is null)) + { + if (simpleProgramEntryPointSymbol is object) + { + var diagnostics = DiagnosticBag.GetInstance(); + diagnostics.Add(ErrorCode.ERR_SimpleProgramNotAnExecutable, NoLocation.Singleton); + entryPoint = new EntryPoint(null, diagnostics.ToReadOnlyAndFree()); + } + else + { + entryPoint = EntryPoint.None; + } + } + else + { + entryPoint = null; - if (_lazyEntryPoint == null) - { - ImmutableArray diagnostics; - var entryPoint = FindEntryPoint(cancellationToken, out diagnostics); - Interlocked.CompareExchange(ref _lazyEntryPoint, new EntryPoint(entryPoint, diagnostics), null); + if (this.Options.MainTypeName != null && !this.Options.MainTypeName.IsValidClrTypeName()) + { + Debug.Assert(!this.Options.Errors.IsDefaultOrEmpty); + entryPoint = EntryPoint.None; + } + + if (entryPoint is null) + { + ImmutableArray diagnostics; + var entryPointMethod = FindEntryPoint(simpleProgramEntryPointSymbol, cancellationToken, out diagnostics); + entryPoint = new EntryPoint(entryPointMethod, diagnostics); + } + + if (this.Options.MainTypeName != null && simpleProgramEntryPointSymbol is object) + { + var diagnostics = DiagnosticBag.GetInstance(); + diagnostics.Add(ErrorCode.ERR_SimpleProgramDisallowsMainType, NoLocation.Singleton); + entryPoint = new EntryPoint(entryPoint.MethodSymbol, entryPoint.Diagnostics.Concat(diagnostics.ToReadOnlyAndFree())); + } + } + + Interlocked.CompareExchange(ref _lazyEntryPoint, entryPoint, null); } return _lazyEntryPoint; } - private MethodSymbol? FindEntryPoint(CancellationToken cancellationToken, out ImmutableArray sealedDiagnostics) + private MethodSymbol? FindEntryPoint(MethodSymbol? simpleProgramEntryPointSymbol, CancellationToken cancellationToken, out ImmutableArray sealedDiagnostics) { var diagnostics = DiagnosticBag.GetInstance(); var entryPointCandidates = ArrayBuilder.GetInstance(); @@ -1575,11 +1603,11 @@ internal bool DeclaresTheObjectClass string? mainTypeName = this.Options.MainTypeName; NamespaceSymbol globalNamespace = this.SourceModule.GlobalNamespace; + var scriptClass = this.ScriptClass; if (mainTypeName != null) { // Global code is the entry point, ignore all other Mains. - var scriptClass = this.ScriptClass; if (scriptClass is object) { // CONSIDER: we could use the symbol instead of just the name. @@ -1612,14 +1640,21 @@ internal bool DeclaresTheObjectClass this.GetSymbolsWithNameCore(WellKnownMemberNames.EntryPointMethodName, SymbolFilter.Member, cancellationToken)); // Global code is the entry point, ignore all other Mains. - var scriptClass = this.ScriptClass; - if (scriptClass is object) + if (scriptClass is object || simpleProgramEntryPointSymbol is object) { foreach (var main in entryPointCandidates) { diagnostics.Add(ErrorCode.WRN_MainIgnored, main.Locations.First(), main); } - return scriptClass.GetScriptEntryPoint(); + + if (scriptClass is object) + { + return scriptClass.GetScriptEntryPoint(); + } + + RoslynDebug.Assert(simpleProgramEntryPointSymbol is object); + entryPointCandidates.Clear(); + entryPointCandidates.Add(simpleProgramEntryPointSymbol); } } @@ -1809,7 +1844,7 @@ internal bool ReturnsAwaitableToVoidOrInt(MethodSymbol method, DiagnosticBag dia /// is either void or int. /// - has either no parameter or a single parameter of type string[] /// - private (bool IsCandidate, bool IsTaskLike) HasEntryPointSignature(MethodSymbol method, DiagnosticBag bag) + internal (bool IsCandidate, bool IsTaskLike) HasEntryPointSignature(MethodSymbol method, DiagnosticBag bag) { if (method.IsVararg) { @@ -1866,6 +1901,8 @@ internal class EntryPoint public readonly MethodSymbol? MethodSymbol; public readonly ImmutableArray Diagnostics; + public static readonly EntryPoint None = new EntryPoint(null, ImmutableArray.Empty); + public EntryPoint(MethodSymbol? methodSymbol, ImmutableArray diagnostics) { this.MethodSymbol = methodSymbol; @@ -2045,15 +2082,28 @@ private protected override bool IsSymbolAccessibleWithinCore( // most convenient. We store them using weak references so that GC pressure will cause them // to be recycled. private WeakReference[]? _binderFactories; + private WeakReference[]? _ignoreAccessibilityBinderFactories; + + internal BinderFactory GetBinderFactory(SyntaxTree syntaxTree, bool ignoreAccessibility = false) + { + if (ignoreAccessibility && SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(this) is object) + { + return GetBinderFactory(syntaxTree, ignoreAccessibility: true, ref _ignoreAccessibilityBinderFactories); + } - internal BinderFactory GetBinderFactory(SyntaxTree syntaxTree) + return GetBinderFactory(syntaxTree, ignoreAccessibility: false, ref _binderFactories); + } + + private BinderFactory GetBinderFactory(SyntaxTree syntaxTree, bool ignoreAccessibility, ref WeakReference[]? cachedBinderFactories) { + Debug.Assert(System.Runtime.CompilerServices.Unsafe.AreSame(ref cachedBinderFactories, ref ignoreAccessibility ? ref _ignoreAccessibilityBinderFactories : ref _binderFactories)); + var treeNum = GetSyntaxTreeOrdinal(syntaxTree); - WeakReference[]? binderFactories = _binderFactories; + WeakReference[]? binderFactories = cachedBinderFactories; if (binderFactories == null) { binderFactories = new WeakReference[this.SyntaxTrees.Length]; - binderFactories = Interlocked.CompareExchange(ref _binderFactories, binderFactories, null) ?? binderFactories; + binderFactories = Interlocked.CompareExchange(ref cachedBinderFactories, binderFactories, null) ?? binderFactories; } BinderFactory? previousFactory; @@ -2063,12 +2113,12 @@ internal BinderFactory GetBinderFactory(SyntaxTree syntaxTree) return previousFactory; } - return AddNewFactory(syntaxTree, ref binderFactories[treeNum]); + return AddNewFactory(syntaxTree, ignoreAccessibility, ref binderFactories[treeNum]); } - private BinderFactory AddNewFactory(SyntaxTree syntaxTree, [NotNull] ref WeakReference? slot) + private BinderFactory AddNewFactory(SyntaxTree syntaxTree, bool ignoreAccessibility, [NotNull] ref WeakReference? slot) { - var newFactory = new BinderFactory(this, syntaxTree); + var newFactory = new BinderFactory(this, syntaxTree, ignoreAccessibility); var newWeakReference = new WeakReference(newFactory); while (true) diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 8cf7fed52d6e8..6d10e5ca597d3 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -2727,6 +2727,14 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp /// The symbol that was declared. public abstract ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)); + /// + /// Given a compilation unit syntax, get the corresponding Simple Program entry point symbol. + /// + /// The compilation unit that declares the entry point member. + /// The cancellation token. + /// The symbol that was declared. + public abstract IMethodSymbol GetDeclaredSymbol(CompilationUnitSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)); + /// /// Given a namespace declaration syntax node, get the corresponding namespace symbol for /// the declaration assembly. @@ -4877,6 +4885,8 @@ protected sealed override ISymbol GetDeclaredSymbolCore(SyntaxNode node, Cancell return this.GetDeclaredSymbol((JoinIntoClauseSyntax)node, cancellationToken); case SyntaxKind.QueryContinuation: return this.GetDeclaredSymbol((QueryContinuationSyntax)node, cancellationToken); + case SyntaxKind.CompilationUnit: + return this.GetDeclaredSymbol((CompilationUnitSyntax)node, cancellationToken); } return null; @@ -4923,9 +4933,34 @@ internal override void ComputeDeclarationsInSpan(TextSpan span, bool getSymbol, CSharpDeclarationComputer.ComputeDeclarationsInSpan(this, span, getSymbol, builder, cancellationToken); } - internal override void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, ArrayBuilder builder, CancellationToken cancellationToken, int? levelsToCompute = null) + internal override void ComputeDeclarationsInNode(SyntaxNode node, ISymbol associatedSymbol, bool getSymbol, ArrayBuilder builder, CancellationToken cancellationToken, int? levelsToCompute = null) { - CSharpDeclarationComputer.ComputeDeclarationsInNode(this, node, getSymbol, builder, cancellationToken, levelsToCompute); + CSharpDeclarationComputer.ComputeDeclarationsInNode(this, associatedSymbol, node, getSymbol, builder, cancellationToken, levelsToCompute); + } + + internal override Func GetSyntaxNodesToAnalyzeFilter(SyntaxNode declaredNode, ISymbol declaredSymbol) + { + if (declaredNode is CompilationUnitSyntax unit && SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(Compilation, unit, fallbackToMainEntryPoint: false) is SynthesizedSimpleProgramEntryPointSymbol entryPoint) + { + switch (declaredSymbol.Kind) + { + case SymbolKind.Namespace: + Debug.Assert(((INamespaceSymbol)declaredSymbol).IsGlobalNamespace); + // Do not include top level global statements into a global namespace + return (node) => node.Kind() != SyntaxKind.GlobalStatement || node.Parent != unit; + + case SymbolKind.Method: + Debug.Assert((object)declaredSymbol.GetSymbol() == (object)entryPoint); + // Include only global statements at the top level + return (node) => node.Parent != unit || node.Kind() == SyntaxKind.GlobalStatement; + + default: + ExceptionUtilities.UnexpectedValue(declaredSymbol.Kind); + break; + } + } + + return base.GetSyntaxNodesToAnalyzeFilter(declaredNode, declaredSymbol); } protected internal override SyntaxNode GetTopmostNodeForDiagnosticAnalysis(ISymbol symbol, SyntaxNode declaringSyntax) diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs index 633aed9752fb7..585ac4ec4982e 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs @@ -18,13 +18,15 @@ internal partial class MemberSemanticModel { protected sealed class NodeMapBuilder : BoundTreeWalkerWithStackGuard { - private NodeMapBuilder(OrderPreservingMultiDictionary map, SyntaxNode thisSyntaxNodeOnly) + private NodeMapBuilder(OrderPreservingMultiDictionary map, SyntaxTree tree, SyntaxNode thisSyntaxNodeOnly) { _map = map; + _tree = tree; _thisSyntaxNodeOnly = thisSyntaxNodeOnly; } private readonly OrderPreservingMultiDictionary _map; + private readonly SyntaxTree _tree; private readonly SyntaxNode _thisSyntaxNodeOnly; /// @@ -34,7 +36,7 @@ private NodeMapBuilder(OrderPreservingMultiDictionary map /// The root of the bound tree. /// The cache. /// The syntax node where to add bound nodes for. - public static void AddToMap(BoundNode root, Dictionary> map, SyntaxNode node = null) + public static void AddToMap(BoundNode root, Dictionary> map, SyntaxTree tree, SyntaxNode node = null) { Debug.Assert(node == null || root == null || !(root.Syntax is StatementSyntax), "individually added nodes are not supposed to be statements."); @@ -45,7 +47,7 @@ public static void AddToMap(BoundNode root, Dictionary.GetInstance(); - var builder = new NodeMapBuilder(additionMap, node); + var builder = new NodeMapBuilder(additionMap, tree, node); builder.Visit(root); foreach (CSharpSyntaxNode key in additionMap.Keys) @@ -126,7 +128,12 @@ public static void AddToMap(BoundNode root, Dictionary boundNodes) return null; } + public override IMethodSymbol GetDeclaredSymbol(CompilationUnitSyntax declarationSyntax, CancellationToken cancellationToken = default) + { + return null; + } + public override IMethodSymbol GetDeclaredSymbol(BaseMethodDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)) { // Can't define method inside member. @@ -1457,7 +1465,8 @@ private ImmutableArray GuardedAddBoundTreeAndGetBoundNodeFromMap(CSha // this may happen if we have races and in such case we are no longer interested in adding if (!alreadyInTree) { - NodeMapBuilder.AddToMap(bound, _guardedNodeMap); + NodeMapBuilder.AddToMap(bound, _guardedNodeMap, SyntaxTree); + Debug.Assert(syntax != _root || _guardedNodeMap.ContainsKey(bound.Syntax)); } ImmutableArray result; @@ -1492,12 +1501,13 @@ protected void GuardedAddBoundTreeForStandaloneSyntax(SyntaxNode syntax, BoundNo // If syntax is a statement, we need to add all its children. // Node cache assumes that if statement is cached, then all // its children are cached too. - NodeMapBuilder.AddToMap(bound, _guardedNodeMap); + NodeMapBuilder.AddToMap(bound, _guardedNodeMap, SyntaxTree); + Debug.Assert(syntax != _root || _guardedNodeMap.ContainsKey(bound.Syntax)); } else { // expressions can be added individually. - NodeMapBuilder.AddToMap(bound, _guardedNodeMap, syntax); + NodeMapBuilder.AddToMap(bound, _guardedNodeMap, SyntaxTree, syntax); } Debug.Assert((manager is null && (!Compilation.NullableSemanticAnalysisEnabled || syntax != Root || syntax is TypeSyntax || @@ -1903,19 +1913,13 @@ private static Binder GetLambdaEnclosingBinder(int position, CSharpSyntaxNode st /// protected void EnsureNullabilityAnalysisPerformedIfNecessary() { - // In DEBUG without nullable analysis enabled, we want to use a temp diagnosticbag - // that can't produce any observable side effects - DiagnosticBag diagnostics = _ignoredDiagnostics; - // If we're in DEBUG mode, always enable the analysis, but throw away the results +#if !DEBUG if (!Compilation.NullableSemanticAnalysisEnabled) { -#if DEBUG - diagnostics = new DiagnosticBag(); -#else return; -#endif } +#endif // If we have a snapshot manager, then we've already done // all the work necessary and we should avoid taking an @@ -1940,47 +1944,71 @@ protected void EnsureNullabilityAnalysisPerformedIfNecessary() return; } + Debug.Assert(_guardedNodeMap.Count == 0); + upgradeableLock.EnterWrite(); - Debug.Assert(Root == GetBindableSyntaxNode(Root)); + Debug.Assert(Root == bindableRoot); - var binder = GetEnclosingBinder(GetAdjustedNodePosition(bindableRoot)); - var boundRoot = Bind(binder, bindableRoot, diagnostics); - if (IsSpeculativeSemanticModel) - { - ensureSpeculativeNodeBound(); - } - else - { - bindAndRewrite(); - } + NullableWalker.SnapshotManager snapshotManager; + var remappedSymbols = _parentRemappedSymbolsOpt; + BoundNode boundRoot; + Binder binder; + + bind(bindableRoot, out binder, out boundRoot); - void ensureSpeculativeNodeBound() + if (IsSpeculativeSemanticModel) { // Not all speculative models are created with existing snapshots. Attributes, // TypeSyntaxes, and MethodBodies do not depend on existing state in a member, // and so the SnapshotManager can be null in these cases. if (_parentSnapshotManagerOpt is null) { - bindAndRewrite(); + rewriteAndCache(); return; } - var remappedSymbols = _parentRemappedSymbolsOpt; boundRoot = NullableWalker.AnalyzeAndRewriteSpeculation(_speculatedPosition, boundRoot, binder, _parentSnapshotManagerOpt, out var newSnapshots, ref remappedSymbols); GuardedAddBoundTreeForStandaloneSyntax(bindableRoot, boundRoot, newSnapshots, remappedSymbols); } + else + { + rewriteAndCache(); + } + + void bind(CSharpSyntaxNode bindableRoot, out Binder binder, out BoundNode boundRoot) + { + binder = GetEnclosingBinder(GetAdjustedNodePosition(bindableRoot)); + boundRoot = Bind(binder, bindableRoot, getDiagnosticBag()); + } + + void rewriteAndCache() + { + boundRoot = RewriteNullableBoundNodesWithSnapshots(boundRoot, binder, getDiagnosticBag(), takeSnapshots: true, out snapshotManager, ref remappedSymbols); + cache(bindableRoot, boundRoot, snapshotManager, remappedSymbols); + } - void bindAndRewrite() + void cache(CSharpSyntaxNode bindableRoot, BoundNode boundRoot, NullableWalker.SnapshotManager snapshotManager, ImmutableDictionary remappedSymbols) { - var remappedSymbols = _parentRemappedSymbolsOpt; - boundRoot = RewriteNullableBoundNodesWithSnapshots(boundRoot, binder, diagnostics, takeSnapshots: true, out var snapshotManager, ref remappedSymbols); #if DEBUG // Don't actually cache the results if the nullable analysis is not enabled in debug mode. if (!Compilation.NullableSemanticAnalysisEnabled) return; #endif GuardedAddBoundTreeForStandaloneSyntax(bindableRoot, boundRoot, snapshotManager, remappedSymbols); } + + DiagnosticBag getDiagnosticBag() + { + // In DEBUG without nullable analysis enabled, we want to use a temp diagnosticbag + // that can't produce any observable side effects +#if DEBUG + if (!Compilation.NullableSemanticAnalysisEnabled) + { + return new DiagnosticBag(); + } +#endif + return _ignoredDiagnostics; + } } #nullable enable @@ -2062,6 +2090,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) // to avoid duplicates in the map if a parent of this node comes through this code path also. var binder = GetEnclosingBinder(GetAdjustedNodePosition(node)); + incrementalBinder = new IncrementalBinder(this, binder); using (_nodeMapLock.DisposableRead()) { @@ -2073,7 +2102,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) // https://github.com/dotnet/roslyn/issues/35038: We have to run analysis on this node in some manner using (_nodeMapLock.DisposableWrite()) { - var boundNode = this.Bind(binder, node, _ignoredDiagnostics); + var boundNode = this.Bind(incrementalBinder, node, _ignoredDiagnostics); GuardedAddBoundTreeForStandaloneSyntax(node, boundNode); results = GuardedGetBoundNodesFromMap(node); } @@ -2324,48 +2353,61 @@ internal override Binder GetBinder(SyntaxNode node) public override BoundStatement BindStatement(StatementSyntax node, DiagnosticBag diagnostics) { // Check the bound node cache to see if the statement was already bound. - BoundStatement synthesizedStatement = _semanticModel.GuardedGetSynthesizedStatementFromMap(node); - - if (synthesizedStatement != null) + if (node.SyntaxTree == _semanticModel.SyntaxTree) { - return synthesizedStatement; - } + BoundStatement synthesizedStatement = _semanticModel.GuardedGetSynthesizedStatementFromMap(node); - BoundNode boundNode = TryGetBoundNodeFromMap(node); + if (synthesizedStatement != null) + { + return synthesizedStatement; + } - if (boundNode == null) - { - // Not bound already. Bind it. It will get added to the cache later by a MemberSemanticModel.NodeMapBuilder. - var statement = base.BindStatement(node, diagnostics); + BoundNode boundNode = TryGetBoundNodeFromMap(node); - // Synthesized statements are not added to the _guardedNodeMap, we cache them explicitly here in - // _lazyGuardedSynthesizedStatementsMap - if (statement.WasCompilerGenerated) + if (boundNode != null) { - _semanticModel.GuardedAddSynthesizedStatementToMap(node, statement); + return (BoundStatement)boundNode; } + } - return statement; + BoundStatement statement = base.BindStatement(node, diagnostics); + + // Synthesized statements are not added to the _guardedNodeMap, we cache them explicitly here in + // _lazyGuardedSynthesizedStatementsMap + if (statement.WasCompilerGenerated && node.SyntaxTree == _semanticModel.SyntaxTree) + { + _semanticModel.GuardedAddSynthesizedStatementToMap(node, statement); } - return (BoundStatement)boundNode; + return statement; } internal override BoundBlock BindEmbeddedBlock(BlockSyntax node, DiagnosticBag diagnostics) { - BoundBlock block = (BoundBlock)TryGetBoundNodeFromMap(node) ?? base.BindEmbeddedBlock(node, diagnostics); + BoundBlock block = (BoundBlock)TryGetBoundNodeFromMap(node); + + if (block is object) + { + return block; + } + + block = base.BindEmbeddedBlock(node, diagnostics); + Debug.Assert(!block.WasCompilerGenerated); return block; } private BoundNode TryGetBoundNodeFromMap(CSharpSyntaxNode node) { - ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); - - if (!boundNodes.IsDefaultOrEmpty) + if (node.SyntaxTree == _semanticModel.SyntaxTree) { - // Already bound. Return the top-most bound node associated with the statement. - return boundNodes[0]; + ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); + + if (!boundNodes.IsDefaultOrEmpty) + { + // Already bound. Return the top-most bound node associated with the statement. + return boundNodes[0]; + } } return null; @@ -2373,7 +2415,16 @@ private BoundNode TryGetBoundNodeFromMap(CSharpSyntaxNode node) public override BoundNode BindMethodBody(CSharpSyntaxNode node, DiagnosticBag diagnostics) { - return TryGetBoundNodeFromMap(node) ?? base.BindMethodBody(node, diagnostics); + BoundNode boundNode = TryGetBoundNodeFromMap(node); + + if (boundNode is object) + { + return boundNode; + } + + boundNode = base.BindMethodBody(node, diagnostics); + + return boundNode; } internal override BoundExpressionStatement BindConstructorInitializer(ConstructorInitializerSyntax node, DiagnosticBag diagnostics) @@ -2383,8 +2434,18 @@ internal override BoundExpressionStatement BindConstructorInitializer(Constructo internal override BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax node, DiagnosticBag diagnostics) { - return (BoundBlock)TryGetBoundNodeFromMap(node) ?? base.BindExpressionBodyAsBlock(node, diagnostics); + BoundBlock block = (BoundBlock)TryGetBoundNodeFromMap(node); + + if (block is object) + { + return block; + } + + block = base.BindExpressionBodyAsBlock(node, diagnostics); + + return block; } } + } } diff --git a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs index 24a643cf16a85..4a6af2f481700 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs @@ -54,7 +54,8 @@ private MethodBodySemanticModel( Debug.Assert((object)owner != null); Debug.Assert(owner.Kind == SymbolKind.Method); Debug.Assert(syntax != null); - Debug.Assert(syntax.Kind() != SyntaxKind.CompilationUnit); + Debug.Assert(parentRemappedSymbolsOpt is null || IsSpeculativeSemanticModel); + Debug.Assert((syntax.Kind() == SyntaxKind.CompilationUnit) == (!IsSpeculativeSemanticModel && owner is SynthesizedSimpleProgramEntryPointSymbol)); } /// @@ -93,6 +94,9 @@ internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, Diagnosti case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: + case SyntaxKind.CompilationUnit: + // When we are binding the root for a multi-unit simple program (for example to do a flow analysis), + // here we are going to bind all units. return binder.BindMethodBody(node, diagnostics); } diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 7f94edfa3c0c0..4fc5ce3d592ea 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -50,7 +50,7 @@ internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree synta throw new ArgumentOutOfRangeException(nameof(syntaxTree), CSharpResources.TreeNotPartOfCompilation); } - _binderFactory = compilation.GetBinderFactory(SyntaxTree); + _binderFactory = compilation.GetBinderFactory(SyntaxTree, ignoreAccessibility); } internal SyntaxTreeSemanticModel(CSharpCompilation parentCompilation, SyntaxTree parentSyntaxTree, SyntaxTree speculatedSyntaxTree) @@ -178,6 +178,7 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, Cancellat case AccessorDeclarationSyntax accessor: model = (accessor.Body != null || accessor.ExpressionBody != null) ? GetOrAddModel(node) : null; break; + default: model = this.GetMemberModel(node); break; @@ -799,7 +800,7 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node) return null; } - var memberDecl = GetMemberDeclaration(node); + var memberDecl = GetMemberDeclaration(node) ?? (node as CompilationUnitSyntax); if (memberDecl != null) { var span = node.Span; @@ -882,8 +883,20 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node) } case SyntaxKind.GlobalStatement: + if (SyntaxFacts.IsSimpleProgramTopLevelStatement((GlobalStatementSyntax)memberDecl)) + { + return GetOrAddModel((CompilationUnitSyntax)memberDecl.Parent); + } + return GetOrAddModel(memberDecl); + case SyntaxKind.CompilationUnit: + if (SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(Compilation, (CompilationUnitSyntax)memberDecl, fallbackToMainEntryPoint: false) is object) + { + return GetOrAddModel(memberDecl); + } + break; + case SyntaxKind.Attribute: return GetOrAddModelForAttribute((AttributeSyntax)memberDecl); @@ -1005,16 +1018,13 @@ internal MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node, Func _binderFactory.GetBinder(node).WithAdditionalFlags(additionalFlags); + Binder defaultOuter() => _binderFactory.GetBinder(node).WithAdditionalFlags(this.IgnoresAccessibility ? BinderFlags.IgnoreAccessibility : BinderFlags.None); switch (node.Kind()) { + case SyntaxKind.CompilationUnit: + return createMethodBodySemanticModel(node, SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(Compilation, (CompilationUnitSyntax)node, fallbackToMainEntryPoint: false)); + case SyntaxKind.MethodDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.OperatorDeclaration: @@ -1023,14 +1033,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) { var memberDecl = (MemberDeclarationSyntax)node; var symbol = GetDeclaredSymbol(memberDecl).GetSymbol(); - ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); - - if (binder == null) - { - return null; - } - - return MethodBodySemanticModel.Create(this, symbol, new MethodBodySemanticModel.InitialState(memberDecl, binder: binder)); + return createMethodBodySemanticModel(memberDecl, symbol); } case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: @@ -1039,14 +1042,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) { var accessorDecl = (AccessorDeclarationSyntax)node; var symbol = GetDeclaredSymbol(accessorDecl).GetSymbol(); - ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); - - if (binder == null) - { - return null; - } - - return MethodBodySemanticModel.Create(this, symbol, new MethodBodySemanticModel.InitialState(accessorDecl, binder: binder)); + return createMethodBodySemanticModel(accessorDecl, symbol); } case SyntaxKind.Block: @@ -1132,7 +1128,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) ExceptionUtilities.UnexpectedValue(node.Parent); } - ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, additionalFlags); + ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, this.IgnoresAccessibility); if (binder == null) { @@ -1176,6 +1172,18 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) } return null; + + MemberSemanticModel createMethodBodySemanticModel(CSharpSyntaxNode memberDecl, SourceMemberMethodSymbol symbol) + { + ExecutableCodeBinder binder = symbol?.TryGetBodyBinder(_binderFactory, this.IgnoresAccessibility); + + if (binder == null) + { + return null; + } + + return MethodBodySemanticModel.Create(this, symbol, new MethodBodySemanticModel.InitialState(memberDecl, binder: binder)); + } } private AttributeSemanticModel CreateModelForAttribute(Binder enclosingBinder, AttributeSyntax attribute, MemberSemanticModel containingModel) @@ -1408,6 +1416,13 @@ private NamespaceOrTypeSymbol GetDeclaredNamespaceOrType(CSharpSyntaxNode declar } } + public override IMethodSymbol GetDeclaredSymbol(CompilationUnitSyntax declarationSyntax, CancellationToken cancellationToken = default) + { + CheckSyntaxNode(declarationSyntax); + + return SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(Compilation, declarationSyntax, fallbackToMainEntryPoint: false).GetPublicSymbol(); + } + /// /// Given a local function declaration syntax, get the corresponding symbol. /// @@ -1843,7 +1858,7 @@ public override IAliasSymbol GetDeclaredSymbol( return null; } - InContainerBinder binder = _binderFactory.GetImportsBinder(declarationSyntax.Parent); + Binder binder = _binderFactory.GetImportsBinder(declarationSyntax.Parent); var imports = binder.GetImports(basesBeingResolved: null); var alias = imports.UsingAliases[declarationSyntax.Alias.Name.Identifier.ValueText]; diff --git a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs index 8745cead75195..18d231a30dafe 100644 --- a/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/DocumentationCommentCompiler.cs @@ -239,7 +239,7 @@ public override void DefaultVisit(Symbol symbol) { _cancellationToken.ThrowIfCancellationRequested(); - if (symbol.IsImplicitlyDeclared || symbol.IsAccessor()) + if (symbol.IsImplicitlyDeclared || symbol.IsAccessor() || symbol is SynthesizedSimpleProgramEntryPointSymbol) { return; } @@ -548,7 +548,7 @@ private static bool RequiresDocumentationComment(Symbol symbol) { Debug.Assert((object)symbol != null); - if (symbol.IsImplicitlyDeclared || symbol.IsAccessor()) + if (symbol.IsImplicitlyDeclared || symbol.IsAccessor() || symbol is SynthesizedSimpleProgramEntryPointSymbol) { return false; } diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 8f909008e3ec8..69c5e62ff7a9e 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -207,10 +207,6 @@ public static void CompileMethodBodies( private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool hasDeclarationErrors, DiagnosticBag diagnostics, CancellationToken cancellationToken) { var entryPointAndDiagnostics = compilation.GetEntryPointAndDiagnostics(cancellationToken); - if (entryPointAndDiagnostics == null) - { - return null; - } Debug.Assert(!entryPointAndDiagnostics.Diagnostics.IsDefault); diagnostics.AddRange(entryPointAndDiagnostics.Diagnostics); @@ -218,7 +214,6 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul if ((object)entryPoint == null) { - Debug.Assert(entryPointAndDiagnostics.Diagnostics.HasAnyErrors() || !compilation.Options.Errors.IsDefaultOrEmpty); return null; } @@ -1667,7 +1662,6 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta if (bodyBinder != null) { importChain = bodyBinder.ImportChain; - bodyBinder.ValidateIteratorMethods(diagnostics); BoundNode methodBody = bodyBinder.BindMethodBody(syntaxNode, diagnostics); BoundNode methodBodyForSemanticModel = methodBody; diff --git a/src/Compilers/CSharp/Portable/Declarations/DeclarationKind.cs b/src/Compilers/CSharp/Portable/Declarations/DeclarationKind.cs index ce85fc04c4cf8..16810510b0093 100644 --- a/src/Compilers/CSharp/Portable/Declarations/DeclarationKind.cs +++ b/src/Compilers/CSharp/Portable/Declarations/DeclarationKind.cs @@ -19,7 +19,8 @@ internal enum DeclarationKind : byte Delegate, Script, Submission, - ImplicitClass + ImplicitClass, + SimpleProgram, } internal static partial class EnumConversions diff --git a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs index f761897d3fc93..9ae2cef7fce15 100644 --- a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs +++ b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs @@ -51,6 +51,11 @@ private ImmutableArray VisitNamespaceChildren( // We look for members that are not allowed in a namespace. // If there are any we create an implicit class to wrap them. bool hasGlobalMembers = false; + bool acceptSimpleProgram = node.Kind() == SyntaxKind.CompilationUnit && _syntaxTree.Options.Kind == SourceCodeKind.Regular; + bool hasAwaitExpressions = false; + bool isIterator = false; + bool hasReturnWithExpression = false; + GlobalStatementSyntax firstGlobalStatement = null; var childrenBuilder = ArrayBuilder.GetInstance(); foreach (var member in members) @@ -60,18 +65,45 @@ private ImmutableArray VisitNamespaceChildren( { childrenBuilder.Add(namespaceOrType); } - else + else if (acceptSimpleProgram && member.IsKind(SyntaxKind.GlobalStatement)) { - hasGlobalMembers = hasGlobalMembers || member.Kind() != SyntaxKind.IncompleteMember; + var global = (GlobalStatementSyntax)member; + firstGlobalStatement ??= global; + var topLevelStatement = global.Statement; + + if (!hasAwaitExpressions) + { + hasAwaitExpressions = SyntaxFacts.HasAwaitOperations(topLevelStatement); + } + + if (!isIterator) + { + isIterator = SyntaxFacts.HasYieldOperations(topLevelStatement); + } + + if (!hasReturnWithExpression) + { + hasReturnWithExpression = SyntaxFacts.HasReturnWithExpression(topLevelStatement); + } + } + else if (!hasGlobalMembers && member.Kind() != SyntaxKind.IncompleteMember) + { + hasGlobalMembers = true; } } + // wrap all global statements in a compilation unit into a simple program type: + if (firstGlobalStatement is object) + { + childrenBuilder.Add(CreateSimpleProgram(firstGlobalStatement, hasAwaitExpressions, isIterator, hasReturnWithExpression)); + } + // wrap all members that are defined in a namespace or compilation unit into an implicit type: if (hasGlobalMembers) { //The implicit class is not static and has no extensions SingleTypeDeclaration.TypeDeclarationFlags declFlags = SingleTypeDeclaration.TypeDeclarationFlags.None; - var memberNames = GetNonTypeMemberNames(internalMembers, ref declFlags); + var memberNames = GetNonTypeMemberNames(internalMembers, ref declFlags, skipGlobalStatements: acceptSimpleProgram); var container = _syntaxTree.GetReference(node); childrenBuilder.Add(CreateImplicitClass(memberNames, container, declFlags)); @@ -95,6 +127,23 @@ private static SingleNamespaceOrTypeDeclaration CreateImplicitClass(ImmutableHas diagnostics: ImmutableArray.Empty); } + private static SingleNamespaceOrTypeDeclaration CreateSimpleProgram(GlobalStatementSyntax firstGlobalStatement, bool hasAwaitExpressions, bool isIterator, bool hasReturnWithExpression) + { + return new SingleTypeDeclaration( + kind: DeclarationKind.SimpleProgram, + name: SimpleProgramNamedTypeSymbol.UnspeakableName, + arity: 0, + modifiers: DeclarationModifiers.Internal | DeclarationModifiers.Partial | DeclarationModifiers.Static, + declFlags: (hasAwaitExpressions ? SingleTypeDeclaration.TypeDeclarationFlags.HasAwaitExpressions : SingleTypeDeclaration.TypeDeclarationFlags.None) | + (isIterator ? SingleTypeDeclaration.TypeDeclarationFlags.IsIterator : SingleTypeDeclaration.TypeDeclarationFlags.None) | + (hasReturnWithExpression ? SingleTypeDeclaration.TypeDeclarationFlags.HasReturnWithExpression : SingleTypeDeclaration.TypeDeclarationFlags.None), + syntaxReference: firstGlobalStatement.SyntaxTree.GetReference(firstGlobalStatement.Parent), + nameLocation: new SourceLocation(firstGlobalStatement.GetFirstToken()), + memberNames: ImmutableHashSet.Empty, + children: ImmutableArray.Empty, + diagnostics: ImmutableArray.Empty); + } + /// /// Creates a root declaration that contains a Script class declaration (possibly in a namespace) and namespace declarations. /// Top-level declarations in script code are nested in Script class. @@ -483,7 +532,7 @@ private static ImmutableHashSet GetEnumMemberNames(SeparatedSyntaxList GetNonTypeMemberNames( - CoreInternalSyntax.SyntaxList members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) + CoreInternalSyntax.SyntaxList members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags, bool skipGlobalStatements = false) { bool anyMethodHadExtensionSyntax = false; bool anyMemberHasAttributes = false; @@ -493,7 +542,7 @@ private static ImmutableHashSet GetNonTypeMemberNames( foreach (var member in members) { - AddNonTypeMemberNames(member, memberNameBuilder, ref anyNonTypeMembers); + AddNonTypeMemberNames(member, memberNameBuilder, ref anyNonTypeMembers, skipGlobalStatements); // Check to see if any method contains a 'this' modifier on its first parameter. // This data is used to determine if a type needs to have its members materialized @@ -602,7 +651,7 @@ private static bool CheckMemberForAttributes(Syntax.InternalSyntax.CSharpSyntaxN } private static void AddNonTypeMemberNames( - Syntax.InternalSyntax.CSharpSyntaxNode member, ImmutableHashSet.Builder set, ref bool anyNonTypeMembers) + Syntax.InternalSyntax.CSharpSyntaxNode member, ImmutableHashSet.Builder set, ref bool anyNonTypeMembers, bool skipGlobalStatements) { switch (member.Kind) { @@ -693,7 +742,10 @@ private static void AddNonTypeMemberNames( break; case SyntaxKind.GlobalStatement: - anyNonTypeMembers = true; + if (!skipGlobalStatements) + { + anyNonTypeMembers = true; + } break; } } diff --git a/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs b/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs index 2ebcef6bb53a8..594438200c009 100644 --- a/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs +++ b/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs @@ -18,7 +18,7 @@ internal sealed class SingleTypeDeclaration : SingleNamespaceOrTypeDeclaration private readonly ImmutableArray _children; [Flags] - internal enum TypeDeclarationFlags : byte + internal enum TypeDeclarationFlags : ushort { None = 0, AnyMemberHasExtensionMethodSyntax = 1 << 1, @@ -26,6 +26,21 @@ internal enum TypeDeclarationFlags : byte HasBaseDeclarations = 1 << 3, AnyMemberHasAttributes = 1 << 4, HasAnyNontypeMembers = 1 << 5, + + /// + /// Simple program uses await expressions. Set only for + /// + HasAwaitExpressions = 1 << 6, + + /// + /// Set only for + /// + IsIterator = 1 << 7, + + /// + /// Set only for + /// + HasReturnWithExpression = 1 << 8, } internal SingleTypeDeclaration( @@ -125,6 +140,30 @@ public bool HasAnyNontypeMembers } } + public bool HasAwaitExpressions + { + get + { + return (_flags & TypeDeclarationFlags.HasAwaitExpressions) != 0; + } + } + + public bool HasReturnWithExpression + { + get + { + return (_flags & TypeDeclarationFlags.HasReturnWithExpression) != 0; + } + } + + public bool IsIterator + { + get + { + return (_flags & TypeDeclarationFlags.IsIterator) != 0; + } + } + protected override ImmutableArray GetNamespaceOrTypeDeclarationChildren() { return StaticCast.From(_children); diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 35b5049f2b64e..4447b721d117b 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1797,6 +1797,12 @@ internal enum ErrorCode ERR_PartialMethodAccessibilityDifference = 8799, ERR_PartialMethodExtendedModDifference = 8800, + ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement = 9000, + ERR_SimpleProgramMultipleUnitsWithTopLevelStatements = 9001, + ERR_TopLevelStatementAfterNamespaceOrType = 9002, + ERR_SimpleProgramDisallowsMainType = 9003, + ERR_SimpleProgramNotAnExecutable = 9004, + #endregion // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index b1b74f2a124e9..51ec42bda7f26 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -199,6 +199,8 @@ internal enum MessageID IDS_FeatureNotPattern = MessageBase + 12775, IDS_FeatureRelationalPattern = MessageBase + 12776, IDS_FeatureExtendedPartialMethods = MessageBase + 12777, + + IDS_TopLevelStatements = MessageBase + 12780, } // Message IDs may refer to strings that need to be localized. @@ -319,6 +321,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureRelationalPattern: case MessageID.IDS_FeatureNativeInt: case MessageID.IDS_FeatureExtendedPartialMethods: // semantic check + case MessageID.IDS_TopLevelStatements: return LanguageVersion.Preview; // C# 8.0 features. diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs index e8e17e455e796..cbc6b8e2f2dfd 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs @@ -37,7 +37,9 @@ internal static HashSet Analyze(CSharpCompilation compilation, Symbol me var result = walker.Analyze(ref badRegion); #if DEBUG // Assert that DataFlowsOut only contains variables that were assigned to inside the region - Debug.Assert(badRegion || !result.Any((variable) => !walker._assignedInside.Contains(variable))); + // https://github.com/dotnet/roslyn/issues/41600 blocks some tests with local functions. + // Enable the following assert once the issue is fixed. + //Debug.Assert(badRegion || !result.Any((variable) => !walker._assignedInside.Contains(variable))); #endif return badRegion ? new HashSet() : result; } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs index cd8578d9c68fe..49e94e42e854e 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/FlowAnalysisPass.cs @@ -41,7 +41,8 @@ public static BoundBlock Rewrite( if (method.ReturnsVoid || method.IsIterator || method.IsAsyncReturningTask(compilation)) { // we don't analyze synthesized void methods. - if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || Analyze(compilation, method, block, diagnostics)) + if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || + Analyze(compilation, method, block, diagnostics)) { block = AppendImplicitReturn(block, method, originalBodyNested); } @@ -116,7 +117,8 @@ internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol me Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause) || - syntax.IsKind(SyntaxKind.ConstructorDeclaration)); + syntax.IsKind(SyntaxKind.ConstructorDeclaration) || + syntax.IsKind(SyntaxKind.CompilationUnit)); BoundStatement ret = (method.IsIterator && !method.IsAsync) ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index f404cb1d97b07..845f4bb69124f 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -752,7 +752,9 @@ internal static void Analyze( { return; } - var binder = compilation.GetBinderFactory(node.SyntaxTree).GetBinder(node.Syntax); + var binder = method is SynthesizedSimpleProgramEntryPointSymbol entryPoint ? + entryPoint.GetBodyBinder(ignoreAccessibility: false) : + compilation.GetBinderFactory(node.SyntaxTree).GetBinder(node.Syntax); var conversions = binder.Conversions; Analyze(compilation, method, diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 5ea43c2e544f4..038ffde6cd776 100644 --- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs +++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs @@ -34,3 +34,4 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Nullable{System.Boolean},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SyntaxTree")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(Microsoft.CodeAnalysis.Text.SourceText,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Nullable{System.Boolean},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SyntaxTree")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DeconstructionPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.DeconstructionPatternClauseSyntax")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.IMethodSymbol")] diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index 8cefd6af7ae91..96cdcc0786c25 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -28,6 +28,8 @@ public static void IssueDiagnostics(CSharpCompilation compilation, BoundNode nod Debug.Assert(node != null); Debug.Assert((object)containingSymbol != null); + ExecutableCodeBinder.ValidateIteratorMethod(compilation, containingSymbol, diagnostics); + try { var diagnosticPass = new DiagnosticsPass(compilation, diagnostics, containingSymbol); @@ -133,6 +135,8 @@ public override BoundNode VisitSizeOfOperator(BoundSizeOfOperator node) public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { + ExecutableCodeBinder.ValidateIteratorMethod(_compilation, node.Symbol, _diagnostics); + var outerLocalFunction = _staticLocalFunction; if (node.Symbol.IsStatic) { diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs index ffa820ea1b697..00318514708d3 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DynamicAnalysisInjector.cs @@ -118,7 +118,7 @@ private DynamicAnalysisInjector( _methodPayload = methodBodyFactory.SynthesizedLocal(_payloadType, kind: SynthesizedLocalKind.InstrumentationPayload, syntax: methodBody.Syntax); // The first point indicates entry into the method and has the span of the method definition. SyntaxNode syntax = MethodDeclarationIfAvailable(methodBody.Syntax); - if (!method.IsImplicitlyDeclared) + if (!method.IsImplicitlyDeclared && !(method is SynthesizedSimpleProgramEntryPointSymbol)) { _methodEntryInstrumentation = AddAnalysisPoint(syntax, SkipAttributes(syntax), methodBodyFactory); } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Block.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Block.cs index d1f8041f18638..a3e42c2c3347b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Block.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Block.cs @@ -32,6 +32,10 @@ public override BoundNode VisitBlock(BoundBlock node) { builder.Insert(0, prologue); } + else if (node == _rootStatement && _factory.TopLevelMethod is SynthesizedSimpleProgramEntryPointSymbol entryPoint) + { + builder.Insert(0, _factory.HiddenSequencePoint()); + } BoundStatement? epilogue = _instrumenter.CreateBlockEpilogue(node); if (epilogue != null) diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs index 834e27bea50b1..ee7f6791e213a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs @@ -674,6 +674,8 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations return default; } } + + internal override bool IsIterator => false; } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs index da6cd2e4d12a7..7c1b5e1c8a77a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs @@ -34,7 +34,7 @@ protected SynthesizedMethodBaseSymbol(NamedTypeSymbol containingType, Location location, string name, DeclarationModifiers declarationModifiers) - : base(containingType, syntaxReference, location) + : base(containingType, syntaxReference, location, isIterator: false) { Debug.Assert((object)containingType != null); Debug.Assert((object)baseMethod != null); @@ -243,5 +243,7 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations Interlocked.Exchange(ref _iteratorElementType, new TypeWithAnnotations.Boxed(value)); } } + + internal override bool IsIterator => BaseMethod.IsIterator; } } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index b5611ba4166d7..3260da26229b3 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.Text; @@ -28,6 +29,7 @@ internal partial class LanguageParser : SyntaxParser private int _recursionDepth; private TerminatorState _termState; // Resettable private bool _isInTry; // Resettable + private bool _checkedTopLevelStatementsFeatureAvailability; // Resettable // NOTE: If you add new state, you should probably add it to ResetPoint as well. @@ -351,6 +353,8 @@ private enum NamespaceParts Usings = 2, GlobalAttributes = 3, MembersAndStatements = 4, + TypesAndNamespaces = 5, + TopLevelStatementsAfterTypesAndNamespaces = 6, } private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuilder body, ref SyntaxListBuilder initialBadNodes, SyntaxKind parentKind) @@ -359,7 +363,6 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil Debug.Assert(!IsInAsync); bool isGlobal = openBrace == null; - bool isGlobalScript = isGlobal && this.IsScript; var saveTerm = _termState; _termState |= TerminatorState.IsNamespaceMemberStartOrStop; @@ -380,12 +383,11 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil var attributeLists = _pool.Allocate(); var modifiers = _pool.Allocate(); - body.Members.Add(this.ParseNamespaceDeclaration(attributeLists, modifiers)); + body.Members.Add(adjustStateAndReportStatementOutOfOrder(ref seen, this.ParseNamespaceDeclaration(attributeLists, modifiers))); _pool.Free(attributeLists); _pool.Free(modifiers); - seen = NamespaceParts.MembersAndStatements; reportUnexpectedToken = true; break; @@ -420,9 +422,9 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil return; case SyntaxKind.ExternKeyword: - if (isGlobalScript && !ScanExternAliasDirective()) + if (isGlobal && !ScanExternAliasDirective()) { - // extern member + // extern member or a local function goto default; } else @@ -447,13 +449,10 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil } case SyntaxKind.UsingKeyword: - if (isGlobalScript && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) + if (isGlobal && (this.PeekToken(1).Kind == SyntaxKind.OpenParenToken || (!IsScript && IsPossibleTopLevelUsingLocalDeclarationStatement()))) { - // incomplete members must be processed before we add any nodes to the body: - AddIncompleteMembers(ref pendingIncompleteMembers, ref body); - - body.Members.Add(_syntaxFactory.GlobalStatement(ParseUsingStatement(attributes: default))); - seen = NamespaceParts.MembersAndStatements; + // Top-level using statement or using local declaration + goto default; } else { @@ -501,7 +500,7 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil goto default; default: - var memberOrStatement = this.ParseMemberDeclarationOrStatement(parentKind); + var memberOrStatement = isGlobal ? this.ParseMemberDeclarationOrStatement(parentKind) : this.ParseMemberDeclaration(parentKind); if (memberOrStatement == null) { // incomplete members must be processed before we add any nodes to the body: @@ -530,8 +529,7 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil // incomplete members must be processed before we add any nodes to the body: AddIncompleteMembers(ref pendingIncompleteMembers, ref body); - body.Members.Add(memberOrStatement); - seen = NamespaceParts.MembersAndStatements; + body.Members.Add(adjustStateAndReportStatementOutOfOrder(ref seen, memberOrStatement)); reportUnexpectedToken = true; } break; @@ -546,6 +544,61 @@ private void ParseNamespaceBody(ref SyntaxToken openBrace, ref NamespaceBodyBuil AddIncompleteMembers(ref pendingIncompleteMembers, ref body); _pool.Free(pendingIncompleteMembers); } + + MemberDeclarationSyntax adjustStateAndReportStatementOutOfOrder(ref NamespaceParts seen, MemberDeclarationSyntax memberOrStatement) + { + switch (memberOrStatement.Kind) + { + case SyntaxKind.GlobalStatement: + if (seen < NamespaceParts.MembersAndStatements) + { + seen = NamespaceParts.MembersAndStatements; + } + else if (seen == NamespaceParts.TypesAndNamespaces) + { + seen = NamespaceParts.TopLevelStatementsAfterTypesAndNamespaces; + + if (!IsScript) + { + memberOrStatement = this.AddError(memberOrStatement, ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType); + } + } + + break; + + case SyntaxKind.NamespaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.StructDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.DelegateDeclaration: + if (seen < NamespaceParts.TypesAndNamespaces) + { + seen = NamespaceParts.TypesAndNamespaces; + } + break; + + default: + if (seen < NamespaceParts.MembersAndStatements) + { + seen = NamespaceParts.MembersAndStatements; + } + break; + } + + return memberOrStatement; + } + } + + private GlobalStatementSyntax CheckTopLevelStatementsFeatureAvailability(GlobalStatementSyntax globalStatementSyntax) + { + if (IsScript || _checkedTopLevelStatementsFeatureAvailability) + { + return globalStatementSyntax; + } + + _checkedTopLevelStatementsFeatureAvailability = true; + return CheckFeatureAvailability(globalStatementSyntax, MessageID.IDS_TopLevelStatements); } private static void AddIncompleteMembers(ref SyntaxListBuilder incompleteMembers, ref NamespaceBodyBuilder body) @@ -1417,7 +1470,7 @@ private TypeDeclarationSyntax ParseClassOrStructOrInterfaceDeclaration(SyntaxLis var saveTerm2 = _termState; _termState |= TerminatorState.IsPossibleMemberStartOrStop; - var memberOrStatement = this.ParseMemberDeclarationOrStatement(classOrStructOrInterface.Kind); + var memberOrStatement = this.ParseMemberDeclaration(classOrStructOrInterface.Kind); if (memberOrStatement != null) { // statements are accepted here, a semantic error will be reported later @@ -1869,7 +1922,7 @@ private bool IsTypeDeclarationStart() } } - private static bool CanReuseMemberDeclaration(SyntaxKind kind) + private bool CanReuseMemberDeclaration(SyntaxKind kind, bool isGlobal) { switch (kind) { @@ -1878,7 +1931,6 @@ private static bool CanReuseMemberDeclaration(SyntaxKind kind) case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.DelegateDeclaration: - case SyntaxKind.FieldDeclaration: case SyntaxKind.EventFieldDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.EventDeclaration: @@ -1886,10 +1938,22 @@ private static bool CanReuseMemberDeclaration(SyntaxKind kind) case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.DestructorDeclaration: - case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.NamespaceDeclaration: return true; + case SyntaxKind.FieldDeclaration: + case SyntaxKind.MethodDeclaration: + if (!isGlobal || IsScript) + { + return true; + } + + // We can reuse original nodes if they came from the global context as well. + return (this.CurrentNode.Parent is Syntax.CompilationUnitSyntax); + + case SyntaxKind.GlobalStatement: + return isGlobal; + default: return false; } @@ -1901,7 +1965,7 @@ public MemberDeclarationSyntax ParseMemberDeclaration() // e.g. including fixed member declarations, but not statements. const SyntaxKind parentKind = SyntaxKind.StructDeclaration; return ParseWithStackGuard( - () => this.ParseMemberDeclarationOrStatement(parentKind), + () => this.ParseMemberDeclaration(parentKind), () => createEmptyNodeFunc()); // Creates a dummy declaration node to which we can attach a stack overflow message @@ -1925,38 +1989,40 @@ internal MemberDeclarationSyntax ParseMemberDeclarationOrStatement(SyntaxKind pa return result; } - // Returns null if we can't parse anything (even partially). + /// + /// Changes in this function around member parsing should be mirrored in . + /// Try keeping structure of both functions similar to simplify this task. The split was made to + /// reduce the stack usage during recursive parsing. + /// + /// Returns null if we can't parse anything (even partially). private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind parentKind) { // "top-level" expressions and statements should never occur inside an asynchronous context Debug.Assert(!IsInAsync); + Debug.Assert(parentKind == SyntaxKind.CompilationUnit); cancellationToken.ThrowIfCancellationRequested(); - bool isGlobalScript = parentKind == SyntaxKind.CompilationUnit && this.IsScript; - bool acceptStatement = isGlobalScript; - // don't reuse members if they were previously declared under a different type keyword kind if (this.IsIncrementalAndFactoryContextMatches) { - if (CanReuseMemberDeclaration(CurrentNodeKind)) + if (CanReuseMemberDeclaration(CurrentNodeKind, isGlobal: true)) { return (MemberDeclarationSyntax)this.EatNode(); } } - var modifiers = _pool.Allocate(); - var saveTermState = _termState; + var attributes = this.ParseAttributeDeclarations(); + bool haveAttributes = (attributes.Count > 0); + + var afterAttributesPoint = this.GetResetPoint(); + + var modifiers = _pool.Allocate(); + try { - var attributes = this.ParseAttributeDeclarations(); - if (attributes.Count > 0) - { - acceptStatement = false; - } - // // Check for the following cases to disambiguate between member declarations and expressions. // Doing this before parsing modifiers simplifies further analysis since some of these keywords can act as modifiers as well. @@ -1970,48 +2036,59 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // new T (...) // new T [...] // - if (acceptStatement) + if (!haveAttributes || !IsScript) { - switch (this.CurrentToken.Kind) + bool wasInAsync = IsInAsync; + if (!IsScript) { - case SyntaxKind.UnsafeKeyword: - if (this.PeekToken(1).Kind == SyntaxKind.OpenBraceToken) - { - return _syntaxFactory.GlobalStatement(ParseUnsafeStatement(attributes)); - } - break; + IsInAsync = true; // We are implicitly in an async context + } - case SyntaxKind.FixedKeyword: - if (this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) - { - return _syntaxFactory.GlobalStatement(ParseFixedStatement(attributes)); - } - break; + try + { + switch (this.CurrentToken.Kind) + { + case SyntaxKind.UnsafeKeyword: + if (this.PeekToken(1).Kind == SyntaxKind.OpenBraceToken) + { + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(ParseUnsafeStatement(attributes))); + } + break; - case SyntaxKind.DelegateKeyword: - switch (this.PeekToken(1).Kind) - { - case SyntaxKind.OpenParenToken: - case SyntaxKind.OpenBraceToken: - return _syntaxFactory.GlobalStatement(ParseExpressionStatement(attributes)); - } - break; + case SyntaxKind.FixedKeyword: + if (this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) + { + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(ParseFixedStatement(attributes))); + } + break; - case SyntaxKind.NewKeyword: - if (IsPossibleNewExpression()) - { - return _syntaxFactory.GlobalStatement(ParseExpressionStatement(attributes)); - } - break; + case SyntaxKind.DelegateKeyword: + switch (this.PeekToken(1).Kind) + { + case SyntaxKind.OpenParenToken: + case SyntaxKind.OpenBraceToken: + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(ParseExpressionStatement(attributes))); + } + break; + + case SyntaxKind.NewKeyword: + if (IsPossibleNewExpression()) + { + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(ParseExpressionStatement(attributes))); + } + break; + } + } + finally + { + IsInAsync = wasInAsync; } } // All modifiers that might start an expression are processed above. this.ParseModifiers(modifiers, forAccessors: false); - if (modifiers.Count > 0) - { - acceptStatement = false; - } + bool haveModifiers = (modifiers.Count > 0); + MemberDeclarationSyntax result; // Check for constructor form if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) @@ -2022,14 +2099,9 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // Script(...) { ... } // ^ // missing ';' - if (!isGlobalScript) - { - return this.ParseConstructorDeclaration(attributes, modifiers); - } - - // Script: - // Unless there modifiers or attributes are present this is more likely to be a method call than a method definition. - if (!acceptStatement) + // + // Unless modifiers or attributes are present this is more likely to be a method call than a method definition. + if (haveAttributes || haveModifiers) { var token = SyntaxFactory.MissingToken(SyntaxKind.VoidKeyword); token = this.AddError(token, ErrorCode.ERR_MemberNeedsType); @@ -2037,20 +2109,33 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind var identifier = this.EatToken(); - return this.ParseMethodDeclaration(attributes, modifiers, voidType, explicitInterfaceOpt: null, identifier: identifier, typeParameterList: null); + if (!IsScript) + { + if (tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + } + else + { + return this.ParseMethodDeclaration(attributes, modifiers, voidType, explicitInterfaceOpt: null, identifier: identifier, typeParameterList: null); + } } } - // Check for destructor form + // Destructors are disallowed in global code, skipping check for them. // TODO: better error messages for script - if (!isGlobalScript && this.CurrentToken.Kind == SyntaxKind.TildeToken) - { - return this.ParseDestructorDeclaration(attributes, modifiers); - } - // Check for constant (prefers const field over const local variable decl) + // Check for constant if (this.CurrentToken.Kind == SyntaxKind.ConstKeyword) { + if (!IsScript && + tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + + // Prefers const field over const local variable decl return this.ParseConstantFieldDeclaration(attributes, modifiers, parentKind); } @@ -2074,8 +2159,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind return this.ParseConversionOperatorDeclaration(attributes, modifiers); } - if (this.CurrentToken.Kind == SyntaxKind.NamespaceKeyword && - parentKind == SyntaxKind.CompilationUnit) + if (this.CurrentToken.Kind == SyntaxKind.NamespaceKeyword) { return ParseNamespaceDeclaration(attributes, modifiers); } @@ -2086,56 +2170,443 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind return this.ParseTypeDeclaration(attributes, modifiers); } - if (acceptStatement && - this.CurrentToken.Kind != SyntaxKind.CloseBraceToken && - this.CurrentToken.Kind != SyntaxKind.EndOfFileToken && - this.IsPossibleStatement(acceptAccessibilityMods: true)) + TypeSyntax type = ParseReturnType(); + + var afterTypeResetPoint = this.GetResetPoint(); + + try { - var saveTerm = _termState; - _termState |= TerminatorState.IsPossibleStatementStartOrStop; // partial statements can abort if a new statement starts - // We don't allow local declaration statements at the top level. We want - // to fall out below and parse them instead as fields. - var statement = this.ParseStatementCore(attributes, isGlobalScriptLevel: true); + if ((!haveAttributes || !IsScript) && !haveModifiers && (type.Kind == SyntaxKind.RefType || !IsOperatorKeyword())) + { + this.Reset(ref afterAttributesPoint); - _termState = saveTerm; - if (statement != null) + if (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken && + this.CurrentToken.Kind != SyntaxKind.EndOfFileToken && + this.IsPossibleStatement(acceptAccessibilityMods: true)) + { + var saveTerm = _termState; + _termState |= TerminatorState.IsPossibleStatementStartOrStop; // partial statements can abort if a new statement starts + bool wasInAsync = IsInAsync; + if (!IsScript) + { + IsInAsync = true; // We are implicitly in an async context + } + // In Script we don't allow local declaration statements at the top level. We want + // to fall out below and parse them instead as fields. For top-level statements, we allow + // them, but want to try properties , etc. first. + var statement = this.ParseStatementCore(attributes, isGlobal: true); + + IsInAsync = wasInAsync; + _termState = saveTerm; + + if (isAcceptableNonDeclarationStatement(statement, IsScript)) + { + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(statement)); + } + } + + this.Reset(ref afterTypeResetPoint); + } + + // Everything that's left -- methods, fields, properties, locals, + // indexers, and non-conversion operators -- starts with a type + // (possibly void). + + // Check for misplaced modifiers. if we see any, then consider this member + // terminated and restart parsing. + if (IsMisplacedModifier(modifiers, attributes, type, out result)) + { + return result; + } + +parse_member_name:; + // If we've seen the ref keyword, we know we must have an indexer, method, property, or local. + bool typeIsRef = type.IsRef; + + // Check here for operators + // Allow old-style implicit/explicit casting operator syntax, just so we can give a better error + if (!typeIsRef && IsOperatorKeyword()) + { + return this.ParseOperatorDeclaration(attributes, modifiers, type); + } + + if ((!typeIsRef || !IsScript) && IsFieldDeclaration(isEvent: false)) + { + var saveTerm = _termState; + + if ((!haveAttributes && !haveModifiers) || !IsScript) + { + // if we are at top-level then statements can occur + _termState |= TerminatorState.IsPossibleStatementStartOrStop; + + if (!IsScript) + { + this.Reset(ref afterAttributesPoint); + if (tryParseLocalDeclarationStatement(attributes, out result)) + { + return result; + } + + this.Reset(ref afterTypeResetPoint); + } + } + + if (!typeIsRef) + { + return this.ParseNormalFieldDeclaration(attributes, modifiers, type, parentKind); + } + else + { + _termState = saveTerm; + } + } + + // At this point we can either have indexers, methods, or + // properties (or something unknown). Try to break apart + // the following name and determine what to do from there. + ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt; + SyntaxToken identifierOrThisOpt; + TypeParameterListSyntax typeParameterListOpt; + this.ParseMemberName(out explicitInterfaceOpt, out identifierOrThisOpt, out typeParameterListOpt, isEvent: false); + + // First, check if we got absolutely nothing. If so, then + // We need to consume a bad member and try again. + if (IsNoneOrIncompleteMember(parentKind, attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt, out result)) + { + return result; + } + + // If the modifiers did not include "async", and the type we got was "async", and there was an + // error in the identifier or its type parameters, then the user is probably in the midst of typing + // an async method. In that case we reconsider "async" to be a modifier, and treat the identifier + // (with the type parameters) as the type (with type arguments). Then we go back to looking for + // the member name again. + // For example, if we get + // async Task< + // then we want async to be a modifier and Task to be a type. + if (ReconsideredTypeAsAsyncModifier(ref modifiers, ref type, ref afterTypeResetPoint, ref explicitInterfaceOpt, ref identifierOrThisOpt, ref typeParameterListOpt)) + { + goto parse_member_name; + } + + Debug.Assert(identifierOrThisOpt != null); + + // check availability of readonly members feature for indexers, properties and methods + CheckForVersionSpecificModifiers(modifiers, SyntaxKind.ReadOnlyKeyword, MessageID.IDS_FeatureReadOnlyMembers); + + if (TryParseIndexerOrPropertyDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt, out result)) + { + return result; + } + + // treat anything else as a method. + + if (!IsScript && explicitInterfaceOpt is null && + tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + + return this.ParseMethodDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); + } + finally + { + this.Release(ref afterTypeResetPoint); + } + } + finally + { + _pool.Free(modifiers); + _termState = saveTermState; + this.Release(ref afterAttributesPoint); + } + + bool tryParseLocalDeclarationStatement(SyntaxList attributes, out MemberDeclarationSyntax result) where DeclarationSyntax : StatementSyntax + { + bool wasInAsync = IsInAsync; + IsInAsync = true; // We are implicitly in an async context + int lastTokenPosition = -1; + IsMakingProgress(ref lastTokenPosition); + + var topLevelStatement = ParseLocalDeclarationStatement(attributes); + IsInAsync = wasInAsync; + + if (topLevelStatement is DeclarationSyntax declaration && IsMakingProgress(ref lastTokenPosition, assertIfFalse: false)) + { + result = CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(declaration)); + return true; + } + + result = null; + return false; + } + + bool tryParseLocalDeclarationStatementFromStartPoint(SyntaxList attributes, ref ResetPoint startPoint, out MemberDeclarationSyntax result) where DeclarationSyntax : StatementSyntax + { + var resetOnFailurePoint = this.GetResetPoint(); + try + { + this.Reset(ref startPoint); + + if (tryParseLocalDeclarationStatement(attributes, out result)) { - return _syntaxFactory.GlobalStatement(statement); + return true; } + + this.Reset(ref resetOnFailurePoint); + return false; + } + finally + { + this.Release(ref resetOnFailurePoint); + } + } + + static bool isAcceptableNonDeclarationStatement(StatementSyntax statement, bool isScript) + { + switch (statement?.Kind) + { + case null: + case SyntaxKind.LocalFunctionStatement: + case SyntaxKind.ExpressionStatement when + !isScript && + // Do not parse a single identifier as an expression statement in a Simple Program, this could be a beginning of a keyword and + // we want completion to offer it. + ((ExpressionStatementSyntax)statement) is var exprStatement && + exprStatement.Expression.Kind == SyntaxKind.IdentifierName && + exprStatement.SemicolonToken.IsMissing: + + return false; + + case SyntaxKind.LocalDeclarationStatement: + return !isScript && ((LocalDeclarationStatementSyntax)statement).UsingKeyword is object; + + default: + return true; + } + } + + + } + + private bool IsMisplacedModifier(SyntaxListBuilder modifiers, SyntaxList attributes, TypeSyntax type, out MemberDeclarationSyntax result) + { + if (GetModifier(this.CurrentToken) != DeclarationModifiers.None && + this.CurrentToken.ContextualKind != SyntaxKind.PartialKeyword && + this.CurrentToken.ContextualKind != SyntaxKind.AsyncKeyword && + IsComplete(type)) + { + var misplacedModifier = this.CurrentToken; + type = this.AddError( + type, + type.FullWidth + misplacedModifier.GetLeadingTriviaWidth(), + misplacedModifier.Width, + ErrorCode.ERR_BadModifierLocation, + misplacedModifier.Text); + + result = _syntaxFactory.IncompleteMember(attributes, modifiers.ToList(), type); + return true; + } + + result = null; + return false; + } + + private bool IsNoneOrIncompleteMember(SyntaxKind parentKind, SyntaxList attributes, SyntaxListBuilder modifiers, TypeSyntax type, + ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt, SyntaxToken identifierOrThisOpt, TypeParameterListSyntax typeParameterListOpt, + out MemberDeclarationSyntax result) + { + if (explicitInterfaceOpt == null && identifierOrThisOpt == null && typeParameterListOpt == null) + { + if (attributes.Count == 0 && modifiers.Count == 0 && type.IsMissing && type.Kind != SyntaxKind.RefType) + { + // we haven't advanced, the caller needs to consume the tokens ahead + result = null; + return true; + } + + var incompleteMember = _syntaxFactory.IncompleteMember(attributes, modifiers.ToList(), type.IsMissing ? null : type); + if (incompleteMember.ContainsDiagnostics) + { + result = incompleteMember; + } + else if (parentKind == SyntaxKind.NamespaceDeclaration || + parentKind == SyntaxKind.CompilationUnit && !IsScript) + { + result = this.AddErrorToLastToken(incompleteMember, ErrorCode.ERR_NamespaceUnexpected); + } + else + { + //the error position should indicate CurrentToken + result = this.AddError( + incompleteMember, + incompleteMember.FullWidth + this.CurrentToken.GetLeadingTriviaWidth(), + this.CurrentToken.Width, + ErrorCode.ERR_InvalidMemberDecl, + this.CurrentToken.Text); + } + + return true; + } + + result = null; + return false; + } + + private bool ReconsideredTypeAsAsyncModifier(ref SyntaxListBuilder modifiers, ref TypeSyntax type, ref ResetPoint afterTypeResetPoint, + ref ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt, ref SyntaxToken identifierOrThisOpt, + ref TypeParameterListSyntax typeParameterListOpt) + { + if (type.Kind != SyntaxKind.RefType && + identifierOrThisOpt != null && + (typeParameterListOpt != null && typeParameterListOpt.ContainsDiagnostics + || this.CurrentToken.Kind != SyntaxKind.OpenParenToken && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken && this.CurrentToken.Kind != SyntaxKind.EqualsGreaterThanToken) && + ReconsiderTypeAsAsyncModifier(ref modifiers, type, identifierOrThisOpt)) + { + this.Reset(ref afterTypeResetPoint); + explicitInterfaceOpt = null; + identifierOrThisOpt = null; + typeParameterListOpt = null; + this.Release(ref afterTypeResetPoint); + type = ParseReturnType(); + afterTypeResetPoint = this.GetResetPoint(); + return true; + } + + return false; + } + + private bool TryParseIndexerOrPropertyDeclaration(SyntaxList attributes, SyntaxListBuilder modifiers, TypeSyntax type, + ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt, SyntaxToken identifierOrThisOpt, + TypeParameterListSyntax typeParameterListOpt, out MemberDeclarationSyntax result) + { + if (identifierOrThisOpt.Kind == SyntaxKind.ThisKeyword) + { + result = this.ParseIndexerDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); + return true; + } + + switch (this.CurrentToken.Kind) + { + case SyntaxKind.OpenBraceToken: + case SyntaxKind.EqualsGreaterThanToken: + result = this.ParsePropertyDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); + return true; + } + + result = null; + return false; + } + + // Returns null if we can't parse anything (even partially). + internal MemberDeclarationSyntax ParseMemberDeclaration(SyntaxKind parentKind) + { + _recursionDepth++; + StackGuard.EnsureSufficientExecutionStack(_recursionDepth); + var result = ParseMemberDeclarationCore(parentKind); + _recursionDepth--; + return result; + } + + /// + /// Changes in this function should be mirrored in . + /// Try keeping structure of both functions similar to simplify this task. The split was made to + /// reduce the stack usage during recursive parsing. + /// + /// Returns null if we can't parse anything (even partially). + private MemberDeclarationSyntax ParseMemberDeclarationCore(SyntaxKind parentKind) + { + // "top-level" expressions and statements should never occur inside an asynchronous context + Debug.Assert(!IsInAsync); + Debug.Assert(parentKind != SyntaxKind.CompilationUnit); + + cancellationToken.ThrowIfCancellationRequested(); + + // don't reuse members if they were previously declared under a different type keyword kind + if (this.IsIncrementalAndFactoryContextMatches) + { + if (CanReuseMemberDeclaration(CurrentNodeKind, isGlobal: false)) + { + return (MemberDeclarationSyntax)this.EatNode(); + } + } + + var modifiers = _pool.Allocate(); + + var saveTermState = _termState; + + try + { + var attributes = this.ParseAttributeDeclarations(); + + this.ParseModifiers(modifiers, forAccessors: false); + + // Check for constructor form + if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) + { + return this.ParseConstructorDeclaration(attributes, modifiers); + } + + // Check for destructor form + if (this.CurrentToken.Kind == SyntaxKind.TildeToken) + { + return this.ParseDestructorDeclaration(attributes, modifiers); + } + + // Check for constant + if (this.CurrentToken.Kind == SyntaxKind.ConstKeyword) + { + return this.ParseConstantFieldDeclaration(attributes, modifiers, parentKind); + } + + // Check for event. + if (this.CurrentToken.Kind == SyntaxKind.EventKeyword) + { + return this.ParseEventDeclaration(attributes, modifiers, parentKind); + } + + // check for fixed size buffers. + if (this.CurrentToken.Kind == SyntaxKind.FixedKeyword) + { + return this.ParseFixedSizeBufferDeclaration(attributes, modifiers, parentKind); + } + + // Check for conversion operators (implicit/explicit) + if (this.CurrentToken.Kind == SyntaxKind.ExplicitKeyword || + this.CurrentToken.Kind == SyntaxKind.ImplicitKeyword || + (this.CurrentToken.Kind == SyntaxKind.OperatorKeyword && !SyntaxFacts.IsAnyOverloadableOperator(this.PeekToken(1).Kind))) + { + return this.ParseConversionOperatorDeclaration(attributes, modifiers); + } + + // Namespaces should be handled by the caller, not checking for them + + // It's valid to have a type declaration here -- check for those + if (IsTypeDeclarationStart()) + { + return this.ParseTypeDeclaration(attributes, modifiers); } // Everything that's left -- methods, fields, properties, // indexers, and non-conversion operators -- starts with a type - // (possibly void). Parse that. + // (possibly void). TypeSyntax type = ParseReturnType(); var afterTypeResetPoint = this.GetResetPoint(); try { - var sawRef = type.Kind == SyntaxKind.RefType; - // Check for misplaced modifiers. if we see any, then consider this member // terminated and restart parsing. - if (GetModifier(this.CurrentToken) != DeclarationModifiers.None && - this.CurrentToken.ContextualKind != SyntaxKind.PartialKeyword && - this.CurrentToken.ContextualKind != SyntaxKind.AsyncKeyword && - IsComplete(type)) + MemberDeclarationSyntax result; + if (IsMisplacedModifier(modifiers, attributes, type, out result)) { - var misplacedModifier = this.CurrentToken; - type = this.AddError( - type, - type.FullWidth + misplacedModifier.GetLeadingTriviaWidth(), - misplacedModifier.Width, - ErrorCode.ERR_BadModifierLocation, - misplacedModifier.Text); - - return _syntaxFactory.IncompleteMember(attributes, modifiers.ToList(), type); + return result; } parse_member_name:; // If we've seen the ref keyword, we know we must have an indexer, method, or property. - if (!sawRef) + if (type.Kind != SyntaxKind.RefType) { // Check here for operators // Allow old-style implicit/explicit casting operator syntax, just so we can give a better error @@ -2146,12 +2617,6 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind if (IsFieldDeclaration(isEvent: false)) { - if (acceptStatement) - { - // if we are script at top-level then statements can occur - _termState |= TerminatorState.IsPossibleStatementStartOrStop; - } - return this.ParseNormalFieldDeclaration(attributes, modifiers, type, parentKind); } } @@ -2166,34 +2631,9 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // First, check if we got absolutely nothing. If so, then // We need to consume a bad member and try again. - if (explicitInterfaceOpt == null && identifierOrThisOpt == null && typeParameterListOpt == null) + if (IsNoneOrIncompleteMember(parentKind, attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt, out result)) { - if (attributes.Count == 0 && modifiers.Count == 0 && type.IsMissing && !sawRef) - { - // we haven't advanced, the caller needs to consume the tokens ahead - return null; - } - - var incompleteMember = _syntaxFactory.IncompleteMember(attributes, modifiers.ToList(), type.IsMissing ? null : type); - if (incompleteMember.ContainsDiagnostics) - { - return incompleteMember; - } - else if (parentKind == SyntaxKind.NamespaceDeclaration || - parentKind == SyntaxKind.CompilationUnit && !IsScript) - { - return this.AddErrorToLastToken(incompleteMember, ErrorCode.ERR_NamespaceUnexpected); - } - else - { - //the error position should indicate CurrentToken - return this.AddError( - incompleteMember, - incompleteMember.FullWidth + this.CurrentToken.GetLeadingTriviaWidth(), - this.CurrentToken.Width, - ErrorCode.ERR_InvalidMemberDecl, - this.CurrentToken.Text); - } + return result; } // If the modifiers did not include "async", and the type we got was "async", and there was an @@ -2204,17 +2644,8 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // For example, if we get // async Task< // then we want async to be a modifier and Task to be a type. - if (!sawRef && - identifierOrThisOpt != null && - (typeParameterListOpt != null && typeParameterListOpt.ContainsDiagnostics - || this.CurrentToken.Kind != SyntaxKind.OpenParenToken && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken && this.CurrentToken.Kind != SyntaxKind.EqualsGreaterThanToken) && - ReconsiderTypeAsAsyncModifier(ref modifiers, type, identifierOrThisOpt)) + if (ReconsideredTypeAsAsyncModifier(ref modifiers, ref type, ref afterTypeResetPoint, ref explicitInterfaceOpt, ref identifierOrThisOpt, ref typeParameterListOpt)) { - this.Reset(ref afterTypeResetPoint); - explicitInterfaceOpt = null; - identifierOrThisOpt = null; - typeParameterListOpt = null; - type = ParseReturnType(); goto parse_member_name; } @@ -2223,23 +2654,13 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // check availability of readonly members feature for indexers, properties and methods CheckForVersionSpecificModifiers(modifiers, SyntaxKind.ReadOnlyKeyword, MessageID.IDS_FeatureReadOnlyMembers); - if (identifierOrThisOpt.Kind == SyntaxKind.ThisKeyword) + if (TryParseIndexerOrPropertyDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt, out result)) { - return this.ParseIndexerDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); + return result; } - else - { - switch (this.CurrentToken.Kind) - { - case SyntaxKind.OpenBraceToken: - case SyntaxKind.EqualsGreaterThanToken: - return this.ParsePropertyDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); - default: - // treat anything else as a method. - return this.ParseMethodDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); - } - } + // treat anything else as a method. + return this.ParseMethodDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); } finally { @@ -6295,20 +6716,19 @@ private TypeSyntax ParsePointerTypeMods(TypeSyntax type) public StatementSyntax ParseStatement() { return ParseWithStackGuard( - () => ParsePossiblyAttributedStatement(isGlobalScriptLevel: false) ?? ParseExpressionStatement(attributes: default), + () => ParsePossiblyAttributedStatement() ?? ParseExpressionStatement(attributes: default), () => SyntaxFactory.EmptyStatement(attributeLists: default, SyntaxFactory.MissingToken(SyntaxKind.SemicolonToken))); } - private StatementSyntax ParsePossiblyAttributedStatement(bool isGlobalScriptLevel) - => ParseStatementCore(ParseAttributeDeclarations(), isGlobalScriptLevel); + private StatementSyntax ParsePossiblyAttributedStatement() + => ParseStatementCore(ParseAttributeDeclarations(), isGlobal: false); - /// If we're being called while parsing a C# script from - /// the top-level. At the top level, we allow most statements *except* for - /// local-decls/local-funcs. Those will instead be parsed out as - /// script-fields/methods. - private StatementSyntax ParseStatementCore(SyntaxList attributes, bool isGlobalScriptLevel) + /// If we're being called while parsing a C# top-level statements (Script or Simple Program). + /// At the top level in Script, we allow most statements *except* for local-decls/local-funcs. + /// Those will instead be parsed out as script-fields/methods. + private StatementSyntax ParseStatementCore(SyntaxList attributes, bool isGlobal) { - if (canReuseStatement(attributes, isGlobalScriptLevel)) + if (canReuseStatement(attributes, isGlobal)) { return (StatementSyntax)this.EatNode(); } @@ -6372,13 +6792,13 @@ private StatementSyntax ParseStatementCore(SyntaxList attri case SyntaxKind.SemicolonToken: return _syntaxFactory.EmptyStatement(attributes, this.EatToken()); case SyntaxKind.IdentifierToken: - result = TryParseStatementStartingWithIdentifier(attributes, isGlobalScriptLevel); + result = TryParseStatementStartingWithIdentifier(attributes, isGlobal); if (result != null) return result; break; } - return ParseStatementCoreRest(attributes, isGlobalScriptLevel, ref resetPointBeforeStatement); + return ParseStatementCoreRest(attributes, isGlobal, ref resetPointBeforeStatement); } finally { @@ -6387,25 +6807,25 @@ private StatementSyntax ParseStatementCore(SyntaxList attri } - bool canReuseStatement(SyntaxList attributes, bool isGlobalScriptLevel) + bool canReuseStatement(SyntaxList attributes, bool isGlobal) { - // Can only reuse a global-script or regular statement if we're in the same - // global-script context we were originally in. return this.IsIncrementalAndFactoryContextMatches && this.CurrentNode is Syntax.StatementSyntax && - isGlobalScriptLevel == (this.CurrentNode.Parent is Syntax.GlobalStatementSyntax) && + !isGlobal && // Top-level statements are reused by ParseMemberDeclarationOrStatementCore when possible. attributes.Count == 0; } } - private StatementSyntax ParseStatementCoreRest(SyntaxList attributes, bool isGlobalScriptLevel, ref ResetPoint resetPointBeforeStatement) + private StatementSyntax ParseStatementCoreRest(SyntaxList attributes, bool isGlobal, ref ResetPoint resetPointBeforeStatement) { - if (!this.IsPossibleLocalDeclarationStatement(isGlobalScriptLevel)) + isGlobal = isGlobal && IsScript; + + if (!this.IsPossibleLocalDeclarationStatement(isGlobal)) { return this.ParseExpressionStatement(attributes); } - if (isGlobalScriptLevel) + if (isGlobal) { // if we're at the global script level, then we don't support local-decls or // local-funcs. The caller instead will look for those and parse them as @@ -6447,7 +6867,7 @@ private StatementSyntax ParseStatementCoreRest(SyntaxList a return result; } - private StatementSyntax TryParseStatementStartingWithIdentifier(SyntaxList attributes, bool isGlobalScriptLevel) + private StatementSyntax TryParseStatementStartingWithIdentifier(SyntaxList attributes, bool isGlobal) { if (this.CurrentToken.ContextualKind == SyntaxKind.AwaitKeyword && this.PeekToken(1).Kind == SyntaxKind.ForEachKeyword) @@ -6474,7 +6894,7 @@ private StatementSyntax TryParseStatementStartingWithIdentifier(SyntaxList - protected bool IsMakingProgress(ref int lastTokenPosition) + protected bool IsMakingProgress(ref int lastTokenPosition, bool assertIfFalse = true) { var pos = CurrentTokenPosition; if (pos > lastTokenPosition) @@ -1123,7 +1123,7 @@ protected bool IsMakingProgress(ref int lastTokenPosition) return true; } - Debug.Assert(false); + Debug.Assert(!assertIfFalse); return false; } diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index bcb26f2d8cb59..63a792b9be166 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -81,6 +81,7 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.TypePatternSyntax.Accept(Microsoft override Microsoft.CodeAnalysis.CSharp.Syntax.TypePatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult override Microsoft.CodeAnalysis.CSharp.Syntax.UnaryPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.UnaryPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult +static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.IMethodSymbol static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.BinaryPattern(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax left, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax right) -> Microsoft.CodeAnalysis.CSharp.Syntax.BinaryPatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.BinaryPattern(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax left, Microsoft.CodeAnalysis.SyntaxToken operatorToken, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax right) -> Microsoft.CodeAnalysis.CSharp.Syntax.BinaryPatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression() -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplay.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplay.cs index d323a6a0fca72..94bcbc856b892 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplay.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplay.cs @@ -230,6 +230,13 @@ private static ImmutableArray ToDisplayParts( Debug.Assert(positionOpt < 0); } + // Do not leak unspeakable name of a Simple Program entry point through diagnostics, + // and, for consistency, with other display options. + if ((symbol as Symbols.PublicModel.MethodSymbol)?.UnderlyingMethodSymbol is SynthesizedSimpleProgramEntryPointSymbol) + { + return ImmutableArray.Create(new SymbolDisplayPart(SymbolDisplayPartKind.MethodName, symbol, "")); + } + var builder = ArrayBuilder.GetInstance(); var visitor = new SymbolDisplayVisitor(builder, format, semanticModelOpt, positionOpt); symbol.Accept(visitor); diff --git a/src/Compilers/CSharp/Portable/Symbols/EnumConversions.cs b/src/Compilers/CSharp/Portable/Symbols/EnumConversions.cs index 4322c0462597a..667e83fe53120 100644 --- a/src/Compilers/CSharp/Portable/Symbols/EnumConversions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/EnumConversions.cs @@ -15,6 +15,7 @@ internal static TypeKind ToTypeKind(this DeclarationKind kind) case DeclarationKind.Class: case DeclarationKind.Script: case DeclarationKind.ImplicitClass: + case DeclarationKind.SimpleProgram: return TypeKind.Class; case DeclarationKind.Submission: diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs index 7bf60c0483954..7e0915df9dc7c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs @@ -944,11 +944,11 @@ public sealed override bool HasUnsupportedMetadata #endregion - internal bool IsIterator + internal virtual bool IsIterator { get { - return !IteratorElementTypeWithAnnotations.IsDefault; + return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs index 2d2b2b2f9c756..a294a533ae171 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbolExtensions.cs @@ -9,6 +9,7 @@ using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -189,13 +190,23 @@ public static bool IsAsyncReturningIAsyncEnumerator(this MethodSymbol method, CS internal static CSharpSyntaxNode ExtractReturnTypeSyntax(this MethodSymbol method) { + if (method is SynthesizedSimpleProgramEntryPointSymbol synthesized) + { + return (CSharpSyntaxNode)synthesized.ReturnTypeSyntax; + } + method = method.PartialDefinitionPart ?? method; foreach (var reference in method.DeclaringSyntaxReferences) { - if (reference.GetSyntax() is MethodDeclarationSyntax methodDeclaration) + SyntaxNode node = reference.GetSyntax(); + if (node is MethodDeclarationSyntax methodDeclaration) { return methodDeclaration.ReturnType; } + else if (node is LocalFunctionStatementSyntax statement) + { + return statement.ReturnType; + } } return (CSharpSyntaxNode)CSharpSyntaxTree.Dummy.GetRoot(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index c8f0b3e133c2d..1868c73b385d1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -48,6 +48,11 @@ public LocalFunctionSymbol( DeclarationModifiers.Private | syntax.Modifiers.ToDeclarationModifiers(diagnostics: _declarationDiagnostics); + if (SyntaxFacts.HasYieldOperations(syntax.Body)) + { + _lazyIteratorElementType = TypeWithAnnotations.Boxed.Sentinel; + } + this.CheckUnsafeModifier(_declarationModifiers, _declarationDiagnostics); ScopeBinder = binder; @@ -130,6 +135,13 @@ internal void GetDeclarationDiagnostics(DiagnosticBag addTo) AsyncMethodChecks(_declarationDiagnostics); addTo.AddRange(_declarationDiagnostics); + + if (IsEntryPointCandidate && !IsGenericMethod && + ContainingSymbol is SynthesizedSimpleProgramEntryPointSymbol && + DeclaringCompilation.HasEntryPointSignature(this, new DiagnosticBag()).IsCandidate) + { + addTo.Add(ErrorCode.WRN_MainIgnored, Syntax.Identifier.GetLocation(), this); + } } internal override void AddDeclarationDiagnostics(DiagnosticBag diagnostics) @@ -301,11 +313,13 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations } set { - Debug.Assert(_lazyIteratorElementType == null || TypeSymbol.Equals(_lazyIteratorElementType.Value.Type, value.Type, TypeCompareKind.ConsiderEverything2)); - Interlocked.CompareExchange(ref _lazyIteratorElementType, new TypeWithAnnotations.Boxed(value), null); + Debug.Assert(_lazyIteratorElementType == TypeWithAnnotations.Boxed.Sentinel || (_lazyIteratorElementType is object && TypeSymbol.Equals(_lazyIteratorElementType.Value.Type, value.Type, TypeCompareKind.ConsiderEverything2))); + Interlocked.CompareExchange(ref _lazyIteratorElementType, new TypeWithAnnotations.Boxed(value), TypeWithAnnotations.Boxed.Sentinel); } } + internal override bool IsIterator => _lazyIteratorElementType is object; + public override MethodKind MethodKind => MethodKind.LocalFunction; public sealed override Symbol ContainingSymbol => _containingSymbol; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs new file mode 100644 index 0000000000000..9bceeb71dde2c --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs @@ -0,0 +1,269 @@ +// 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. + +#nullable enable + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents implicitly declared type for a Simple Program feature. + /// + internal sealed class SimpleProgramNamedTypeSymbol : SourceMemberContainerTypeSymbol + { + internal const string UnspeakableName = "$Program"; + + internal SimpleProgramNamedTypeSymbol(NamespaceSymbol globalNamespace, MergedTypeDeclaration declaration, DiagnosticBag diagnostics) + : base(globalNamespace, declaration, diagnostics) + { + Debug.Assert(globalNamespace.IsGlobalNamespace); + Debug.Assert(declaration.Kind == DeclarationKind.SimpleProgram); + Debug.Assert(declaration.Name == UnspeakableName); + + state.NotePartComplete(CompletionPart.EnumUnderlyingType); // No work to do for this. + } + + internal static SynthesizedSimpleProgramEntryPointSymbol? GetSimpleProgramEntryPoint(CSharpCompilation compilation) + { + return (SynthesizedSimpleProgramEntryPointSymbol?)GetSimpleProgramNamedTypeSymbol(compilation)?.GetMembersAndInitializers().NonTypeNonIndexerMembers[0]; + } + + private static SimpleProgramNamedTypeSymbol? GetSimpleProgramNamedTypeSymbol(CSharpCompilation compilation) + { + return compilation.SourceModule.GlobalNamespace.GetTypeMembers(UnspeakableName).OfType().SingleOrDefault(); + } + + internal static SynthesizedSimpleProgramEntryPointSymbol? GetSimpleProgramEntryPoint(CSharpCompilation compilation, CompilationUnitSyntax compilationUnit, bool fallbackToMainEntryPoint) + { + var type = GetSimpleProgramNamedTypeSymbol(compilation); + + if (type is null) + { + return null; + } + + ImmutableArray entryPoints = type.GetMembersAndInitializers().NonTypeNonIndexerMembers; + + foreach (SynthesizedSimpleProgramEntryPointSymbol entryPoint in entryPoints) + { + if (entryPoint.SyntaxTree == compilationUnit.SyntaxTree && entryPoint.SyntaxNode == compilationUnit) + { + return entryPoint; + } + } + + return fallbackToMainEntryPoint ? (SynthesizedSimpleProgramEntryPointSymbol)entryPoints[0] : null; + } + + protected override NamedTypeSymbol WithTupleDataCore(TupleExtraData newData) + => throw ExceptionUtilities.Unreachable; + + public override ImmutableArray GetAttributes() + { + state.NotePartComplete(CompletionPart.Attributes); + return ImmutableArray.Empty; + } + + internal override AttributeUsageInfo GetAttributeUsageInfo() + { + return AttributeUsageInfo.Null; + } + + protected override Location GetCorrespondingBaseListLocation(NamedTypeSymbol @base) + { + return NoLocation.Singleton; // No explicit base list + } + + internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics + => this.DeclaringCompilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Object); + + protected override void CheckBase(DiagnosticBag diagnostics) + { + // check that System.Object is available. + var info = this.DeclaringCompilation.GetSpecialType(SpecialType.System_Object).GetUseSiteDiagnostic(); + if (info != null) + { + Symbol.ReportUseSiteDiagnostic(info, diagnostics, NoLocation.Singleton); + } + } + + internal override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) + { + return BaseTypeNoUseSiteDiagnostics; + } + + internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved) + { + return ImmutableArray.Empty; + } + + internal override ImmutableArray GetDeclaredInterfaces(ConsList basesBeingResolved) + { + return ImmutableArray.Empty; + } + + protected override void CheckInterfaces(DiagnosticBag diagnostics) + { + // nop + } + + public override ImmutableArray TypeParameters + { + get { return ImmutableArray.Empty; } + } + + internal override ImmutableArray TypeArgumentsWithAnnotationsNoUseSiteDiagnostics + { + get { return ImmutableArray.Empty; } + } + + public sealed override bool AreLocalsZeroed + { + get { return ContainingModule.AreLocalsZeroed; } + } + + internal override bool IsComImport + { + get { return false; } + } + + internal override NamedTypeSymbol? ComImportCoClass + { + get { return null; } + } + + internal override bool HasSpecialName + { + get { return false; } + } + + internal override bool ShouldAddWinRTMembers + { + get { return false; } + } + + internal sealed override bool IsWindowsRuntimeImport + { + get { return false; } + } + + public sealed override bool IsSerializable + { + get { return false; } + } + + internal sealed override TypeLayout Layout + { + get { return default(TypeLayout); } + } + + internal bool HasStructLayoutAttribute + { + get { return false; } + } + + internal override CharSet MarshallingCharSet + { + get { return DefaultMarshallingCharSet; } + } + + internal sealed override bool HasDeclarativeSecurity + { + get { return false; } + } + + internal sealed override IEnumerable GetSecurityInformation() + { + throw ExceptionUtilities.Unreachable; + } + + internal override ImmutableArray GetAppliedConditionalSymbols() + { + return ImmutableArray.Empty; + } + + internal override ObsoleteAttributeData? ObsoleteAttributeData + { + get { return null; } + } + + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + + protected override MembersAndInitializers BuildMembersAndInitializers(DiagnosticBag diagnostics) + { + bool reportAnError = false; + foreach (var singleDecl in declaration.Declarations) + { + if (reportAnError) + { + Binder.Error(diagnostics, ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, singleDecl.NameLocation); + } + else + { + reportAnError = true; + } + } + + return new MembersAndInitializers(nonTypeNonIndexerMembers: declaration.Declarations.SelectAsArray(singleDeclaration => new SynthesizedSimpleProgramEntryPointSymbol(this, singleDeclaration, diagnostics)), + staticInitializers: ImmutableArray>.Empty, + instanceInitializers: ImmutableArray>.Empty, + indexerDeclarations: ImmutableArray.Empty, + staticInitializersSyntaxLength: 0, + instanceInitializersSyntaxLength: 0); + } + + public override bool IsImplicitlyDeclared => true; + + internal override bool IsDefinedInSourceTree(SyntaxTree tree, TextSpan? definedWithinSpan, CancellationToken cancellationToken) + { + foreach (var member in GetMembersAndInitializers().NonTypeNonIndexerMembers) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (member.IsDefinedInSourceTree(tree, definedWithinSpan, cancellationToken)) + { + return true; + } + } + + return false; + } + + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) + { + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); + + AddSynthesizedAttribute(ref attributes, + this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); + } + + /// + /// Returns an instance of a symbol that represents an native integer + /// if this underlying symbol represents System.IntPtr or System.UIntPtr. + /// For other symbols, throws . + /// + internal override NamedTypeSymbol AsNativeInteger() + { + throw ExceptionUtilities.Unreachable; + } + + /// + /// If this is a native integer, returns the symbol for the underlying type, + /// either or . + /// Otherwise, returns null. + /// + internal override NamedTypeSymbol? NativeIntegerUnderlyingType => null; + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 7fea001900bc7..7b11b59be4eda 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -32,7 +32,7 @@ private SourceConstructorSymbol( ConstructorDeclarationSyntax syntax, MethodKind methodKind, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), ImmutableArray.Create(location)) + base(containingType, syntax.GetReference(), ImmutableArray.Create(location), isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { bool hasBlockBody = syntax.Body != null; _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs index 674cd42218367..5f5bc94fc114d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs @@ -28,7 +28,9 @@ internal SourceCustomEventAccessorSymbol( DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), - ImmutableArray.Create(syntax.Keyword.GetLocation()), explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder: syntax.Kind() == SyntaxKind.AddAccessorDeclaration) + ImmutableArray.Create(syntax.Keyword.GetLocation()), explicitlyImplementedEventOpt, aliasQualifierOpt, + isAdder: syntax.Kind() == SyntaxKind.AddAccessorDeclaration, + isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind() == SyntaxKind.AddAccessorDeclaration || syntax.Kind() == SyntaxKind.RemoveAccessorDeclaration); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index 6681603d93bb3..22dfc4ba10b7f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -22,7 +22,7 @@ protected SourceDelegateMethodSymbol( DelegateDeclarationSyntax syntax, MethodKind methodKind, DeclarationModifiers declarationModifiers) - : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation()) + : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation(), isIterator: false) { _returnType = returnType; this.MakeFlags(methodKind, declarationModifiers, _returnType.IsVoidType(), isExtensionMethod: false); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs index a93ecbf2c7682..46e5a112bb8e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs @@ -18,7 +18,7 @@ internal SourceDestructorSymbol( SourceMemberContainerTypeSymbol containingType, DestructorDeclarationSyntax syntax, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), syntax.Identifier.GetLocation()) + base(containingType, syntax.GetReference(), syntax.Identifier.GetLocation(), isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { const MethodKind methodKind = MethodKind.Destructor; Location location = this.Locations[0]; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs index f6ab1fa46bc04..c57dc1d96a988 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -29,8 +29,9 @@ public SourceEventAccessorSymbol( ImmutableArray locations, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, - bool isAdder) - : base(@event.containingType, syntaxReference, locations) + bool isAdder, + bool isIterator) + : base(@event.containingType, syntaxReference, locations, isIterator) { _event = @event; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index ab6f419779b7d..22f5fafa01439 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -918,7 +918,7 @@ internal override bool IsDefinedInSourceTree(SyntaxTree tree, TextSpan? definedW /// CONSIDER: most types won't have indexers, so we could move the indexer list /// into a subclass to spare most instances the space required for the field. /// - private sealed class MembersAndInitializers + protected sealed class MembersAndInitializers { internal readonly ImmutableArray NonTypeNonIndexerMembers; internal readonly ImmutableArray> StaticInitializers; @@ -1340,7 +1340,7 @@ private Dictionary> GetEarlyAttributeDecodingMemb // we often need to get members just to do a lookup. // All additional checks and diagnostics may be not // needed yet or at all. - private MembersAndInitializers GetMembersAndInitializers() + protected MembersAndInitializers GetMembersAndInitializers() { var membersAndInitializers = _lazyMembersAndInitializers; if (membersAndInitializers != null) @@ -1690,6 +1690,8 @@ private void ReportMethodSignatureCollision(DiagnosticBag diagnostics, SourceMem // these could be 2 parts of the same partial method. // Partial methods are allowed to collide by signature. return; + case (SynthesizedSimpleProgramEntryPointSymbol { }, SynthesizedSimpleProgramEntryPointSymbol { }): + return; } // If method1 is a constructor only because its return type is missing, then @@ -2402,7 +2404,7 @@ internal void AddOrWrapTupleMembers(SourceMemberContainerTypeSymbol type) } } - private MembersAndInitializers BuildMembersAndInitializers(DiagnosticBag diagnostics) + protected virtual MembersAndInitializers BuildMembersAndInitializers(DiagnosticBag diagnostics) { var builder = new MembersAndInitializersBuilder(); AddDeclaredNontypeMembers(builder, diagnostics); @@ -3341,7 +3343,7 @@ private void AddNonTypeMembers( AddInitializer(ref instanceInitializers, ref builder.InstanceSyntaxLength, null, globalStatement); } - else if (reportMisplacedGlobalCode) + else if (reportMisplacedGlobalCode && !SyntaxFacts.IsSimpleProgramTopLevelStatement((GlobalStatementSyntax)m)) { diagnostics.Add(ErrorCode.ERR_GlobalStatement, new SourceLocation(globalStatement)); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index da00327b943d4..078b490f0dc59 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -201,12 +201,12 @@ internal ImmutableArray SetDiagnostics(ImmutableArray ne return _cachedDiagnostics; } - protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, Location location) - : this(containingType, syntaxReferenceOpt, ImmutableArray.Create(location)) + protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, Location location, bool isIterator) + : this(containingType, syntaxReferenceOpt, ImmutableArray.Create(location), isIterator) { } - protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, ImmutableArray locations) + protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, ImmutableArray locations, bool isIterator) : base(syntaxReferenceOpt) { Debug.Assert((object)containingType != null); @@ -214,6 +214,11 @@ protected SourceMemberMethodSymbol(NamedTypeSymbol containingType, SyntaxReferen _containingType = containingType; this.locations = locations; + + if (isIterator) + { + _lazyIteratorElementType = TypeWithAnnotations.Boxed.Sentinel; + } } protected void CheckEffectiveAccessibility(TypeWithAnnotations returnType, ImmutableArray parameters, DiagnosticBag diagnostics) @@ -589,7 +594,7 @@ internal sealed override Cci.CallingConvention CallingConvention } } - internal Binder TryGetInMethodBinder(BinderFactory binderFactoryOpt = null) + private Binder TryGetInMethodBinder(BinderFactory binderFactoryOpt = null) { CSharpSyntaxNode contextNode = GetInMethodSyntaxNode(); if (contextNode == null) @@ -616,10 +621,10 @@ internal Binder TryGetInMethodBinder(BinderFactory binderFactoryOpt = null) return result; } - internal ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, BinderFlags additionalFlags = BinderFlags.None) + internal virtual ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, bool ignoreAccessibility = false) { Binder inMethod = TryGetInMethodBinder(binderFactoryOpt); - return inMethod == null ? null : new ExecutableCodeBinder(SyntaxNode, this, inMethod.WithAdditionalFlags(additionalFlags)); + return inMethod == null ? null : new ExecutableCodeBinder(SyntaxNode, this, inMethod.WithAdditionalFlags(ignoreAccessibility ? BinderFlags.IgnoreAccessibility : BinderFlags.None)); } /// @@ -687,11 +692,13 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations } set { - Debug.Assert(_lazyIteratorElementType == null || TypeSymbol.Equals(_lazyIteratorElementType.Value.Type, value.Type, TypeCompareKind.ConsiderEverything2)); - Interlocked.CompareExchange(ref _lazyIteratorElementType, new TypeWithAnnotations.Boxed(value), null); + Debug.Assert(_lazyIteratorElementType == TypeWithAnnotations.Boxed.Sentinel || TypeSymbol.Equals(_lazyIteratorElementType.Value.Type, value.Type, TypeCompareKind.ConsiderEverything2)); + Interlocked.CompareExchange(ref _lazyIteratorElementType, new TypeWithAnnotations.Boxed(value), TypeWithAnnotations.Boxed.Sentinel); } } + internal override bool IsIterator => _lazyIteratorElementType is object; + //overridden appropriately in SourceMemberMethodSymbol public override ImmutableArray ExplicitInterfaceImplementations { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs index 2e2ae5b7faad8..2898fd30b46f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs @@ -49,6 +49,8 @@ protected SourceMethodSymbolWithAttributes(SyntaxReference syntaxReferenceOpt) return arrowExpression; case LocalFunctionStatementSyntax localFunction: return (CSharpSyntaxNode?)localFunction.Body ?? localFunction.ExpressionBody; + case CompilationUnitSyntax _ when this is SynthesizedSimpleProgramEntryPointSymbol entryPoint: + return (CSharpSyntaxNode)entryPoint.ReturnTypeSyntax; default: return null; } @@ -63,7 +65,7 @@ internal SyntaxReference SyntaxRef } } - internal CSharpSyntaxNode SyntaxNode + internal virtual CSharpSyntaxNode SyntaxNode { get { @@ -79,7 +81,7 @@ internal SyntaxTree SyntaxTree } } - public sealed override ImmutableArray DeclaringSyntaxReferences + public override ImmutableArray DeclaringSyntaxReferences { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs index 0ce68725202ea..18f300c59b6c2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs @@ -400,6 +400,9 @@ private NamespaceOrTypeSymbol BuildSymbol(MergedNamespaceOrTypeDeclaration decla case DeclarationKind.ImplicitClass: return new ImplicitNamedTypeSymbol(this, (MergedTypeDeclaration)declaration, diagnostics); + case DeclarationKind.SimpleProgram: + return new SimpleProgramNamedTypeSymbol(this, (MergedTypeDeclaration)declaration, diagnostics); + default: throw ExceptionUtilities.UnexpectedValue(declaration.Kind); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 5c3b6788b14d9..de9cc1213c061 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -77,7 +77,8 @@ private SourceOrdinaryMethodSymbol( DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), - location) + location, + isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { _name = name; _explicitInterfaceType = explicitInterfaceType; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 33c89f5910037..f7355ed6e4ab0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -154,7 +154,7 @@ private SourcePropertyAccessorSymbol( ArrowExpressionClauseSyntax syntax, bool isExplicitInterfaceImplementation, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), location) + base(containingType, syntax.GetReference(), location, isIterator: false) { _property = property; _explicitInterfaceImplementations = explicitInterfaceImplementations; @@ -209,7 +209,8 @@ private SourcePropertyAccessorSymbol( DiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), - location) + location, + isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { _property = property; _explicitInterfaceImplementations = explicitInterfaceImplementations; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index 7d2829c378a9c..a79f0ac41e073 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -28,7 +28,7 @@ protected SourceUserDefinedOperatorSymbolBase( Location location, BaseMethodDeclarationSyntax syntax, DiagnosticBag diagnostics) : - base(containingType, syntax.GetReference(), location) + base(containingType, syntax.GetReference(), location, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body)) { _name = name; _isExpressionBodied = syntax.Body == null && syntax.ExpressionBody != null; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs index 7dd23510fad98..02ba399486a1d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs @@ -25,7 +25,7 @@ internal sealed class SynthesizedEventAccessorSymbol : SourceEventAccessorSymbol private readonly object _methodChecksLockObject = new object(); internal SynthesizedEventAccessorSymbol(SourceEventSymbol @event, bool isAdder, EventSymbol explicitlyImplementedEventOpt = null, string aliasQualifierOpt = null) - : base(@event, null, @event.Locations, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder) + : base(@event, null, @event.Locations, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder, isIterator: false) { } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs new file mode 100644 index 0000000000000..1a82a79059c8c --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs @@ -0,0 +1,254 @@ +// 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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + internal sealed class SynthesizedSimpleProgramEntryPointSymbol : SourceMemberMethodSymbol + { + /// + /// The corresponding . + /// + private readonly SingleTypeDeclaration _declaration; + + private readonly TypeSymbol _returnType; + private readonly ImmutableArray _parameters; + private WeakReference? _weakBodyBinder; + private WeakReference? _weakIgnoreAccessibilityBodyBinder; + + internal SynthesizedSimpleProgramEntryPointSymbol(SimpleProgramNamedTypeSymbol containingType, SingleTypeDeclaration declaration, DiagnosticBag diagnostics) + : base(containingType, syntaxReferenceOpt: declaration.SyntaxReference, ImmutableArray.Create(declaration.SyntaxReference.GetLocation()), isIterator: declaration.IsIterator) + { + _declaration = declaration; + + bool hasAwait = declaration.HasAwaitExpressions; + bool hasReturnWithExpression = declaration.HasReturnWithExpression; + + CSharpCompilation compilation = containingType.DeclaringCompilation; + switch (hasAwait, hasReturnWithExpression) + { + case (true, false): + _returnType = Binder.GetWellKnownType(compilation, WellKnownType.System_Threading_Tasks_Task, diagnostics, NoLocation.Singleton); + break; + case (false, false): + _returnType = Binder.GetSpecialType(compilation, SpecialType.System_Void, NoLocation.Singleton, diagnostics); + break; + case (true, true): + _returnType = Binder.GetWellKnownType(compilation, WellKnownType.System_Threading_Tasks_Task_T, diagnostics, NoLocation.Singleton). + Construct(Binder.GetSpecialType(compilation, SpecialType.System_Int32, NoLocation.Singleton, diagnostics)); + break; + case (false, true): + _returnType = Binder.GetSpecialType(compilation, SpecialType.System_Int32, NoLocation.Singleton, diagnostics); + break; + } + + this.MakeFlags( + MethodKind.Ordinary, + DeclarationModifiers.Static | DeclarationModifiers.Private | (hasAwait ? DeclarationModifiers.Async : DeclarationModifiers.None), + returnsVoid: !hasAwait && !hasReturnWithExpression, + isExtensionMethod: false, + isMetadataVirtualIgnoringModifiers: false); + + _parameters = ImmutableArray.Create(SynthesizedParameterSymbol.Create(this, + TypeWithAnnotations.Create( + ArrayTypeSymbol.CreateCSharpArray(compilation.Assembly, + TypeWithAnnotations.Create(Binder.GetSpecialType(compilation, SpecialType.System_String, NoLocation.Singleton, diagnostics)))), 0, RefKind.None, "args")); + } + + public override string Name + { + get + { + return "$Main"; + } + } + + internal override System.Reflection.MethodImplAttributes ImplementationAttributes + { + get { return default(System.Reflection.MethodImplAttributes); } + } + + public override bool IsVararg + { + get + { + return false; + } + } + + public override ImmutableArray TypeParameters + { + get + { + return ImmutableArray.Empty; + } + } + + internal override int ParameterCount + { + get + { + return 1; + } + } + + public override ImmutableArray Parameters + { + get + { + return _parameters; + } + } + + public override Accessibility DeclaredAccessibility + { + get + { + return Accessibility.Private; + } + } + + public override RefKind RefKind + { + get + { + return RefKind.None; + } + } + + public override TypeWithAnnotations ReturnTypeWithAnnotations + { + get + { + return TypeWithAnnotations.Create(_returnType); + } + } + + public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None; + + public override ImmutableHashSet ReturnNotNullIfParameterNotNull => ImmutableHashSet.Empty; + + public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None; + + public override ImmutableArray RefCustomModifiers + { + get + { + return ImmutableArray.Empty; + } + } + + public sealed override bool IsImplicitlyDeclared + { + get + { + return false; + } + } + + internal sealed override bool GenerateDebugInfo + { + get + { + return true; + } + } + + internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) + { + return localPosition; + } + + protected override void MethodChecks(DiagnosticBag diagnostics) + { + } + + internal override bool IsExpressionBodied => false; + + public override ImmutableArray GetTypeParameterConstraintClauses() + => ImmutableArray.Empty; + + protected override object MethodChecksLockObject => _declaration; + + internal CompilationUnitSyntax CompilationUnit => (CompilationUnitSyntax)SyntaxNode; + + internal override ExecutableCodeBinder TryGetBodyBinder(BinderFactory? binderFactoryOpt = null, bool ignoreAccessibility = false) + { + return GetBodyBinder(ignoreAccessibility); + } + + private ExecutableCodeBinder CreateBodyBinder(bool ignoreAccessibility) + { + CSharpCompilation compilation = DeclaringCompilation; + + Binder result = new BuckStopsHereBinder(compilation); + result = new InContainerBinder(compilation.GlobalNamespace, result, SyntaxNode, inUsing: false); + result = new InContainerBinder(ContainingType, result); + result = new InMethodBinder(this, result); + result = result.WithAdditionalFlags(ignoreAccessibility ? BinderFlags.IgnoreAccessibility : BinderFlags.None); + + return new ExecutableCodeBinder(SyntaxNode, this, result); + } + + internal ExecutableCodeBinder GetBodyBinder(bool ignoreAccessibility) + { + ref WeakReference? weakBinder = ref ignoreAccessibility ? ref _weakIgnoreAccessibilityBodyBinder : ref _weakBodyBinder; + + while (true) + { + var previousWeakReference = weakBinder; + if (previousWeakReference != null && previousWeakReference.TryGetTarget(out ExecutableCodeBinder? previousBinder)) + { + return previousBinder; + } + + ExecutableCodeBinder newBinder = CreateBodyBinder(ignoreAccessibility); + if (Interlocked.CompareExchange(ref weakBinder, new WeakReference(newBinder), previousWeakReference) == previousWeakReference) + { + return newBinder; + } + } + } + + internal override bool IsDefinedInSourceTree(SyntaxTree tree, TextSpan? definedWithinSpan, CancellationToken cancellationToken) + { + if (_declaration.SyntaxReference.SyntaxTree == tree) + { + if (!definedWithinSpan.HasValue) + { + return true; + } + else + { + var span = definedWithinSpan.GetValueOrDefault(); + + foreach (var global in ((CompilationUnitSyntax)tree.GetRoot()).Members.OfType()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (global.Span.IntersectsWith(span)) + { + return true; + } + } + } + } + + return false; + } + + public SyntaxNode ReturnTypeSyntax => CompilationUnit.Members.First(m => m.Kind() == SyntaxKind.GlobalStatement); + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs index 5507899aa8d35..8735a46e549dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs @@ -22,6 +22,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] internal sealed class Boxed { + internal readonly static Boxed Sentinel = new Boxed(default); + internal readonly TypeWithAnnotations Value; internal Boxed(TypeWithAnnotations value) { diff --git a/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs index 6e8623e887195..799a194925490 100644 --- a/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs @@ -13,5 +13,7 @@ internal abstract partial class TypeSyntax public bool IsNuint => IsIdentifierName("nuint"); private bool IsIdentifierName(string id) => this is IdentifierNameSyntax name && name.Identifier.ToString() == id; + + public bool IsRef => Kind == SyntaxKind.RefType; } } diff --git a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs index ecb00bb1421ee..65e07faa99390 100644 --- a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs +++ b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs @@ -382,6 +382,7 @@ internal static bool IsClosureScope(SyntaxNode node) { switch (node.Kind()) { + case SyntaxKind.CompilationUnit: case SyntaxKind.Block: case SyntaxKind.SwitchStatement: case SyntaxKind.ArrowExpressionClause: // expression-bodied member diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs index b9b16e41fe1c6..90781aa2e50f5 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs @@ -5,6 +5,8 @@ #nullable enable using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -489,5 +491,62 @@ internal static bool HasAnyBody(this BaseMethodDeclarationSyntax declaration) { return (declaration.Body ?? (SyntaxNode?)declaration.ExpressionBody) != null; } + + internal static bool IsTopLevelStatement([NotNullWhen(true)] GlobalStatementSyntax? syntax) + { + return syntax?.Parent?.IsKind(SyntaxKind.CompilationUnit) == true; + } + + internal static bool IsSimpleProgramTopLevelStatement(GlobalStatementSyntax? syntax) + { + return IsTopLevelStatement(syntax) && syntax.SyntaxTree.Options.Kind == SourceCodeKind.Regular; + } + + internal static bool HasAwaitOperations(SyntaxNode node) + { + // Do not descend into functions + return node.DescendantNodesAndSelf(child => !IsNestedFunction(child)).Any( + node => + { + switch (node) + { + case AwaitExpressionSyntax _: + case LocalDeclarationStatementSyntax local when local.AwaitKeyword.IsKind(SyntaxKind.AwaitKeyword): + case CommonForEachStatementSyntax @foreach when @foreach.AwaitKeyword.IsKind(SyntaxKind.AwaitKeyword): + case UsingStatementSyntax @using when @using.AwaitKeyword.IsKind(SyntaxKind.AwaitKeyword): + return true; + default: + return false; + } + }); + } + + internal static bool IsNestedFunction(SyntaxNode child) + { + switch (child.Kind()) + { + case SyntaxKind.LocalFunctionStatement: + case SyntaxKind.AnonymousMethodExpression: + case SyntaxKind.SimpleLambdaExpression: + case SyntaxKind.ParenthesizedLambdaExpression: + return true; + default: + return false; + } + } + + internal static bool HasYieldOperations(SyntaxNode? node) + { + // Do not descend into functions and expressions + return node is object && + node.DescendantNodesAndSelf(child => !IsNestedFunction(child) && !(node is ExpressionSyntax)).Any(n => n is YieldStatementSyntax); + } + + internal static bool HasReturnWithExpression(SyntaxNode? node) + { + // Do not descend into functions and expressions + return node is object && + node.DescendantNodesAndSelf(child => !IsNestedFunction(child) && !(node is ExpressionSyntax)).Any(n => n is ReturnStatementSyntax { Expression: { } }); + } } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 62788cbf1f37e..868eef14e5fa9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -487,6 +487,26 @@ Cílový modul runtime nepodporuje pro člena rozhraní přístupnost na úrovni Protected, Protected internal nebo Private protected. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Vzor deconstruct s jedním elementem vyžaduje určitou další syntaxi pro zajištění jednoznačnosti. Doporučuje se přidat označení discard „_“ za koncovou závorku „)“. @@ -532,6 +552,11 @@ Řídící výraz switch je nutné uzavřít do závorek. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Neočekáváná posloupnost znaků ... @@ -1166,6 +1191,11 @@ (Umístění symbolu vzhledem k předchozímu upozornění) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Potlačení upozornění zvažte jenom v případě, když určitě nechcete če - The entry point of the program is global script code; ignoring '{0}' entry point. - Vstupní bod programu je globální kód skriptu; vstupní bod se bude ignorovat {0}. + The entry point of the program is global code; ignoring '{0}' entry point. + Vstupní bod programu je globální kód skriptu; vstupní bod se bude ignorovat {0}. - The entry point of the program is global script code; ignoring entry point - Vstupním bodem programu je globální kód skriptu. Vstupní bod se ignoruje. + The entry point of the program is global code; ignoring entry point + Vstupním bodem programu je globální kód skriptu. Vstupní bod se ignoruje. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 2319426546f6d..5bad50f6c19ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -487,6 +487,26 @@ Die Zugriffsoptionen "protected", "protected internal" oder "private protected" werden von der Zielruntime für einen Member einer Schnittstelle nicht unterstützt. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Ein aus einem Element bestehendes deconstruct-Muster erfordert zur Vermeidung einer Mehrdeutigkeit eine etwas andere Syntax. Es wird empfohlen, nach der schließenden Klammer ")" einen discard-Kennzeichner "_" hinzuzufügen. @@ -532,6 +552,11 @@ Der Ausdruck zur Steuerung von Schaltern muss in Klammern eingeschlossen werden. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Unerwartete Zeichenfolge "...". @@ -1166,6 +1191,11 @@ (Position des Symbols für die vorherige Warnung) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Sie sollten das Unterdrücken der Warnung nur in Betracht ziehen, wenn Sie siche - The entry point of the program is global script code; ignoring '{0}' entry point. - Der Einstiegspunkt des Programms ist globaler Skriptcode. Der Einstiegspunkt "{0}" wird ignoriert. + The entry point of the program is global code; ignoring '{0}' entry point. + Der Einstiegspunkt des Programms ist globaler Skriptcode. Der Einstiegspunkt "{0}" wird ignoriert. - The entry point of the program is global script code; ignoring entry point - Der Einstiegspunkt des Programms ist globaler Skriptcode; der Einstiegspunkt wird ignoriert. + The entry point of the program is global code; ignoring entry point + Der Einstiegspunkt des Programms ist globaler Skriptcode; der Einstiegspunkt wird ignoriert. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 51a6f2de4dabf..28fa94835b19d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -487,6 +487,26 @@ El entorno de ejecución de destino no admite la accesibilidad protegida, protegida interna o protegida privada para un miembro de una interfaz. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Un patrón de deconstrucción de un solo elemento requiere más sintaxis para la desambiguación. Se recomienda agregar un designador de descarte "_" después del paréntesis de cierre ")". @@ -532,6 +552,11 @@ La expresión switch aplicable requiere paréntesis. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Secuencia de caracteres "..." inesperada. @@ -1166,6 +1191,11 @@ (Ubicación del símbolo relacionado con la advertencia anterior) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Considere la posibilidad de suprimir la advertencia solo si tiene la seguridad d - The entry point of the program is global script code; ignoring '{0}' entry point. - El punto de entrada del programa es código de script global: se omite el punto de entrada '{0}'. + The entry point of the program is global code; ignoring '{0}' entry point. + El punto de entrada del programa es código de script global: se omite el punto de entrada '{0}'. - The entry point of the program is global script code; ignoring entry point - El punto de entrada del programa es código de script global. Ignorando punto de entrada + The entry point of the program is global code; ignoring entry point + El punto de entrada del programa es código de script global. Ignorando punto de entrada diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 61f37d1f0ac86..360011b97b718 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -487,6 +487,26 @@ Le runtime cible ne prend pas en charge l'accessibilité 'protected', 'protected internal' ou 'private protected' d'un membre d'interface. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Un modèle de déconstruction d'un seul élément nécessite une autre syntaxe pour la désambiguïsation. Il est recommandé d'ajouter un désignateur d'abandon '_' après la parenthèse de fermeture ')'. @@ -532,6 +552,11 @@ Des parenthèses sont obligatoires autour de l'expression régissant switch. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Séquence de caractères inattendue '...' @@ -1166,6 +1191,11 @@ (Emplacement du symbole par rapport à l'avertissement précédent) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Supprimez l'avertissement seulement si vous êtes sûr de ne pas vouloir attendr - The entry point of the program is global script code; ignoring '{0}' entry point. - Le point d'entrée du programme est du code de script global ; point d'entrée '{0}' ignoré. + The entry point of the program is global code; ignoring '{0}' entry point. + Le point d'entrée du programme est du code de script global ; point d'entrée '{0}' ignoré. - The entry point of the program is global script code; ignoring entry point - Le point d'entrée du programme est du code de script global ; ce point d'entrée est ignoré + The entry point of the program is global code; ignoring entry point + Le point d'entrée du programme est du code de script global ; ce point d'entrée est ignoré diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 5ab1b57308d2b..99302bee03cdb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -487,6 +487,26 @@ Il runtime di destinazione non supporta l'accessibilità 'protected', 'protected internal' o 'private protected' per un membro di un'interfaccia. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Per risolvere le ambiguità, è necessario usare una sintassi diversa per il criterio di decostruzione di singoli elementi. È consigliabile aggiungere un indicatore di rimozione '_' dopo la parentesi di chiusura ')'. @@ -532,6 +552,11 @@ L'espressione che gestisce lo switch deve essere racchiusa tra parentesi. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' La sequenza di caratteri '...' è imprevista @@ -1166,6 +1191,11 @@ (Posizione del simbolo relativo all'avviso precedente) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Come procedura consigliata, è consigliabile attendere sempre la chiamata. - The entry point of the program is global script code; ignoring '{0}' entry point. - Il punto di ingresso del programma è codice script globale. Il punto di ingresso '{0}' verrà ignorato. + The entry point of the program is global code; ignoring '{0}' entry point. + Il punto di ingresso del programma è codice script globale. Il punto di ingresso '{0}' verrà ignorato. - The entry point of the program is global script code; ignoring entry point - Il punto di ingresso del programma è codice script globale. Il punto di ingresso verrà ignorato + The entry point of the program is global code; ignoring entry point + Il punto di ingresso del programma è codice script globale. Il punto di ingresso verrà ignorato diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 4eef4de7172a1..49cd25c916ff9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -487,6 +487,26 @@ ターゲット ランタイムは、インターフェイスのメンバーに対して 'protected'、'protected internal'、'private protected' アクセシビリティをサポートしていません。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. 単一要素の分解パターンには、あいまいさを排除するための他の構文が必要です。破棄指定子 '_' を閉じかっこ ')' の後に追加することをお勧めします。 @@ -532,6 +552,11 @@ switch を制御する式の周囲にはかっこが必要です。 + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' 予期しない文字シーケンス '...' @@ -1166,6 +1191,11 @@ (以前のエラーに関連する警告の位置) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ You should consider suppressing the warning only if you're sure that you don't w - The entry point of the program is global script code; ignoring '{0}' entry point. - プログラムのエントリ ポイントは、グローバル スクリプト コードです。エントリ ポイント '{0}' を無視します。 + The entry point of the program is global code; ignoring '{0}' entry point. + プログラムのエントリ ポイントは、グローバル スクリプト コードです。エントリ ポイント '{0}' を無視します。 - The entry point of the program is global script code; ignoring entry point - プログラムのエントリ ポイントは、グローバル スクリプト コードです。エントリ ポイントを無視します + The entry point of the program is global code; ignoring entry point + プログラムのエントリ ポイントは、グローバル スクリプト コードです。エントリ ポイントを無視します diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 8a6fdd75d6a81..f84f7721686ab 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -487,6 +487,26 @@ 대상 런타임이 인터페이스 멤버의 'protected', 'protected internal' 또는 'private protected' 접근성을 지원하지 않습니다. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. 단일 요소 분해 패턴은 명확성을 위해 다른 구문이 필요합니다. 닫는 괄호 ')' 뒤에 무시 항목 지정자 '_'을 추가하는 것이 좋습니다. @@ -532,6 +552,11 @@ 식을 제어하는 switch 주위에 괄호가 필요합니다. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' 예기치 않은 '...' 문자 시퀀스입니다. @@ -1166,6 +1191,11 @@ (이전 경고와 관련된 기호 위치) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ You should consider suppressing the warning only if you're sure that you don't w - The entry point of the program is global script code; ignoring '{0}' entry point. - 프로그램의 진입점은 전역 스크립트 코드이므로 '{0}' 진입점을 무시합니다. + The entry point of the program is global code; ignoring '{0}' entry point. + 프로그램의 진입점은 전역 스크립트 코드이므로 '{0}' 진입점을 무시합니다. - The entry point of the program is global script code; ignoring entry point - 프로그램의 진입점이 전역 스크립트 코드이며 진입점을 무시함 + The entry point of the program is global code; ignoring entry point + 프로그램의 진입점이 전역 스크립트 코드이며 진입점을 무시함 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 8f0caa828eac1..72aa5fbc1211c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -487,6 +487,26 @@ Docelowe środowisko uruchomieniowe nie obsługuje specyfikatorów dostępu „protected”, „protected internal” i „private protected” dla składowej interfejsu. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Wzorzec dekonstrukcji z jednym elementem wymaga innej składni w celu ujednoznacznienia. Zaleca się dodanie desygnatora odrzucania „_” po nawiasie zamykającym „)”. @@ -532,6 +552,11 @@ Wymagane są nawiasy wokół wyrażenia sterującego instrukcją switch. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Nieoczekiwana sekwencja znaków „...” @@ -1166,6 +1191,11 @@ (Lokalizacja symbolu związanego z poprzednim ostrzeżeniem) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Pominięcie ostrzeżenia należy wziąć pod uwagę tylko w sytuacji, gdy na pew - The entry point of the program is global script code; ignoring '{0}' entry point. - Punkt wejścia programu to kod skryptu globalnego. Punkt wejścia „{0}” został zignorowany. + The entry point of the program is global code; ignoring '{0}' entry point. + Punkt wejścia programu to kod skryptu globalnego. Punkt wejścia „{0}” został zignorowany. - The entry point of the program is global script code; ignoring entry point - Punkt wejścia programu to kod skryptu globalnego. Punkt wejścia został zignorowany + The entry point of the program is global code; ignoring entry point + Punkt wejścia programu to kod skryptu globalnego. Punkt wejścia został zignorowany diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 4463dd1bb5576..795b3991cb749 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -487,6 +487,26 @@ O runtime de destino não é compatível com a acessibilidade 'protected', 'protected internal' ou 'private protected' para um membro de uma interface. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Um padrão de desconstrução de elemento único requer alguma outra sintaxe para desambiguação. É recomendado adicionar um designador de descarte '_' após o parêntese de fechamento ')'. @@ -532,6 +552,11 @@ É necessário colocar a expressão que rege a switch entre parênteses. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Sequência de caracteres inesperada '...' @@ -1165,6 +1190,11 @@ (Local do símbolo relacionado ao aviso anterior) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7894,13 +7924,13 @@ Você pode suprimir o aviso se tiver certeza de que não vai querer aguardar a c - The entry point of the program is global script code; ignoring '{0}' entry point. - O ponto de entrada do programa é o código de script global; ignorando "{0}" ponto de entrada. + The entry point of the program is global code; ignoring '{0}' entry point. + O ponto de entrada do programa é o código de script global; ignorando "{0}" ponto de entrada. - The entry point of the program is global script code; ignoring entry point - O ponto de entrada do programa é o código de script global; ignorando o ponto de entrada + The entry point of the program is global code; ignoring entry point + O ponto de entrada do programa é o código de script global; ignorando o ponto de entrada diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index e02721c0347f8..f5af9cc60b3ae 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -487,6 +487,26 @@ Целевая среда выполнения не поддерживает специальные возможности "защищенный", "внутренний защищенный" или "частный защищенный" для члена интерфейса. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Для шаблона деконструкции с одним элементом требуется другой синтаксис для устранения неоднозначности. Рекомендуется добавить указатель отмены "_" после закрывающей скобки ")". @@ -532,6 +552,11 @@ Вокруг главного выражения switch требуются скобки. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Неожиданная последовательность символов "…" @@ -1166,6 +1191,11 @@ (Местоположение символа, связанного с предыдущим предупреждением) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ You should consider suppressing the warning only if you're sure that you don't w - The entry point of the program is global script code; ignoring '{0}' entry point. - Точкой входа программы является глобальный код скрипта; игнорируйте точку входа "{0}". + The entry point of the program is global code; ignoring '{0}' entry point. + Точкой входа программы является глобальный код скрипта; игнорируйте точку входа "{0}". - The entry point of the program is global script code; ignoring entry point - Точка входа в программе является глобальным кодом скрипта; выполняется пропуск точки входа + The entry point of the program is global code; ignoring entry point + Точка входа в программе является глобальным кодом скрипта; выполняется пропуск точки входа diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index c1d8e6b23ba7a..284a95e0fae75 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -487,6 +487,26 @@ Hedef çalışma zamanı, bir arabirim üyesi için 'protected', 'protected internal' veya 'private protected' erişilebilirliğini desteklemez. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. Tek öğeli bir ayrıştırma deseni, kesinleştirme için başka bir söz dizimi gerektirir. ')' kapanış parantezinden sonra '_' atma belirleyicisinin eklenmesi önerilir. @@ -532,6 +552,11 @@ Switch yönetim ifadesinin parantez içine alınması gerekir. + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' Beklenmeyen karakter sırası '...' @@ -1166,6 +1191,11 @@ (Önceki uyarıyla ilgili sembolün konumu) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ Yalnızca asenkron çağrının tamamlanmasını beklemek istemediğinizden ve - The entry point of the program is global script code; ignoring '{0}' entry point. - Programın giriş noktası genel betik kodudur; '{0}' giriş noktası yoksayılıyor. + The entry point of the program is global code; ignoring '{0}' entry point. + Programın giriş noktası genel betik kodudur; '{0}' giriş noktası yoksayılıyor. - The entry point of the program is global script code; ignoring entry point - Programın giriş noktası genel betik kodudur, giriş noktası yoksayılıyor + The entry point of the program is global code; ignoring entry point + Programın giriş noktası genel betik kodudur, giriş noktası yoksayılıyor diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 186b8c1e0c84d..092f55946e2bd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -487,6 +487,26 @@ 目标运行时不支持对接口的成员使用 "protected"、"protected internal" 或 "private protected" 辅助功能。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. 单元素解构模式需要一些其他语法来消除歧义。建议在关闭 paren ")" 之后添加放弃指示符 "_"。 @@ -532,6 +552,11 @@ switch governing 表达式的周围需要括号。 + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' 意外的字符序列 “...” @@ -1166,6 +1191,11 @@ (与前一个警告相关的符号位置) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ You should consider suppressing the warning only if you're sure that you don't w - The entry point of the program is global script code; ignoring '{0}' entry point. - 程序的入口点是全局脚本代码;正在忽略“{0}”入口点。 + The entry point of the program is global code; ignoring '{0}' entry point. + 程序的入口点是全局脚本代码;正在忽略“{0}”入口点。 - The entry point of the program is global script code; ignoring entry point - 程序的入口点是全局脚本代码;正在忽略入口点 + The entry point of the program is global code; ignoring entry point + 程序的入口点是全局脚本代码;正在忽略入口点 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 7d07f0e4b87cc..fdd72a62642e8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -487,6 +487,26 @@ 目標執行階段不支援介面成員的 'protected'、'protected internal' 或 'private protected' 存取權。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. + + + + Only one compilation unit can have top-level statements. + Only one compilation unit can have top-level statements. + + + + Program using top-level statements must be an executable. + Program using top-level statements must be an executable. + + A single-element deconstruct pattern requires some other syntax for disambiguation. It is recommended to add a discard designator '_' after the close paren ')'. 單一元素解構模式需要一些其他語法才能使其明確。建議在右括弧 ')' 後新增捨棄指示項 '_'。 @@ -532,6 +552,11 @@ switch 主導的運算式前後必須有括弧。 + + Top-level statements must precede namespace and type declarations. + Top-level statements must precede namespace and type declarations. + + Unexpected character sequence '...' 未預期的字元順序 '...' @@ -1166,6 +1191,11 @@ (與之前警告相關符號的位置) + + top-level statements + top-level statements + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> @@ -7895,13 +7925,13 @@ You should consider suppressing the warning only if you're sure that you don't w - The entry point of the program is global script code; ignoring '{0}' entry point. - 程式的進入點為全域指令碼; 將略過 '{0}' 進入點。 + The entry point of the program is global code; ignoring '{0}' entry point. + 程式的進入點為全域指令碼; 將略過 '{0}' 進入點。 - The entry point of the program is global script code; ignoring entry point - 程式的進入點是全域指令碼; 將忽略進入點 + The entry point of the program is global code; ignoring entry point + 程式的進入點是全域指令碼; 將忽略進入點 diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 20f93102ab307..cc185b3ea88be 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -7177,8 +7177,12 @@ public void SpecifyProperCodePage() a.cs(1,7): error CS1001: Identifier expected a.cs(1,7): error CS1514: { expected a.cs(1,7): error CS1513: } expected -a.cs(1,7): error CS1022: Type or namespace definition, or end-of-file expected -a.cs(1,10): error CS1022: Type or namespace definition, or end-of-file expected".Trim(), +a.cs(1,7): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. +a.cs(1,7): error CS9002: Top-level statements must precede namespace and type declarations. +a.cs(1,7): error CS1525: Invalid expression term '??' +a.cs(1,9): error CS1525: Invalid expression term '{' +a.cs(1,9): error CS1002: ; expected +".Trim(), Regex.Replace(output, "^.*a.cs", "a.cs", RegexOptions.Multiline).Trim()); CleanupAllGeneratedFiles(file.Path); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs index 570c643ea14c4..51d6ffaa29cbb 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs @@ -5040,30 +5040,22 @@ .locals init (int V_0, } [Fact] - public void NoGlobalDeconstructionOutsideScript() + public void GlobalDeconstructionOutsideScript() { var source = @" (string x, int y) = (""hello"", 42); +System.Console.Write(x); +System.Console.Write(y); "; - var comp = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.Regular, options: TestOptions.DebugExe, references: s_valueTupleRefs); + var comp = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe, references: s_valueTupleRefs); - comp.VerifyDiagnostics( - // (2,19): error CS1022: Type or namespace definition, or end-of-file expected - // (string x, int y) = ("hello", 42); - Diagnostic(ErrorCode.ERR_EOFExpected, "=").WithLocation(2, 19), - // (2,22): error CS1022: Type or namespace definition, or end-of-file expected - // (string x, int y) = ("hello", 42); - Diagnostic(ErrorCode.ERR_EOFExpected, @"""hello""").WithLocation(2, 22), - // (2,22): error CS1026: ) expected - // (string x, int y) = ("hello", 42); - Diagnostic(ErrorCode.ERR_CloseParenExpected, @"""hello""").WithLocation(2, 22), - // error CS5001: Program does not contain a static 'Main' method suitable for an entry point - Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1) - ); + comp.VerifyDiagnostics(); var nodes = comp.SyntaxTrees[0].GetCompilationUnitRoot().DescendantNodesAndSelf(); - Assert.False(nodes.Any(n => n.Kind() == SyntaxKind.SimpleAssignmentExpression)); + Assert.True(nodes.Any(n => n.Kind() == SyntaxKind.SimpleAssignmentExpression)); + + CompileAndVerify(comp, expectedOutput: "hello42"); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 899573d34540d..7f05a8f9e6780 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -5405,7 +5405,7 @@ public void TupleUnsupportedInUsingStatement() var source = @" using VT2 = (int, int); "; - var comp = CreateCompilation(source, parseOptions: TestOptions.Regular); + var comp = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); comp.VerifyDiagnostics( // (2,13): error CS1001: Identifier expected // using VT2 = (int, int); @@ -5413,12 +5413,12 @@ public void TupleUnsupportedInUsingStatement() // (2,13): error CS1002: ; expected // using VT2 = (int, int); Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(2, 13), - // (2,22): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,14): error CS1525: Invalid expression term 'int' // using VT2 = (int, int); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, ")").WithLocation(2, 22), - // (2,23): error CS1022: Type or namespace definition, or end-of-file expected + 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_EOFExpected, ";").WithLocation(2, 23), + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(2, 19), // (2,1): hidden CS8019: Unnecessary using directive. // using VT2 = (int, int); Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using VT2 = ").WithLocation(2, 1) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs index f21c1a4ad59d4..3063d42bbe92f 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs @@ -3307,6 +3307,57 @@ File 3 verifier.VerifyDiagnostics(); } + [Fact] + [CompilerTrait(CompilerFeature.TopLevelStatements)] + public void TopLevelStatements_01() + { + var source = @" +using System; + +Test(); +Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload(); + +static void Test() +{ + Console.WriteLine(""Test""); +} + +" + InstrumentationHelperSource; + + var checker = new CSharpInstrumentationChecker(); + checker.Method(1, 1, snippet: "", expectBodySpan: false) + .True("Test();") + .True("Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();") + .True(@"Console.WriteLine(""Test"");"); + checker.Method(4, 1) + .True() + .False() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True() + .True(); + + var expectedOutput = @"Test +" + checker.ExpectedOutput; + + var verifier = CompileAndVerify(source, expectedOutput, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + checker.CompleteCheck(verifier.Compilation, source); + verifier.VerifyDiagnostics(); + + verifier = CompileAndVerify(source, expectedOutput, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); + checker.CompleteCheck(verifier.Compilation, source); + verifier.VerifyDiagnostics(); + } + private static void AssertNotInstrumented(CompilationVerifier verifier, string qualifiedMethodName) => AssertInstrumented(verifier, qualifiedMethodName, expected: false); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs index eae4d6d759b28..c30ab74df76eb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs @@ -3309,7 +3309,10 @@ public static void Bug1098197_02() @" void f() { if () const int i = 0; } "; - CreateCompilation(source).VerifyDiagnostics( + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,6): warning CS8321: The local function 'f' is declared but never used + // void f() { if () const int i = 0; } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "f").WithArguments("f").WithLocation(2, 6), // (2,16): error CS1525: Invalid expression term ')' // void f() { if () const int i = 0; } Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(2, 16), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs index 9e1a8096b18cc..7acf1039af81e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs @@ -21,6 +21,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests [CompilerTrait(CompilerFeature.OutVar)] public class OutVarTests : CompilingTestBase { + [Fact] public void OldVersion() { @@ -1089,7 +1090,11 @@ private static void VerifyDataFlow(SemanticModel model, DeclarationExpressionSyn if (dataFlowParent == null) { - Assert.IsAssignableFrom(decl.Parent.Parent.Parent); + if (isExecutableCode || !(decl.Parent.Parent.Parent is VariableDeclaratorSyntax)) + { + Assert.IsAssignableFrom(decl.Parent.Parent.Parent); + } + return; } @@ -23184,30 +23189,97 @@ static bool TakeOutParam(object y, out int x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_MemberAlreadyExists - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + compilation.VerifyDiagnostics( + // (14,34): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // catch when (TakeOutParam(out var x4) && x4 > 0) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(14, 34), + // (20,13): error CS0841: Cannot use local variable 'x6' before it is declared + // catch when (x6 && TakeOutParam(out var x6)) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(20, 13), + // (28,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(28, 9), + // (38,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(38, 26), + // (45,38): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // catch when (TakeOutParam(out var x9) && x9 > 0) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(45, 38), + // (52,26): error CS0103: The name 'y10' does not exist in the current context + // catch when (TakeOutParam(y10, out var x10)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(52, 26), + // (67,42): error CS0128: A local variable or function named 'x14' is already defined in this scope + // TakeOutParam(out var x14), // 2 + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(67, 42), + // (75,42): error CS0128: A local variable or function named 'x15' is already defined in this scope + // when (Dummy(TakeOutParam(out var x15), x15)) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x15").WithArguments("x15").WithLocation(75, 42), + // (85,13): error CS0128: A local variable or function named 'TakeOutParam' is already defined in this scope + // static bool TakeOutParam(object y, out int x) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(85, 13), + // (85,13): warning CS8321: The local function 'TakeOutParam' is declared but never used + // static bool TakeOutParam(object y, out int x) + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(85, 13) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x4Decl = GetOutVarDeclaration(tree, "x4"); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAnOutLocal(model, x4Ref[0]); + VerifyModelForOutVar(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetOutVarDeclaration(tree, "x6"); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForOutVar(model, x6Decl, x6Ref); + + var x7Decl = GetOutVarDeclaration(tree, "x7"); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForOutVar(model, x7Decl, x7Ref[0]); + VerifyNotAnOutLocal(model, x7Ref[1]); + + var x8Decl = GetOutVarDeclaration(tree, "x8"); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForOutVar(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForOutVar(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForOutVar(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAnOutLocal(model, y10Ref[1]); + + var x14Decl = GetOutVarDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForOutVar(model, x14Decl[0], x14Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x14Decl[1]); + + var x15Decl = GetOutVarDeclaration(tree, "x15"); + var x15Ref = GetReferences(tree, "x15").ToArray(); + Assert.Equal(2, x15Ref.Length); + VerifyModelForOutVarDuplicateInSameScope(model, x15Decl); + VerifyNotAnOutLocal(model, x15Ref[0]); + VerifyNotAnOutLocal(model, x15Ref[1]); } } @@ -23309,25 +23381,36 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_TypeVarNotFound - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (9,31): error CS0102: The type '' already contains a definition for 'x2' - // H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(9, 31) + compilation.VerifyDiagnostics( + // (7,8): warning CS0168: The variable 'x2' is declared but never used + // object x2; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x2").WithArguments("x2").WithLocation(7, 8), + // (9,31): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(9, 31), + // (15,9): error CS0103: The name 'x3' does not exist in the current context + // H.Dummy(x3); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(15, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(1, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyNotInScope(model, x3Ref); } } @@ -23567,40 +23650,101 @@ static bool TakeOutParam(object y, out bool x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists, - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (20,42): error CS0102: The type '' already contains a definition for 'x4' - // Dummy(TakeOutParam(true, out var x4) && x4) - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(20, 42), - // (33,9): error CS0102: The type '' already contains a definition for 'x7' - // var x7 = 12; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x7").WithArguments("", "x7").WithLocation(33, 9), - // (50,46): error CS0102: The type '' already contains a definition for 'x9' - // Dummy(TakeOutParam(true, out var x9) && x9) // 2 - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x9").WithArguments("", "x9").WithLocation(50, 46) + compilation.VerifyDiagnostics( + // (20,42): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // Dummy(TakeOutParam(true, out var x4) && x4) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(20, 42), + // (74,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(74, 5), + // (25,15): error CS0841: Cannot use local variable 'x6' before it is declared + // Dummy(x6 && TakeOutParam(true, out var x6)) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(25, 15), + // (33,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(33, 9), + // (42,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(42, 26), + // (50,46): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // Dummy(TakeOutParam(true, out var x9) && x9) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(50, 46), + // (56,28): error CS0103: The name 'y10' does not exist in the current context + // Dummy(TakeOutParam(y10, out var x10)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(56, 28), + // (72,28): error CS0103: The name 'y12' does not exist in the current context + // Dummy(TakeOutParam(y12, out var x12)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(72, 28), + // (83,37): error CS0128: A local variable or function named 'x14' is already defined in this scope + // TakeOutParam(2, out var x14), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(83, 37), + // (11,1): warning CS0162: Unreachable code detected + // for ( // 2 + Diagnostic(ErrorCode.WRN_UnreachableCode, "for").WithLocation(11, 1), + // (74,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(74, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForOutVar(model, x2Decl, x2Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAnOutLocal(model, x4Ref[0]); + VerifyModelForOutVar(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForOutVar(model, x6Decl, x6Ref); + + var x7Decl = GetOutVarDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForOutVar(model, x7Decl, x7Ref[0]); + VerifyNotAnOutLocal(model, x7Ref[1]); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForOutVar(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForOutVar(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForOutVar(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAnOutLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetOutVarDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForOutVar(model, x14Decl[0], x14Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x14Decl[1]); } } @@ -23665,7 +23809,7 @@ static bool TakeOutParam(int y, out int x) public void GlobalCode_Foreach_01() { var source = -@" +@"using static Helpers; System.Collections.IEnumerable Dummy(params object[] x) {return null;} foreach (var i in Dummy(TakeOutParam(true, out var x1) && x1)) @@ -23734,16 +23878,19 @@ public void GlobalCode_Foreach_01() Dummy(x15); } -static bool TakeOutParam(int y, out int x) +static class Helpers { - x = y; - return true; -} + public static bool TakeOutParam(int y, out int x) + { + x = y; + return true; + } -static bool TakeOutParam(bool y, out bool x) -{ - x = y; - return true; + public static bool TakeOutParam(bool y, out bool x) + { + x = y; + return true; + } } "; { @@ -23847,31 +23994,107 @@ static bool TakeOutParam(bool y, out bool x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + compilation.VerifyDiagnostics( + // (15,52): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var i in Dummy(TakeOutParam(true, out var x4) && x4)) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 52), + // (52,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(52, 5), + // (18,25): error CS0841: Cannot use local variable 'x6' before it is declared + // foreach (var i in Dummy(x6 && TakeOutParam(true, out var x6))) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(18, 25), + // (23,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(23, 9), + // (30,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(30, 26), + // (35,57): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var i2 in Dummy(TakeOutParam(true, out var x9) && x9)) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(35, 57), + // (39,38): error CS0103: The name 'y10' does not exist in the current context + // foreach (var i in Dummy(TakeOutParam(y10, out var x10))) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(39, 38), + // (51,38): error CS0103: The name 'y12' does not exist in the current context + // foreach (var i in Dummy(TakeOutParam(y12, out var x12))) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(51, 38), + // (58,49): error CS0128: A local variable or function named 'x14' is already defined in this scope + // TakeOutParam(2, out var x14), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(58, 49), + // (64,14): error CS0136: A local or parameter named 'x15' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var x15 in + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x15").WithArguments("x15").WithLocation(64, 14), + // (52,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(52, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForOutVar(model, x2Decl, x2Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAnOutLocal(model, x4Ref[0]); + VerifyModelForOutVar(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForOutVar(model, x6Decl, x6Ref); + + var x7Decl = GetOutVarDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForOutVar(model, x7Decl, x7Ref[0]); + VerifyNotAnOutLocal(model, x7Ref[1]); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForOutVar(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForOutVar(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForOutVar(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAnOutLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetOutVarDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForOutVar(model, x14Decl[0], x14Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x14Decl[1]); + + var x15Decl = GetOutVarDeclarations(tree, "x15").Single(); + var x15Ref = GetReferences(tree, "x15").ToArray(); + Assert.Equal(2, x15Ref.Length); + VerifyModelForOutVar(model, x15Decl, x15Ref[0]); + VerifyNotAnOutLocal(model, x15Ref[1]); } } @@ -24060,53 +24283,131 @@ static bool TakeOutParam(bool y, out bool x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + compilation.VerifyDiagnostics( + // (6,41): error CS0841: Cannot use local variable 'x4' before it is declared + // Dummy((System.Func) (o => x4 && TakeOutParam(o, out var x4))); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(6, 41), + // (9,82): error CS0128: A local variable or function named 'x5' is already defined in this scope + // TakeOutParam(o2, out var x5) && + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(9, 82), + // (14,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, 1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(14, 7), + // (15,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 7), + // (17,9): error CS0103: The name 'x7' does not exist in the current context + // x7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(17, 9), + // (18,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, 2); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(18, 7), + // (20,7): error CS0019: Operator '&&' cannot be applied to operands of type 'bool' and 'int' + // Dummy(TakeOutParam(true, out var x8) && x8, (System.Func) (o => TakeOutParam(o, out var y8) && x8)); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "TakeOutParam(true, out var x8) && x8").WithArguments("&&", "bool", "int").WithLocation(20, 7), + // (20,79): error CS0019: Operator '&&' cannot be applied to operands of type 'bool' and 'int' + // Dummy(TakeOutParam(true, out var x8) && x8, (System.Func) (o => TakeOutParam(o, out var y8) && x8)); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "TakeOutParam(o, out var y8) && x8").WithArguments("&&", "bool", "int").WithLocation(20, 79), + // (37,9): error CS0841: Cannot use local variable 'x12' before it is declared + // x12); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x12").WithArguments("x12").WithLocation(37, 9), + // (47,13): error CS0128: A local variable or function named 'TakeOutParam' is already defined in this scope + // static bool TakeOutParam(bool y, out bool x) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(47, 13), + // (47,13): warning CS8321: The local function 'TakeOutParam' is declared but never used + // static bool TakeOutParam(bool y, out bool x) + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(47, 13) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); - } - } + var model = compilation.GetSemanticModel(tree); - [Fact] - [WorkItem(16935, "https://github.com/dotnet/roslyn/issues/16935")] - public void GlobalCode_Lambda_02() - { - var source = -@" -System.Func l = () => TakeOutParam(1, out int x1) && Dummy(x1); -System.Console.WriteLine(l()); + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); -static bool Dummy(int x) -{ - System.Console.WriteLine(x); - return true; -} + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").Single(); + VerifyModelForOutVar(model, x4Decl, x4Ref); -static bool TakeOutParam(int y, out int x) -{ - x = y; - return true; + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").Single(); + Assert.Equal(2, x5Decl.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl[1]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").ToArray(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Decl.Length); + Assert.Equal(2, x6Ref.Length); + VerifyModelForOutVar(model, x6Decl[0], x6Ref[0]); + VerifyModelForOutVar(model, x6Decl[1], x6Ref[1]); + + var x7Decl = GetOutVarDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(5, x7Ref.Length); + VerifyNotInScope(model, x7Ref[0]); + VerifyNotInScope(model, x7Ref[1]); + VerifyModelForOutVar(model, x7Decl, x7Ref[2]); + VerifyNotInScope(model, x7Ref[3]); + VerifyNotInScope(model, x7Ref[4]); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(2, x8Ref.Length); + VerifyModelForOutVar(model, x8Decl, x8Ref); + + var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(2, x9Ref.Length); + VerifyModelForOutVar(model, x9Decl[0], x9Ref[1]); + VerifyModelForOutVar(model, x9Decl[1], x9Ref[0]); + + var x10Decl = GetOutVarDeclarations(tree, "x10").ToArray(); + var x10Ref = GetReferences(tree, "x10").ToArray(); + Assert.Equal(2, x10Decl.Length); + Assert.Equal(2, x10Ref.Length); + VerifyModelForOutVar(model, x10Decl[0], x10Ref[0]); + VerifyModelForOutVar(model, x10Decl[1], x10Ref[1]); + + var x11Decl = GetOutVarDeclarations(tree, "x11").Single(); + var x11Ref = GetReferences(tree, "x11").ToArray(); + Assert.Equal(3, x11Ref.Length); + VerifyNotAnOutLocal(model, x11Ref[0]); + VerifyModelForOutVar(model, x11Decl, x11Ref[1]); + VerifyNotAnOutLocal(model, x11Ref[2]); + + var x12Decl = GetOutVarDeclarations(tree, "x12").Single(); + var x12Ref = GetReferences(tree, "x12").ToArray(); + Assert.Equal(3, x12Ref.Length); + VerifyModelForOutVar(model, x12Decl, x12Ref[0]); + VerifyNotAnOutLocal(model, x12Ref[1]); + VerifyNotAnOutLocal(model, x12Ref[2]); + } + } + + [Fact] + [WorkItem(16935, "https://github.com/dotnet/roslyn/issues/16935")] + public void GlobalCode_Lambda_02() + { + var source = +@" +System.Func l = () => TakeOutParam(1, out int x1) && Dummy(x1); +System.Console.WriteLine(l()); + +static bool Dummy(int x) +{ + System.Console.WriteLine(x); + return true; +} + +static bool TakeOutParam(int y, out int x) +{ + x = y; + return true; } "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script); @@ -24507,48 +24808,262 @@ static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_NameNotInContext - }; + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (29,48): error CS1938: The name 'TakeOutParam' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. - // equals x2 + y4 + z4 + (TakeOutParam(4, out var v4) ? v4 : 0) + - Diagnostic(ErrorCode.ERR_QueryInnerKey, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(29, 48), - // (30,29): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. - // u4 - Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(30, 29), - // (42,48): error CS1938: The name 'TakeOutParam' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. - // equals x2 + y5 + z5 + (TakeOutParam(4, out var v5) ? v5 : 0) + - Diagnostic(ErrorCode.ERR_QueryInnerKey, "TakeOutParam").WithArguments("TakeOutParam").WithLocation(42, 48), - // (43,29): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. - // u5 - Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(43, 29), - // (86,18): error CS1931: The range variable 'y10' conflicts with a previous declaration of 'y10' - // from y10 in new[] { 1 } - Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "y10").WithArguments("y10").WithLocation(86, 18), - // (90,17): error CS1931: The range variable 'y11' conflicts with a previous declaration of 'y11' - // let y11 = x1 + 1 - Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "y11").WithArguments("y11").WithLocation(90, 17) + compilation.VerifyDiagnostics( + // (14,21): error CS0103: The name 'z2' does not exist in the current context + // z2; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(14, 21), + // (16,7): error CS0103: The name 'z2' does not exist in the current context + // Dummy(z2); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(16, 7), + // (21,25): error CS0103: The name 'z3' does not exist in the current context + // z3}; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(21, 25), + // (23,7): error CS0103: The name 'z3' does not exist in the current context + // Dummy(z3); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(23, 7), + // (28,29): error CS0103: The name 'v4' does not exist in the current context + // v4 + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(28, 29), + // (30,29): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. + // u4 + Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(30, 29), + // (32,25): error CS0103: The name 'u4' does not exist in the current context + // u4, v4 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(32, 25), + // (32,29): error CS0103: The name 'v4' does not exist in the current context + // u4, v4 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(32, 29), + // (35,7): error CS0103: The name 'u4' does not exist in the current context + // Dummy(u4); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(35, 7), + // (36,7): error CS0103: The name 'v4' does not exist in the current context + // Dummy(v4); + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(36, 7), + // (41,29): error CS0103: The name 'v5' does not exist in the current context + // v5 + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(41, 29), + // (43,29): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. + // u5 + Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(43, 29), + // (46,25): error CS0103: The name 'u5' does not exist in the current context + // u5, v5 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(46, 25), + // (46,29): error CS0103: The name 'v5' does not exist in the current context + // u5, v5 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(46, 29), + // (49,7): error CS0103: The name 'u5' does not exist in the current context + // Dummy(u5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(49, 7), + // (50,7): error CS0103: The name 'v5' does not exist in the current context + // Dummy(v5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(50, 7), + // (55,21): error CS0103: The name 'z6' does not exist in the current context + // z6; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(55, 21), + // (57,7): error CS0103: The name 'z6' does not exist in the current context + // Dummy(z6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(57, 7), + // (61,21): error CS0103: The name 'u7' does not exist in the current context + // u7, + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(61, 21), + // (63,21): error CS0103: The name 'z7' does not exist in the current context + // z7 + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(63, 21), + // (65,21): error CS0103: The name 'z7' does not exist in the current context + // z7 + u7; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(65, 21), + // (65,26): error CS0103: The name 'u7' does not exist in the current context + // z7 + u7; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(65, 26), + // (67,7): error CS0103: The name 'z7' does not exist in the current context + // Dummy(z7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(67, 7), + // (68,7): error CS0103: The name 'u7' does not exist in the current context + // Dummy(u7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(68, 7), + // (73,7): error CS0103: The name 'z8' does not exist in the current context + // Dummy(z8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z8").WithArguments("z8").WithLocation(73, 7), + // (77,17): error CS0103: The name 'u9' does not exist in the current context + // u9 + Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(77, 17), + // (80,17): error CS0103: The name 'z9' does not exist in the current context + // z9; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(80, 17), + // (82,7): error CS0103: The name 'z9' does not exist in the current context + // Dummy(z9); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(82, 7), + // (83,7): error CS0103: The name 'u9' does not exist in the current context + // Dummy(u9); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(83, 7), + // (86,18): error CS1931: The range variable 'y10' conflicts with a previous declaration of 'y10' + // from y10 in new[] { 1 } + Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "y10").WithArguments("y10").WithLocation(86, 18), + // (90,17): error CS1931: The range variable 'y11' conflicts with a previous declaration of 'y11' + // let y11 = x1 + 1 + Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "y11").WithArguments("y11").WithLocation(90, 17) ); var tree = compilation.SyntaxTrees.Single(); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var y1Decl = GetOutVarDeclarations(tree, "y1").Single(); + var y1Ref = GetReferences(tree, "y1").ToArray(); + Assert.Equal(4, y1Ref.Length); + VerifyModelForOutVar(model, y1Decl, y1Ref); + + var y2Decl = GetOutVarDeclarations(tree, "y2").Single(); + var y2Ref = GetReferences(tree, "y2").ToArray(); + Assert.Equal(3, y2Ref.Length); + VerifyModelForOutVar(model, y2Decl, y2Ref); + + var z2Decl = GetOutVarDeclarations(tree, "z2").Single(); + var z2Ref = GetReferences(tree, "z2").ToArray(); + Assert.Equal(4, z2Ref.Length); + VerifyModelForOutVar(model, z2Decl, z2Ref[0], z2Ref[1]); + VerifyNotInScope(model, z2Ref[2]); + VerifyNotInScope(model, z2Ref[3]); + + var y3Decl = GetOutVarDeclarations(tree, "y3").Single(); + var y3Ref = GetReferences(tree, "y3").ToArray(); + Assert.Equal(3, y3Ref.Length); + VerifyModelForOutVar(model, y3Decl, y3Ref); + + var z3Decl = GetOutVarDeclarations(tree, "z3").Single(); + var z3Ref = GetReferences(tree, "z3").ToArray(); + Assert.Equal(3, z3Ref.Length); + VerifyModelForOutVar(model, z3Decl, z3Ref[0]); + VerifyNotInScope(model, z3Ref[1]); + VerifyNotInScope(model, z3Ref[2]); + + var y4Decl = GetOutVarDeclarations(tree, "y4").Single(); + var y4Ref = GetReferences(tree, "y4").ToArray(); + Assert.Equal(5, y4Ref.Length); + VerifyModelForOutVar(model, y4Decl, y4Ref); + + var z4Decl = GetOutVarDeclarations(tree, "z4").Single(); + var z4Ref = GetReferences(tree, "z4").ToArray(); + Assert.Equal(6, z4Ref.Length); + VerifyModelForOutVar(model, z4Decl, z4Ref); + + var u4Decl = GetOutVarDeclarations(tree, "u4").Single(); + var u4Ref = GetReferences(tree, "u4").ToArray(); + Assert.Equal(4, u4Ref.Length); + VerifyModelForOutVar(model, u4Decl, u4Ref[0]); + VerifyNotInScope(model, u4Ref[1]); + VerifyNotInScope(model, u4Ref[2]); + VerifyNotInScope(model, u4Ref[3]); + + var v4Decl = GetOutVarDeclarations(tree, "v4").Single(); + var v4Ref = GetReferences(tree, "v4").ToArray(); + Assert.Equal(4, v4Ref.Length); + VerifyNotInScope(model, v4Ref[0]); + VerifyModelForOutVar(model, v4Decl, v4Ref[1]); + VerifyNotInScope(model, v4Ref[2]); + VerifyNotInScope(model, v4Ref[3]); + + var y5Decl = GetOutVarDeclarations(tree, "y5").Single(); + var y5Ref = GetReferences(tree, "y5").ToArray(); + Assert.Equal(5, y5Ref.Length); + VerifyModelForOutVar(model, y5Decl, y5Ref); + + var z5Decl = GetOutVarDeclarations(tree, "z5").Single(); + var z5Ref = GetReferences(tree, "z5").ToArray(); + Assert.Equal(6, z5Ref.Length); + VerifyModelForOutVar(model, z5Decl, z5Ref); + + var u5Decl = GetOutVarDeclarations(tree, "u5").Single(); + var u5Ref = GetReferences(tree, "u5").ToArray(); + Assert.Equal(4, u5Ref.Length); + VerifyModelForOutVar(model, u5Decl, u5Ref[0]); + VerifyNotInScope(model, u5Ref[1]); + VerifyNotInScope(model, u5Ref[2]); + VerifyNotInScope(model, u5Ref[3]); + + var v5Decl = GetOutVarDeclarations(tree, "v5").Single(); + var v5Ref = GetReferences(tree, "v5").ToArray(); + Assert.Equal(4, v5Ref.Length); + VerifyNotInScope(model, v5Ref[0]); + VerifyModelForOutVar(model, v5Decl, v5Ref[1]); + VerifyNotInScope(model, v5Ref[2]); + VerifyNotInScope(model, v5Ref[3]); + + var y6Decl = GetOutVarDeclarations(tree, "y6").Single(); + var y6Ref = GetReferences(tree, "y6").ToArray(); + Assert.Equal(3, y6Ref.Length); + VerifyModelForOutVar(model, y6Decl, y6Ref); + + var z6Decl = GetOutVarDeclarations(tree, "z6").Single(); + var z6Ref = GetReferences(tree, "z6").ToArray(); + Assert.Equal(3, z6Ref.Length); + VerifyModelForOutVar(model, z6Decl, z6Ref[0]); + VerifyNotInScope(model, z6Ref[1]); + VerifyNotInScope(model, z6Ref[2]); + + var y7Decl = GetOutVarDeclarations(tree, "y7").Single(); + var y7Ref = GetReferences(tree, "y7").ToArray(); + Assert.Equal(4, y7Ref.Length); + VerifyModelForOutVar(model, y7Decl, y7Ref); + + var z7Decl = GetOutVarDeclarations(tree, "z7").Single(); + var z7Ref = GetReferences(tree, "z7").ToArray(); + Assert.Equal(4, z7Ref.Length); + VerifyModelForOutVar(model, z7Decl, z7Ref[0]); + VerifyNotInScope(model, z7Ref[1]); + VerifyNotInScope(model, z7Ref[2]); + VerifyNotInScope(model, z7Ref[3]); + + var u7Decl = GetOutVarDeclarations(tree, "u7").Single(); + var u7Ref = GetReferences(tree, "u7").ToArray(); + Assert.Equal(4, u7Ref.Length); + VerifyNotInScope(model, u7Ref[0]); + VerifyModelForOutVar(model, u7Decl, u7Ref[1]); + VerifyNotInScope(model, u7Ref[2]); + VerifyNotInScope(model, u7Ref[3]); + + var y8Decl = GetOutVarDeclarations(tree, "y8").Single(); + var y8Ref = GetReferences(tree, "y8").ToArray(); + Assert.Equal(2, y8Ref.Length); + VerifyModelForOutVar(model, y8Decl, y8Ref); + + var z8Decl = GetOutVarDeclarations(tree, "z8").Single(); + var z8Ref = GetReferences(tree, "z8").ToArray(); + Assert.Equal(2, z8Ref.Length); + VerifyModelForOutVar(model, z8Decl, z8Ref[0]); + VerifyNotInScope(model, z8Ref[1]); + + var y9Decl = GetOutVarDeclarations(tree, "y9").Single(); + var y9Ref = GetReferences(tree, "y9").ToArray(); + Assert.Equal(3, y9Ref.Length); + VerifyModelForOutVar(model, y9Decl, y9Ref); + + var z9Decl = GetOutVarDeclarations(tree, "z9").Single(); + var z9Ref = GetReferences(tree, "z9").ToArray(); + Assert.Equal(3, z9Ref.Length); + VerifyModelForOutVar(model, z9Decl, z9Ref[0]); + VerifyNotInScope(model, z9Ref[1]); + VerifyNotInScope(model, z9Ref[2]); + + var u9Decl = GetOutVarDeclarations(tree, "u9").Single(); + var u9Ref = GetReferences(tree, "u9").ToArray(); + Assert.Equal(3, u9Ref.Length); + VerifyNotInScope(model, u9Ref[0]); + VerifyModelForOutVar(model, u9Decl, u9Ref[1]); + VerifyNotInScope(model, u9Ref[2]); + + var y10Decl = GetOutVarDeclarations(tree, "y10").Single(); + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyModelForOutVar(model, y10Decl, y10Ref[0]); + VerifyNotAnOutLocal(model, y10Ref[1]); + + var y11Decl = GetOutVarDeclarations(tree, "y11").Single(); + var y11Ref = GetReferences(tree, "y11").ToArray(); + Assert.Equal(2, y11Ref.Length); + VerifyModelForOutVar(model, y11Decl, y11Ref[0]); + VerifyNotAnOutLocal(model, y11Ref[1]); } } @@ -24759,29 +25274,102 @@ static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_DuplicateNameInClass, - (int)ErrorCode.ERR_MemberAlreadyExists - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + compilation.VerifyDiagnostics( + // (15,41): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // using (Dummy(TakeOutParam(true, out var x4), x4)) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 41), + // (18,14): error CS0841: Cannot use local variable 'x6' before it is declared + // using (Dummy(x6 && TakeOutParam(true, out var x6))) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(18, 14), + // (23,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(23, 9), + // (30,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(30, 26), + // (35,45): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // using (Dummy(TakeOutParam(true, out var x9), x9)) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(35, 45), + // (39,27): error CS0103: The name 'y10' does not exist in the current context + // using (Dummy(TakeOutParam(y10, out var x10), x10)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(39, 27), + // (51,27): error CS0103: The name 'y12' does not exist in the current context + // using (Dummy(TakeOutParam(y12, out var x12), x12)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(51, 27), + // (52,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(52, 5), + // (52,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(52, 9), + // (58,41): error CS0128: A local variable or function named 'x14' is already defined in this scope + // TakeOutParam(2, out var x14), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(58, 41) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForOutVar(model, x2Decl, x2Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAnOutLocal(model, x4Ref[0]); + VerifyModelForOutVar(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForOutVar(model, x6Decl, x6Ref); + + var x7Decl = GetOutVarDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForOutVar(model, x7Decl, x7Ref[0]); + VerifyNotAnOutLocal(model, x7Ref[1]); + + var x8Decl = GetOutVarDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForOutVar(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForOutVar(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForOutVar(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var x10Decl = GetOutVarDeclarations(tree, "x10").Single(); + var x10Ref = GetReferences(tree, "x10").Single(); + VerifyModelForOutVar(model, x10Decl, x10Ref); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAnOutLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetOutVarDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForOutVar(model, x14Decl[0], x14Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x14Decl[1]); } } @@ -24860,7 +25448,7 @@ public void GlobalCode_ExpressionStatement_01() H.Dummy(H.TakeOutParam(41, out int x4), H.TakeOutParam(42, out int x4)); - +Test(); void Test() { H.Dummy(x1, x2, x3, x4); @@ -24924,42 +25512,48 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,27): error CS0102: The type '' already contains a definition for 'x2' - // H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 27), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,36): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 36), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (6,27): error CS0128: A local variable or function named 'x2' is already defined in this scope + // H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 27), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,36): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 36), + // (13,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(13, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -24984,7 +25578,7 @@ public void GlobalCode_ExpressionStatement_02() H.Dummy(H.TakeOutParam(41, out var x4), H.TakeOutParam(42, out var x4)); - +Test(); void Test() { H.Dummy(x1, x2, x3, x4); @@ -25048,43 +25642,48 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,27): error CS0102: The type '' already contains a definition for 'x2' - // H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 27), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,36): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 36), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (6,27): error CS0128: A local variable or function named 'x2' is already defined in this scope + // H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 27), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,36): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 36), + // (13,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(13, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -25163,6 +25762,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -25228,51 +25829,64 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,31): error CS0102: The type '' already contains a definition for 'x2' - // if (H.TakeOutParam(2, out int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 31), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,40): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 40), - // (16,37): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 37), - // (24,12): error CS0102: The type '' already contains a definition for 'x6' - // string x6 = "6"; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x6").WithArguments("", "x6").WithLocation(24, 12), - // (30,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(30, 13), - // (30,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(30, 17), - // (30,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(30, 21), - // (30,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(30, 25), - // (30,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(30, 29) + compilation.VerifyDiagnostics( + // (6,31): error CS0128: A local variable or function named 'x2' is already defined in this scope + // if (H.TakeOutParam(2, out int x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 31), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,40): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 40), + // (16,37): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 37), + // (21,5): warning CS0219: The variable 'x6' is assigned but its value is never used + // int x6 = 6; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x6").WithArguments("x6").WithLocation(21, 5), + // (24,12): error CS0136: A local or parameter named 'x6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // string x6 = "6"; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x6").WithArguments("x6").WithLocation(24, 12), + // (33,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(33, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); } } @@ -25305,6 +25919,8 @@ void Test() } H.Dummy(x5); +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -25370,49 +25986,61 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,31): error CS0102: The type '' already contains a definition for 'x2' - // if (H.TakeOutParam(2, out var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 31), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,40): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 40), - // (21,34): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(21, 34), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25), - // (16,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(16, 29) + compilation.VerifyDiagnostics( + // (6,31): error CS0128: A local variable or function named 'x2' is already defined in this scope + // if (H.TakeOutParam(2, out var x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 31), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,40): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 40), + // (16,29): error CS0841: Cannot use local variable 'x5' before it is declared + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x5").WithArguments("x5").WithLocation(16, 29), + // (21,34): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(21, 34), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[0], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[1]); } } @@ -25532,6 +26160,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -25602,42 +26232,51 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,40): error CS0102: The type '' already contains a definition for 'x2' - // yield return H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 40), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,49): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 49), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // yield return H.TakeOutParam(1, out int x1); + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "yield return H.TakeOutParam(1, out int x1);").WithArguments("", "void").WithLocation(2, 1), + // (6,40): error CS0128: A local variable or function named 'x2' is already defined in this scope + // yield return H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 40), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,49): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 49), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -25663,6 +26302,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -25734,43 +26375,51 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,40): error CS0102: The type '' already contains a definition for 'x2' - // yield return H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 40), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,49): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 49), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // yield return H.TakeOutParam(1, out var x1); + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "yield return H.TakeOutParam(1, out var x1);").WithArguments("", "void").WithLocation(2, 1), + // (6,40): error CS0128: A local variable or function named 'x2' is already defined in this scope + // yield return H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 40), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,49): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 49), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -25857,42 +26506,64 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,34): error CS0102: The type '' already contains a definition for 'x2' - // return H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 34), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,43): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 43), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(1, out int x1); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(1, out int x1)").WithArguments("bool", "int").WithLocation(2, 8), + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(2, out int x2)").WithArguments("bool", "int").WithLocation(6, 8), + // (6,34): error CS0128: A local variable or function named 'x2' is already defined in this scope + // return H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 34), + // (8,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(3, out int x3); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(3, out int x3)").WithArguments("bool", "int").WithLocation(8, 8), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.Dummy(H.TakeOutParam(41, out int x4), + Diagnostic(ErrorCode.ERR_NoImplicitConv, @"H.Dummy(H.TakeOutParam(41, out int x4), + H.TakeOutParam(42, out int x4))").WithArguments("bool", "int").WithLocation(11, 8), + // (12,43): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 43), + // (14,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(14, 6) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -25979,43 +26650,64 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,34): error CS0102: The type '' already contains a definition for 'x2' - // return H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 34), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,43): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 43), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(1, out var x1); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(1, out var x1)").WithArguments("bool", "int").WithLocation(2, 8), + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(2, out var x2)").WithArguments("bool", "int").WithLocation(6, 8), + // (6,34): error CS0128: A local variable or function named 'x2' is already defined in this scope + // return H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 34), + // (8,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.TakeOutParam(3, out var x3); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "H.TakeOutParam(3, out var x3)").WithArguments("bool", "int").WithLocation(8, 8), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,8): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return H.Dummy(H.TakeOutParam(41, out var x4), + Diagnostic(ErrorCode.ERR_NoImplicitConv, @"H.Dummy(H.TakeOutParam(41, out var x4), + H.TakeOutParam(42, out var x4))").WithArguments("bool", "int").WithLocation(11, 8), + // (12,43): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 43), + // (14,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(14, 6) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -26086,6 +26778,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static System.Exception Dummy(params object[] x) {return null;} @@ -26147,42 +26841,48 @@ public static System.Exception TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,33): error CS0102: The type '' already contains a definition for 'x2' - // throw H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 33), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,42): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 42), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,33): error CS0128: A local variable or function named 'x2' is already defined in this scope + // throw H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 33), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,42): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 42) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -26208,6 +26908,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static System.Exception Dummy(params object[] x) {return null;} @@ -26270,43 +26972,48 @@ public static System.Exception TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,33): error CS0102: The type '' already contains a definition for 'x2' - // throw H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 33), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,42): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 42), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,33): error CS0128: A local variable or function named 'x2' is already defined in this scope + // throw H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 33), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,42): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 42) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -26341,6 +27048,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -26406,48 +27115,58 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,35): error CS0102: The type '' already contains a definition for 'x2' - // switch (H.TakeOutParam(2, out int x2)) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 35), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,44): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4))) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 44), - // (17,37): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(17, 37), - // (25,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(25, 13), - // (25,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(25, 17), - // (25,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(25, 21), - // (25,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(25, 25), - // (25,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(25, 29) + compilation.VerifyDiagnostics( + // (6,35): error CS0128: A local variable or function named 'x2' is already defined in this scope + // switch (H.TakeOutParam(2, out int x2)) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 35), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,44): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4))) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 44), + // (17,37): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(17, 37), + // (28,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(28, 1), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); } } @@ -26482,6 +27201,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -26526,91 +27247,80 @@ public static bool TakeOutParam(T y, out T x) var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); + VerifyModelForOutFieldDuplicate(model, x2Decl, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); + VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutField(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); + } + + { + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,35): error CS0128: A local variable or function named 'x2' is already defined in this scope + // switch (H.TakeOutParam(2, out var x2)) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 35), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,44): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4))) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 44), + // (17,34): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(17, 34), + // (28,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(28, 1), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutFieldDuplicate(model, x3Decl, x3Ref); + VerifyModelForOutVar(model, x3Decl, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForOutFieldDuplicate(model, x4Decl[0], x4Ref); - VerifyModelForOutFieldDuplicate(model, x4Decl[1], x4Ref); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); var x5Ref = GetReferences(tree, "x5").ToArray(); Assert.Equal(2, x5Decl.Length); Assert.Equal(3, x5Ref.Length); - VerifyModelForOutField(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[1], x5Ref[2]); VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); } - - { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,35): error CS0102: The type '' already contains a definition for 'x2' - // switch (H.TakeOutParam(2, out var x2)) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 35), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,44): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4))) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 44), - // (17,34): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(17, 34), - // (6,31): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.TakeOutParam(2, out var x2)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(6, 31), - // (8,31): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.TakeOutParam(3, out var x3)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(8, 31), - // (11,40): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.Dummy(H.TakeOutParam(41, out var x4), - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(11, 40), - // (12,40): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // H.TakeOutParam(42, out var x4))) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(12, 40), - // (14,32): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.TakeOutParam(51, out var x5)) - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(14, 32), - // (17,30): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // H.TakeOutParam("52", out var x5); - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(17, 30), - // (2,31): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.TakeOutParam(1, out var x1)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(2, 31), - // (25,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(25, 13), - // (25,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(25, 17), - // (25,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(25, 21), - // (25,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(25, 25), - // (25,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(25, 29) - ); - - var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); - } } [Fact] @@ -26765,48 +27475,76 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,34): error CS0102: The type '' already contains a definition for 'x2' - // while (H.TakeOutParam(2, out int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 34), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,43): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 43), - // (16,37): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 37), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,34): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while (H.TakeOutParam(2, out int x2)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 34), + // (8,34): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while (H.TakeOutParam(3, out int x3)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 34), + // (12,43): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 43), + // (16,37): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 37), + // (19,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 9), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyNotAnOutLocal(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -26914,49 +27652,76 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,34): error CS0102: The type '' already contains a definition for 'x2' - // while (H.TakeOutParam(2, out var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 34), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,43): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 43), - // (16,34): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 34), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,34): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while (H.TakeOutParam(2, out var x2)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 34), + // (8,34): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while (H.TakeOutParam(3, out var x3)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 34), + // (12,43): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 43), + // (16,34): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 34), + // (19,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 9), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyNotAnOutLocal(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -27100,48 +27865,76 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,40): error CS0102: The type '' already contains a definition for 'x2' - // do {} while (H.TakeOutParam(2, out int x2)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 40), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,49): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4))); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 49), - // (19,35): error CS0102: The type '' already contains a definition for 'x5' - // while (H.TakeOutParam(51, out int x5)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(19, 35), - // (24,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), - // (24,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(24, 17), - // (24,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(24, 21), - // (24,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), - // (24,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,40): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while (H.TakeOutParam(2, out int x2)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 40), + // (8,40): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while (H.TakeOutParam(3, out int x3)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 40), + // (12,49): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4))); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 49), + // (16,37): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 37), + // (20,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 9), + // (22,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(22, 6), + // (24,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), + // (24,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), + // (24,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyNotAnOutLocal(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[0]); + VerifyModelForOutVar(model, x5Decl[1]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -27250,49 +28043,76 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,40): error CS0102: The type '' already contains a definition for 'x2' - // do {} while (H.TakeOutParam(2, out var x2)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 40), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,49): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4))); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 49), - // (19,35): error CS0102: The type '' already contains a definition for 'x5' - // while (H.TakeOutParam(51, out var x5)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(19, 35), - // (24,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), - // (24,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(24, 17), - // (24,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(24, 21), - // (24,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), - // (24,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,40): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while (H.TakeOutParam(2, out var x2)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 40), + // (8,40): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while (H.TakeOutParam(3, out var x3)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 40), + // (12,49): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4))); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 49), + // (16,34): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 34), + // (20,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 9), + // (22,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(22, 6), + // (24,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), + // (24,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), + // (24,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVar(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl); + VerifyNotAnOutLocal(model, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[0]); + VerifyModelForOutVar(model, x5Decl[1]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -27370,6 +28190,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static object Dummy(params object[] x) {return true;} @@ -27435,48 +28257,58 @@ public static object TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,33): error CS0102: The type '' already contains a definition for 'x2' - // lock (H.TakeOutParam(2, out int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 33), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,42): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 42), - // (16,37): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 37), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + compilation.VerifyDiagnostics( + // (6,33): error CS0128: A local variable or function named 'x2' is already defined in this scope + // lock (H.TakeOutParam(2, out int x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 33), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,42): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 42), + // (16,37): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 37), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); - var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); } } @@ -27509,6 +28341,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static object Dummy(params object[] x) {return true;} @@ -27574,49 +28408,58 @@ public static object TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,33): error CS0102: The type '' already contains a definition for 'x2' - // lock (H.TakeOutParam(2, out var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 33), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,42): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 42), - // (16,34): error CS0102: The type '' already contains a definition for 'x5' - // H.TakeOutParam("52", out var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 34), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + compilation.VerifyDiagnostics( + // (6,33): error CS0128: A local variable or function named 'x2' is already defined in this scope + // lock (H.TakeOutParam(2, out var x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 33), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,42): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 42), + // (16,34): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.TakeOutParam("52", out var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 34), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForOutVar(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForOutVar(model, x5Decl[1], x5Ref[0]); } } @@ -27734,7 +28577,7 @@ public void GlobalCode_DeconstructionDeclarationStatement_01() (bool x5, bool x6) = (H.TakeOutParam(5, out int x5), H.TakeOutParam(6, out int x6)); - +Test(); void Test() { H.Dummy(x1, x2, x3, x4, x5, x6); @@ -27821,48 +28664,67 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,46): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = (H.TakeOutParam(2, out int x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 46), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,48): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 48), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) + compilation.VerifyDiagnostics( + // (6,46): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = (H.TakeOutParam(2, out int x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 46), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,48): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 48), + // (14,49): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = (H.TakeOutParam(5, out int x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 49), + // (15,49): error CS0128: A local variable or function named 'x6' is already defined in this scope + // H.TakeOutParam(6, out int x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 49), + // (16,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(16, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(1, x5Ref.Length); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref[0]); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(1, x6Ref.Length); + VerifyModelForOutVarDuplicateInSameScope(model, x6Decl); + VerifyNotAnOutLocal(model, x6Ref[0]); } } @@ -27888,6 +28750,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -27958,42 +28822,60 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,30): error CS0102: The type '' already contains a definition for 'x2' - // b: H.TakeOutParam(2, out int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 30), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,39): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 39), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: H.TakeOutParam(1, out int x1); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // b: H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "b").WithLocation(6, 1), + // (6,30): error CS0128: A local variable or function named 'x2' is already defined in this scope + // b: H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 30), + // (8,1): warning CS0164: This label has not been referenced + // c: H.TakeOutParam(3, out int x3); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(8, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,1): warning CS0164: This label has not been referenced + // d: H.Dummy(H.TakeOutParam(41, out int x4), + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "d").WithLocation(11, 1), + // (12,39): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 39), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -28019,6 +28901,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -28089,43 +28973,60 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,30): error CS0102: The type '' already contains a definition for 'x2' - // b: H.TakeOutParam(2, out var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 30), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,39): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 39), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: H.TakeOutParam(1, out var x1); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // b: H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "b").WithLocation(6, 1), + // (6,30): error CS0128: A local variable or function named 'x2' is already defined in this scope + // b: H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 30), + // (8,1): warning CS0164: This label has not been referenced + // c: H.TakeOutParam(3, out var x3); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(8, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,1): warning CS0164: This label has not been referenced + // d: H.Dummy(H.TakeOutParam(41, out var x4), + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "d").WithLocation(11, 1), + // (12,39): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 39), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); } } @@ -28204,6 +29105,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -28282,34 +29185,42 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), + // (7,36): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 36), + // (8,1): warning CS0164: This label has not been referenced + // e: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (11,1): warning CS0164: This label has not been referenced + // g: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), + // (13,45): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), + // (14,1): warning CS0164: This label has not been referenced + // i: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), + // (15,37): error CS0128: A local variable or function named 'x5' is already defined in this scope + // bool x5 = H.TakeOutParam(5, out int x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(15, 37), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -28318,31 +29229,29 @@ public static bool TakeOutParam(T y, out T x) var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForOutVar(model, x1Decl, x1Ref); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForOutVar(model, x3Decl, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").ToArray(); Assert.Equal(2, x5Ref.Length); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref[0]); + VerifyNotAnOutLocal(model, x5Ref[1]); } } @@ -28372,6 +29281,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -28450,34 +29361,42 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), + // (7,36): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 36), + // (8,1): warning CS0164: This label has not been referenced + // e: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (11,1): warning CS0164: This label has not been referenced + // g: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), + // (13,45): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), + // (14,1): warning CS0164: This label has not been referenced + // i: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), + // (15,37): error CS0128: A local variable or function named 'x5' is already defined in this scope + // bool x5 = H.TakeOutParam(5, out var x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(15, 37), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -28486,36 +29405,34 @@ public static bool TakeOutParam(T y, out T x) var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForOutVar(model, x1Decl, x1Ref); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForOutVar(model, x3Decl, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").ToArray(); Assert.Equal(2, x5Ref.Length); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref[0]); + VerifyNotAnOutLocal(model, x5Ref[1]); } } [ConditionalFact(typeof(IsRelease), Reason = "https://github.com/dotnet/roslyn/issues/25702")] - public void GlobalCode_LabeledStatement_06() + public void GlobalCode_LabeledStatement_06_Script() { string source = @" @@ -28564,6 +29481,54 @@ public static bool TakeOutParam(T y, out T x) VerifyModelForOutField(model, x1Decl, x1Ref); } + [Fact] + public void GlobalCode_LabeledStatement_06_SimpleProgram() + { + string source = +@" + +a:b:c: +var d = H.TakeOutParam(1, out var x1); +Test(); + +void Test() +{ + System.Console.WriteLine(x1); +} + +class H +{ + public static bool TakeOutParam(T y, out T x) + { + x = y; + return true; + } +} +"; + + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); + + CompileAndVerify(compilation, expectedOutput: +@"1").VerifyDiagnostics( + // (3,1): warning CS0164: This label has not been referenced + // a:b:c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(3, 1), + // (3,3): warning CS0164: This label has not been referenced + // a:b:c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "b").WithLocation(3, 3), + // (3,5): warning CS0164: This label has not been referenced + // a:b:c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(3, 5) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").Single(); + VerifyModelForOutVar(model, x1Decl, x1Ref); + } + [Fact] [CompilerTrait(CompilerFeature.Tuples)] public void GlobalCode_LabeledStatement_07() @@ -28590,6 +29555,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -28686,48 +29653,80 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,46): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = (H.TakeOutParam(2, out int x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 46), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,48): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 48), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) + compilation.VerifyDiagnostics( + // (1,1): warning CS0164: This label has not been referenced + // l1: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1), + // (5,1): warning CS0164: This label has not been referenced + // l2: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l2").WithLocation(5, 1), + // (6,46): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = (H.TakeOutParam(2, out int x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 46), + // (7,1): warning CS0164: This label has not been referenced + // l3: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l3").WithLocation(7, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (10,1): warning CS0164: This label has not been referenced + // l4: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l4").WithLocation(10, 1), + // (12,48): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 48), + // (13,1): warning CS0164: This label has not been referenced + // l5: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l5").WithLocation(13, 1), + // (14,49): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = (H.TakeOutParam(5, out int x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 49), + // (15,49): error CS0128: A local variable or function named 'x6' is already defined in this scope + // H.TakeOutParam(6, out int x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 49), + // (22,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(22, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x6Decl); + VerifyNotAnOutLocal(model, x6Ref); } } @@ -28757,6 +29756,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -28853,49 +29854,80 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,46): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = (H.TakeOutParam(2, out var x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 46), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,48): error CS0102: The type '' already contains a definition for 'x4' - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 48), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) + compilation.VerifyDiagnostics( + // (1,1): warning CS0164: This label has not been referenced + // l1: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1), + // (5,1): warning CS0164: This label has not been referenced + // l2: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l2").WithLocation(5, 1), + // (6,46): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = (H.TakeOutParam(2, out var x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 46), + // (7,1): warning CS0164: This label has not been referenced + // l3: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l3").WithLocation(7, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (10,1): warning CS0164: This label has not been referenced + // l4: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l4").WithLocation(10, 1), + // (12,48): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 48), + // (13,1): warning CS0164: This label has not been referenced + // l5: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l5").WithLocation(13, 1), + // (14,49): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = (H.TakeOutParam(5, out var x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 49), + // (15,49): error CS0128: A local variable or function named 'x6' is already defined in this scope + // H.TakeOutParam(6, out var x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 49), + // (22,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(22, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetOutVarDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForOutVar(model, x1Decl, x1Ref); + + var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); + + var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForOutVar(model, x3Decl, x3Ref); + + var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref); + + var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").Single(); + VerifyModelForOutVarDuplicateInSameScope(model, x6Decl); + VerifyNotAnOutLocal(model, x6Ref); } } @@ -28980,6 +30012,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -29058,37 +30092,33 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + compilation.VerifyDiagnostics( + // (7,36): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 36), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (13,45): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), + // (16,37): error CS0128: A local variable or function named 'x5' is already defined in this scope + // H.TakeOutParam(5, out int x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(16, 37), + // (19,10): error CS0128: A local variable or function named 'x6' is already defined in this scope + // x6; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(19, 10), + // (19,10): warning CS0168: The variable 'x6' is declared but never used + // x6; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x6").WithArguments("x6").WithLocation(19, 10), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -29097,35 +30127,31 @@ public static bool TakeOutParam(T y, out T x) var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForOutVar(model, x1Decl, x1Ref); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForOutVar(model, x3Decl, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref); var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); - VerifyModelForOutVar(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyModelForOutVar(model, x6Decl, x6Ref); } } @@ -29158,6 +30184,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -29236,37 +30264,33 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,45): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + compilation.VerifyDiagnostics( + // (7,36): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 36), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (13,45): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 45), + // (16,37): error CS0128: A local variable or function named 'x5' is already defined in this scope + // H.TakeOutParam(5, out var x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(16, 37), + // (19,10): error CS0128: A local variable or function named 'x6' is already defined in this scope + // x6; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(19, 10), + // (19,10): warning CS0168: The variable 'x6' is declared but never used + // x6; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x6").WithArguments("x6").WithLocation(19, 10), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -29275,35 +30299,31 @@ public static bool TakeOutParam(T y, out T x) var x1Decl = GetOutVarDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForOutVar(model, x1Decl, x1Ref); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x2Decl); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForOutVar(model, x3Decl, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForOutVar(model, x4Decl[0]); + VerifyModelForOutVar(model, x4Decl[0], x4Ref); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForOutVarDuplicateInSameScope(model, x5Decl); + VerifyNotAnOutLocal(model, x5Ref); var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); - VerifyModelForOutVar(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyModelForOutVar(model, x6Decl, x6Ref); } } @@ -29559,6 +30579,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -29627,34 +30649,45 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,54): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + compilation.VerifyDiagnostics( + // (3,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool b { get; } = H.TakeOutParam(1, out int x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 6), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool d { get; } = H.TakeOutParam(2, out int x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 6), + // (9,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool f { get; } = H.TakeOutParam(3, out int x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 6), + // (12,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool h { get; } = H.Dummy(H.TakeOutParam(41, out int x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 6), + // (13,54): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), + // (15,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool x5 { get; } = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 6), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1), + // (23,1): error CS0165: Use of unassigned local variable 'x3' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x3").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -29664,29 +30697,30 @@ public static bool TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAnOutLocal(model, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForOutVar(model, x4Decl[0]); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); } } @@ -29716,6 +30750,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -29784,34 +30820,45 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,54): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + compilation.VerifyDiagnostics( + // (3,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool b { get; } = H.TakeOutParam(1, out var x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 6), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool d { get; } = H.TakeOutParam(2, out var x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 6), + // (9,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool f { get; } = H.TakeOutParam(3, out var x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 6), + // (12,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool h { get; } = H.Dummy(H.TakeOutParam(41, out var x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 6), + // (13,54): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 54), + // (15,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool x5 { get; } = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 6), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1), + // (23,1): error CS0165: Use of unassigned local variable 'x3' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x3").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -29821,29 +30868,30 @@ public static bool TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAnOutLocal(model, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForOutVar(model, x4Decl[0]); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); } } @@ -30136,37 +31184,31 @@ public static System.Action TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + int[] exclude = new int[] { (int)ErrorCode.ERR_NamespaceUnexpected }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,52): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (13,52): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), + // (23,33): error CS0103: The name 'x6' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) ); var tree = compilation.SyntaxTrees.Single(); @@ -30176,34 +31218,35 @@ public static System.Action TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAnOutLocal(model, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForOutVar(model, x4Decl[0]); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); VerifyModelForOutVar(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyNotInScope(model, x6Ref); } } @@ -30314,37 +31357,31 @@ public static System.Action TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + int[] exclude = new int[] { (int)ErrorCode.ERR_NamespaceUnexpected }; compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,52): error CS0128: A local variable named 'x4' is already defined in this scope - // H.TakeOutParam(42, out var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (13,52): error CS0128: A local variable or function named 'x4' is already defined in this scope + // H.TakeOutParam(42, out var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 52), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), + // (23,33): error CS0103: The name 'x6' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) ); var tree = compilation.SyntaxTrees.Single(); @@ -30354,34 +31391,35 @@ public static System.Action TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForOutVar(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetOutVarDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForOutVar(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAnOutLocal(model, x2Ref); var x3Decl = GetOutVarDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForOutVar(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAnOutLocal(model, x3Ref); var x4Decl = GetOutVarDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForOutVar(model, x4Decl[0]); VerifyModelForOutVarDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetOutVarDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForOutVar(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); var x6Decl = GetOutVarDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); VerifyModelForOutVar(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyNotInScope(model, x6Ref); } } @@ -30664,28 +31702,27 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // bool a, b(out var x1); - Diagnostic(ErrorCode.ERR_BadVarDecl, "(out var x1").WithLocation(3, 10), - // (3,10): error CS1003: Syntax error, '[' expected - // bool a, b(out var x1); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), - // (3,21): error CS1003: Syntax error, ']' expected - // bool a, b(out var x1); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 21), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + compilation.VerifyDiagnostics( + // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // bool a, b(out var x1); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(out var x1").WithLocation(3, 10), + // (3,10): error CS1003: Syntax error, '[' expected + // bool a, b(out var x1); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), + // (3,21): error CS1003: Syntax error, ']' expected + // bool a, b(out var x1); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 21), + // (3,6): warning CS0168: The variable 'a' is declared but never used + // bool a, b(out var x1); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(3, 6), + // (3,9): warning CS0168: The variable 'b' is declared but never used + // bool a, b(out var x1); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(3, 9), + // (6,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(6, 6) ); var tree = compilation.SyntaxTrees.Single(); @@ -30695,7 +31732,7 @@ public static bool TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelForOutVarInNotExecutableCode(model, x1Decl, x1Ref); } } @@ -30752,28 +31789,33 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // bool a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.TakeOutParam(1, out var x1)").WithLocation(3, 10), - // (3,10): error CS1003: Syntax error, '[' expected - // bool a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), - // (3,40): error CS1003: Syntax error, ']' expected - // bool a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 40), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + compilation.VerifyDiagnostics( + // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // bool a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.TakeOutParam(1, out var x1)").WithLocation(3, 10), + // (3,10): error CS1003: Syntax error, '[' expected + // bool a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), + // (3,40): error CS1003: Syntax error, ']' expected + // bool a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 40), + // (2,1): warning CS0164: This label has not been referenced + // label: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "label").WithLocation(2, 1), + // (4,9): error CS0165: Use of unassigned local variable 'x1' + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(4, 9), + // (3,6): warning CS0168: The variable 'a' is declared but never used + // bool a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(3, 6), + // (3,9): warning CS0168: The variable 'b' is declared but never used + // bool a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(3, 9), + // (6,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(6, 6) ); var tree = compilation.SyntaxTrees.Single(); @@ -30783,7 +31825,7 @@ public static bool TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelForOutVarInNotExecutableCode(model, x1Decl, x1Ref); } } @@ -30837,28 +31879,27 @@ public static bool TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,25): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // event System.Action a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.TakeOutParam(1, out var x1)").WithLocation(3, 25), - // (3,25): error CS1003: Syntax error, '[' expected - // event System.Action a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 25), - // (3,55): error CS1003: Syntax error, ']' expected - // event System.Action a, b(H.TakeOutParam(1, out var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 55), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + compilation.VerifyDiagnostics( + // (3,25): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // event System.Action a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.TakeOutParam(1, out var x1)").WithLocation(3, 25), + // (3,25): error CS1003: Syntax error, '[' expected + // event System.Action a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 25), + // (3,55): error CS1003: Syntax error, ']' expected + // event System.Action a, b(H.TakeOutParam(1, out var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 55), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (6,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(6, 6), + // (8,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) ); var tree = compilation.SyntaxTrees.Single(); @@ -30868,7 +31909,9 @@ public static bool TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelNotSupported(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); } } @@ -30926,31 +31969,33 @@ public static int TakeOutParam(T y, out T x) } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,18): error CS1642: Fixed size buffer fields may only be members of structs - // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; - Diagnostic(ErrorCode.ERR_FixedNotInStruct, "b").WithLocation(3, 18), - // (3,20): error CS0133: The expression being assigned to '.b' must be constant - // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; - Diagnostic(ErrorCode.ERR_NotConstantExpression, "H.TakeOutParam(1, out var x1)").WithArguments(".b").WithLocation(3, 20), - // (3,12): error CS1642: Fixed size buffer fields may only be members of structs - // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; - Diagnostic(ErrorCode.ERR_FixedNotInStruct, "a").WithLocation(3, 12), - // (3,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context - // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; - Diagnostic(ErrorCode.ERR_UnsafeNeeded, "a[2]").WithLocation(3, 12), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + compilation.VerifyDiagnostics( + // (3,12): error CS0116: A namespace cannot directly contain members such as fields or methods + // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "a").WithLocation(3, 12), + // (3,18): error CS1642: Fixed size buffer fields may only be members of structs + // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; + Diagnostic(ErrorCode.ERR_FixedNotInStruct, "b").WithLocation(3, 18), + // (3,20): error CS0133: The expression being assigned to '.b' must be constant + // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; + Diagnostic(ErrorCode.ERR_NotConstantExpression, "H.TakeOutParam(1, out var x1)").WithArguments(".b").WithLocation(3, 20), + // (3,12): error CS1642: Fixed size buffer fields may only be members of structs + // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; + Diagnostic(ErrorCode.ERR_FixedNotInStruct, "a").WithLocation(3, 12), + // (3,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // fixed bool a[2], b[H.TakeOutParam(1, out var x1)]; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "a[2]").WithLocation(3, 12), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (8,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13), + // (6,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(6, 6) ); var tree = compilation.SyntaxTrees.Single(); @@ -30960,7 +32005,9 @@ public static int TakeOutParam(T y, out T x) var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelNotSupported(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTestBase.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTestBase.cs index c16c478d893c3..8419db67dd2b5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTestBase.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTestBase.cs @@ -173,7 +173,7 @@ protected static void VerifyModelForDuplicateVariableDeclarationInSameScope(Sema internal static void VerifyModelForDuplicateVariableDeclarationInSameScope( SemanticModel model, SingleVariableDesignationSyntax designation, - LocalDeclarationKind kind) + LocalDeclarationKind kind = LocalDeclarationKind.PatternVariable) { var symbol = model.GetDeclaredSymbol(designation); Assert.Equal(designation.Identifier.ValueText, symbol.Name); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs index 373049206ee32..b441ec079f967 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Global.cs @@ -18,6 +18,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class PatternMatchingTests_Global : PatternMatchingTestBase { + [Fact] public void GlobalCode_ExpressionStatement_01() { @@ -40,6 +41,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -93,41 +96,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // H.Dummy(2 is int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,20): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 20), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,18): error CS0128: A local variable or function named 'x2' is already defined in this scope + // H.Dummy(2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 18), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,20): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 20), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDuplicateVariableDeclarationInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDuplicateVariableDeclarationInSameScope(model, x4Decl[1]); } } @@ -153,6 +163,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -206,42 +218,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // H.Dummy(2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,20): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 20), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,18): error CS0128: A local variable or function named 'x2' is already defined in this scope + // H.Dummy(2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 18), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,20): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 20), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDuplicateVariableDeclarationInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDuplicateVariableDeclarationInSameScope(model, x4Decl[1]); } } @@ -315,6 +333,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -375,50 +395,64 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,15): error CS0102: The type '' already contains a definition for 'x2' - // if ((2 is int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 15), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,24): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 24), - // (16,28): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 28), - // (24,12): error CS0102: The type '' already contains a definition for 'x6' - // string x6 = "6"; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x6").WithArguments("", "x6").WithLocation(24, 12), - // (30,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(30, 13), - // (30,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(30, 17), - // (30,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(30, 21), - // (30,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(30, 25), - // (30,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(30, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,15): error CS0128: A local variable or function named 'x2' is already defined in this scope + // if ((2 is int x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 15), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,24): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 24), + // (16,28): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 28), + // (21,5): warning CS0219: The variable 'x6' is assigned but its value is never used + // int x6 = 6; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x6").WithArguments("x6").WithLocation(21, 5), + // (24,12): error CS0136: A local or parameter named 'x6' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // string x6 = "6"; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x6").WithArguments("x6").WithLocation(24, 12), + // (33,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(33, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); } } @@ -451,6 +485,8 @@ void Test() } H.Dummy(x5); +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -511,48 +547,61 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,15): error CS0102: The type '' already contains a definition for 'x2' - // if ((2 is var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 15), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,24): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 24), - // (21,25): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(21, 25), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25), - // (16,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(16, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,15): error CS0128: A local variable or function named 'x2' is already defined in this scope + // if ((2 is var x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 15), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,24): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 24), + // (16,29): error CS0841: Cannot use local variable 'x5' before it is declared + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x5").WithArguments("x5").WithLocation(16, 29), + // (21,25): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(21, 25), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[0], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[1]); } } @@ -661,6 +710,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -726,41 +777,51 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // yield return (2 is int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,33): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 33), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // yield return (1 is int x1); + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "yield return (1 is int x1);").WithArguments("", "void").WithLocation(2, 1), + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // yield return (2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,33): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 33), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -786,6 +847,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -852,42 +915,51 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // yield return (2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,33): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 33), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // yield return (1 is var x1); + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "yield return (1 is var x1);").WithArguments("", "void").WithLocation(2, 1), + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // yield return (2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,33): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 33), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -969,41 +1041,57 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // return (2 is int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,27): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 27), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,9): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return (1 is int x1); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1 is int x1").WithArguments("bool", "int").WithLocation(2, 9), + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,18): error CS0128: A local variable or function named 'x2' is already defined in this scope + // return (2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 18), + // (8,9): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return (3 is int x3); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "3 is int x3").WithArguments("bool", "int").WithLocation(8, 9), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,27): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 27), + // (14,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(14, 6) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -1085,50 +1173,65 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // return (2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,27): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 27), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,9): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return (1 is var x1); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1 is var x1").WithArguments("bool", "int").WithLocation(2, 9), + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,18): error CS0128: A local variable or function named 'x2' is already defined in this scope + // return (2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 18), + // (8,9): error CS0029: Cannot implicitly convert type 'bool' to 'int' + // return (3 is var x3); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "3 is var x3").WithArguments("bool", "int").WithLocation(8, 9), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,27): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 27), + // (14,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(14, 6) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - } - } + var model = compilation.GetSemanticModel(tree); - [Fact] - public void GlobalCode_ReturnStatement_03() - { - string source = -@" + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + } + } + + [Fact] + public void GlobalCode_ReturnStatement_03() + { + string source = +@" System.Console.WriteLine(x1); Test(); return H.Dummy((1 is var x1), x1); @@ -1186,6 +1289,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static System.Exception Dummy(params object[] x) {return null;} @@ -1242,41 +1347,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // throw H.Dummy(2 is int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,26): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 26), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // throw H.Dummy(2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,26): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 26) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -1302,6 +1414,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static System.Exception Dummy(params object[] x) {return null;} @@ -1359,42 +1473,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // throw H.Dummy(2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,26): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 26), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,1): warning CS0162: Unreachable code detected + // H.Dummy(x1); + Diagnostic(ErrorCode.WRN_UnreachableCode, "H").WithLocation(3, 1), + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // throw H.Dummy(2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,26): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 26) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -1429,6 +1549,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -1489,47 +1611,58 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,19): error CS0102: The type '' already contains a definition for 'x2' - // switch ((2 is int x2)) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 19), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,28): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4))) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 28), - // (17,28): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(17, 28), - // (25,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(25, 13), - // (25,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(25, 17), - // (25,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(25, 21), - // (25,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(25, 25), - // (25,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(25, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,19): error CS0128: A local variable or function named 'x2' is already defined in this scope + // switch ((2 is int x2)) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 19), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,28): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4))) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 28), + // (17,28): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(17, 28), + // (28,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(28, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); } } @@ -1563,6 +1696,9 @@ void Test() { H.Dummy(x1, x2, x3, x4, x5); } + +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -1623,68 +1759,58 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,19): error CS0102: The type '' already contains a definition for 'x2' - // switch ((2 is var x2)) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 19), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,28): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4))) {default: break;} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 28), - // (17,25): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(17, 25), - // (6,15): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch ((2 is var x2)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(6, 15), - // (8,15): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch ((3 is var x3)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(8, 15), - // (11,24): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch (H.Dummy((41 is var x4), - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(11, 24), - // (12,24): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // (42 is var x4))) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(12, 24), - // (14,16): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch ((51 is var x5)) - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(14, 16), - // (17,21): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // H.Dummy("52" is var x5); - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(17, 21), - // (2,15): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code - // switch ((1 is var x1)) {default: break;} - Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(2, 15), - // (25,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(25, 13), - // (25,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(25, 17), - // (25,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(25, 21), - // (25,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(25, 25), - // (25,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(25, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,19): error CS0128: A local variable or function named 'x2' is already defined in this scope + // switch ((2 is var x2)) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 19), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,28): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4))) {default: break;} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 28), + // (17,25): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(17, 25), + // (28,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(28, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); } } @@ -1760,6 +1886,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -1830,47 +1958,73 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // while ((2 is int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,27): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 27), - // (16,28): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 28), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,18): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while ((2 is int x2)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 18), + // (8,18): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while ((3 is int x3)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 18), + // (12,27): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 27), + // (16,28): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 28), + // (19,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 9), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); + VerifyNotAPatternLocal(model, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -1903,6 +2057,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -1973,61 +2129,86 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,18): error CS0102: The type '' already contains a definition for 'x2' - // while ((2 is var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 18), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,27): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 27), - // (16,25): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 25), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,18): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while ((2 is var x2)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 18), + // (8,18): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // while ((3 is var x3)) {} + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 18), + // (12,27): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 27), + // (16,25): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 25), + // (19,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 9), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - } - } + var model = compilation.GetSemanticModel(tree); - [Fact] - public void GlobalCode_WhileStatement_03() - { - string source = -@" -while ((1 is var x1)) -{ - System.Console.WriteLine(x1); - break; -} + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); + VerifyNotAPatternLocal(model, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); + } + } + + [Fact] + public void GlobalCode_WhileStatement_03() + { + string source = +@" +while ((1 is var x1)) +{ + System.Console.WriteLine(x1); + break; +} class H { @@ -2079,6 +2260,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -2149,47 +2332,73 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // do {} while ((2 is int x2)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,33): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4))); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 33), - // (19,19): error CS0102: The type '' already contains a definition for 'x5' - // while ((51 is int x5)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(19, 19), - // (24,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), - // (24,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(24, 17), - // (24,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(24, 21), - // (24,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), - // (24,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,24): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while ((2 is int x2)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 24), + // (8,24): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while ((3 is int x3)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 24), + // (12,33): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4))); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 33), + // (16,28): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 28), + // (20,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 9), + // (24,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), + // (24,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), + // (24,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); + VerifyNotAPatternLocal(model, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -2223,6 +2432,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -2293,48 +2504,73 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // do {} while ((2 is var x2)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,33): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4))); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 33), - // (19,19): error CS0102: The type '' already contains a definition for 'x5' - // while ((51 is var x5)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(19, 19), - // (24,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), - // (24,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(24, 17), - // (24,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(24, 21), - // (24,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), - // (24,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(3, 9), + // (6,24): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while ((2 is var x2)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(6, 24), + // (8,24): error CS0136: A local or parameter named 'x3' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // do {} while ((3 is var x3)); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x3").WithArguments("x3").WithLocation(8, 24), + // (12,33): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4))); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 33), + // (16,25): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 25), + // (20,9): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 9), + // (24,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(24, 13), + // (24,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(24, 25), + // (24,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(24, 29) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); + VerifyNotAPatternLocal(model, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + VerifyNotInScope(model, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1]); + VerifyNotInScope(model, x5Ref[1]); + VerifyNotInScope(model, x5Ref[2]); } } @@ -2408,6 +2644,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static object Dummy(params object[] x) {return true;} @@ -2468,47 +2706,58 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // lock (H.Dummy(2 is int x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,26): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 26), - // (16,28): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is string x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 28), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // lock (H.Dummy(2 is int x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,26): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 26), + // (16,28): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is string x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 28), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); } } @@ -2541,6 +2790,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static object Dummy(params object[] x) {return true;} @@ -2601,48 +2852,58 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,24): error CS0102: The type '' already contains a definition for 'x2' - // lock (H.Dummy(2 is var x2)) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 24), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,26): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4))) {} - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 26), - // (16,25): error CS0102: The type '' already contains a definition for 'x5' - // H.Dummy("52" is var x5); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("", "x5").WithLocation(16, 25), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,24): error CS0128: A local variable or function named 'x2' is already defined in this scope + // lock (H.Dummy(2 is var x2)) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 24), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,26): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4))) {} + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 26), + // (16,25): error CS0136: A local or parameter named 'x5' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy("52" is var x5); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x5").WithArguments("x5").WithLocation(16, 25), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(2, x5Decl.Length); + Assert.Equal(3, x5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref[1], x5Ref[2]); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[1], x5Ref[0]); } } @@ -2759,6 +3020,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -2833,49 +3096,67 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,30): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = ((2 is int x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 30), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,32): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 32), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) - ); - - var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - } - } + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,30): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = ((2 is int x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 30), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (12,32): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 32), + // (14,33): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = ((5 is int x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 33), + // (15,33): error CS0128: A local variable or function named 'x6' is already defined in this scope + // (6 is int x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 33), + // (22,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(22, 1) + ); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x6Decl); + VerifyNotAPatternLocal(model, x6Ref); + } + } [Fact] public void GlobalCode_LabeledStatement_01() @@ -2899,6 +3180,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -2964,41 +3247,60 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,21): error CS0102: The type '' already contains a definition for 'x2' - // b: H.Dummy(2 is int x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 21), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,23): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 23), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: H.Dummy(1 is int x1); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // b: H.Dummy(2 is int x2); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "b").WithLocation(6, 1), + // (6,21): error CS0128: A local variable or function named 'x2' is already defined in this scope + // b: H.Dummy(2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 21), + // (8,1): warning CS0164: This label has not been referenced + // c: H.Dummy(3 is int x3); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(8, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,1): warning CS0164: This label has not been referenced + // d: H.Dummy((41 is int x4), + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "d").WithLocation(11, 1), + // (12,23): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 23), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -3024,6 +3326,8 @@ void Test() H.Dummy(x1, x2, x3, x4); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -3089,42 +3393,60 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,21): error CS0102: The type '' already contains a definition for 'x2' - // b: H.Dummy(2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 21), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,23): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 23), - // (16,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(16, 13), - // (16,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(16, 17), - // (16,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(16, 21), - // (16,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(16, 25) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: H.Dummy(1 is var x1); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // b: H.Dummy(2 is var x2); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "b").WithLocation(6, 1), + // (6,21): error CS0128: A local variable or function named 'x2' is already defined in this scope + // b: H.Dummy(2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 21), + // (8,1): warning CS0164: This label has not been referenced + // c: H.Dummy(3 is var x3); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(8, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (11,1): warning CS0164: This label has not been referenced + // d: H.Dummy((41 is var x4), + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "d").WithLocation(11, 1), + // (12,23): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 23), + // (19,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(19, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); } } @@ -3198,6 +3520,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -3271,34 +3595,42 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), + // (7,20): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = (2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 20), + // (8,1): warning CS0164: This label has not been referenced + // e: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (11,1): warning CS0164: This label has not been referenced + // g: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), + // (13,29): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), + // (14,1): warning CS0164: This label has not been referenced + // i: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), + // (15,21): error CS0128: A local variable or function named 'x5' is already defined in this scope + // bool x5 = (5 is int x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(15, 21), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -3307,31 +3639,29 @@ class H var x1Decl = GetPatternDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").ToArray(); Assert.Equal(2, x5Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref[0]); + VerifyNotAPatternLocal(model, x5Ref[1]); } } @@ -3361,6 +3691,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -3434,34 +3766,42 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // a: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "a").WithLocation(2, 1), + // (6,1): warning CS0164: This label has not been referenced + // c: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "c").WithLocation(6, 1), + // (7,20): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = (2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 20), + // (8,1): warning CS0164: This label has not been referenced + // e: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "e").WithLocation(8, 1), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (11,1): warning CS0164: This label has not been referenced + // g: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "g").WithLocation(11, 1), + // (13,29): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), + // (14,1): warning CS0164: This label has not been referenced + // i: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i").WithLocation(14, 1), + // (15,21): error CS0128: A local variable or function named 'x5' is already defined in this scope + // bool x5 = (5 is var x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(15, 21), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -3470,31 +3810,29 @@ class H var x1Decl = GetPatternDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").ToArray(); Assert.Equal(2, x5Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref[0]); + VerifyNotAPatternLocal(model, x5Ref[1]); } } @@ -3565,6 +3903,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -3656,47 +3996,82 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,30): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = ((2 is int x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 30), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,32): error CS0102: The type '' already contains a definition for 'x4' - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 32), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (1,1): warning CS0164: This label has not been referenced + // l1: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1), + // (5,1): warning CS0164: This label has not been referenced + // l2: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l2").WithLocation(5, 1), + // (6,30): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = ((2 is int x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 30), + // (7,1): warning CS0164: This label has not been referenced + // l3: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l3").WithLocation(7, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (10,1): warning CS0164: This label has not been referenced + // l4: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l4").WithLocation(10, 1), + // (12,32): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 32), + // (13,1): warning CS0164: This label has not been referenced + // l5: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l5").WithLocation(13, 1), + // (14,33): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = ((5 is int x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 33), + // (15,33): error CS0128: A local variable or function named 'x6' is already defined in this scope + // (6 is int x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 33), + // (22,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(22, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(1, x5Ref.Length); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref[0]); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(1, x6Ref.Length); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x6Decl); + VerifyNotAPatternLocal(model, x6Ref[0]); } } @@ -3726,6 +4101,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -3817,48 +4194,82 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (6,30): error CS0102: The type '' already contains a definition for 'x2' - // (bool c, int d) = ((2 is var x2), 2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(6, 30), - // (9,8): error CS0102: The type '' already contains a definition for 'x3' - // object x3; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x3").WithArguments("", "x3").WithLocation(9, 8), - // (12,32): error CS0102: The type '' already contains a definition for 'x4' - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(12, 32), - // (19,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(19, 13), - // (19,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(19, 17), - // (19,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(19, 21), - // (19,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(19, 25), - // (19,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(19, 29), - // (19,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(19, 33) + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (1,1): warning CS0164: This label has not been referenced + // l1: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1), + // (5,1): warning CS0164: This label has not been referenced + // l2: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l2").WithLocation(5, 1), + // (6,30): error CS0128: A local variable or function named 'x2' is already defined in this scope + // (bool c, int d) = ((2 is var x2), 2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(6, 30), + // (7,1): warning CS0164: This label has not been referenced + // l3: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l3").WithLocation(7, 1), + // (9,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(9, 8), + // (9,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 8), + // (10,1): warning CS0164: This label has not been referenced + // l4: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l4").WithLocation(10, 1), + // (12,32): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(12, 32), + // (13,1): warning CS0164: This label has not been referenced + // l5: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l5").WithLocation(13, 1), + // (14,33): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (bool x5, bool x6) = ((5 is var x5), + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(14, 33), + // (15,33): error CS0128: A local variable or function named 'x6' is already defined in this scope + // (6 is var x6)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(15, 33), + // (22,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(22, 1) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); + var x4Ref = GetReferences(tree, "x4").Single(); + Assert.Equal(2, x4Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); + + var x5Decl = GetPatternDeclarations(tree, "x5").Single(); + var x5Ref = GetReferences(tree, "x5").ToArray(); + Assert.Equal(1, x5Ref.Length); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref[0]); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(1, x6Ref.Length); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x6Decl); + VerifyNotAPatternLocal(model, x6Ref[0]); } } @@ -3934,6 +4345,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -4007,37 +4420,33 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (7,20): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = (2 is int x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 20), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (13,29): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), + // (16,21): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (5 is int x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(16, 21), + // (19,10): error CS0128: A local variable or function named 'x6' is already defined in this scope + // x6; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(19, 10), + // (19,10): warning CS0168: The variable 'x6' is declared but never used + // x6; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x6").WithArguments("x6").WithLocation(19, 10), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -4046,35 +4455,31 @@ class H var x1Decl = GetPatternDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref); var x6Decl = GetPatternDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); } } @@ -4107,6 +4512,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5, x6); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -4180,37 +4587,33 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,29): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (7,20): error CS0128: A local variable or function named 'x2' is already defined in this scope + // bool d = (2 is var x2); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x2").WithArguments("x2").WithLocation(7, 20), + // (10,8): error CS0128: A local variable or function named 'x3' is already defined in this scope + // object x3; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x3").WithArguments("x3").WithLocation(10, 8), + // (10,8): warning CS0168: The variable 'x3' is declared but never used + // object x3; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(10, 8), + // (13,29): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 29), + // (16,21): error CS0128: A local variable or function named 'x5' is already defined in this scope + // (5 is var x5); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(16, 21), + // (19,10): error CS0128: A local variable or function named 'x6' is already defined in this scope + // x6; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(19, 10), + // (19,10): warning CS0168: The variable 'x6' is declared but never used + // x6; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x6").WithArguments("x6").WithLocation(19, 10), + // (26,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(26, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -4219,35 +4622,31 @@ class H var x1Decl = GetPatternDeclarations(tree, "x1").Single(); var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x2Decl); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); - VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0], x4Ref); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl); + VerifyNotAPatternLocal(model, x5Ref); var x6Decl = GetPatternDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); - VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); } } @@ -4466,6 +4865,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -4529,34 +4930,45 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,38): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool b { get; } = (1 is int x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 6), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool d { get; } = (2 is int x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 6), + // (9,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool f { get; } = (3 is int x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 6), + // (12,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool h { get; } = H.Dummy((41 is int x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 6), + // (13,38): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), + // (15,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool x5 { get; } = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 6), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1), + // (23,1): error CS0165: Use of unassigned local variable 'x3' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x3").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -4566,29 +4978,30 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAPatternLocal(model, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); } } @@ -4618,6 +5031,8 @@ void Test() H.Dummy(x1, x2, x3, x4, x5); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -4681,34 +5096,45 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,38): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), - // (20,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), - // (20,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(20, 17), - // (20,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(20, 21), - // (20,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), - // (20,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool b { get; } = (1 is var x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 6), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool d { get; } = (2 is var x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 6), + // (9,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool f { get; } = (3 is var x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 6), + // (12,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool h { get; } = H.Dummy((41 is var x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 6), + // (13,38): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 38), + // (15,6): error CS0116: A namespace cannot directly contain members such as fields or methods + // bool x5 { get; } = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 6), + // (20,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(20, 13), + // (20,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(20, 25), + // (20,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(20, 29), + // (23,1): error CS0165: Use of unassigned local variable 'x2' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x2").WithLocation(23, 1), + // (23,1): error CS0165: Use of unassigned local variable 'x3' + // Test(); + Diagnostic(ErrorCode.ERR_UseDefViolation, "Test()").WithArguments("x3").WithLocation(23, 1) ); var tree = compilation.SyntaxTrees.Single(); @@ -4718,29 +5144,30 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAPatternLocal(model, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); } } @@ -5000,37 +5427,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,36): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is int x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action b = H.Dummy(1 is int x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 21), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action d = H.Dummy(2 is int x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 21), + // (9,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action f = H.Dummy(3 is int x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 21), + // (12,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action h = H.Dummy((41 is int x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 21), + // (13,36): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is int x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), + // (15,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action x5 = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 21), + // (18,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action i = H.Dummy(5 is int x6), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "i").WithLocation(18, 21), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), + // (23,33): error CS0103: The name 'x6' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) ); var tree = compilation.SyntaxTrees.Single(); @@ -5040,34 +5478,35 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAPatternLocal(model, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); var x6Decl = GetPatternDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyNotInScope(model, x6Ref); } } @@ -5173,37 +5612,48 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (13,36): error CS0128: A local variable named 'x4' is already defined in this scope - // (42 is var x4)); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), - // (23,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), - // (23,17): error CS0103: The name 'x2' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x2").WithArguments("x2").WithLocation(23, 17), - // (23,21): error CS0103: The name 'x3' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(23, 21), - // (23,25): error CS0103: The name 'x4' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), - // (23,29): error CS0103: The name 'x5' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), - // (23,33): error CS0103: The name 'x6' does not exist in the current context - // H.Dummy(x1, x2, x3, x4, x5, x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action b = H.Dummy(1 is var x1); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(3, 21), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (7,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action d = H.Dummy(2 is var x2); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d").WithLocation(7, 21), + // (9,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action f = H.Dummy(3 is var x3); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "f").WithLocation(9, 21), + // (12,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action h = H.Dummy((41 is var x4), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "h").WithLocation(12, 21), + // (13,36): error CS0128: A local variable or function named 'x4' is already defined in this scope + // (42 is var x4)); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(13, 36), + // (15,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action x5 = + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "x5").WithLocation(15, 21), + // (18,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action i = H.Dummy(5 is var x6), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "i").WithLocation(18, 21), + // (21,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(21, 6), + // (23,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(23, 13), + // (23,25): error CS0103: The name 'x4' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x4").WithArguments("x4").WithLocation(23, 25), + // (23,29): error CS0103: The name 'x5' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x5").WithArguments("x5").WithLocation(23, 29), + // (23,33): error CS0103: The name 'x6' does not exist in the current context + // H.Dummy(x1, x2, x3, x4, x5, x6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x6").WithArguments("x6").WithLocation(23, 33) ); var tree = compilation.SyntaxTrees.Single(); @@ -5213,34 +5663,35 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl); - VerifyModelNotSupported(model, x1Ref); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); var x2Decl = GetPatternDeclarations(tree, "x2").Single(); var x2Ref = GetReferences(tree, "x2").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl); - VerifyModelNotSupported(model, x2Ref); + VerifyNotAPatternLocal(model, x2Ref); var x3Decl = GetPatternDeclarations(tree, "x3").Single(); var x3Ref = GetReferences(tree, "x3").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); - VerifyModelNotSupported(model, x3Ref); + VerifyNotAPatternLocal(model, x3Ref); var x4Decl = GetPatternDeclarations(tree, "x4").ToArray(); var x4Ref = GetReferences(tree, "x4").Single(); Assert.Equal(2, x4Decl.Length); VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl[0]); VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x4Decl[1]); - VerifyModelNotSupported(model, x4Ref); + VerifyNotInScope(model, x4Ref); var x5Decl = GetPatternDeclarations(tree, "x5").Single(); var x5Ref = GetReferences(tree, "x5").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl); - VerifyModelNotSupported(model, x5Ref); + VerifyNotInScope(model, x5Ref); var x6Decl = GetPatternDeclarations(tree, "x6").Single(); var x6Ref = GetReferences(tree, "x6").Single(); VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl); - VerifyModelNotSupported(model, x6Ref); + VerifyNotInScope(model, x6Ref); } } @@ -5494,28 +5945,30 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // bool a, b("5948" is var x1); - Diagnostic(ErrorCode.ERR_BadVarDecl, @"(""5948"" is var x1").WithLocation(3, 10), - // (3,10): error CS1003: Syntax error, '[' expected - // bool a, b("5948" is var x1); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), - // (3,27): error CS1003: Syntax error, ']' expected - // bool a, b("5948" is var x1); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 27), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,6): warning CS0168: The variable 'a' is declared but never used + // bool a, b("5948" is var x1); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(3, 6), + // (3,9): warning CS0168: The variable 'b' is declared but never used + // bool a, b("5948" is var x1); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(3, 9), + // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // bool a, b("5948" is var x1); + Diagnostic(ErrorCode.ERR_BadVarDecl, @"(""5948"" is var x1").WithLocation(3, 10), + // (3,10): error CS1003: Syntax error, '[' expected + // bool a, b("5948" is var x1); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), + // (3,27): error CS1003: Syntax error, ']' expected + // bool a, b("5948" is var x1); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 27), + // (4,9): error CS0165: Use of unassigned local variable 'x1' + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(4, 9), + // (6,6): warning CS8321: The local function 'Test' is declared but never used + // void Test() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test").WithArguments("Test").WithLocation(6, 6) ); var tree = compilation.SyntaxTrees.Single(); @@ -5525,7 +5978,7 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelForDeclarationOrVarSimplePatternWithoutDataFlow(model, x1Decl, x1Ref); } } @@ -5543,6 +5996,8 @@ void Test() H.Dummy(x1); } +Test(); + class H { public static bool Dummy(params object[] x) {return true;} @@ -5577,28 +6032,30 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // bool a, b((1 is var x1)); - Diagnostic(ErrorCode.ERR_BadVarDecl, "((1 is var x1)").WithLocation(3, 10), - // (3,10): error CS1003: Syntax error, '[' expected - // bool a, b((1 is var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), - // (3,24): error CS1003: Syntax error, ']' expected - // bool a, b((1 is var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 24), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (2,1): warning CS0164: This label has not been referenced + // label: + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "label").WithLocation(2, 1), + // (3,6): warning CS0168: The variable 'a' is declared but never used + // bool a, b((1 is var x1)); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(3, 6), + // (3,9): warning CS0168: The variable 'b' is declared but never used + // bool a, b((1 is var x1)); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(3, 9), + // (3,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // bool a, b((1 is var x1)); + Diagnostic(ErrorCode.ERR_BadVarDecl, "((1 is var x1)").WithLocation(3, 10), + // (3,10): error CS1003: Syntax error, '[' expected + // bool a, b((1 is var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 10), + // (3,24): error CS1003: Syntax error, ']' expected + // bool a, b((1 is var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 24), + // (4,9): error CS0165: Use of unassigned local variable 'x1' + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(4, 9) ); var tree = compilation.SyntaxTrees.Single(); @@ -5608,7 +6065,7 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); } } @@ -5626,6 +6083,8 @@ void Test() H.Dummy(x1); } +Test(); + class H { public static bool Dummy(params object[] x) {return false;} @@ -5658,28 +6117,24 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,25): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) - // event System.Action a, b(H.Dummy(1 is var x1)); - Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.Dummy(1 is var x1)").WithLocation(3, 25), - // (3,25): error CS1003: Syntax error, '[' expected - // event System.Action a, b(H.Dummy(1 is var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 25), - // (3,46): error CS1003: Syntax error, ']' expected - // event System.Action a, b(H.Dummy(1 is var x1)); - Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 46), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,25): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // event System.Action a, b(H.Dummy(1 is var x1)); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(H.Dummy(1 is var x1)").WithLocation(3, 25), + // (3,25): error CS1003: Syntax error, '[' expected + // event System.Action a, b(H.Dummy(1 is var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(3, 25), + // (3,46): error CS1003: Syntax error, ']' expected + // event System.Action a, b(H.Dummy(1 is var x1)); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(3, 46), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (8,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) ); var tree = compilation.SyntaxTrees.Single(); @@ -5689,7 +6144,10 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + // the following would fail due to https://github.com/dotnet/roslyn/issues/13569 + // VerifyModelForDeclarationOrVarSimplePatternWithoutDataFlow(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); } } @@ -5707,6 +6165,8 @@ void Test() H.Dummy(x1); } +Test(); + class H { public static int Dummy(params object[] x) {return 0;} @@ -5743,31 +6203,30 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (3,18): error CS1642: Fixed size buffer fields may only be members of structs - // fixed bool a[2], b[H.Dummy(1 is var x1)]; - Diagnostic(ErrorCode.ERR_FixedNotInStruct, "b").WithLocation(3, 18), - // (3,20): error CS0133: The expression being assigned to '.b' must be constant - // fixed bool a[2], b[H.Dummy(1 is var x1)]; - Diagnostic(ErrorCode.ERR_NotConstantExpression, "H.Dummy(1 is var x1)").WithArguments(".b").WithLocation(3, 20), - // (3,12): error CS1642: Fixed size buffer fields may only be members of structs - // fixed bool a[2], b[H.Dummy(1 is var x1)]; - Diagnostic(ErrorCode.ERR_FixedNotInStruct, "a").WithLocation(3, 12), - // (3,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context - // fixed bool a[2], b[H.Dummy(1 is var x1)]; - Diagnostic(ErrorCode.ERR_UnsafeNeeded, "a[2]").WithLocation(3, 12), - // (8,13): error CS0103: The name 'x1' does not exist in the current context - // H.Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (3,12): error CS0116: A namespace cannot directly contain members such as fields or methods + // fixed bool a[2], b[H.Dummy(1 is var x1)]; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "a").WithLocation(3, 12), + // (3,18): error CS1642: Fixed size buffer fields may only be members of structs + // fixed bool a[2], b[H.Dummy(1 is var x1)]; + Diagnostic(ErrorCode.ERR_FixedNotInStruct, "b").WithLocation(3, 18), + // (3,12): error CS1642: Fixed size buffer fields may only be members of structs + // fixed bool a[2], b[H.Dummy(1 is var x1)]; + Diagnostic(ErrorCode.ERR_FixedNotInStruct, "a").WithLocation(3, 12), + // (3,12): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // fixed bool a[2], b[H.Dummy(1 is var x1)]; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "a[2]").WithLocation(3, 12), + // (3,20): error CS0133: The expression being assigned to '.b' must be constant + // fixed bool a[2], b[H.Dummy(1 is var x1)]; + Diagnostic(ErrorCode.ERR_NotConstantExpression, "H.Dummy(1 is var x1)").WithArguments(".b").WithLocation(3, 20), + // (4,9): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(4, 9), + // (8,13): error CS0103: The name 'x1' does not exist in the current context + // H.Dummy(x1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(8, 13) ); var tree = compilation.SyntaxTrees.Single(); @@ -5777,7 +6236,10 @@ class H var x1Ref = GetReferences(tree, "x1").ToArray(); Assert.Equal(2, x1Ref.Length); AssertContainedInDeclaratorArguments(x1Decl); - VerifyModelNotSupported(model, x1Decl, x1Ref); + // the following would fail due to https://github.com/dotnet/roslyn/issues/13569 + //VerifyModelForDeclarationOrVarSimplePatternWithoutDataFlow(model, x1Decl); + VerifyNotInScope(model, x1Ref[0]); + VerifyNotInScope(model, x1Ref[1]); } } @@ -6106,73 +6568,91 @@ public void GlobalCode_Catch_01() } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (16,5): error CS0111: Type '' already defines a member called 'Dummy' with the same parameter types - // (67,32): error CS0100: The parameter name 'x14' is a duplicate - // 123 is var x14, // 2 - Diagnostic(ErrorCode.ERR_DuplicateParamName, "x14").WithArguments("x14").WithLocation(67, 32), - // (7,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x1); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(7, 5), - // (16,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x4); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(16, 5), - // (22,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x6); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(22, 5), - // (28,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter - // var x7 = 12; - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(28, 9), - // (29,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x7); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(29, 5), - // (35,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x8); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(35, 5), - // (43,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x9); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(43, 5), - // (45,28): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter - // catch when (123 is var x9 && x9 > 0) // 2 - Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(45, 28), - // (47,9): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(x9); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(47, 9), - // (55,5): error CS0103: The name 'Dummy' does not exist in the current context - // Dummy(y10); - Diagnostic(ErrorCode.ERR_NameNotInContext, "Dummy").WithArguments("Dummy").WithLocation(55, 5) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (14,24): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // catch when (123 is var x4 && x4 > 0) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(14, 24), + // (20,13): error CS0841: Cannot use local variable 'x6' before it is declared + // catch when (x6 && 123 is var x6) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(20, 13), + // (28,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(28, 9), + // (38,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(38, 26), + // (45,28): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // catch when (123 is var x9 && x9 > 0) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(45, 28), + // (52,13): error CS0103: The name 'y10' does not exist in the current context + // catch when (y10 is var x10) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(52, 13), + // (67,32): error CS0128: A local variable or function named 'x14' is already defined in this scope + // 123 is var x14, // 2 + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(67, 32), + // (75,32): error CS0128: A local variable or function named 'x15' is already defined in this scope + // when (Dummy(123 is var x15, x15)) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x15").WithArguments("x15").WithLocation(75, 32) ); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); - Assert.Equal(1, GetPatternDeclarations(tree).Count()); - var x9Decl = GetPatternDeclaration(tree, "x9"); + var x1Decl = GetPatternDeclaration(tree, "x1"); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x4Decl = GetPatternDeclaration(tree, "x4"); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAPatternLocal(model, x4Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetPatternDeclaration(tree, "x6"); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); + + var x7Decl = GetPatternDeclaration(tree, "x7"); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x7Decl, x7Ref[0]); + VerifyNotAPatternLocal(model, x7Ref[1]); + + var x8Decl = GetPatternDeclaration(tree, "x8"); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetPatternDeclarations(tree, "x9").ToArray(); var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); Assert.Equal(4, x9Ref.Length); - VerifyNotInScope(model, x9Ref[0]); - Assert.Equal(SymbolKind.Parameter, model.GetSymbolInfo(x9Ref[1]).Symbol.Kind); - VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl, x9Ref[2]); - VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl, x9Ref[3]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[1], x9Ref[2], x9Ref[3]); - AssertNoGlobalStatements(tree); + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAPatternLocal(model, y10Ref[1]); + + var x14Decl = GetPatternDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x14Decl[0], x14Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x14Decl[1]); + + var x15Decl = GetPatternDeclaration(tree, "x15"); + var x15Ref = GetReferences(tree, "x15").ToArray(); + Assert.Equal(2, x15Ref.Length); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x15Decl); + VerifyNotAPatternLocal(model, x15Ref[0]); + VerifyNotAPatternLocal(model, x15Ref[1]); } } @@ -6263,25 +6743,36 @@ class H } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_TypeVarNotFound - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (9,22): error CS0102: The type '' already contains a definition for 'x2' - // H.Dummy(2 is var x2); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("", "x2").WithLocation(9, 22) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (7,8): warning CS0168: The variable 'x2' is declared but never used + // object x2; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x2").WithArguments("x2").WithLocation(7, 8), + // (9,22): error CS0136: A local or parameter named 'x2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // H.Dummy(2 is var x2); + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x2").WithArguments("x2").WithLocation(9, 22), + // (15,9): error CS0103: The name 'x3' does not exist in the current context + // H.Dummy(x3); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(15, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(1, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl, x2Ref); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl); + VerifyNotInScope(model, x3Ref); } } @@ -6506,54 +6997,109 @@ public void GlobalCode_For_01() } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (20,27): error CS0102: The type '' already contains a definition for 'x4' - // Dummy(true is var x4 && x4) - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("", "x4").WithLocation(20, 27), - // (33,9): error CS0102: The type '' already contains a definition for 'x7' - // var x7 = 12; - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x7").WithArguments("", "x7").WithLocation(33, 9), - // (50,31): error CS0102: The type '' already contains a definition for 'x9' - // Dummy(true is var x9 && x9) // 2 - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x9").WithArguments("", "x9").WithLocation(50, 31), - // (83,22): error CS0102: The type '' already contains a definition for 'x14' - // 2 is var x14, - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x14").WithArguments("", "x14").WithLocation(83, 22), - // (84,13): error CS0102: The type '' already contains a definition for 'x14' - // x14) - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x14").WithArguments("", "x14").WithLocation(84, 13) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (20,27): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // Dummy(true is var x4 && x4) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(20, 27), + // (74,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(74, 5), + // (25,15): error CS0841: Cannot use local variable 'x6' before it is declared + // Dummy(x6 && true is var x6) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(25, 15), + // (33,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(33, 9), + // (42,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(42, 26), + // (50,31): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // Dummy(true is var x9 && x9) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(50, 31), + // (56,15): error CS0103: The name 'y10' does not exist in the current context + // Dummy(y10 is var x10) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(56, 15), + // (72,15): error CS0103: The name 'y12' does not exist in the current context + // Dummy(y12 is var x12) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(72, 15), + // (83,22): error CS0128: A local variable or function named 'x14' is already defined in this scope + // 2 is var x14, + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(83, 22), + // (11,1): warning CS0162: Unreachable code detected + // for ( // 2 + Diagnostic(ErrorCode.WRN_UnreachableCode, "for").WithLocation(11, 1), + // (74,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(74, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - AssertNoGlobalStatements(tree); - } - } + var model = compilation.GetSemanticModel(tree); - [Fact] - public void GlobalCode_For_02() - { - var source = -@" + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl, x2Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAPatternLocal(model, x4Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); + + var x7Decl = GetPatternDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x7Decl, x7Ref[0]); + VerifyNotAPatternLocal(model, x7Ref[1]); + + var x8Decl = GetPatternDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetPatternDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAPatternLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetPatternDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x14Decl[0], x14Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x14Decl[1]); + } + } + + [Fact] + public void GlobalCode_For_02() + { + var source = +@" bool f = true; for (Dummy(f, ((f ? 10 : 20)) is var x0, x0); @@ -6774,35 +7320,107 @@ public void GlobalCode_Foreach_01() } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (9,19): error CS0111: Type '' already defines a member called 'Dummy' with the same parameter types - // (58,34): error CS0100: The parameter name 'x14' is a duplicate - // 2 is var x14, - Diagnostic(ErrorCode.ERR_DuplicateParamName, "x14").WithArguments("x14").WithLocation(58, 34) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (15,37): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var i in Dummy(true is var x4 && x4)) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 37), + // (52,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(52, 5), + // (18,25): error CS0841: Cannot use local variable 'x6' before it is declared + // foreach (var i in Dummy(x6 && true is var x6)) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(18, 25), + // (23,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(23, 9), + // (30,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(30, 26), + // (35,42): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var i2 in Dummy(true is var x9 && x9)) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(35, 42), + // (39,25): error CS0103: The name 'y10' does not exist in the current context + // foreach (var i in Dummy(y10 is var x10)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(39, 25), + // (51,25): error CS0103: The name 'y12' does not exist in the current context + // foreach (var i in Dummy(y12 is var x12)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(51, 25), + // (58,34): error CS0128: A local variable or function named 'x14' is already defined in this scope + // 2 is var x14, + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(58, 34), + // (64,14): error CS0136: A local or parameter named 'x15' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // foreach (var x15 in + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x15").WithArguments("x15").WithLocation(64, 14), + // (52,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(52, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl, x2Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAPatternLocal(model, x4Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); + + var x7Decl = GetPatternDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x7Decl, x7Ref[0]); + VerifyNotAPatternLocal(model, x7Ref[1]); + + var x8Decl = GetPatternDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetPatternDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAPatternLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetPatternDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x14Decl[0], x14Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x14Decl[1]); + + var x15Decl = GetPatternDeclarations(tree, "x15").Single(); + var x15Ref = GetReferences(tree, "x15").ToArray(); + Assert.Equal(2, x15Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x15Decl, x15Ref[0]); + VerifyNotAPatternLocal(model, x15Ref[1]); } } @@ -6973,41 +7591,97 @@ o2 is var x5 && } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_MemberAlreadyExists - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( - // (12,1): error CS0111: Type '' already defines a member called 'Dummy' with the same parameter types - // (9,67): error CS0100: The parameter name 'x5' is a duplicate - // o2 is var x5 && - Diagnostic(ErrorCode.ERR_DuplicateParamName, "x5").WithArguments("x5").WithLocation(9, 67), - // (23,49): error CS0100: The parameter name 'x9' is a duplicate - // (System.Func) (o => o is var x9 && - Diagnostic(ErrorCode.ERR_DuplicateParamName, "x9").WithArguments("x9").WithLocation(23, 49), - // (28,26): error CS0102: The type '' already contains a definition for 'x10' - // true is var x10, x10); - Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x10").WithArguments("", "x10").WithLocation(28, 26) + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (6,39): error CS0841: Cannot use local variable 'x4' before it is declared + // Dummy((System.Func) (o => x4 && o is var x4)); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(6, 39), + // (9,67): error CS0128: A local variable or function named 'x5' is already defined in this scope + // o2 is var x5 && + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(9, 67), + // (14,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, 1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(14, 7), + // (15,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 7), + // (17,9): error CS0103: The name 'x7' does not exist in the current context + // x7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(17, 9), + // (18,7): error CS0103: The name 'x7' does not exist in the current context + // Dummy(x7, 2); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(18, 7), + // (37,9): error CS0841: Cannot use local variable 'x12' before it is declared + // x12); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x12").WithArguments("x12").WithLocation(37, 9) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x3Decl = GetPatternDeclarations(tree, "x3").Single(); + var x3Ref = GetReferences(tree, "x3").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x3Decl, x3Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl, x4Ref); + + var x5Decl = GetPatternDeclarations(tree, "x5").ToArray(); + var x5Ref = GetReferences(tree, "x5").Single(); + Assert.Equal(2, x5Decl.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x5Decl[0], x5Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x5Decl[1]); + + var x6Decl = GetPatternDeclarations(tree, "x6").ToArray(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Decl.Length); + Assert.Equal(2, x6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl[0], x6Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl[1], x6Ref[1]); + + var x7Decl = GetPatternDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(5, x7Ref.Length); + VerifyNotInScope(model, x7Ref[0]); + VerifyNotInScope(model, x7Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x7Decl, x7Ref[2]); + VerifyNotInScope(model, x7Ref[3]); + VerifyNotInScope(model, x7Ref[4]); + + var x8Decl = GetPatternDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(2, x8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x8Decl, x8Ref); + + var x9Decl = GetPatternDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(2, x9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[0], x9Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[1], x9Ref[0]); + + var x10Decl = GetPatternDeclarations(tree, "x10").ToArray(); + var x10Ref = GetReferences(tree, "x10").ToArray(); + Assert.Equal(2, x10Decl.Length); + Assert.Equal(2, x10Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x10Decl[0], x10Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x10Decl[1], x10Ref[1]); + + var x11Decl = GetPatternDeclarations(tree, "x11").Single(); + var x11Ref = GetReferences(tree, "x11").ToArray(); + Assert.Equal(3, x11Ref.Length); + VerifyNotAPatternLocal(model, x11Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x11Decl, x11Ref[1]); + VerifyNotAPatternLocal(model, x11Ref[2]); + + var x12Decl = GetPatternDeclarations(tree, "x12").Single(); + var x12Ref = GetReferences(tree, "x12").ToArray(); + Assert.Equal(3, x12Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x12Decl, x12Ref[0]); + VerifyNotAPatternLocal(model, x12Ref[1]); + VerifyNotAPatternLocal(model, x12Ref[2]); } } @@ -7412,33 +8086,96 @@ from y10 in new[] { 1 } } { - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_SyntaxError, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_PredefinedValueTupleTypeNotFound, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_TupleElementNamesAttributeMissing, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_NameNotInContext, - (int)ErrorCode.ERR_UseDefViolation - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (14,21): error CS0103: The name 'z2' does not exist in the current context + // z2; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(14, 21), + // (21,25): error CS0103: The name 'z3' does not exist in the current context + // z3}; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(21, 25), + // (28,29): error CS0103: The name 'v4' does not exist in the current context + // v4 + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(28, 29), // (30,29): error CS1938: The name 'u4' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u4 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u4").WithArguments("u4").WithLocation(30, 29), + // (32,25): error CS0103: The name 'u4' does not exist in the current context + // u4, v4 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(32, 25), + // (32,29): error CS0103: The name 'v4' does not exist in the current context + // u4, v4 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(32, 29), + // (41,29): error CS0103: The name 'v5' does not exist in the current context + // v5 + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(41, 29), // (43,29): error CS1938: The name 'u5' is not in scope on the right side of 'equals'. Consider swapping the expressions on either side of 'equals'. // u5 Diagnostic(ErrorCode.ERR_QueryInnerKey, "u5").WithArguments("u5").WithLocation(43, 29), + // (46,25): error CS0103: The name 'u5' does not exist in the current context + // u5, v5 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(46, 25), + // (46,29): error CS0103: The name 'v5' does not exist in the current context + // u5, v5 }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(46, 29), + // (55,21): error CS0103: The name 'z6' does not exist in the current context + // z6; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(55, 21), + // (61,21): error CS0103: The name 'u7' does not exist in the current context + // u7, + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(61, 21), + // (63,21): error CS0103: The name 'z7' does not exist in the current context + // z7 + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(63, 21), + // (65,21): error CS0103: The name 'z7' does not exist in the current context + // z7 + u7; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(65, 21), + // (65,26): error CS0103: The name 'u7' does not exist in the current context + // z7 + u7; + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(65, 26), + // (80,17): error CS0103: The name 'z9' does not exist in the current context + // z9; + Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(80, 17), + // (77,17): error CS0103: The name 'u9' does not exist in the current context + // u9 + Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(77, 17), + // (16,7): error CS0103: The name 'z2' does not exist in the current context + // Dummy(z2); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z2").WithArguments("z2").WithLocation(16, 7), + // (23,7): error CS0103: The name 'z3' does not exist in the current context + // Dummy(z3); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z3").WithArguments("z3").WithLocation(23, 7), + // (35,7): error CS0103: The name 'u4' does not exist in the current context + // Dummy(u4); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u4").WithArguments("u4").WithLocation(35, 7), + // (36,7): error CS0103: The name 'v4' does not exist in the current context + // Dummy(v4); + Diagnostic(ErrorCode.ERR_NameNotInContext, "v4").WithArguments("v4").WithLocation(36, 7), + // (49,7): error CS0103: The name 'u5' does not exist in the current context + // Dummy(u5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u5").WithArguments("u5").WithLocation(49, 7), + // (50,7): error CS0103: The name 'v5' does not exist in the current context + // Dummy(v5); + Diagnostic(ErrorCode.ERR_NameNotInContext, "v5").WithArguments("v5").WithLocation(50, 7), + // (57,7): error CS0103: The name 'z6' does not exist in the current context + // Dummy(z6); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z6").WithArguments("z6").WithLocation(57, 7), + // (67,7): error CS0103: The name 'z7' does not exist in the current context + // Dummy(z7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z7").WithArguments("z7").WithLocation(67, 7), + // (68,7): error CS0103: The name 'u7' does not exist in the current context + // Dummy(u7); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u7").WithArguments("u7").WithLocation(68, 7), + // (73,7): error CS0103: The name 'z8' does not exist in the current context + // Dummy(z8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z8").WithArguments("z8").WithLocation(73, 7), + // (82,7): error CS0103: The name 'z9' does not exist in the current context + // Dummy(z9); + Diagnostic(ErrorCode.ERR_NameNotInContext, "z9").WithArguments("z9").WithLocation(82, 7), + // (83,7): error CS0103: The name 'u9' does not exist in the current context + // Dummy(u9); + Diagnostic(ErrorCode.ERR_NameNotInContext, "u9").WithArguments("u9").WithLocation(83, 7), // (86,18): error CS1931: The range variable 'y10' conflicts with a previous declaration of 'y10' // from y10 in new[] { 1 } Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "y10").WithArguments("y10").WithLocation(86, 18), @@ -7448,7 +8185,163 @@ from y10 in new[] { 1 } ); var tree = compilation.SyntaxTrees.Single(); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var y1Decl = GetPatternDeclarations(tree, "y1").Single(); + var y1Ref = GetReferences(tree, "y1").ToArray(); + Assert.Equal(4, y1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y1Decl, y1Ref); + + var y2Decl = GetPatternDeclarations(tree, "y2").Single(); + var y2Ref = GetReferences(tree, "y2").ToArray(); + Assert.Equal(3, y2Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y2Decl, y2Ref); + + var z2Decl = GetPatternDeclarations(tree, "z2").Single(); + var z2Ref = GetReferences(tree, "z2").ToArray(); + Assert.Equal(4, z2Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z2Decl, z2Ref[0], z2Ref[1]); + VerifyNotInScope(model, z2Ref[2]); + VerifyNotInScope(model, z2Ref[3]); + + var y3Decl = GetPatternDeclarations(tree, "y3").Single(); + var y3Ref = GetReferences(tree, "y3").ToArray(); + Assert.Equal(3, y3Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y3Decl, y3Ref); + + var z3Decl = GetPatternDeclarations(tree, "z3").Single(); + var z3Ref = GetReferences(tree, "z3").ToArray(); + Assert.Equal(3, z3Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z3Decl, z3Ref[0]); + VerifyNotInScope(model, z3Ref[1]); + VerifyNotInScope(model, z3Ref[2]); + + var y4Decl = GetPatternDeclarations(tree, "y4").Single(); + var y4Ref = GetReferences(tree, "y4").ToArray(); + Assert.Equal(5, y4Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y4Decl, y4Ref); + + var z4Decl = GetPatternDeclarations(tree, "z4").Single(); + var z4Ref = GetReferences(tree, "z4").ToArray(); + Assert.Equal(6, z4Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z4Decl, z4Ref); + + var u4Decl = GetPatternDeclarations(tree, "u4").Single(); + var u4Ref = GetReferences(tree, "u4").ToArray(); + Assert.Equal(4, u4Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, u4Decl, u4Ref[0]); + VerifyNotInScope(model, u4Ref[1]); + VerifyNotInScope(model, u4Ref[2]); + VerifyNotInScope(model, u4Ref[3]); + + var v4Decl = GetPatternDeclarations(tree, "v4").Single(); + var v4Ref = GetReferences(tree, "v4").ToArray(); + Assert.Equal(4, v4Ref.Length); + VerifyNotInScope(model, v4Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, v4Decl, v4Ref[1]); + VerifyNotInScope(model, v4Ref[2]); + VerifyNotInScope(model, v4Ref[3]); + + var y5Decl = GetPatternDeclarations(tree, "y5").Single(); + var y5Ref = GetReferences(tree, "y5").ToArray(); + Assert.Equal(5, y5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y5Decl, y5Ref); + + var z5Decl = GetPatternDeclarations(tree, "z5").Single(); + var z5Ref = GetReferences(tree, "z5").ToArray(); + Assert.Equal(6, z5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z5Decl, z5Ref); + + var u5Decl = GetPatternDeclarations(tree, "u5").Single(); + var u5Ref = GetReferences(tree, "u5").ToArray(); + Assert.Equal(4, u5Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, u5Decl, u5Ref[0]); + VerifyNotInScope(model, u5Ref[1]); + VerifyNotInScope(model, u5Ref[2]); + VerifyNotInScope(model, u5Ref[3]); + + var v5Decl = GetPatternDeclarations(tree, "v5").Single(); + var v5Ref = GetReferences(tree, "v5").ToArray(); + Assert.Equal(4, v5Ref.Length); + VerifyNotInScope(model, v5Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, v5Decl, v5Ref[1]); + VerifyNotInScope(model, v5Ref[2]); + VerifyNotInScope(model, v5Ref[3]); + + var y6Decl = GetPatternDeclarations(tree, "y6").Single(); + var y6Ref = GetReferences(tree, "y6").ToArray(); + Assert.Equal(3, y6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y6Decl, y6Ref); + + var z6Decl = GetPatternDeclarations(tree, "z6").Single(); + var z6Ref = GetReferences(tree, "z6").ToArray(); + Assert.Equal(3, z6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z6Decl, z6Ref[0]); + VerifyNotInScope(model, z6Ref[1]); + VerifyNotInScope(model, z6Ref[2]); + + var y7Decl = GetPatternDeclarations(tree, "y7").Single(); + var y7Ref = GetReferences(tree, "y7").ToArray(); + Assert.Equal(4, y7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y7Decl, y7Ref); + + var z7Decl = GetPatternDeclarations(tree, "z7").Single(); + var z7Ref = GetReferences(tree, "z7").ToArray(); + Assert.Equal(4, z7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z7Decl, z7Ref[0]); + VerifyNotInScope(model, z7Ref[1]); + VerifyNotInScope(model, z7Ref[2]); + VerifyNotInScope(model, z7Ref[3]); + + var u7Decl = GetPatternDeclarations(tree, "u7").Single(); + var u7Ref = GetReferences(tree, "u7").ToArray(); + Assert.Equal(4, u7Ref.Length); + VerifyNotInScope(model, u7Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, u7Decl, u7Ref[1]); + VerifyNotInScope(model, u7Ref[2]); + VerifyNotInScope(model, u7Ref[3]); + + var y8Decl = GetPatternDeclarations(tree, "y8").Single(); + var y8Ref = GetReferences(tree, "y8").ToArray(); + Assert.Equal(2, y8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y8Decl, y8Ref); + + var z8Decl = GetPatternDeclarations(tree, "z8").Single(); + var z8Ref = GetReferences(tree, "z8").ToArray(); + Assert.Equal(2, z8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z8Decl, z8Ref[0]); + VerifyNotInScope(model, z8Ref[1]); + + var y9Decl = GetPatternDeclarations(tree, "y9").Single(); + var y9Ref = GetReferences(tree, "y9").ToArray(); + Assert.Equal(3, y9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y9Decl, y9Ref); + + var z9Decl = GetPatternDeclarations(tree, "z9").Single(); + var z9Ref = GetReferences(tree, "z9").ToArray(); + Assert.Equal(3, z9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, z9Decl, z9Ref[0]); + VerifyNotInScope(model, z9Ref[1]); + VerifyNotInScope(model, z9Ref[2]); + + var u9Decl = GetPatternDeclarations(tree, "u9").Single(); + var u9Ref = GetReferences(tree, "u9").ToArray(); + Assert.Equal(3, u9Ref.Length); + VerifyNotInScope(model, u9Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, u9Decl, u9Ref[1]); + VerifyNotInScope(model, u9Ref[2]); + + var y10Decl = GetPatternDeclarations(tree, "y10").Single(); + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y10Decl, y10Ref[0]); + VerifyNotAPatternLocal(model, y10Ref[1]); + + var y11Decl = GetPatternDeclarations(tree, "y11").Single(); + var y11Ref = GetReferences(tree, "y11").ToArray(); + Assert.Equal(2, y11Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, y11Decl, y11Ref[0]); + VerifyNotAPatternLocal(model, y11Ref[1]); } } @@ -7647,29 +8540,102 @@ public void GlobalCode_Using_01() } { - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); - int[] exclude = new int[] { (int)ErrorCode.ERR_EOFExpected, - (int)ErrorCode.ERR_CloseParenExpected, - (int)ErrorCode.ERR_SemicolonExpected, - (int)ErrorCode.ERR_TypeExpected, - (int)ErrorCode.ERR_NamespaceUnexpected, - (int)ErrorCode.ERR_TupleTooFewElements, - (int)ErrorCode.ERR_IdentifierExpected, - (int)ErrorCode.ERR_MemberNeedsType, - (int)ErrorCode.ERR_IdentifierExpectedKW, - (int)ErrorCode.ERR_SingleTypeNameNotFound, - (int)ErrorCode.ERR_ConcreteMissingBody, - (int)ErrorCode.ERR_TypeVarNotFound, - (int)ErrorCode.ERR_DuplicateNameInClass, - (int)ErrorCode.ERR_MemberAlreadyExists - }; - - compilation.GetDiagnostics().Where(d => !exclude.Contains(d.Code)).Verify( + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularPreview); + + compilation.VerifyDiagnostics( + // (15,26): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // using (Dummy(true is var x4, x4)) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(15, 26), + // (18,14): error CS0841: Cannot use local variable 'x6' before it is declared + // using (Dummy(x6 && true is var x6)) + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(18, 14), + // (23,9): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // var x7 = 12; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(23, 9), + // (30,26): error CS0103: The name 'x8' does not exist in the current context + // System.Console.WriteLine(x8); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(30, 26), + // (35,30): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // using (Dummy(true is var x9, x9)) // 2 + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(35, 30), + // (39,14): error CS0103: The name 'y10' does not exist in the current context + // using (Dummy(y10 is var x10, x10)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y10").WithArguments("y10").WithLocation(39, 14), + // (51,14): error CS0103: The name 'y12' does not exist in the current context + // using (Dummy(y12 is var x12, x12)) + Diagnostic(ErrorCode.ERR_NameNotInContext, "y12").WithArguments("y12").WithLocation(51, 14), + // (52,5): error CS1023: Embedded statement cannot be a declaration or labeled statement + // var y12 = 12; + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(52, 5), + // (52,9): warning CS0219: The variable 'y12' is assigned but its value is never used + // var y12 = 12; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y12").WithArguments("y12").WithLocation(52, 9), + // (58,26): error CS0128: A local variable or function named 'x14' is already defined in this scope + // 2 is var x14, + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x14").WithArguments("x14").WithLocation(58, 26) ); var tree = compilation.SyntaxTrees.Single(); - Assert.Empty(GetPatternDeclarations(tree)); - AssertNoGlobalStatements(tree); + var model = compilation.GetSemanticModel(tree); + + var x1Decl = GetPatternDeclarations(tree, "x1").Single(); + var x1Ref = GetReferences(tree, "x1").ToArray(); + Assert.Equal(2, x1Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x1Decl, x1Ref); + + var x2Decl = GetPatternDeclarations(tree, "x2").Single(); + var x2Ref = GetReferences(tree, "x2").ToArray(); + Assert.Equal(2, x2Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x2Decl, x2Ref); + + var x4Decl = GetPatternDeclarations(tree, "x4").Single(); + var x4Ref = GetReferences(tree, "x4").ToArray(); + Assert.Equal(3, x4Ref.Length); + VerifyNotAPatternLocal(model, x4Ref[0]); + VerifyModelForDeclarationOrVarSimplePattern(model, x4Decl, x4Ref[1], x4Ref[2]); + + var x6Decl = GetPatternDeclarations(tree, "x6").Single(); + var x6Ref = GetReferences(tree, "x6").ToArray(); + Assert.Equal(2, x6Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x6Decl, x6Ref); + + var x7Decl = GetPatternDeclarations(tree, "x7").Single(); + var x7Ref = GetReferences(tree, "x7").ToArray(); + Assert.Equal(2, x7Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x7Decl, x7Ref[0]); + VerifyNotAPatternLocal(model, x7Ref[1]); + + var x8Decl = GetPatternDeclarations(tree, "x8").Single(); + var x8Ref = GetReferences(tree, "x8").ToArray(); + Assert.Equal(3, x8Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x8Decl, x8Ref[0], x8Ref[1]); + VerifyNotInScope(model, x8Ref[2]); + + var x9Decl = GetPatternDeclarations(tree, "x9").ToArray(); + var x9Ref = GetReferences(tree, "x9").ToArray(); + Assert.Equal(2, x9Decl.Length); + Assert.Equal(4, x9Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[0], x9Ref[0], x9Ref[1]); + VerifyModelForDeclarationOrVarSimplePattern(model, x9Decl[1], x9Ref[2], x9Ref[3]); + + var x10Decl = GetPatternDeclarations(tree, "x10").Single(); + var x10Ref = GetReferences(tree, "x10").Single(); + VerifyModelForDeclarationOrVarSimplePattern(model, x10Decl, x10Ref); + + var y10Ref = GetReferences(tree, "y10").ToArray(); + Assert.Equal(2, y10Ref.Length); + VerifyNotInScope(model, y10Ref[0]); + VerifyNotAPatternLocal(model, y10Ref[1]); + + var y12Ref = GetReferences(tree, "y12").Single(); + VerifyNotInScope(model, y12Ref); + + var x14Decl = GetPatternDeclarations(tree, "x14").ToArray(); + var x14Ref = GetReferences(tree, "x14").ToArray(); + Assert.Equal(2, x14Decl.Length); + Assert.Equal(2, x14Ref.Length); + VerifyModelForDeclarationOrVarSimplePattern(model, x14Decl[0], x14Ref); + VerifyModelForDeclarationOrVarPatternDuplicateInSameScope(model, x14Decl[1]); } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs index 3b678cea2ad7c..932eaf0967f38 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs @@ -1170,8 +1170,9 @@ public void FixedBuffer_02() ); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44418")] [WorkItem(10023, "https://github.com/dotnet/roslyn/issues/10023")] + [WorkItem(44418, "https://github.com/dotnet/roslyn/issues/44418")] public void Errors_01() { var code = "System.Console.WriteLine(1);"; @@ -1258,8 +1259,9 @@ public void Errors_01() ); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44418")] [WorkItem(10023, "https://github.com/dotnet/roslyn/issues/10023")] + [WorkItem(44418, "https://github.com/dotnet/roslyn/issues/44418")] public void Errors_02() { var compilationUnit = CSharp.SyntaxFactory.ParseCompilationUnit("\nSystem.Console.WriteLine(1);", options: new CSharp.CSharpParseOptions(kind: SourceCodeKind.Script)); @@ -1295,8 +1297,9 @@ public void Errors_02() ); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44418")] [WorkItem(10023, "https://github.com/dotnet/roslyn/issues/10023")] + [WorkItem(44418, "https://github.com/dotnet/roslyn/issues/44418")] public void Errors_03() { var code = "System.Console.WriteLine(out var x, x);"; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index f1782fb532dd2..e81489e0d6783 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -2720,7 +2720,11 @@ public void CS0116ERR_NamespaceUnexpected_1() var test = @" int x; "; - DiagnosticsUtils.VerifyErrorsAndGetCompilationWithMscorlib(test, new ErrorDescription { Code = (int)ErrorCode.ERR_NamespaceUnexpected, Line = 2, Column = 5 }); + CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,5): warning CS0168: The variable 'x' is declared but never used + // int x; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithLocation(2, 5) + ); } [Fact] @@ -2780,9 +2784,14 @@ public void CS0116ERR_NamespaceUnexpected_4() delegate int D(); D d = null; "; - CreateCompilation(test).VerifyDiagnostics( - // (3,3): error CS0116: A namespace does not directly contain members such as fields or methods - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "d")); + CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (3,1): error CS9002: Top-level statements must precede namespace and type declarations. + // D d = null; + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "D d = null;").WithLocation(3, 1), + // (3,3): warning CS0219: The variable 'd' is assigned but its value is never used + // D d = null; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "d").WithArguments("d").WithLocation(3, 3) + ); } [WorkItem(540091, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540091")] @@ -2795,7 +2804,10 @@ public void CS0116ERR_NamespaceUnexpected_5() "; // In this case, CS0116 is suppressed because of the syntax errors - CreateCompilation(test).VerifyDiagnostics( + CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (3,1): error CS9002: Top-level statements must precede namespace and type declarations. + // D d = {;} + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "D d = {;").WithLocation(3, 1), // (3,8): error CS1513: } expected Diagnostic(ErrorCode.ERR_RbraceExpected, ";"), // (3,9): error CS1022: Type or namespace definition, or end-of-file expected diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SuppressAccessibilityChecksTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SuppressAccessibilityChecksTests.cs index a314cbb05e3c3..c566c147d98d3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SuppressAccessibilityChecksTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SuppressAccessibilityChecksTests.cs @@ -55,6 +55,12 @@ public void TestAccessPrivateMemberOfInternalType() Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name); Assert.NotEmpty(semanticModel.LookupSymbols(position, name: "A")); + + semanticModel = semanticModel.Compilation.GetSemanticModel(semanticModel.SyntaxTree); + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); + Assert.Null(semanticModel.GetSymbolInfo(invocation).Symbol); + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).CandidateSymbols.Single().Name); + Assert.Equal(CandidateReason.Inaccessible, semanticModel.GetSymbolInfo(invocation).CandidateReason); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs new file mode 100644 index 0000000000000..d618fef05bf93 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs @@ -0,0 +1,8519 @@ +// 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 System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.FlowAnalysis; +using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeAnalysis.Test.Extensions; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + [CompilerTrait(CompilerFeature.TopLevelStatements)] + public class TopLevelStatementsTests : CompilingTestBase + { + private static CSharpParseOptions DefaultParseOptions => TestOptions.RegularPreview; + + [Fact] + public void Simple_01() + { + var text = @"System.Console.WriteLine(""Hi!"");"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + private static void AssertEntryPointParameter(SynthesizedSimpleProgramEntryPointSymbol entryPoint) + { + Assert.Equal(1, entryPoint.ParameterCount); + ParameterSymbol parameter = entryPoint.Parameters.Single(); + Assert.Equal("System.String[] args", parameter.ToTestDisplayString(includeNonNullable: true)); + Assert.True(parameter.IsImplicitlyDeclared); + Assert.Same(entryPoint, parameter.ContainingSymbol); + } + + [Fact] + public void Simple_02() + { + var text = @" +using System; +using System.Threading.Tasks; + +Console.Write(""hello ""); +await Task.Factory.StartNew(() => 5); +Console.Write(""async main""); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "hello async main"); + } + + [Fact] + public void Simple_03() + { + var text1 = @" +System.Console.Write(""1""); +"; + var text2 = @" +// +System.Console.Write(""2""); +System.Console.WriteLine(); +System.Console.WriteLine(); +"; + var text3 = @" +// +// +System.Console.Write(""3""); +System.Console.WriteLine(); +System.Console.WriteLine(); +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,1): error CS9001: Only one compilation unit can have top-level statements. + // System.Console.Write("2"); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "System").WithLocation(3, 1) + ); + + comp = CreateCompilation(new[] { text1, text2, text3 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,1): error CS9001: Only one compilation unit can have top-level statements. + // System.Console.Write("2"); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "System").WithLocation(3, 1), + // (4,1): error CS9001: Only one compilation unit can have top-level statements. + // System.Console.Write("3"); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "System").WithLocation(4, 1) + ); + } + + [Fact] + public void Simple_04() + { + var text = @" +Type.M(); + +static class Type +{ + public static void M() + { + System.Console.WriteLine(""Hi!""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Simple_05() + { + var text1 = @" +Type.M(); +"; + var text2 = @" +static class Type +{ + public static void M() + { + System.Console.WriteLine(""Hi!""); + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Hi!"); + + comp = CreateCompilation(new[] { text2, text1 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Simple_06_01() + { + var text1 = +@" +local(); +void local() => System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "2"); + + verifyModel(comp, comp.SyntaxTrees[0]); + + comp = CreateCompilation(text1, options: TestOptions.DebugExe.WithNullableContextOptions(NullableContextOptions.Enable), parseOptions: DefaultParseOptions); + verifyModel(comp, comp.SyntaxTrees[0], nullableEnabled: true); + + static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, bool nullableEnabled = false) + { + Assert.Equal(nullableEnabled, comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + var model1 = comp.GetSemanticModel(tree1); + + verifyModelForGlobalStatements(tree1, model1); + + var unit1 = (CompilationUnitSyntax)tree1.GetRoot(); + var localRef = unit1.DescendantNodes().OfType().First(); + var refSymbol = model1.GetSymbolInfo(localRef).Symbol; + Assert.Equal("void local()", refSymbol.ToTestDisplayString()); + Assert.Contains(refSymbol.Name, model1.LookupNames(localRef.SpanStart)); + Assert.Contains(refSymbol, model1.LookupSymbols(localRef.SpanStart)); + Assert.Same(refSymbol, model1.LookupSymbols(localRef.SpanStart, name: refSymbol.Name).Single()); + var operation1 = model1.GetOperation(localRef.Parent); + Assert.NotNull(operation1); + Assert.IsAssignableFrom(operation1); + + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation1.Parent.Parent).Parent)); + + model1.VerifyOperationTree(unit1, +@" +IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'local(); ... iteLine(2);') + BlockBody: + IBlockOperation (2 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'local(); ... iteLine(2);') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'local();') + Expression: + IInvocationOperation (void local()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'local()') + Instance Receiver: + null + Arguments(0) + ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null) (Syntax: 'void local( ... iteLine(2);') + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') + ReturnedValue: + null + ExpressionBody: + null +"); + var localDecl = unit1.DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Same(declSymbol.ContainingSymbol, model1.GetDeclaredSymbol(unit1)); + Assert.Same(declSymbol.ContainingSymbol, model1.GetDeclaredSymbol((SyntaxNode)unit1)); + Assert.Same(refSymbol, declSymbol); + Assert.Contains(declSymbol.Name, model1.LookupNames(localDecl.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localDecl.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: declSymbol.Name).Single()); + var operation2 = model1.GetOperation(localDecl); + Assert.NotNull(operation2); + Assert.IsAssignableFrom(operation2); + + static void verifyModelForGlobalStatements(SyntaxTree tree1, SemanticModel model1) + { + var symbolInfo = model1.GetSymbolInfo(tree1.GetRoot()); + Assert.Null(symbolInfo.Symbol); + Assert.Empty(symbolInfo.CandidateSymbols); + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + var typeInfo = model1.GetTypeInfo(tree1.GetRoot()); + Assert.Null(typeInfo.Type); + Assert.Null(typeInfo.ConvertedType); + + foreach (var globalStatement in tree1.GetRoot().DescendantNodes().OfType()) + { + symbolInfo = model1.GetSymbolInfo(globalStatement); + Assert.Null(model1.GetOperation(globalStatement)); + Assert.Null(symbolInfo.Symbol); + Assert.Empty(symbolInfo.CandidateSymbols); + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + typeInfo = model1.GetTypeInfo(globalStatement); + Assert.Null(typeInfo.Type); + Assert.Null(typeInfo.ConvertedType); + } + } + } + } + + [Fact] + public void Simple_06_02() + { + var text1 = @"local();"; + var text2 = @"void local() => System.Console.WriteLine(2);"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (1,1): error CS9001: Only one compilation unit can have top-level statements. + // void local() => System.Console.WriteLine(2); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(1, 1), + // (1,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(1, 1), + // (1,6): warning CS8321: The local function 'local' is declared but never used + // void local() => System.Console.WriteLine(2); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(1, 6) + ); + + verifyModel(comp, comp.SyntaxTrees[0], comp.SyntaxTrees[1]); + + comp = CreateCompilation(new[] { text2, text1 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (1,1): error CS9001: Only one compilation unit can have top-level statements. + // local(); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "local").WithLocation(1, 1), + // (1,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(1, 1), + // (1,6): warning CS8321: The local function 'local' is declared but never used + // void local() => System.Console.WriteLine(2); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(1, 6) + ); + + verifyModel(comp, comp.SyntaxTrees[1], comp.SyntaxTrees[0]); + + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe.WithNullableContextOptions(NullableContextOptions.Enable), parseOptions: DefaultParseOptions); + verifyModel(comp, comp.SyntaxTrees[0], comp.SyntaxTrees[1], nullableEnabled: true); + + static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, SyntaxTree tree2, bool nullableEnabled = false) + { + Assert.Equal(nullableEnabled, comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + var model1 = comp.GetSemanticModel(tree1); + + verifyModelForGlobalStatements(tree1, model1); + + var unit1 = (CompilationUnitSyntax)tree1.GetRoot(); + var localRef = unit1.DescendantNodes().OfType().Single(); + var refSymbol = model1.GetSymbolInfo(localRef).Symbol; + var refMethod = model1.GetDeclaredSymbol(unit1); + Assert.NotNull(refMethod); + Assert.Null(refSymbol); + var name = localRef.Identifier.ValueText; + Assert.DoesNotContain(name, model1.LookupNames(localRef.SpanStart)); + Assert.Empty(model1.LookupSymbols(localRef.SpanStart).Where(s => s.Name == name)); + Assert.Empty(model1.LookupSymbols(localRef.SpanStart, name: name)); + var operation1 = model1.GetOperation(localRef.Parent); + Assert.NotNull(operation1); + Assert.IsAssignableFrom(operation1); + + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation1.Parent.Parent).Parent)); + + model1.VerifyOperationTree(unit1, +@" +IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'local();') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid, IsImplicit) (Syntax: 'local();') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'local();') + Expression: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local()') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local') + Children(0) + ExpressionBody: + null +"); + + SyntaxTreeSemanticModel syntaxTreeModel = ((SyntaxTreeSemanticModel)model1); + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit1]; + + var model2 = comp.GetSemanticModel(tree2); + + verifyModelForGlobalStatements(tree2, model2); + + var unit2 = (CompilationUnitSyntax)tree2.GetRoot(); + var declMethod = model2.GetDeclaredSymbol(unit2); + var localDecl = unit2.DescendantNodes().OfType().Single(); + var declSymbol = model2.GetDeclaredSymbol(localDecl); + Assert.Equal("void local()", declSymbol.ToTestDisplayString()); + Assert.Same(declSymbol.ContainingSymbol, declMethod); + Assert.NotEqual(refMethod, declMethod); + Assert.Contains(declSymbol.Name, model2.LookupNames(localDecl.SpanStart)); + Assert.Contains(declSymbol, model2.LookupSymbols(localDecl.SpanStart)); + Assert.Same(declSymbol, model2.LookupSymbols(localDecl.SpanStart, name: declSymbol.Name).Single()); + var operation2 = model2.GetOperation(localDecl); + Assert.NotNull(operation2); + Assert.IsAssignableFrom(operation2); + + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation2.Parent).Parent)); + + var isInvalid = comp.SyntaxTrees[1] == tree2 ? ", IsInvalid" : ""; + + model2.VerifyOperationTree(unit2, +@" +IMethodBodyOperation (OperationKind.MethodBody, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null" + isInvalid + @", IsImplicit) (Syntax: 'void local( ... iteLine(2);') + ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') + ReturnedValue: + null + ExpressionBody: + null +"); + + static void verifyModelForGlobalStatements(SyntaxTree tree1, SemanticModel model1) + { + var symbolInfo = model1.GetSymbolInfo(tree1.GetRoot()); + Assert.Null(symbolInfo.Symbol); + Assert.Empty(symbolInfo.CandidateSymbols); + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + var typeInfo = model1.GetTypeInfo(tree1.GetRoot()); + Assert.Null(typeInfo.Type); + Assert.Null(typeInfo.ConvertedType); + + foreach (var globalStatement in tree1.GetRoot().DescendantNodes().OfType()) + { + symbolInfo = model1.GetSymbolInfo(globalStatement); + Assert.Null(model1.GetOperation(globalStatement)); + Assert.Null(symbolInfo.Symbol); + Assert.Empty(symbolInfo.CandidateSymbols); + Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); + typeInfo = model1.GetTypeInfo(globalStatement); + Assert.Null(typeInfo.Type); + Assert.Null(typeInfo.ConvertedType); + } + } + } + } + + [Fact] + public void Simple_07() + { + var text1 = @" +var i = 1; +local(); +"; + var text2 = @" +void local() => System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // void local() => System.Console.WriteLine(i); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(2, 1), + // (2,5): warning CS0219: The variable 'i' is assigned but its value is never used + // var i = 1; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(2, 5), + // (2,6): warning CS8321: The local function 'local' is declared but never used + // void local() => System.Console.WriteLine(i); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(2, 6), + // (2,42): error CS0103: The name 'i' does not exist in the current context + // void local() => System.Console.WriteLine(i); + Diagnostic(ErrorCode.ERR_NameNotInContext, "i").WithArguments("i").WithLocation(2, 42), + // (3,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(3, 1) + ); + + verifyModel(comp, comp.SyntaxTrees[0], comp.SyntaxTrees[1]); + + comp = CreateCompilation(new[] { text2, text1 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // var i = 1; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "var").WithLocation(2, 1), + // (2,5): warning CS0219: The variable 'i' is assigned but its value is never used + // var i = 1; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(2, 5), + // (2,6): warning CS8321: The local function 'local' is declared but never used + // void local() => System.Console.WriteLine(i); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(2, 6), + // (2,42): error CS0103: The name 'i' does not exist in the current context + // void local() => System.Console.WriteLine(i); + Diagnostic(ErrorCode.ERR_NameNotInContext, "i").WithArguments("i").WithLocation(2, 42), + // (3,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(3, 1) + ); + + verifyModel(comp, comp.SyntaxTrees[1], comp.SyntaxTrees[0]); + + static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, SyntaxTree tree2) + { + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.Int32 i", declSymbol.ToTestDisplayString()); + Assert.Contains(declSymbol.Name, model1.LookupNames(localDecl.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localDecl.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: declSymbol.Name).Single()); + Assert.NotNull(model1.GetOperation(tree1.GetRoot())); + var operation1 = model1.GetOperation(localDecl); + Assert.NotNull(operation1); + Assert.IsAssignableFrom(operation1); + + var localFuncRef = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local").Single(); + Assert.Contains(declSymbol.Name, model1.LookupNames(localFuncRef.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localFuncRef.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localFuncRef.SpanStart, name: declSymbol.Name).Single()); + + Assert.DoesNotContain(declSymbol, model1.AnalyzeDataFlow(localDecl.Ancestors().OfType().First()).DataFlowsOut); + + var model2 = comp.GetSemanticModel(tree2); + var localRef = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "i").Single(); + var refSymbol = model2.GetSymbolInfo(localRef).Symbol; + Assert.Null(refSymbol); + var name = localRef.Identifier.ValueText; + Assert.DoesNotContain(name, model2.LookupNames(localRef.SpanStart)); + Assert.Empty(model2.LookupSymbols(localRef.SpanStart).Where(s => s.Name == name)); + Assert.Empty(model2.LookupSymbols(localRef.SpanStart, name: name)); + Assert.NotNull(model2.GetOperation(tree2.GetRoot())); + var operation2 = model2.GetOperation(localRef); + Assert.NotNull(operation2); + Assert.IsAssignableFrom(operation2); + + Assert.DoesNotContain(declSymbol, model2.AnalyzeDataFlow(localRef).DataFlowsIn); + } + } + + [Fact] + public void Simple_08() + { + var text1 = @" +var i = 1; +System.Console.Write(i++); +System.Console.Write(i); +"; + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "12"); + + var tree1 = comp.SyntaxTrees[0]; + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.Int32 i", declSymbol.ToTestDisplayString()); + Assert.Contains(declSymbol.Name, model1.LookupNames(localDecl.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localDecl.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: declSymbol.Name).Single()); + + var localRefs = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "i").ToArray(); + Assert.Equal(2, localRefs.Length); + + foreach (var localRef in localRefs) + { + var refSymbol = model1.GetSymbolInfo(localRef).Symbol; + Assert.Same(declSymbol, refSymbol); + Assert.Contains(declSymbol.Name, model1.LookupNames(localRef.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localRef.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localRef.SpanStart, name: declSymbol.Name).Single()); + } + } + + [Fact] + public void Simple_09() + { + var text1 = @" +var i = 1; +local(); +void local() => System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "1"); + + verifyModel(comp, comp.SyntaxTrees[0]); + + static void verifyModel(CSharpCompilation comp, SyntaxTree tree1) + { + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.Int32 i", declSymbol.ToTestDisplayString()); + Assert.Contains(declSymbol.Name, model1.LookupNames(localDecl.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localDecl.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: declSymbol.Name).Single()); + Assert.NotNull(model1.GetOperation(tree1.GetRoot())); + var operation1 = model1.GetOperation(localDecl); + Assert.NotNull(operation1); + Assert.IsAssignableFrom(operation1); + + var localFuncRef = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local").Single(); + Assert.Contains(declSymbol.Name, model1.LookupNames(localFuncRef.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localFuncRef.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localFuncRef.SpanStart, name: declSymbol.Name).Single()); + + Assert.Contains(declSymbol, model1.AnalyzeDataFlow(localDecl.Ancestors().OfType().First()).DataFlowsOut); + + var localRef = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "i").Single(); + var refSymbol = model1.GetSymbolInfo(localRef).Symbol; + Assert.Same(declSymbol, refSymbol); + Assert.Contains(refSymbol.Name, model1.LookupNames(localRef.SpanStart)); + Assert.Contains(refSymbol, model1.LookupSymbols(localRef.SpanStart)); + Assert.Same(refSymbol, model1.LookupSymbols(localRef.SpanStart, name: refSymbol.Name).Single()); + var operation2 = model1.GetOperation(localRef); + Assert.NotNull(operation2); + Assert.IsAssignableFrom(operation2); + + // The following assert fails due to https://github.com/dotnet/roslyn/issues/41853, enable once the issue is fixed. + //Assert.Contains(declSymbol, model1.AnalyzeDataFlow(localRef).DataFlowsIn); + } + } + + [Fact] + public void LanguageVersion_01() + { + var text = @"System.Console.WriteLine(""Hi!"");"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular8); + + comp.VerifyDiagnostics( + // (1,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_FeatureInPreview, @"System.Console.WriteLine(""Hi!"");").WithArguments("top-level statements").WithLocation(1, 1) + ); + } + + [Fact] + public void WithinType_01() + { + var text = @" +class Test +{ + System.Console.WriteLine(""Hi!""); +} +"; + + var comp = CreateCompilation(text, parseOptions: DefaultParseOptions); + + var expected = new[] { + // (4,29): error CS1519: Invalid token '(' in class, struct, or interface member declaration + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "(").WithArguments("(").WithLocation(4, 29), + // (4,30): error CS1031: Type expected + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_TypeExpected, @"""Hi!""").WithLocation(4, 30), + // (4,30): error CS8124: Tuple must contain at least two elements. + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_TupleTooFewElements, @"""Hi!""").WithLocation(4, 30), + // (4,30): error CS1026: ) expected + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_CloseParenExpected, @"""Hi!""").WithLocation(4, 30), + // (4,30): error CS1519: Invalid token '"Hi!"' in class, struct, or interface member declaration + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, @"""Hi!""").WithArguments(@"""Hi!""").WithLocation(4, 30) + }; + + comp.GetDiagnostics(CompilationStage.Parse, includeEarlierStages: false, cancellationToken: default).Verify(expected); + comp.VerifyDiagnostics(expected); + } + + [Fact] + public void WithinNamespace_01() + { + var text = @" +namespace Test +{ + System.Console.WriteLine(""Hi!""); +} +"; + + var comp = CreateCompilation(text, parseOptions: DefaultParseOptions); + + var expected = new[] { + // (4,20): error CS0116: A namespace cannot directly contain members such as fields or methods + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "WriteLine").WithLocation(4, 20), + // (4,30): error CS1026: ) expected + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_CloseParenExpected, @"""Hi!""").WithLocation(4, 30), + // (4,30): error CS1022: Type or namespace definition, or end-of-file expected + // System.Console.WriteLine("Hi!"); + Diagnostic(ErrorCode.ERR_EOFExpected, @"""Hi!""").WithLocation(4, 30) + }; + + comp.GetDiagnostics(CompilationStage.Parse, includeEarlierStages: false, cancellationToken: default).Verify(expected); + comp.VerifyDiagnostics(expected); + } + + [Fact] + public void LocalDeclarationStatement_01() + { + var text = @" +string s = ""Hi!""; +System.Console.WriteLine(s); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var declarator = tree.GetRoot().DescendantNodes().OfType().Single(); + var reference = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "s").Single(); + + var local = model.GetDeclaredSymbol(declarator); + Assert.Same(local, model.GetSymbolInfo(reference).Symbol); + Assert.Equal("System.String s", local.ToTestDisplayString()); + Assert.Equal(SymbolKind.Local, local.Kind); + + Assert.Equal(SymbolKind.Method, local.ContainingSymbol.Kind); + Assert.False(local.ContainingSymbol.IsImplicitlyDeclared); + Assert.Equal(SymbolKind.NamedType, local.ContainingSymbol.ContainingSymbol.Kind); + Assert.True(local.ContainingSymbol.ContainingSymbol.IsImplicitlyDeclared); + Assert.True(((INamespaceSymbol)local.ContainingSymbol.ContainingSymbol.ContainingSymbol).IsGlobalNamespace); + } + + [Fact] + public void LocalDeclarationStatement_02() + { + var text = @" +new string a = ""Hi!""; +System.Console.WriteLine(a); +public string b = ""Hi!""; +System.Console.WriteLine(b); +static string c = ""Hi!""; +System.Console.WriteLine(c); +readonly string d = ""Hi!""; +System.Console.WriteLine(d); +volatile string e = ""Hi!""; +System.Console.WriteLine(e); +[System.Obsolete()] +string f = ""Hi!""; +System.Console.WriteLine(f); +[System.Obsolete()] +const string g = ""Hi!""; +System.Console.WriteLine(g); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,12): error CS0116: A namespace cannot directly contain members such as fields or methods + // new string a = "Hi!"; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "a").WithLocation(2, 12), + // (2,12): warning CS0109: The member '.a' does not hide an accessible member. The new keyword is not required. + // new string a = "Hi!"; + Diagnostic(ErrorCode.WRN_NewNotRequired, "a").WithArguments(".a").WithLocation(2, 12), + // (3,26): error CS0103: The name 'a' does not exist in the current context + // System.Console.WriteLine(a); + Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(3, 26), + // (4,15): error CS0116: A namespace cannot directly contain members such as fields or methods + // public string b = "Hi!"; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "b").WithLocation(4, 15), + // (5,26): error CS0103: The name 'b' does not exist in the current context + // System.Console.WriteLine(b); + Diagnostic(ErrorCode.ERR_NameNotInContext, "b").WithArguments("b").WithLocation(5, 26), + // (6,1): error CS0106: The modifier 'static' is not valid for this item + // static string c = "Hi!"; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(6, 1), + // (8,1): error CS0106: The modifier 'readonly' is not valid for this item + // readonly string d = "Hi!"; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(8, 1), + // (10,1): error CS0106: The modifier 'volatile' is not valid for this item + // volatile string e = "Hi!"; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "volatile").WithArguments("volatile").WithLocation(10, 1), + // (12,1): error CS7014: Attributes are not valid in this context. + // [System.Obsolete()] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[System.Obsolete()]").WithLocation(12, 1), + // (15,1): error CS7014: Attributes are not valid in this context. + // [System.Obsolete()] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[System.Obsolete()]").WithLocation(15, 1) + ); + } + + [Fact] + public void LocalDeclarationStatement_03() + { + var text = @" +string a = ""1""; +string a = ""2""; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,8): warning CS0219: The variable 'a' is assigned but its value is never used + // string a = "1"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a").WithLocation(2, 8), + // (3,8): error CS0128: A local variable or function named 'a' is already defined in this scope + // string a = "2"; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "a").WithArguments("a").WithLocation(3, 8), + // (3,8): warning CS0219: The variable 'a' is assigned but its value is never used + // string a = "2"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a").WithLocation(3, 8) + ); + } + + [Fact] + public void LocalDeclarationStatement_04() + { + var text = @" +using System; +using System.Threading.Tasks; + +var s = await local(); +System.Console.WriteLine(s); + +async Task local() +{ + await Task.Factory.StartNew(() => 5); + return ""Hi!""; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void LocalDeclarationStatement_05() + { + var text = @" +const string s = ""Hi!""; +System.Console.WriteLine(s); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void LocalDeclarationStatement_06() + { + var text = @" +a.ToString(); +string a = ""2""; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS0841: Cannot use local variable 'a' before it is declared + // a.ToString(); + Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "a").WithArguments("a").WithLocation(2, 1) + ); + } + + [Fact] + public void LocalDeclarationStatement_07() + { + var text1 = @" +string x = ""1""; +System.Console.Write(x); +"; + var text2 = @" +int x = 1; +System.Console.Write(x); +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // int x = 1; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "int").WithLocation(2, 1) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().Single()); + Assert.Equal("System.String x", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single()).Symbol); + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + var symbol2 = model2.GetDeclaredSymbol(tree2.GetRoot().DescendantNodes().OfType().Single()); + Assert.Equal("System.Int32 x", symbol2.ToTestDisplayString()); + Assert.Same(symbol2, model2.GetSymbolInfo(tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single()).Symbol); + } + + [Fact] + public void LocalDeclarationStatement_08() + { + var text = @" +int a = 0; +int b = 0; +int c = -100; + +ref int d = ref c; +d = 300; +d = ref local(true, ref a, ref b); +d = 100; +d = ref local(false, ref a, ref b); +d = 200; + +System.Console.Write(a); +System.Console.Write(' '); +System.Console.Write(b); +System.Console.Write(' '); +System.Console.Write(c); + +ref int local(bool flag, ref int a, ref int b) +{ + return ref flag ? ref a : ref b; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "100 200 300", verify: Verification.Skipped); + } + + [Fact] + public void LocalDeclarationStatement_09() + { + var text = @" +using var a = new MyDisposable(); +System.Console.Write(1); + +class MyDisposable : System.IDisposable +{ + public void Dispose() + { + System.Console.Write(2); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "12", verify: Verification.Skipped); + } + + [Fact] + public void LocalDeclarationStatement_10() + { + string source = @" +await using var x = new C(); +System.Console.Write(""body ""); + +class C : System.IAsyncDisposable, System.IDisposable +{ + public System.Threading.Tasks.ValueTask DisposeAsync() + { + System.Console.Write(""DisposeAsync""); + return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask); + } + public void Dispose() + { + System.Console.Write(""IGNORED""); + } +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "body DisposeAsync"); + } + + [Fact] + public void LocalDeclarationStatement_11() + { + var text1 = @" +string x = ""1""; +System.Console.Write(x); +int x = 1; +System.Console.Write(x); +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,5): error CS0128: A local variable or function named 'x' is already defined in this scope + // int x = 1; + Diagnostic(ErrorCode.ERR_LocalDuplicate, "x").WithArguments("x").WithLocation(4, 5), + // (4,5): warning CS0219: The variable 'x' is assigned but its value is never used + // int x = 1; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(4, 5) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().First()); + Assert.Equal("System.String x", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").First()).Symbol); + + var symbol2 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().Skip(1).Single()); + Assert.Equal("System.Int32 x", symbol2.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Skip(1).Single()).Symbol); + } + + [Fact] + public void LocalDeclarationStatement_12() + { + var text = @" +(int x, int y) = (1, 2); +System.Console.WriteLine(x+y); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "3"); + } + + [Fact] + public void LocalDeclarationStatement_13() + { + var text = @" +var (x, y) = (1, 2); +System.Console.WriteLine(x+y); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "3"); + } + + [Fact] + public void LocalDeclarationStatement_14() + { + var text1 = @" +string args = ""1""; +System.Console.Write(args); +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,8): error CS0136: A local or parameter named 'args' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // string args = "1"; + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "args").WithArguments("args").WithLocation(2, 8) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().First()); + Assert.Equal("System.String args", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "args").Single()).Symbol); + } + + [Fact] + public void LocalDeclarationStatement_15() + { + var text1 = @" +using System.Linq; +string x = null; +_ = from x in new object[0] select x; +System.Console.Write(x); +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,10): error CS1931: The range variable 'x' conflicts with a previous declaration of 'x' + // _ = from x in new object[0] select x; + Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "x").WithArguments("x").WithLocation(4, 10) + ); + } + + [Fact] + public void LocalDeclarationStatement_16() + { + var text = @" +System.Console.WriteLine(); +string await = ""Hi!""; +System.Console.WriteLine(await); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,8): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression + // string await = "Hi!"; + Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(3, 8), + // (3,8): warning CS0219: The variable 'await' is assigned but its value is never used + // string await = "Hi!"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "await").WithArguments("await").WithLocation(3, 8), + // (4,31): error CS1525: Invalid expression term ')' + // System.Console.WriteLine(await); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(4, 31) + ); + + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnType.IsErrorType()); + AssertEntryPointParameter(entryPoint); + } + + [Fact] + public void LocalDeclarationStatement_17() + { + var text = @" +string async = ""Hi!""; +System.Console.WriteLine(async); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void LocalDeclarationStatement_18() + { + var text = @" +int c = -100; +ref int d = ref c; +System.Console.Write(d); +await System.Threading.Tasks.Task.Yield(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,9): error CS8177: Async methods cannot have by-reference locals + // ref int d = ref c; + Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "d").WithLocation(3, 9) + ); + } + + [Fact] + public void UsingStatement_01() + { + string source = @" +await using (var x = new C()) +{ + System.Console.Write(""body ""); +} + +class C : System.IAsyncDisposable, System.IDisposable +{ + public System.Threading.Tasks.ValueTask DisposeAsync() + { + System.Console.Write(""DisposeAsync""); + return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask); + } + public void Dispose() + { + System.Console.Write(""IGNORED""); + } +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "body DisposeAsync"); + } + + [Fact] + public void UsingStatement_02() + { + string source = @" +await using (new C()) +{ + System.Console.Write(""body ""); +} + +class C : System.IAsyncDisposable, System.IDisposable +{ + public System.Threading.Tasks.ValueTask DisposeAsync() + { + System.Console.Write(""DisposeAsync""); + return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask); + } + public void Dispose() + { + System.Console.Write(""IGNORED""); + } +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "body DisposeAsync"); + } + + [Fact] + public void UsingStatement_03() + { + string source = @" +using (new C()) +{ + System.Console.Write(""body ""); +} + +class C : System.IDisposable +{ + public void Dispose() + { + System.Console.Write(""Dispose""); + } +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "body Dispose"); + } + + [Fact] + public void ForeachStatement_01() + { + string source = @" +using System.Threading.Tasks; + +await foreach (var i in new C()) +{ +} + +System.Console.Write(""Done""); + +class C +{ + public Enumerator GetAsyncEnumerator() + { + return new Enumerator(); + } + public sealed class Enumerator + { + public async Task MoveNextAsync() + { + System.Console.Write(""MoveNextAsync ""); + await Task.Yield(); + return false; + } + public int Current + { + get => throw null; + } + public async Task DisposeAsync() + { + System.Console.Write(""DisposeAsync ""); + await Task.Yield(); + } + } +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: "MoveNextAsync DisposeAsync Done"); + } + + [Fact] + public void ForeachStatement_02() + { + var text = @" +int i = 0; +foreach (var j in new [] {2, 3}) +{ + i += j; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "5"); + } + + [Fact] + public void ForeachStatement_03() + { + var text = @" +int i = 0; +foreach (var (j, k) in new [] {(2,200), (3,300)}) +{ + i += j; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "5"); + } + + [Fact] + public void LocalUsedBeforeDeclaration_01() + { + var text1 = @" +const string x = y; +System.Console.Write(x); +"; + var text2 = @" +const string y = x; +System.Console.Write(y); +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // const string y = x; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "const").WithLocation(2, 1), + // (2,18): error CS0103: The name 'y' does not exist in the current context + // const string x = y; + Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y").WithLocation(2, 18), + // (2,18): error CS0103: The name 'x' does not exist in the current context + // const string y = x; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(2, 18) + ); + + comp = CreateCompilation(new[] { "System.Console.WriteLine();", text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // const string x = y; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "const").WithLocation(2, 1), + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // const string y = x; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "const").WithLocation(2, 1), + // (2,18): error CS0103: The name 'y' does not exist in the current context + // const string x = y; + Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y").WithLocation(2, 18), + // (2,18): error CS0103: The name 'x' does not exist in the current context + // const string y = x; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(2, 18) + ); + } + + [Fact] + public void LocalUsedBeforeDeclaration_02() + { + var text1 = @" +var x = y; +System.Console.Write(x); +"; + var text2 = @" +var y = x; +System.Console.Write(y); +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // var y = x; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "var").WithLocation(2, 1), + // (2,9): error CS0103: The name 'y' does not exist in the current context + // var x = y; + Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y").WithLocation(2, 9), + // (2,9): error CS0103: The name 'x' does not exist in the current context + // var y = x; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(2, 9) + ); + + comp = CreateCompilation(new[] { "System.Console.WriteLine();", text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // var x = y; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "var").WithLocation(2, 1), + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // var y = x; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "var").WithLocation(2, 1), + // (2,9): error CS0103: The name 'y' does not exist in the current context + // var x = y; + Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y").WithLocation(2, 9), + // (2,9): error CS0103: The name 'x' does not exist in the current context + // var y = x; + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(2, 9) + ); + } + + [Fact] + public void LocalUsedBeforeDeclaration_03() + { + var text1 = @" +string x = ""x""; +System.Console.Write(x); +"; + var text2 = @" +class C1 +{ + void Test() + { + System.Console.Write(x); + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,30): error CS9000: Cannot use local variable or local function 'x' declared in a top-level statement in this context. + // System.Console.Write(x); + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "x").WithArguments("x").WithLocation(6, 30) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + var nameRef = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single(); + var symbol2 = model2.GetSymbolInfo(nameRef).Symbol; + Assert.Equal("System.String x", symbol2.ToTestDisplayString()); + Assert.Equal("System.String", model2.GetTypeInfo(nameRef).Type.ToTestDisplayString()); + Assert.Null(model2.GetOperation(tree2.GetRoot())); + + comp = CreateCompilation(new[] { text2, text1 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,30): error CS9000: Cannot use local variable or local function 'x' declared in a top-level statement in this context. + // System.Console.Write(x); + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "x").WithArguments("x").WithLocation(6, 30) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + tree2 = comp.SyntaxTrees[0]; + model2 = comp.GetSemanticModel(tree2); + nameRef = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single(); + symbol2 = model2.GetSymbolInfo(nameRef).Symbol; + Assert.Equal("System.String x", symbol2.ToTestDisplayString()); + Assert.Equal("System.String", model2.GetTypeInfo(nameRef).Type.ToTestDisplayString()); + Assert.Null(model2.GetOperation(tree2.GetRoot())); + } + + [Fact] + public void LocalUsedBeforeDeclaration_04() + { + var text1 = @" +string x = ""x""; +local(); +"; + var text2 = @" +void local() +{ + System.Console.Write(x); +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // void local() + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(2, 1), + // (2,6): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(2, 6), + // (2,8): warning CS0219: The variable 'x' is assigned but its value is never used + // string x = "x"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(2, 8), + // (3,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(3, 1), + // (4,26): error CS0103: The name 'x' does not exist in the current context + // System.Console.Write(x); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(4, 26) + ); + + comp = CreateCompilation(new[] { text2, text1 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // string x = "x"; + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "string").WithLocation(2, 1), + // (2,6): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(2, 6), + // (2,8): warning CS0219: The variable 'x' is assigned but its value is never used + // string x = "x"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(2, 8), + // (3,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(3, 1), + // (4,26): error CS0103: The name 'x' does not exist in the current context + // System.Console.Write(x); + Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(4, 26) + ); + } + + [Fact] + public void FlowAnalysis_01() + { + var text = @" +#nullable enable +string a = ""1""; +string? b; +System.Console.WriteLine(b); +string? c = null; +c.ToString(); +d: System.Console.WriteLine(); +string e() => ""1""; + +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (3,8): warning CS0219: The variable 'a' is assigned but its value is never used + // string a = "1"; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a").WithLocation(3, 8), + // (5,26): error CS0165: Use of unassigned local variable 'b' + // System.Console.WriteLine(b); + Diagnostic(ErrorCode.ERR_UseDefViolation, "b").WithArguments("b").WithLocation(5, 26), + // (7,1): warning CS8602: Dereference of a possibly null reference. + // c.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(7, 1), + // (8,1): warning CS0164: This label has not been referenced + // d: System.Console.WriteLine(); + Diagnostic(ErrorCode.WRN_UnreferencedLabel, "d").WithLocation(8, 1), + // (9,8): warning CS8321: The local function 'e' is declared but never used + // string e() => "1"; + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "e").WithArguments("e").WithLocation(9, 8) + ); + + var tree = comp.SyntaxTrees.Single(); + var reference = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "c").Single(); + + var model1 = comp.GetSemanticModel(tree); + Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, model1.GetTypeInfo(reference).Nullability.FlowState); + + var model2 = comp.GetSemanticModel(tree); + Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, model1.GetTypeInfo(reference).Nullability.FlowState); + } + + [Fact] + public void FlowAnalysis_02() + { + var text = @" +System.Console.WriteLine(); + +if (args.Length == 0) +{ + return 10; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS0161: '': not all code paths return a value + // System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_ReturnExpected, @"System.Console.WriteLine(); + +if (args.Length == 0) +{ + return 10; +} +").WithArguments("").WithLocation(2, 1) + ); + } + + [Fact] + public void NullableRewrite_01() + { + var text1 = @" +void local1() +{ + System.Console.WriteLine(""local1 - "" + s); +} +"; + var text2 = @" +using System; + +string s = ""Hello world!""; + +foreach (var c in s) +{ + Console.Write(c); +} + +goto label1; +label1: Console.WriteLine(); + +local1(); +local2(); +"; + var text3 = @" +void local2() +{ + System.Console.WriteLine(""local2 - "" + s); +} +"; + + var comp = CreateCompilation(new[] { text1, text2, text3 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + var tree = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree); + + foreach (var id in tree.GetRoot().DescendantNodes().OfType()) + { + _ = model1.GetTypeInfo(id).Nullability; + } + + var model2 = comp.GetSemanticModel(tree); + foreach (var id in tree.GetRoot().DescendantNodes().OfType()) + { + _ = model2.GetTypeInfo(id).Nullability; + } + } + + [Fact] + public void Scope_01() + { + var text = @" +using alias1 = Test; + +string Test = ""1""; +System.Console.WriteLine(Test); + +class Test {} + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 5 + Test.ToString(); // 6 + Test.EndsWith(null); // 7 + _ = nameof(Test); // 8 + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 20), + // (34,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(34, 38), + // (35,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(35, 13), + // (36,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(36, 13), + // (37,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(37, 24) + ); + + var getHashCode = ((Compilation)comp).GetMember("System.Object." + nameof(GetHashCode)); + var testType = ((Compilation)comp).GetTypeByMetadataName("Test"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().First(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.String Test", declSymbol.ToTestDisplayString()); + var names = model1.LookupNames(localDecl.SpanStart); + Assert.Contains(getHashCode.Name, names); + var symbols = model1.LookupSymbols(localDecl.SpanStart); + Assert.Contains(getHashCode, symbols); + Assert.Same(getHashCode, model1.LookupSymbols(localDecl.SpanStart, name: getHashCode.Name).Single()); + + Assert.Contains("Test", names); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: "Test").Single()); + + symbols = model1.LookupNamespacesAndTypes(localDecl.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupNamespacesAndTypes(localDecl.SpanStart, name: "Test").Single()); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var nameRefs = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "Test").ToArray(); + + var nameRef = nameRefs[1]; + Assert.Equal("System.Console.WriteLine(Test)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + nameRef = nameRefs[0]; + Assert.Equal("using alias1 = Test;", nameRef.Parent.ToString()); + + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + names = model.LookupNames(nameRef.SpanStart); + Assert.DoesNotContain(getHashCode.Name, names); + Assert.Contains("Test", names); + + symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(getHashCode, symbols); + Assert.Empty(model.LookupSymbols(nameRef.SpanStart, name: getHashCode.Name)); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + nameRef = nameRefs[2]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + Assert.DoesNotContain(getHashCode.Name, model.LookupNames(nameRef.SpanStart)); + verifyModel(declSymbol, model, nameRef); + + nameRef = nameRefs[4]; + Assert.Equal("System.Console.WriteLine(Test)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model, nameRef); + + nameRef = nameRefs[8]; + Assert.Equal("using alias2 = Test;", nameRef.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model, nameRef); + + nameRef = nameRefs[9]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + Assert.DoesNotContain(getHashCode.Name, model.LookupNames(nameRef.SpanStart)); + verifyModel(declSymbol, model, nameRef); + + nameRef = nameRefs[11]; + Assert.Equal("System.Console.WriteLine(Test)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model, nameRef); + + void verifyModel(ISymbol declSymbol, SemanticModel model, IdentifierNameSyntax nameRef) + { + var names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + var symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + symbols = model.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model.LookupNamespacesAndTypes(nameRef.SpanStart, name: "Test").Single()); + } + } + + [Fact] + public void Scope_02() + { + var text1 = @" +string Test = ""1""; +System.Console.WriteLine(Test); +"; + var text2 = @" +using alias1 = Test; + +class Test {} + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 5 + Test.ToString(); // 6 + Test.EndsWith(null); // 7 + _ = nameof(Test); // 8 + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 20), + // (31,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(31, 38), + // (32,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(32, 13), + // (33,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(33, 13), + // (34,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(34, 24) + ); + + var getHashCode = ((Compilation)comp).GetMember("System.Object." + nameof(GetHashCode)); + var testType = ((Compilation)comp).GetTypeByMetadataName("Test"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.String Test", declSymbol.ToTestDisplayString()); + var names = model1.LookupNames(localDecl.SpanStart); + Assert.Contains(getHashCode.Name, names); + var symbols = model1.LookupSymbols(localDecl.SpanStart); + Assert.Contains(getHashCode, symbols); + Assert.Same(getHashCode, model1.LookupSymbols(localDecl.SpanStart, name: getHashCode.Name).Single()); + + Assert.Contains("Test", names); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: "Test").Single()); + + symbols = model1.LookupNamespacesAndTypes(localDecl.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupNamespacesAndTypes(localDecl.SpanStart, name: "Test").Single()); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + Assert.Null(model2.GetDeclaredSymbol((CompilationUnitSyntax)tree2.GetRoot())); + var nameRefs = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "Test").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = Test;", nameRef.Parent.ToString()); + + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + names = model2.LookupNames(nameRef.SpanStart); + Assert.DoesNotContain(getHashCode.Name, names); + Assert.Contains("Test", names); + + symbols = model2.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(getHashCode, symbols); + Assert.Empty(model2.LookupSymbols(nameRef.SpanStart, name: getHashCode.Name)); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + nameRef = nameRefs[1]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + Assert.DoesNotContain(getHashCode.Name, model2.LookupNames(nameRef.SpanStart)); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[3]; + Assert.Equal("System.Console.WriteLine(Test)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[7]; + Assert.Equal("using alias2 = Test;", nameRef.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[8]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + Assert.DoesNotContain(getHashCode.Name, model2.LookupNames(nameRef.SpanStart)); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[10]; + Assert.Equal("System.Console.WriteLine(Test)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + void verifyModel(ISymbol declSymbol, SemanticModel model2, IdentifierNameSyntax nameRef) + { + var names = model2.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + var symbols = model2.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + symbols = model2.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "Test").Single()); + } + } + + [Fact] + public void Scope_03() + { + var text1 = @" +string Test = ""1""; +System.Console.WriteLine(Test); +"; + var text2 = @" +class Test {} + +class Derived : Test +{ + void M() + { + int Test = 0; + System.Console.WriteLine(Test++); + } +} + +namespace N1 +{ + class Derived : Test + { + void M() + { + int Test = 1; + System.Console.WriteLine(Test++); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + + comp = CreateCompilation(text1 + text2, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + + Assert.Throws(() => CreateCompilation(new[] { Parse(text1, filename: "text1", DefaultParseOptions), + Parse(text1, filename: "text2", TestOptions.Regular6) }, + options: TestOptions.DebugExe)); + + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7); + comp.VerifyDiagnostics( + // (2,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // string Test = "1"; + Diagnostic(ErrorCode.ERR_FeatureInPreview, @"string Test = ""1"";").WithArguments("top-level statements").WithLocation(2, 1) + ); + } + + [Fact] + public void Scope_04() + { + var text = @" +using alias1 = Test; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class Test {} + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 6 + Test().ToString(); // 7 + Test().EndsWith(null); // 8 + var d = new System.Func(Test); // 9 + d(); + _ = nameof(Test); // 10 + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20), + // (36,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(36, 38), + // (37,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(37, 13), + // (38,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(38, 13), + // (39,45): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // var d = new System.Func(Test); // 9 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(39, 45), + // (41,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 10 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(41, 24) + ); + + var testType = ((Compilation)comp).GetTypeByMetadataName("Test"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.String Test()", declSymbol.ToTestDisplayString()); + var names = model1.LookupNames(localDecl.SpanStart); + var symbols = model1.LookupSymbols(localDecl.SpanStart); + + Assert.Contains("Test", names); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: "Test").Single()); + + symbols = model1.LookupNamespacesAndTypes(localDecl.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupNamespacesAndTypes(localDecl.SpanStart, name: "Test").Single()); + + var nameRefs = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "Test").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = Test;", nameRef.Parent.ToString()); + + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + names = model1.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + symbols = model1.LookupSymbols(nameRef.SpanStart); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + nameRef = nameRefs[2]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + nameRef = nameRefs[4]; + Assert.Equal("System.Console.WriteLine(Test())", nameRef.Parent.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + nameRef = nameRefs[9]; + Assert.Equal("using alias2 = Test;", nameRef.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + nameRef = nameRefs[10]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + nameRef = nameRefs[12]; + Assert.Equal("System.Console.WriteLine(Test())", nameRef.Parent.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model1, nameRef); + + void verifyModel(ISymbol declSymbol, SemanticModel model2, IdentifierNameSyntax nameRef) + { + var names = model2.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + var symbols = model2.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + symbols = model2.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "Test").Single()); + } + } + + [Fact] + public void Scope_05() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +using alias1 = Test; + +class Test {} + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 6 + Test().ToString(); // 7 + Test().EndsWith(null); // 8 + var d = new System.Func(Test); // 9 + d(); + _ = nameof(Test); // 10 + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 33), + // (18,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 20), + // (33,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(33, 38), + // (34,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(34, 13), + // (35,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(35, 13), + // (36,45): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // var d = new System.Func(Test); // 9 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(36, 45), + // (38,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 10 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(38, 24) + ); + + var testType = ((Compilation)comp).GetTypeByMetadataName("Test"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.String Test()", declSymbol.ToTestDisplayString()); + var names = model1.LookupNames(localDecl.SpanStart); + var symbols = model1.LookupSymbols(localDecl.SpanStart); + + Assert.Contains("Test", names); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model1.LookupSymbols(localDecl.SpanStart, name: "Test").Single()); + + symbols = model1.LookupNamespacesAndTypes(localDecl.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupNamespacesAndTypes(localDecl.SpanStart, name: "Test").Single()); + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + var nameRefs = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "Test").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = Test;", nameRef.Parent.ToString()); + + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + names = model2.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + symbols = model2.LookupSymbols(nameRef.SpanStart); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + nameRef = nameRefs[1]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[3]; + Assert.Equal("System.Console.WriteLine(Test())", nameRef.Parent.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[8]; + Assert.Equal("using alias2 = Test;", nameRef.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[9]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + nameRef = nameRefs[11]; + Assert.Equal("System.Console.WriteLine(Test())", nameRef.Parent.Parent.Parent.Parent.ToString()); + Assert.Same(declSymbol, model2.GetSymbolInfo(nameRef).Symbol); + verifyModel(declSymbol, model2, nameRef); + + void verifyModel(ISymbol declSymbol, SemanticModel model2, IdentifierNameSyntax nameRef) + { + var names = model2.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + var symbols = model2.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(declSymbol, symbols); + Assert.Same(declSymbol, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + symbols = model2.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "Test").Single()); + } + } + + [Fact] + public void Scope_06() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +class Test {} + +class Derived : Test +{ + void M() + { + int Test() => 1; + int x = Test() + 1; + System.Console.WriteLine(x); + } +} + +namespace N1 +{ + class Derived : Test + { + void M() + { + int Test() => 1; + int x = Test() + 1; + System.Console.WriteLine(x); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + + comp = CreateCompilation(text1 + text2, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(); + + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7); + comp.VerifyDiagnostics( + // (2,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // string Test() => "1"; + Diagnostic(ErrorCode.ERR_FeatureInPreview, @"string Test() => ""1"";").WithArguments("top-level statements").WithLocation(2, 1) + ); + } + + [Fact] + public void Scope_07() + { + var text = @" +using alias1 = Test; +goto Test; +Test: System.Console.WriteLine(""1""); + +class Test {} + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + goto Test; // 1 + } +} + +namespace N1 +{ + using alias2 = Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + goto Test; // 2 + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (15,14): error CS0159: No such label 'Test' within the scope of the goto statement + // goto Test; // 1 + Diagnostic(ErrorCode.ERR_LabelNotFound, "Test").WithArguments("Test").WithLocation(15, 14), + // (30,18): error CS0159: No such label 'Test' within the scope of the goto statement + // goto Test; // 2 + Diagnostic(ErrorCode.ERR_LabelNotFound, "Test").WithArguments("Test").WithLocation(30, 18) + ); + + var testType = ((Compilation)comp).GetTypeByMetadataName("Test"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var labelDecl = tree1.GetRoot().DescendantNodes().OfType().Single(); + var declSymbol = model1.GetDeclaredSymbol(labelDecl); + Assert.Equal("Test", declSymbol.ToTestDisplayString()); + Assert.Equal(SymbolKind.Label, declSymbol.Kind); + var names = model1.LookupNames(labelDecl.SpanStart); + var symbols = model1.LookupSymbols(labelDecl.SpanStart); + + Assert.Contains("Test", names); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupSymbols(labelDecl.SpanStart, name: "Test").Single()); + + symbols = model1.LookupNamespacesAndTypes(labelDecl.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupNamespacesAndTypes(labelDecl.SpanStart, name: "Test").Single()); + + Assert.Same(declSymbol, model1.LookupLabels(labelDecl.SpanStart).Single()); + Assert.Same(declSymbol, model1.LookupLabels(labelDecl.SpanStart, name: "Test").Single()); + + var nameRefs = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "Test").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = Test;", nameRef.Parent.ToString()); + + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + names = model1.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + symbols = model1.LookupSymbols(nameRef.SpanStart); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + Assert.Empty(model1.LookupLabels(nameRef.SpanStart)); + Assert.Empty(model1.LookupLabels(nameRef.SpanStart, name: "Test")); + + nameRef = nameRefs[1]; + Assert.Equal("goto Test;", nameRef.Parent.ToString()); + Assert.Same(declSymbol, model1.GetSymbolInfo(nameRef).Symbol); + + names = model1.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + symbols = model1.LookupSymbols(nameRef.SpanStart); + + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model1.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + Assert.Same(declSymbol, model1.LookupLabels(nameRef.SpanStart).Single()); + Assert.Same(declSymbol, model1.LookupLabels(nameRef.SpanStart, name: "Test").Single()); + + nameRef = nameRefs[2]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(model1, nameRef); + + nameRef = nameRefs[4]; + Assert.Equal("goto Test;", nameRef.Parent.ToString()); + Assert.Null(model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(model1, nameRef); + + nameRef = nameRefs[5]; + Assert.Equal("using alias2 = Test;", nameRef.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(model1, nameRef); + + nameRef = nameRefs[6]; + Assert.Equal(": Test", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model1.GetSymbolInfo(nameRef).Symbol); + verifyModel(model1, nameRef); + + nameRef = nameRefs[8]; + Assert.Null(model1.GetSymbolInfo(nameRef).Symbol); + Assert.Equal("goto Test;", nameRef.Parent.ToString()); + verifyModel(model1, nameRef); + + void verifyModel(SemanticModel model2, IdentifierNameSyntax nameRef) + { + var names = model2.LookupNames(nameRef.SpanStart); + Assert.Contains("Test", names); + + var symbols = model2.LookupSymbols(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupSymbols(nameRef.SpanStart, name: "Test").Single()); + + symbols = model2.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "Test").Single()); + + Assert.Empty(model2.LookupLabels(nameRef.SpanStart)); + Assert.Empty(model2.LookupLabels(nameRef.SpanStart, name: "Test")); + } + } + + [Fact] + public void Scope_08() + { + var text = @" +goto Test; +Test: System.Console.WriteLine(""1""); + +class Test {} + +class Derived : Test +{ + void M() + { + goto Test; + Test: System.Console.WriteLine(); + } +} + +namespace N1 +{ + class Derived : Test + { + void M() + { + goto Test; + Test: System.Console.WriteLine(); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics(); + } + + [Fact] + public void Scope_09() + { + var text = @" +string Test = ""1""; +System.Console.WriteLine(Test); + +new void M() +{ + int Test = 0; + System.Console.WriteLine(Test++); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (5,10): error CS0116: A namespace cannot directly contain members such as fields or methods + // new void M() + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "M").WithLocation(5, 10), + // (5,10): warning CS0109: The member '.M()' does not hide an accessible member. The new keyword is not required. + // new void M() + Diagnostic(ErrorCode.WRN_NewNotRequired, "M").WithArguments(".M()").WithLocation(5, 10) + ); + } + + [Fact] + public void Scope_10() + { + var text = @" +string Test = ""1""; +System.Console.WriteLine(Test); + +new int F = C1.GetInt(out var Test); + +class C1 +{ + public static int GetInt(out int v) + { + v = 1; + return v; + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (5,9): error CS0116: A namespace cannot directly contain members such as fields or methods + // new int F = C1.GetInt(out var Test); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "F").WithLocation(5, 9), + // (5,9): warning CS0109: The member '.F' does not hide an accessible member. The new keyword is not required. + // new int F = C1.GetInt(out var Test); + Diagnostic(ErrorCode.WRN_NewNotRequired, "F").WithArguments(".F").WithLocation(5, 9) + ); + } + + [Fact] + public void Scope_11() + { + var text = @" +goto Test; +Test: System.Console.WriteLine(); + +new void M() +{ + goto Test; + Test: System.Console.WriteLine(); +}"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (5,10): error CS0116: A namespace cannot directly contain members such as fields or methods + // new void M() + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "M").WithLocation(5, 10), + // (5,10): warning CS0109: The member '.M()' does not hide an accessible member. The new keyword is not required. + // new void M() + Diagnostic(ErrorCode.WRN_NewNotRequired, "M").WithArguments(".M()").WithLocation(5, 10) + ); + } + + [Fact] + public void Scope_12() + { + var text = @" +using alias1 = Test; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class Test {} + +struct Derived +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + + struct Derived + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 6 + Test().ToString(); // 7 + Test().EndsWith(null); // 8 + var d = new System.Func(Test); // 9 + d(); + _ = nameof(Test); // 10 + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20), + // (36,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(36, 38), + // (37,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(37, 13), + // (38,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(38, 13), + // (39,45): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // var d = new System.Func(Test); // 9 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(39, 45), + // (41,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 10 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(41, 24) + ); + } + + [Fact] + public void Scope_13() + { + var text = @" +using alias1 = Test; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class Test {} + +interface Derived +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + + interface Derived + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 6 + Test().ToString(); // 7 + Test().EndsWith(null); // 8 + var d = new System.Func(Test); // 9 + d(); + _ = nameof(Test); // 10 + } + } +} +"; + + var comp = CreateCompilation(text, targetFramework: TargetFramework.NetStandardLatest, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20), + // (36,38): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 6 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(36, 38), + // (37,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 7 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(37, 13), + // (38,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 8 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(38, 13), + // (39,45): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // var d = new System.Func(Test); // 9 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(39, 45), + // (41,24): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 10 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(41, 24) + ); + } + + [Fact] + public void Scope_14() + { + var text = @" +using alias1 = Test; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class Test {} + +delegate Test D(alias1 x); + +namespace N1 +{ + using alias2 = Test; + + delegate Test D(alias2 x); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics(); + } + + [Fact] + public void Scope_15() + { + var text = @" +const int Test = 1; +System.Console.WriteLine(Test); + +class Test {} + +enum E1 +{ + T = Test, +} + +namespace N1 +{ + enum E1 + { + T = Test, + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (9,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // T = Test, + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(9, 9), + // (16,13): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // T = Test, + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 13) + ); + } + + [Fact] + public void Scope_16() + { + var text1 = @" +using alias1 = System.String; +alias1 x = ""1""; +alias2 y = ""1""; +System.Console.WriteLine(x); +System.Console.WriteLine(y); +local(); +"; + var text2 = @" +using alias2 = System.String; +void local() +{ + alias1 a = ""2""; + alias2 b = ""2""; + System.Console.WriteLine(a); + System.Console.WriteLine(b); +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,1): error CS9001: Only one compilation unit can have top-level statements. + // void local() + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(3, 1), + // (3,6): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(3, 6), + // (4,1): error CS0246: The type or namespace name 'alias2' could not be found (are you missing a using directive or an assembly reference?) + // alias2 y = "1"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias2").WithArguments("alias2").WithLocation(4, 1), + // (5,5): error CS0246: The type or namespace name 'alias1' could not be found (are you missing a using directive or an assembly reference?) + // alias1 a = "2"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias1").WithArguments("alias1").WithLocation(5, 5), + // (7,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(7, 1) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + + var nameRef = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "alias1" && !id.Parent.IsKind(SyntaxKind.NameEquals)).Single(); + + Assert.NotEmpty(model1.LookupNamespacesAndTypes(nameRef.SpanStart, name: "alias1")); + Assert.Empty(model1.LookupNamespacesAndTypes(nameRef.SpanStart, name: "alias2")); + + nameRef = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "alias2").Single(); + model1.GetDiagnostics(nameRef.Ancestors().OfType().First().Span).Verify( + // (4,1): error CS0246: The type or namespace name 'alias2' could not be found (are you missing a using directive or an assembly reference?) + // alias2 y = "1"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias2").WithArguments("alias2").WithLocation(4, 1) + ); + model1.GetDiagnostics().Verify( + // (4,1): error CS0246: The type or namespace name 'alias2' could not be found (are you missing a using directive or an assembly reference?) + // alias2 y = "1"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias2").WithArguments("alias2").WithLocation(4, 1), + // (7,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(7, 1) + ); + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + nameRef = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "alias2" && !id.Parent.IsKind(SyntaxKind.NameEquals)).Single(); + + Assert.Empty(model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "alias1")); + Assert.NotEmpty(model2.LookupNamespacesAndTypes(nameRef.SpanStart, name: "alias2")); + + nameRef = tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "alias1").Single(); + model2.GetDiagnostics(nameRef.Ancestors().OfType().First().Span).Verify( + // (5,5): error CS0246: The type or namespace name 'alias1' could not be found (are you missing a using directive or an assembly reference?) + // alias1 a = "2"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias1").WithArguments("alias1").WithLocation(5, 5) + ); + model2.GetDiagnostics().Verify( + // (3,1): error CS9001: Only one compilation unit can have top-level statements. + // void local() + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(3, 1), + // (3,6): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(3, 6), + // (5,5): error CS0246: The type or namespace name 'alias1' could not be found (are you missing a using directive or an assembly reference?) + // alias1 a = "2"; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias1").WithArguments("alias1").WithLocation(5, 5) + ); + } + + [Fact] + public void Scope_17() + { + var text = @" +using alias1 = N2.Test; +using N2; +string Test = ""1""; +System.Console.WriteLine(Test); + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 20) + ); + } + + [Fact] + public void Scope_18() + { + var text1 = @" +string Test = ""1""; +System.Console.WriteLine(Test); +"; + var text2 = @" +using alias1 = N2.Test; +using N2; +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 20) + ); + } + + [Fact] + public void Scope_19() + { + var text = @" +using alias1 = N2.Test; +using N2; +string Test() => ""1""; +System.Console.WriteLine(Test()); + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20) + ); + } + + [Fact] + public void Scope_20() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +using alias1 = N2.Test; +using N2; +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 33), + // (18,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 20) + ); + } + + [Fact] + public void Scope_21() + { + var text = @" +using Test = N2.Test; + +string Test = ""1""; +System.Console.WriteLine(Test); + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + + System.Console.WriteLine(x); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using Test = N2.Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 20) + ); + } + + [Fact] + public void Scope_22() + { + var text1 = @" +string Test = ""1""; +System.Console.WriteLine(Test); +"; + var text2 = @" +using Test = N2.Test; + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + + System.Console.WriteLine(x); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using Test = N2.Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 20) + ); + } + + [Fact] + public void Scope_23() + { + var text = @" +using Test = N2.Test; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + + System.Console.WriteLine(x); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using Test = N2.Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20) + ); + } + + [Fact] + public void Scope_24() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +using Test = N2.Test; + +namespace N2 { class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + + System.Console.WriteLine(x); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using Test = N2.Test; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 33), + // (18,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 20) + ); + } + + [Fact] + public void Scope_25() + { + var text = @" +using alias1 = N2.Test; +using static N2; +string Test = ""1""; +System.Console.WriteLine(Test); + +class N2 { public class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using static N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 20) + ); + } + + [Fact] + public void Scope_26() + { + var text1 = @" +string Test = ""1""; +System.Console.WriteLine(Test); +"; + var text2 = @" +using alias1 = N2.Test; +using static N2; +class N2 { public class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test); // 1 + Test.ToString(); // 2 + Test.EndsWith(null); // 3 + _ = nameof(Test); // 4 + } +} + +namespace N1 +{ + using alias2 = Test; + using static N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test.EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 20) + ); + } + + [Fact] + public void Scope_27() + { + var text = @" +using alias1 = N2.Test; +using static N2; +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class N2 { public class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using static N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (16,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 34), + // (17,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(17, 9), + // (18,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 9), + // (19,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(19, 33), + // (21,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(21, 20) + ); + } + + [Fact] + public void Scope_28() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +using alias1 = N2.Test; +using static N2; +class N2 { public class Test {} } + +class Derived : Test +{ + void M() + { + Test x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using alias2 = Test; + using static N2; + + class Derived : Test + { + void M() + { + Test x = null; + alias2 y = x; + System.Console.WriteLine(y); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 33), + // (18,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 20) + ); + } + + [Fact] + public void Scope_29() + { + var text = @" +using static N2; + +string Test() => ""1""; +System.Console.WriteLine(Test()); + +class N2 { public static string Test() => null; } + +class Derived +{ + void M() + { + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using static N2; + + class Derived + { + void M() + { + System.Console.WriteLine(Test()); + Test().ToString(); + Test().EndsWith(null); + var d = new System.Func(Test); + d(); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using static N2; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static N2;").WithLocation(2, 1), + // (13,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 34), + // (14,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(14, 9), + // (15,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 9), + // (16,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(16, 33), + // (18,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(18, 20) + ); + } + + [Fact] + public void Scope_30() + { + var text1 = @" +string Test() => ""1""; +System.Console.WriteLine(Test()); +"; + var text2 = @" +using static N2; + +class N2 { public static string Test() => null; } + +class Derived +{ + void M() + { + System.Console.WriteLine(Test()); // 1 + Test().ToString(); // 2 + Test().EndsWith(null); // 3 + System.Func d = Test; // 4 + d(); + _ = nameof(Test); // 5 + } +} + +namespace N1 +{ + using static N2; + + class Derived + { + void M() + { + System.Console.WriteLine(Test()); + Test().ToString(); + Test().EndsWith(null); + var d = new System.Func(Test); + d(); + _ = nameof(Test); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using static N2; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static N2;").WithLocation(2, 1), + // (10,34): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Console.WriteLine(Test()); // 1 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(10, 34), + // (11,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().ToString(); // 2 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(11, 9), + // (12,9): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // Test().EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(12, 9), + // (13,33): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // System.Func d = Test; // 4 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(13, 33), + // (15,20): error CS9000: Cannot use local variable or local function 'Test' declared in a top-level statement in this context. + // _ = nameof(Test); // 5 + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "Test").WithArguments("Test").WithLocation(15, 20) + ); + } + + [Fact] + public void Scope_31() + { + var text = @" +using alias1 = args; + +System.Console.WriteLine(args); + +class args {} + +class Derived : args +{ + void M() + { + args x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(args); // 1 + args.ToString(); // 2 + args[0].EndsWith(null); // 3 + _ = nameof(args); + } +} + +namespace N1 +{ + using alias2 = args; + + class Derived : args + { + void M() + { + args x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(args); // 4 + args.ToString(); // 5 + args[0].EndsWith(null); // 6 + _ = nameof(args); + } + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (15,34): error CS0119: 'args' is a type, which is not valid in the given context + // System.Console.WriteLine(args); // 1 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(15, 34), + // (16,9): error CS0120: An object reference is required for the non-static field, method, or property 'object.ToString()' + // args.ToString(); // 2 + Diagnostic(ErrorCode.ERR_ObjectRequired, "args.ToString").WithArguments("object.ToString()").WithLocation(16, 9), + // (17,9): error CS0119: 'args' is a type, which is not valid in the given context + // args[0].EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(17, 9), + // (33,38): error CS0119: 'args' is a type, which is not valid in the given context + // System.Console.WriteLine(args); // 4 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(33, 38), + // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'object.ToString()' + // args.ToString(); // 5 + Diagnostic(ErrorCode.ERR_ObjectRequired, "args.ToString").WithArguments("object.ToString()").WithLocation(34, 13), + // (35,13): error CS0119: 'args' is a type, which is not valid in the given context + // args[0].EndsWith(null); // 6 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(35, 13) + ); + + var testType = ((Compilation)comp).GetTypeByMetadataName("args"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + var nameRefs = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "args").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = args;", nameRef.Parent.ToString()); + + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + var names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("args", names); + + var symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.False(symbols.Any(s => s.Kind == SymbolKind.Parameter)); + Assert.Same(testType, model.LookupSymbols(nameRef.SpanStart, name: "args").Single()); + + nameRef = nameRefs[1]; + Assert.Equal("System.Console.WriteLine(args)", nameRef.Parent.Parent.Parent.ToString()); + var parameter = model.GetSymbolInfo(nameRef).Symbol; + Assert.Equal("System.String[] args", parameter.ToTestDisplayString()); + Assert.Equal("", parameter.ContainingSymbol.ToTestDisplayString()); + + names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("args", names); + + symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.DoesNotContain(testType, symbols); + Assert.Contains(parameter, symbols); + Assert.Same(parameter, model.LookupSymbols(nameRef.SpanStart, name: "args").Single()); + + symbols = model.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(parameter, symbols); + Assert.Same(testType, model.LookupNamespacesAndTypes(nameRef.SpanStart, name: "args").Single()); + + nameRef = nameRefs[2]; + Assert.Equal(": args", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(parameter, model, nameRef); + + nameRef = nameRefs[4]; + Assert.Equal("System.Console.WriteLine(args)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(parameter, model, nameRef); + + nameRef = nameRefs[8]; + Assert.Equal("using alias2 = args;", nameRef.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(parameter, model, nameRef); + + nameRef = nameRefs[9]; + Assert.Equal(": args", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(parameter, model, nameRef); + + nameRef = nameRefs[11]; + Assert.Equal("System.Console.WriteLine(args)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(parameter, model, nameRef); + + void verifyModel(ISymbol declSymbol, SemanticModel model, IdentifierNameSyntax nameRef) + { + var names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("args", names); + + var symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model.LookupSymbols(nameRef.SpanStart, name: "args").Single()); + + symbols = model.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.DoesNotContain(declSymbol, symbols); + Assert.Same(testType, model.LookupNamespacesAndTypes(nameRef.SpanStart, name: "args").Single()); + } + } + + [Fact] + public void Scope_32() + { + var text1 = @" +System.Console.WriteLine(args); +"; + var text2 = @" +using alias1 = args; + +class args {} + +class Derived : args +{ + void M() + { + args x = null; + alias1 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(args); // 1 + args.ToString(); // 2 + args[0].EndsWith(null); // 3 + _ = nameof(args); + } +} + +namespace N1 +{ + using alias2 = args; + + class Derived : args + { + void M() + { + args x = null; + alias2 y = x; + System.Console.WriteLine(y); + System.Console.WriteLine(args); // 4 + args.ToString(); // 5 + args[0].EndsWith(null); // 6 + _ = nameof(args); + } + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (13,34): error CS0119: 'args' is a type, which is not valid in the given context + // System.Console.WriteLine(args); // 1 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(13, 34), + // (14,9): error CS0120: An object reference is required for the non-static field, method, or property 'object.ToString()' + // args.ToString(); // 2 + Diagnostic(ErrorCode.ERR_ObjectRequired, "args.ToString").WithArguments("object.ToString()").WithLocation(14, 9), + // (15,9): error CS0119: 'args' is a type, which is not valid in the given context + // args[0].EndsWith(null); // 3 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(15, 9), + // (31,38): error CS0119: 'args' is a type, which is not valid in the given context + // System.Console.WriteLine(args); // 4 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(31, 38), + // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'object.ToString()' + // args.ToString(); // 5 + Diagnostic(ErrorCode.ERR_ObjectRequired, "args.ToString").WithArguments("object.ToString()").WithLocation(32, 13), + // (33,13): error CS0119: 'args' is a type, which is not valid in the given context + // args[0].EndsWith(null); // 6 + Diagnostic(ErrorCode.ERR_BadSKunknown, "args").WithArguments("args", "type").WithLocation(33, 13) + ); + + var testType = ((Compilation)comp).GetTypeByMetadataName("args"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees[1]; + var model = comp.GetSemanticModel(tree); + var nameRefs = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "args").ToArray(); + + var nameRef = nameRefs[0]; + Assert.Equal("using alias1 = args;", nameRef.Parent.ToString()); + + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + var names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("args", names); + + var symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.False(symbols.Any(s => s.Kind == SymbolKind.Parameter)); + Assert.Same(testType, model.LookupSymbols(nameRef.SpanStart, name: "args").Single()); + + nameRef = nameRefs[1]; + Assert.Equal(": args", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(model, nameRef); + + nameRef = nameRefs[3]; + Assert.Equal("System.Console.WriteLine(args)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(model, nameRef); + + nameRef = nameRefs[7]; + Assert.Equal("using alias2 = args;", nameRef.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(model, nameRef); + + nameRef = nameRefs[8]; + Assert.Equal(": args", nameRef.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(model, nameRef); + + nameRef = nameRefs[10]; + Assert.Equal("System.Console.WriteLine(args)", nameRef.Parent.Parent.Parent.ToString()); + Assert.Same(testType, model.GetSymbolInfo(nameRef).Symbol); + verifyModel(model, nameRef); + + void verifyModel(SemanticModel model, IdentifierNameSyntax nameRef) + { + var names = model.LookupNames(nameRef.SpanStart); + Assert.Contains("args", names); + + var symbols = model.LookupSymbols(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.False(symbols.Any(s => s.Kind == SymbolKind.Parameter)); + Assert.Same(testType, model.LookupSymbols(nameRef.SpanStart, name: "args").Single()); + + symbols = model.LookupNamespacesAndTypes(nameRef.SpanStart); + Assert.Contains(testType, symbols); + Assert.False(symbols.Any(s => s.Kind == SymbolKind.Parameter)); + Assert.Same(testType, model.LookupNamespacesAndTypes(nameRef.SpanStart, name: "args").Single()); + } + } + + [Fact] + public void Scope_33() + { + var text = @" +System.Console.WriteLine(args); + +class Test +{ + void M() + { + System.Console.WriteLine(args); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (8,34): error CS0103: The name 'args' does not exist in the current context + // System.Console.WriteLine(args); + Diagnostic(ErrorCode.ERR_NameNotInContext, "args").WithArguments("args").WithLocation(8, 34) + ); + } + + [Fact] + public void Scope_34() + { + var text1 = @" +System.Console.WriteLine(args); +"; + var text2 = @" +class Test +{ + void M() + { + System.Console.WriteLine(args); + } +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,34): error CS0103: The name 'args' does not exist in the current context + // System.Console.WriteLine(args); + Diagnostic(ErrorCode.ERR_NameNotInContext, "args").WithArguments("args").WithLocation(6, 34) + ); + } + + [Fact] + public void LocalFunctionStatement_01() + { + var text = @" +local(); + +void local() +{ + System.Console.WriteLine(15); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "15"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var declarator = tree.GetRoot().DescendantNodes().OfType().Single(); + var reference = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local").Single(); + + var local = model.GetDeclaredSymbol(declarator); + Assert.Same(local, model.GetSymbolInfo(reference).Symbol); + Assert.Equal("void local()", local.ToTestDisplayString()); + Assert.Equal(MethodKind.LocalFunction, ((IMethodSymbol)local).MethodKind); + + Assert.Equal(SymbolKind.Method, local.ContainingSymbol.Kind); + Assert.False(local.ContainingSymbol.IsImplicitlyDeclared); + Assert.Equal(SymbolKind.NamedType, local.ContainingSymbol.ContainingSymbol.Kind); + Assert.True(local.ContainingSymbol.ContainingSymbol.IsImplicitlyDeclared); + Assert.True(((INamespaceSymbol)local.ContainingSymbol.ContainingSymbol.ContainingSymbol).IsGlobalNamespace); + + VerifyFlowGraph(comp, tree.GetRoot(), +@" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} +.locals {R1} +{ + Methods: [void local()] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'local();') + Expression: + IInvocationOperation (void local()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'local()') + Instance Receiver: + null + Arguments(0) + Next (Regular) Block[B2] + Leaving: {R1} + + { void local() + + Block[B0#0R1] - Entry + Statements (0) + Next (Regular) Block[B1#0R1] + Block[B1#0R1] - Block + Predecessors: [B0#0R1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'System.Cons ... teLine(15);') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... iteLine(15)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '15') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 15) (Syntax: '15') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + Next (Regular) Block[B2#0R1] + Block[B2#0R1] - Exit + Predecessors: [B1#0R1] + Statements (0) + } +} +Block[B2] - Exit + Predecessors: [B1] + Statements (0) +"); + } + + [Fact] + public void LocalFunctionStatement_02() + { + var text = @" +local(); + +void local() => System.Console.WriteLine(""Hi!""); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void LocalFunctionStatement_03() + { + var text = @" +local(); + +void I1.local() +{ + System.Console.WriteLine(""Hi!""); +} + +interface I1 +{ + void local(); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS0103: The name 'local' does not exist in the current context + // local(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 1), + // (4,6): error CS0540: '.I1.local()': containing type does not implement interface 'I1' + // void I1.local() + Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I1").WithArguments(".I1.local()", "I1").WithLocation(4, 6), + // (4,9): error CS0116: A namespace cannot directly contain members such as fields or methods + // void I1.local() + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 9) + ); + } + + [Fact] + public void LocalFunctionStatement_04() + { + var text = @" +new void localA() => System.Console.WriteLine(); +localA(); +public void localB() => System.Console.WriteLine(); +localB(); +virtual void localC() => System.Console.WriteLine(); +localC(); +sealed void localD() => System.Console.WriteLine(); +localD(); +override void localE() => System.Console.WriteLine(); +localE(); +abstract void localF() => System.Console.WriteLine(); +localF(); +partial void localG() => System.Console.WriteLine(); +localG(); +extern void localH() => System.Console.WriteLine(); +localH(); +[System.Obsolete()] +void localI() => System.Console.WriteLine(); +localI(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,10): error CS0116: A namespace cannot directly contain members such as fields or methods + // new void localA() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localA").WithLocation(2, 10), + // (2,10): warning CS0109: The member '.localA()' does not hide an accessible member. The new keyword is not required. + // new void localA() => System.Console.WriteLine(); + Diagnostic(ErrorCode.WRN_NewNotRequired, "localA").WithArguments(".localA()").WithLocation(2, 10), + // (3,1): error CS0103: The name 'localA' does not exist in the current context + // localA(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localA").WithArguments("localA").WithLocation(3, 1), + // (4,1): error CS0106: The modifier 'public' is not valid for this item + // public void localB() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "public").WithArguments("public").WithLocation(4, 1), + // (6,14): error CS0116: A namespace cannot directly contain members such as fields or methods + // virtual void localC() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localC").WithLocation(6, 14), + // (6,14): error CS0621: '.localC()': virtual or abstract members cannot be private + // virtual void localC() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_VirtualPrivate, "localC").WithArguments(".localC()").WithLocation(6, 14), + // (7,1): error CS0103: The name 'localC' does not exist in the current context + // localC(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localC").WithArguments("localC").WithLocation(7, 1), + // (8,13): error CS0116: A namespace cannot directly contain members such as fields or methods + // sealed void localD() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localD").WithLocation(8, 13), + // (8,13): error CS0238: '.localD()' cannot be sealed because it is not an override + // sealed void localD() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_SealedNonOverride, "localD").WithArguments(".localD()").WithLocation(8, 13), + // (9,1): error CS0103: The name 'localD' does not exist in the current context + // localD(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localD").WithArguments("localD").WithLocation(9, 1), + // (10,15): error CS0116: A namespace cannot directly contain members such as fields or methods + // override void localE() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localE").WithLocation(10, 15), + // (10,15): error CS0621: '.localE()': virtual or abstract members cannot be private + // override void localE() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_VirtualPrivate, "localE").WithArguments(".localE()").WithLocation(10, 15), + // (10,15): error CS0115: '.localE()': no suitable method found to override + // override void localE() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_OverrideNotExpected, "localE").WithArguments(".localE()").WithLocation(10, 15), + // (11,1): error CS0103: The name 'localE' does not exist in the current context + // localE(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localE").WithArguments("localE").WithLocation(11, 1), + // (12,15): error CS0116: A namespace cannot directly contain members such as fields or methods + // abstract void localF() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localF").WithLocation(12, 15), + // (12,15): error CS0500: '.localF()' cannot declare a body because it is marked abstract + // abstract void localF() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_AbstractHasBody, "localF").WithArguments(".localF()").WithLocation(12, 15), + // (12,15): error CS0621: '.localF()': virtual or abstract members cannot be private + // abstract void localF() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_VirtualPrivate, "localF").WithArguments(".localF()").WithLocation(12, 15), + // (13,1): error CS0103: The name 'localF' does not exist in the current context + // localF(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localF").WithArguments("localF").WithLocation(13, 1), + // (14,14): error CS0116: A namespace cannot directly contain members such as fields or methods + // partial void localG() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "localG").WithLocation(14, 14), + // (14,14): error CS0759: No defining declaration found for implementing declaration of partial method '.localG()' + // partial void localG() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "localG").WithArguments(".localG()").WithLocation(14, 14), + // (14,14): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface + // partial void localG() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_PartialMethodOnlyInPartialClass, "localG").WithLocation(14, 14), + // (15,1): error CS0103: The name 'localG' does not exist in the current context + // localG(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "localG").WithArguments("localG").WithLocation(15, 1), + // (16,13): error CS0179: 'localH()' cannot be extern and declare a body + // extern void localH() => System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_ExternHasBody, "localH").WithArguments("localH()").WithLocation(16, 13), + // (20,1): warning CS0612: 'localI()' is obsolete + // localI(); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "localI()").WithArguments("localI()").WithLocation(20, 1) + ); + } + + [Fact] + public void LocalFunctionStatement_05() + { + var text = @" +void local1() => System.Console.Write(""1""); +local1(); +void local2() => System.Console.Write(""2""); +local2(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "12"); + } + + [Fact] + public void LocalFunctionStatement_06() + { + var text = @" +local(); + +static void local() +{ + System.Console.WriteLine(""Hi!""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void LocalFunctionStatement_07() + { + var text1 = @" +local1(1); +void local1(int x) +{} +local2(); +"; + var text2 = @" +void local1(byte y) +{} + +void local2() +{ + local1(2); +} +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // void local1(byte y) + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "void").WithLocation(2, 1), + // (5,1): error CS0103: The name 'local2' does not exist in the current context + // local2(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "local2").WithArguments("local2").WithLocation(5, 1), + // (5,6): warning CS8321: The local function 'local2' is declared but never used + // void local2() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local2").WithArguments("local2").WithLocation(5, 6) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().Single()); + Assert.Equal("void local1(System.Int32 x)", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local1").Single()).Symbol); + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + var symbol2 = model2.GetDeclaredSymbol(tree2.GetRoot().DescendantNodes().OfType().First()); + Assert.Equal("void local1(System.Byte y)", symbol2.ToTestDisplayString()); + Assert.Same(symbol2, model2.GetSymbolInfo(tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local1").Single()).Symbol); + } + + [Fact] + public void LocalFunctionStatement_08() + { + var text = @" +void local() +{ + System.Console.WriteLine(""Hi!""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,6): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(2, 6) + ); + + CompileAndVerify(comp, expectedOutput: ""); + } + + [Fact] + public void LocalFunctionStatement_09() + { + var text1 = @" +local1(1); +void local1(int x) +{} +local2(); + +void local1(byte y) +{} + +void local2() +{ + local1(2); +} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (7,6): error CS0128: A local variable or function named 'local1' is already defined in this scope + // void local1(byte y) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "local1").WithArguments("local1").WithLocation(7, 6), + // (7,6): warning CS8321: The local function 'local1' is declared but never used + // void local1(byte y) + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local1").WithArguments("local1").WithLocation(7, 6) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().First()); + Assert.Equal("void local1(System.Int32 x)", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local1").First()).Symbol); + + var symbol2 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().Skip(1).First()); + Assert.Equal("void local1(System.Byte y)", symbol2.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "local1").Skip(1).Single()).Symbol); + } + + [Fact] + public void LocalFunctionStatement_10() + { + var text = @" +int i = 1; +local(); +System.Console.WriteLine(i); + +void local() +{ + i++; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void LocalFunctionStatement_11() + { + var text1 = @" +args(1); +void args(int x) +{} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,6): error CS0136: A local or parameter named 'args' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // void args(int x) + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "args").WithArguments("args").WithLocation(3, 6) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().First()); + Assert.Equal("void args(System.Int32 x)", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "args").Single()).Symbol); + } + + [Fact] + public void LocalFunctionStatement_12() + { + var text1 = @" +local(1); +void local(args x) +{ + System.Console.WriteLine(x); +} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "1"); + } + + [Fact] + public void LocalFunctionStatement_13() + { + var text1 = @" +local(); +void local() +{ + var args = 2; + System.Console.WriteLine(args); +} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void LocalFunctionStatement_14() + { + var text1 = @" +local(3); +void local(int args) +{ + System.Console.WriteLine(args); +} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "3"); + } + + [Fact] + public void LocalFunctionStatement_15() + { + var text1 = @" +local(); +void local() +{ + args(4); + void args(int x) + { + System.Console.WriteLine(x); + } +} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "4"); + } + + [Fact] + public void LocalFunctionStatement_16() + { + var text1 = @" +using System.Linq; +_ = from local in new object[0] select local; +local(); +void local() {} +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,10): error CS1931: The range variable 'local' conflicts with a previous declaration of 'local' + // _ = from local in new object[0] select local; + Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "local").WithArguments("local").WithLocation(3, 10) + ); + } + + [Fact] + public void LocalFunctionStatement_17() + { + var text = @" +System.Console.WriteLine(); +string await() => ""Hi!""; +System.Console.WriteLine(await()); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,8): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression + // string await() => "Hi!"; + Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(3, 8), + // (3,8): warning CS8321: The local function 'await' is declared but never used + // string await() => "Hi!"; + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "await").WithArguments("await").WithLocation(3, 8), + // (4,32): error CS1525: Invalid expression term ')' + // System.Console.WriteLine(await()); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(4, 32) + ); + } + + [Fact] + public void LocalFunctionStatement_18() + { + var text = @" +string async() => ""Hi!""; +System.Console.WriteLine(async()); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Lambda_01() + { + var text = @" +int i = 1; +System.Action l = () => i++; +l(); +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void PropertyDeclaration_01() + { + var text = @" +_ = local; + +int local => 1; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,5): error CS0103: The name 'local' does not exist in the current context + // _ = local; + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 5), + // (4,5): error CS0116: A namespace cannot directly contain members such as fields or methods + // int local => 1; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 5) + ); + } + + [Fact] + public void PropertyDeclaration_02() + { + var text = @" +_ = local; + +int local { get => 1; } +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,5): error CS0103: The name 'local' does not exist in the current context + // _ = local; + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 5), + // (4,5): error CS0116: A namespace cannot directly contain members such as fields or methods + // int local { get => 1; } + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 5) + ); + } + + [Fact] + public void PropertyDeclaration_03() + { + var text = @" +_ = local; + +int local { get { return 1; } } +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,5): error CS0103: The name 'local' does not exist in the current context + // _ = local; + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 5), + // (4,5): error CS0116: A namespace cannot directly contain members such as fields or methods + // int local { get { return 1; } } + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 5) + ); + } + + [Fact] + public void EventDeclaration_01() + { + var text = @" +local += null; + +event System.Action local; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS0103: The name 'local' does not exist in the current context + // local += null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 1), + // (4,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action local; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 21) + ); + } + + [Fact] + public void EventDeclaration_02() + { + var text = @" +local -= null; + +event System.Action local +{ + add {} + remove {} +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS0103: The name 'local' does not exist in the current context + // local -= null; + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 1), + // (4,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // event System.Action local + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 21) + ); + } + + [Fact] + public void LabeledStatement_01() + { + var text = @" +goto label1; +label1: System.Console.WriteLine(""Hi!""); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var declarator = tree.GetRoot().DescendantNodes().OfType().Single(); + var reference = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "label1").Single(); + + var label = model.GetDeclaredSymbol(declarator); + Assert.Same(label, model.GetSymbolInfo(reference).Symbol); + Assert.Equal("label1", label.ToTestDisplayString()); + Assert.Equal(SymbolKind.Label, label.Kind); + + Assert.Equal(SymbolKind.Method, label.ContainingSymbol.Kind); + Assert.False(label.ContainingSymbol.IsImplicitlyDeclared); + Assert.Equal(SymbolKind.NamedType, label.ContainingSymbol.ContainingSymbol.Kind); + Assert.True(label.ContainingSymbol.ContainingSymbol.IsImplicitlyDeclared); + Assert.True(((INamespaceSymbol)label.ContainingSymbol.ContainingSymbol.ContainingSymbol).IsGlobalNamespace); + } + + [Fact] + public void LabeledStatement_02() + { + var text = @" +goto label1; +label1: System.Console.WriteLine(""Hi!""); +label1: System.Console.WriteLine(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,1): error CS0140: The label 'label1' is a duplicate + // label1: System.Console.WriteLine(); + Diagnostic(ErrorCode.ERR_DuplicateLabel, "label1").WithArguments("label1").WithLocation(4, 1) + ); + } + + [Fact] + public void LabeledStatement_03() + { + var text1 = @" +goto label1; +label1: System.Console.Write(1); +"; + var text2 = @" +label1: System.Console.Write(2); +goto label1; +"; + + var comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): error CS9001: Only one compilation unit can have top-level statements. + // label1: System.Console.Write(2); + Diagnostic(ErrorCode.ERR_SimpleProgramMultipleUnitsWithTopLevelStatements, "label1").WithLocation(2, 1) + ); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree1 = comp.SyntaxTrees[0]; + var model1 = comp.GetSemanticModel(tree1); + var symbol1 = model1.GetDeclaredSymbol(tree1.GetRoot().DescendantNodes().OfType().Single()); + Assert.Equal("label1", symbol1.ToTestDisplayString()); + Assert.Same(symbol1, model1.GetSymbolInfo(tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "label1").Single()).Symbol); + + var tree2 = comp.SyntaxTrees[1]; + var model2 = comp.GetSemanticModel(tree2); + var symbol2 = model2.GetDeclaredSymbol(tree2.GetRoot().DescendantNodes().OfType().Single()); + Assert.Equal("label1", symbol2.ToTestDisplayString()); + Assert.NotEqual(symbol1, symbol2); + Assert.Same(symbol2, model2.GetSymbolInfo(tree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "label1").Single()).Symbol); + } + + [Fact] + public void LabeledStatement_04() + { + var text = @" +goto args; +args: System.Console.WriteLine(""Hi!""); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + + Assert.False(comp.NullableSemanticAnalysisEnabled); // To make sure we test incremental binding for SemanticModel + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var declarator = tree.GetRoot().DescendantNodes().OfType().Single(); + var reference = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "args").Single(); + + var label = model.GetDeclaredSymbol(declarator); + Assert.Same(label, model.GetSymbolInfo(reference).Symbol); + Assert.Equal("args", label.ToTestDisplayString()); + Assert.Equal(SymbolKind.Label, label.Kind); + + Assert.Equal(SymbolKind.Method, label.ContainingSymbol.Kind); + Assert.False(label.ContainingSymbol.IsImplicitlyDeclared); + Assert.Equal(SymbolKind.NamedType, label.ContainingSymbol.ContainingSymbol.Kind); + Assert.True(label.ContainingSymbol.ContainingSymbol.IsImplicitlyDeclared); + Assert.True(((INamespaceSymbol)label.ContainingSymbol.ContainingSymbol.ContainingSymbol).IsGlobalNamespace); + } + + [Fact] + public void ExplicitMain_01() + { + var text = @" +static void Main() +{} + +System.Console.Write(""Hi!""); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,13): warning CS7022: The entry point of the program is global code; ignoring 'Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main()").WithLocation(2, 13), + // (2,13): warning CS8321: The local function 'Main' is declared but never used + // static void Main() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Main").WithArguments("Main").WithLocation(2, 13) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_02() + { + var text = @" +System.Console.Write(""H""); +Main(); +System.Console.Write(""!""); + +static void Main() +{ + System.Console.Write(""i""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,13): warning CS7022: The entry point of the program is global code; ignoring 'Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main()").WithLocation(6, 13) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_03() + { + var text = @" +using System; +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static async Task Main() + { + Console.Write(""hello ""); + await Task.Factory.StartNew(() => 5); + Console.Write(""async main""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (9,23): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static async Task Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(9, 23) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_04() + { + var text = @" +using System; +using System.Threading.Tasks; + +await Task.Factory.StartNew(() => 5); +System.Console.Write(""Hi!""); + +class Program +{ + static async Task Main() + { + Console.Write(""hello ""); + await Task.Factory.StartNew(() => 5); + Console.Write(""async main""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (10,23): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static async Task Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(10, 23) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_05() + { + var text = @" +using System; +using System.Threading.Tasks; + +await Task.Factory.StartNew(() => 5); +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + Console.Write(""hello ""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (10,17): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(10, 17) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_06() + { + var text = @" +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + System.Console.Write(""hello ""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,17): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(6, 17) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_07() + { + var text = @" +using System; +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static void Main(string[] args) + { + Console.Write(""hello ""); + } + + static async Task Main() + { + Console.Write(""hello ""); + await Task.Factory.StartNew(() => 5); + Console.Write(""async main""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (9,17): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main(string[])' entry point. + // static void Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main(string[])").WithLocation(9, 17), + // (14,23): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static async Task Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(14, 23) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_08() + { + var text = @" +using System; +using System.Threading.Tasks; + +await Task.Factory.StartNew(() => 5); +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + Console.Write(""hello ""); + } + + static async Task Main(string[] args) + { + await Task.Factory.StartNew(() => 5); + Console.Write(""async main""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (10,17): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main()").WithLocation(10, 17), + // (15,23): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main(string[])' entry point. + // static async Task Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Program.Main(string[])").WithLocation(15, 23) + ); + + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_09() + { + var text1 = @" +using System; +using System.Threading.Tasks; + +string s = ""Hello world!""; + +foreach (var c in s) +{ + await N1.Helpers.Wait(); + Console.Write(c); +} + +Console.WriteLine(); + +namespace N1 +{ + class Helpers + { + static void Main() + { } + + public static async Task Wait() + { + await Task.Delay(500); + } + } +}"; + var text4 = @" +using System.Threading.Tasks; + +class Helpers +{ + public static async Task Wait() + { + await Task.Delay(500); + } +} +"; + + var comp = CreateCompilation(new[] { text1, text4 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics( + // (19,21): warning CS7022: The entry point of the program is global code; ignoring 'Helpers.Main()' entry point. + // static void Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("N1.Helpers.Main()").WithLocation(19, 21) + ); + } + + [Fact] + public void ExplicitMain_10() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + } + + static async Task Main(string[] args) + { + await Task.Factory.StartNew(() => 5); + } +} + +class Program2 +{ + static void Main(string[] args) + { + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithMainTypeName("Program"), parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics( + // error CS9003: Cannot specify /main if there is a compilation unit with top-level statements. + Diagnostic(ErrorCode.ERR_SimpleProgramDisallowsMainType).WithLocation(1, 1) + ); + } + + [Fact] + public void ExplicitMain_11() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithMainTypeName(""), parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics( + // error CS7088: Invalid 'MainTypeName' value: ''. + Diagnostic(ErrorCode.ERR_BadCompilationOptionValue).WithArguments("MainTypeName", "").WithLocation(1, 1), + // error CS9003: Cannot specify /main if there is a compilation unit with top-level statements. + Diagnostic(ErrorCode.ERR_SimpleProgramDisallowsMainType).WithLocation(1, 1) + ); + } + + [Fact] + public void ExplicitMain_12() + { + var text = @" +System.Console.Write(""H""); +Main(); +System.Console.Write(""!""); + +void Main() +{ + System.Console.Write(""i""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_13() + { + var text = @" +System.Console.Write(""H""); +Main(""""); +System.Console.Write(""!""); + +static void Main(string args) +{ + System.Console.Write(""i""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_14() + { + var text = @" +System.Console.Write(""H""); +Main(); +System.Console.Write(""!""); + +static long Main() +{ + System.Console.Write(""i""); + return 0; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_15() + { + var text = @" +System.Console.Write(""H""); +Main(); +System.Console.Write(""!""); + +static int Main() +{ + System.Console.Write(""i""); + return 0; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,12): warning CS7022: The entry point of the program is global code; ignoring 'Main()' entry point. + // static int Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main()").WithLocation(6, 12) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_16() + { + var text = @" +System.Console.Write(""H""); +Main(null); +System.Console.Write(""!""); + +static void Main(string[] args) +{ + System.Console.Write(""i""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,13): warning CS7022: The entry point of the program is global code; ignoring 'Main(string[])' entry point. + // static void Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main(string[])").WithLocation(6, 13) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_17() + { + var text = @" +System.Console.Write(""H""); +Main(null); +System.Console.Write(""!""); + +static int Main(string[] args) +{ + System.Console.Write(""i""); + return 0; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,12): warning CS7022: The entry point of the program is global code; ignoring 'Main(string[])' entry point. + // static int Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main(string[])").WithLocation(6, 12) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_18() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""H""); +await Main(); +System.Console.Write(""!""); + +async static Task Main() +{ + System.Console.Write(""i""); + await Task.Yield(); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (8,19): warning CS7022: The entry point of the program is global code; ignoring 'Main()' entry point. + // async static Task Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main()").WithLocation(8, 19) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_19() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""H""); +await Main(); +System.Console.Write(""!""); + +static async Task Main() +{ + System.Console.Write(""i""); + await Task.Yield(); + return 0; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (8,24): warning CS7022: The entry point of the program is global code; ignoring 'Main()' entry point. + // static async Task Main() + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main()").WithLocation(8, 24) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_20() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""H""); +await Main(null); +System.Console.Write(""!""); + +static async Task Main(string[] args) +{ + System.Console.Write(""i""); + await Task.Yield(); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (8,19): warning CS7022: The entry point of the program is global code; ignoring 'Main(string[])' entry point. + // static async Task Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main(string[])").WithLocation(8, 19) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_21() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""H""); +await Main(null); +System.Console.Write(""!""); + +static async Task Main(string[] args) +{ + System.Console.Write(""i""); + await Task.Yield(); + return 0; +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (8,24): warning CS7022: The entry point of the program is global code; ignoring 'Main(string[])' entry point. + // static async Task Main(string[] args) + Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("Main(string[])").WithLocation(8, 24) + ); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_22() + { + var text = @" +System.Console.Write(""H""); +Main(); +System.Console.Write(""!""); + +static void Main() +{ + System.Console.Write(""i""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void ExplicitMain_23() + { + var text = @" +System.Console.Write(""H""); +local(); +System.Console.Write(""!""); + +static void local() +{ + Main(); + + static void Main() + { + System.Console.Write(""i""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Yield_01() + { + var text = @"yield break;"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (1,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // yield break; + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "yield break;").WithArguments("", "void").WithLocation(1, 1) + ); + } + + [Fact] + public void Yield_02() + { + var text = @"{yield return 0;}"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (1,1): error CS1624: The body of '' cannot be an iterator block because 'void' is not an iterator interface type + // {yield return 0;} + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "{yield return 0;}").WithArguments("", "void").WithLocation(1, 1) + ); + } + + [Fact] + public void OutOfOrder_01() + { + var text = @" +class C {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(4, 1) + ); + } + + [Fact] + public void OutOfOrder_02() + { + var text = @" +System.Console.WriteLine(0); + +namespace C {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_03() + { + var text = @" +class C {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); + +class D {} + +System.Console.WriteLine(3); +System.Console.WriteLine(4); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(4, 1) + ); + } + + [Fact] + public void OutOfOrder_04() + { + var text = @" +System.Console.WriteLine(0); + +namespace C {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); + +namespace D {} + +System.Console.WriteLine(3); +System.Console.WriteLine(4); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_05() + { + var text = @" +System.Console.WriteLine(0); + +struct S {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_06() + { + var text = @" +System.Console.WriteLine(0); + +enum C { V } + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_07() + { + var text = @" +System.Console.WriteLine(0); + +interface C {} + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_08() + { + var text = @" +System.Console.WriteLine(0); + +delegate void D (); + +System.Console.WriteLine(1); +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_09() + { + var text = @" +System.Console.WriteLine(0); + +using System; + +Console.WriteLine(1); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,1): error CS1529: A using clause must precede all other elements defined in the namespace except extern alias declarations + // using System; + Diagnostic(ErrorCode.ERR_UsingAfterElements, "using System;").WithLocation(4, 1), + // (6,1): error CS0103: The name 'Console' does not exist in the current context + // Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Console").WithArguments("Console").WithLocation(6, 1) + ); + } + + [Fact] + public void OutOfOrder_10() + { + var text = @" +System.Console.WriteLine(0); + +[module: MyAttribute] + +class MyAttribute : System.Attribute +{} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,2): error CS1730: Assembly and module attributes must precede all other elements defined in a file except using clauses and extern alias declarations + // [module: MyAttribute] + Diagnostic(ErrorCode.ERR_GlobalAttributesNotFirst, "module").WithLocation(4, 2) + ); + } + + [Fact] + public void OutOfOrder_11() + { + var text = @" +System.Console.WriteLine(0); + +extern alias A; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (4,1): error CS0439: An extern alias declaration must precede all other elements defined in the namespace + // extern alias A; + Diagnostic(ErrorCode.ERR_ExternAfterElements, "extern").WithLocation(4, 1) + ); + } + + [Fact] + public void OutOfOrder_12() + { + var text = @" +extern alias A; +using System; + +[module: MyAttribute] + +Console.WriteLine(1); + +class MyAttribute : System.Attribute +{} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (2,1): hidden CS8020: Unused extern alias. + // extern alias A; + Diagnostic(ErrorCode.HDN_UnusedExternAlias, "extern alias A;").WithLocation(2, 1), + // (2,14): error CS0430: The extern alias 'A' was not specified in a /reference option + // extern alias A; + Diagnostic(ErrorCode.ERR_BadExternAlias, "A").WithArguments("A").WithLocation(2, 14) + ); + } + + [Fact] + public void OutOfOrder_13() + { + var text = @" +local(); + +class C {} + +void local() => System.Console.WriteLine(1); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (6,1): error CS9002: Top-level statements must precede namespace and type declarations. + // void local() => System.Console.WriteLine(1); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "void local() => System.Console.WriteLine(1);").WithLocation(6, 1) + ); + } + + [Fact] + public void Attributes_01() + { + var text1 = @" +[MyAttribute(i)] +const int i = 1; + +[MyAttribute(i + 1)] +System.Console.Write(i); + +[MyAttribute(i + 2)] +int j = i; +System.Console.Write(j); + +[MyAttribute(i + 3)] +new MyAttribute(i); + +[MyAttribute(i + 4)] +local(); + +[MyAttribute(i + 5)] +void local() {} + +class MyAttribute : System.Attribute +{ + public MyAttribute(int x) {} +} +"; + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,1): error CS7014: Attributes are not valid in this context. + // [MyAttribute(i)] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i)]").WithLocation(2, 1), + // (5,1): error CS7014: Attributes are not valid in this context. + // [MyAttribute(i + 1)] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i + 1)]").WithLocation(5, 1), + // (8,1): error CS7014: Attributes are not valid in this context. + // [MyAttribute(i + 2)] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i + 2)]").WithLocation(8, 1), + // (12,1): error CS7014: Attributes are not valid in this context. + // [MyAttribute(i + 3)] + Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i + 3)]").WithLocation(12, 1), + // (16,1): error CS0246: The type or namespace name 'local' could not be found (are you missing a using directive or an assembly reference?) + // local(); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "local").WithArguments("local").WithLocation(16, 1), + // (16,6): error CS1001: Identifier expected + // local(); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(16, 6), + // (16,6): error CS8112: Local function '()' must declare a body because it is not marked 'static extern'. + // local(); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "").WithArguments("()").WithLocation(16, 6), + // (19,6): warning CS8321: The local function 'local' is declared but never used + // void local() {} + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(19, 6) + ); + + var tree1 = comp.SyntaxTrees[0]; + + var model1 = comp.GetSemanticModel(tree1); + var localDecl = tree1.GetRoot().DescendantNodes().OfType().First(); + var declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.Int32 i", declSymbol.ToTestDisplayString()); + + var localRefs = tree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "i").ToArray(); + Assert.Equal(9, localRefs.Length); + + foreach (var localRef in localRefs) + { + var refSymbol = model1.GetSymbolInfo(localRef).Symbol; + Assert.Same(declSymbol, refSymbol); + Assert.Contains(declSymbol.Name, model1.LookupNames(localRef.SpanStart)); + Assert.Contains(declSymbol, model1.LookupSymbols(localRef.SpanStart)); + Assert.Same(declSymbol, model1.LookupSymbols(localRef.SpanStart, name: declSymbol.Name).Single()); + } + + localDecl = tree1.GetRoot().DescendantNodes().OfType().ElementAt(1); + declSymbol = model1.GetDeclaredSymbol(localDecl); + Assert.Equal("System.Int32 j", declSymbol.ToTestDisplayString()); + } + + [Fact] + public void Attributes_02() + { + var source = @" +using System.Runtime.CompilerServices; + +return; + +#pragma warning disable 8321 // Unreferenced local function + +[MethodImpl(MethodImplOptions.ForwardRef)] +static void forwardRef() { System.Console.WriteLine(0); } + +[MethodImpl(MethodImplOptions.NoInlining)] +static void noInlining() { System.Console.WriteLine(1); } + +[MethodImpl(MethodImplOptions.NoOptimization)] +static void noOptimization() { System.Console.WriteLine(2); } + +[MethodImpl(MethodImplOptions.Synchronized)] +static void synchronized() { System.Console.WriteLine(3); } + +[MethodImpl(MethodImplOptions.InternalCall)] +extern static void internalCallStatic(); +"; + var verifier = CompileAndVerify( + source, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: DefaultParseOptions, + assemblyValidator: validateAssembly, + verify: Verification.Skipped); + + var comp = verifier.Compilation; + var syntaxTree = comp.SyntaxTrees.Single(); + var semanticModel = comp.GetSemanticModel(syntaxTree); + var localFunctions = syntaxTree.GetRoot().DescendantNodes().OfType().ToList(); + + checkImplAttributes(localFunctions[0], MethodImplAttributes.ForwardRef); + checkImplAttributes(localFunctions[1], MethodImplAttributes.NoInlining); + checkImplAttributes(localFunctions[2], MethodImplAttributes.NoOptimization); + checkImplAttributes(localFunctions[3], MethodImplAttributes.Synchronized); + checkImplAttributes(localFunctions[4], MethodImplAttributes.InternalCall); + + void checkImplAttributes(LocalFunctionStatementSyntax localFunctionStatement, MethodImplAttributes expectedFlags) + { + var localFunction = semanticModel.GetDeclaredSymbol(localFunctionStatement).GetSymbol(); + Assert.Equal(expectedFlags, localFunction.ImplementationAttributes); + } + + void validateAssembly(PEAssembly assembly) + { + var peReader = assembly.GetMetadataReader(); + + foreach (var methodHandle in peReader.MethodDefinitions) + { + var methodDef = peReader.GetMethodDefinition(methodHandle); + var actualFlags = methodDef.ImplAttributes; + + var methodName = peReader.GetString(methodDef.Name); + var expectedFlags = methodName switch + { + "<$Main>g__forwardRef|0_0" => MethodImplAttributes.ForwardRef, + "<$Main>g__noInlining|0_1" => MethodImplAttributes.NoInlining, + "<$Main>g__noOptimization|0_2" => MethodImplAttributes.NoOptimization, + "<$Main>g__synchronized|0_3" => MethodImplAttributes.Synchronized, + "<$Main>g__internalCallStatic|0_4" => MethodImplAttributes.InternalCall, + ".ctor" => MethodImplAttributes.IL, + "$Main" => MethodImplAttributes.IL, + _ => throw TestExceptionUtilities.UnexpectedValue(methodName) + }; + + Assert.Equal(expectedFlags, actualFlags); + } + } + } + + [Fact] + public void Attributes_03() + { + var source = @" +using System.Runtime.InteropServices; + +local1(); + +[DllImport( + ""something.dll"", + EntryPoint = ""a"", + CharSet = CharSet.Ansi, + SetLastError = true, + ExactSpelling = true, + PreserveSig = false, + CallingConvention = CallingConvention.Cdecl, + BestFitMapping = false, + ThrowOnUnmappableChar = true)] +static extern void local1(); +"; + var verifier = CompileAndVerify( + source, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: DefaultParseOptions, + symbolValidator: validate, + verify: Verification.Skipped); + + var comp = verifier.Compilation; + var syntaxTree = comp.SyntaxTrees.Single(); + var semanticModel = comp.GetSemanticModel(syntaxTree); + + var localFunction = semanticModel + .GetDeclaredSymbol(syntaxTree.GetRoot().DescendantNodes().OfType().Single()) + .GetSymbol(); + + Assert.Equal(new[] { "DllImportAttribute" }, GetAttributeNames(localFunction.GetAttributes())); + validateLocalFunction(localFunction); + + void validate(ModuleSymbol module) + { + var cClass = module.GlobalNamespace.GetMember("$Program"); + Assert.Equal(new[] { "CompilerGeneratedAttribute" }, GetAttributeNames(cClass.GetAttributes().As())); + + Assert.Empty(cClass.GetMethod("$Main").GetAttributes()); + + var localFn1 = cClass.GetMethod("<$Main>g__local1|0_0"); + + Assert.Empty(localFn1.GetAttributes()); + validateLocalFunction(localFn1); + } + + static void validateLocalFunction(MethodSymbol localFunction) + { + Assert.True(localFunction.IsExtern); + + var importData = localFunction.GetDllImportData(); + Assert.NotNull(importData); + Assert.Equal("something.dll", importData.ModuleName); + Assert.Equal("a", importData.EntryPointName); + Assert.Equal(CharSet.Ansi, importData.CharacterSet); + Assert.True(importData.SetLastError); + Assert.True(importData.ExactSpelling); + Assert.Equal(MethodImplAttributes.IL, localFunction.ImplementationAttributes); + Assert.Equal(CallingConvention.Cdecl, importData.CallingConvention); + Assert.False(importData.BestFitMapping); + Assert.True(importData.ThrowOnUnmappableCharacter); + } + } + + [Fact] + public void ModelWithIgnoredAccessibility_01() + { + var source = @" +new A().M(); + +class A +{ + A M() { return new A(); } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,9): error CS0122: 'A.M()' is inaccessible due to its protection level + // new A().M(); + Diagnostic(ErrorCode.ERR_BadAccess, "M").WithArguments("A.M()").WithLocation(2, 9) + ); + + var a = ((Compilation)comp).SourceModule.GlobalNamespace.GetTypeMember("A"); + var syntaxTree = comp.SyntaxTrees.Single(); + var invocation = syntaxTree.GetRoot().DescendantNodes().OfType().Single(); + + var semanticModel = comp.GetSemanticModel(syntaxTree); + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); + Assert.Null(semanticModel.GetSymbolInfo(invocation).Symbol); + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).CandidateSymbols.Single().Name); + Assert.Equal(CandidateReason.Inaccessible, semanticModel.GetSymbolInfo(invocation).CandidateReason); + Assert.Empty(semanticModel.LookupSymbols(invocation.SpanStart, container: a, name: "M")); + + semanticModel = comp.GetSemanticModel(syntaxTree, ignoreAccessibility: true); + + Assert.Equal("A", semanticModel.GetTypeInfo(invocation).Type.Name); + Assert.Equal("M", semanticModel.GetSymbolInfo(invocation).Symbol.Name); + Assert.NotEmpty(semanticModel.LookupSymbols(invocation.SpanStart, container: a, name: "M")); + } + + [Fact] + public void ModelWithIgnoredAccessibility_02() + { + var source = @" +var x = new A().M(); + +class A +{ + A M() + { + x = null; + return new A(); + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (2,17): error CS0122: 'A.M()' is inaccessible due to its protection level + // var x = new A().M(); + Diagnostic(ErrorCode.ERR_BadAccess, "M").WithArguments("A.M()").WithLocation(2, 17), + // (8,9): error CS9000: Cannot use local variable or local function 'x' declared in a top-level statement in this context. + // x = null; + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "x").WithArguments("x").WithLocation(8, 9) + ); + + var a = ((Compilation)comp).SourceModule.GlobalNamespace.GetTypeMember("A"); + var syntaxTree = comp.SyntaxTrees.Single(); + var localDecl = syntaxTree.GetRoot().DescendantNodes().OfType().Single(); + var localRef = syntaxTree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single(); + + var semanticModel = comp.GetSemanticModel(syntaxTree, ignoreAccessibility: true); + + var x = semanticModel.GetDeclaredSymbol(localDecl); + Assert.Same(x, semanticModel.LookupSymbols(localDecl.SpanStart, name: "x").Single()); + Assert.Same(x, semanticModel.GetSymbolInfo(localRef).Symbol); + Assert.Same(x, semanticModel.LookupSymbols(localRef.SpanStart, name: "x").Single()); + } + + [Fact] + public void ModelWithIgnoredAccessibility_03() + { + var source = @" +var x = new B().M(1); + +class A +{ + public long M(long i) => i; +} + +class B : A +{ + protected int M(int i) + { + _ = x; + return i; + } +} +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (13,13): error CS9000: Cannot use local variable or local function 'x' declared in a top-level statement in this context. + // _ = x; + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "x").WithArguments("x").WithLocation(13, 13) + ); + + var a = ((Compilation)comp).SourceModule.GlobalNamespace.GetTypeMember("A"); + var syntaxTree1 = comp.SyntaxTrees.Single(); + var localDecl = syntaxTree1.GetRoot().DescendantNodes().OfType().Single(); + var localRef = syntaxTree1.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single(); + + verifyModel(ignoreAccessibility: true, "System.Int32"); + verifyModel(ignoreAccessibility: false, "System.Int64"); + + void verifyModel(bool ignoreAccessibility, string expectedType) + { + var semanticModel1 = comp.GetSemanticModel(syntaxTree1, ignoreAccessibility); + + var xDecl = semanticModel1.GetDeclaredSymbol(localDecl); + Assert.Same(xDecl, semanticModel1.LookupSymbols(localDecl.SpanStart, name: "x").Single()); + var xRef = semanticModel1.GetSymbolInfo(localRef).Symbol; + Assert.Same(xRef, semanticModel1.LookupSymbols(localRef.SpanStart, name: "x").Single()); + Assert.Equal(expectedType, ((ILocalSymbol)xRef).Type.ToTestDisplayString()); + Assert.Equal(expectedType, ((ILocalSymbol)xDecl).Type.ToTestDisplayString()); + Assert.Same(xDecl, xRef); + } + } + + [Fact] + public void ModelWithIgnoredAccessibility_04() + { + var source1 = @" +var x = new B().M(1); +"; + var source2 = @" +class A +{ + public long M(long i) => i; +} + +class B : A +{ + protected int M(int i) + { + _ = x; + return i; + } +} +"; + var comp = CreateCompilation(new[] { source1, source2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics( + // (11,13): error CS9000: Cannot use local variable or local function 'x' declared in a top-level statement in this context. + // _ = x; + Diagnostic(ErrorCode.ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement, "x").WithArguments("x").WithLocation(11, 13) + ); + + var a = ((Compilation)comp).SourceModule.GlobalNamespace.GetTypeMember("A"); + var syntaxTree1 = comp.SyntaxTrees.First(); + var localDecl = syntaxTree1.GetRoot().DescendantNodes().OfType().Single(); + var syntaxTree2 = comp.SyntaxTrees[1]; + var localRef = syntaxTree2.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "x").Single(); + + verifyModel(ignoreAccessibility: true, "System.Int32"); + verifyModel(ignoreAccessibility: false, "System.Int64"); + + void verifyModel(bool ignoreAccessibility, string expectedType) + { + var semanticModel1 = comp.GetSemanticModel(syntaxTree1, ignoreAccessibility); + + var xDecl = semanticModel1.GetDeclaredSymbol(localDecl); + Assert.Same(xDecl, semanticModel1.LookupSymbols(localDecl.SpanStart, name: "x").Single()); + Assert.Equal(expectedType, ((ILocalSymbol)xDecl).Type.ToTestDisplayString()); + + var semanticModel2 = comp.GetSemanticModel(syntaxTree2, ignoreAccessibility); + + var xRef = semanticModel2.GetSymbolInfo(localRef).Symbol; + Assert.Same(xRef, semanticModel2.LookupSymbols(localRef.SpanStart, name: "x").Single()); + Assert.Equal(expectedType, ((ILocalSymbol)xRef).Type.ToTestDisplayString()); + Assert.Same(xDecl, xRef); + } + } + + [Fact] + public void AnalyzerActions_01() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_01_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(0, analyzer.FireCount4); + Assert.Equal(1, analyzer.FireCount5); + Assert.Equal(0, analyzer.FireCount6); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_01_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(1, analyzer.FireCount4); + Assert.Equal(1, analyzer.FireCount5); + Assert.Equal(1, analyzer.FireCount6); + } + + private class AnalyzerActions_01_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + public int FireCount4; + public int FireCount5; + public int FireCount6; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSyntaxNodeAction(Handle1, SyntaxKind.GlobalStatement); + context.RegisterSyntaxNodeAction(Handle2, SyntaxKind.CompilationUnit); + } + + private void Handle1(SyntaxNodeAnalysisContext context) + { + var model = context.SemanticModel; + var globalStatement = (GlobalStatementSyntax)context.Node; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + switch (globalStatement.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + Assert.Same(globalStatement.SyntaxTree, context.ContainingSymbol.DeclaringSyntaxReferences.Single().SyntaxTree); + Assert.True(syntaxTreeModel.TestOnlyMemberModels.ContainsKey(globalStatement.Parent)); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[globalStatement.Parent]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(globalStatement.Statement).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(globalStatement.Statement)); + } + + private void Handle2(SyntaxNodeAnalysisContext context) + { + var model = context.SemanticModel; + var unit = (CompilationUnitSyntax)context.Node; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + switch (unit.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref context.ContainingSymbol.Kind == SymbolKind.Namespace ? ref FireCount5 : ref FireCount3); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref context.ContainingSymbol.Kind == SymbolKind.Namespace ? ref FireCount6 : ref FireCount4); + break; + default: + Assert.True(false); + break; + } + + switch (context.ContainingSymbol.ToTestDisplayString()) + { + case "": + Assert.Same(unit.SyntaxTree, context.ContainingSymbol.DeclaringSyntaxReferences.Single().SyntaxTree); + Assert.True(syntaxTreeModel.TestOnlyMemberModels.ContainsKey(unit)); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(unit)); + break; + case "": + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_02() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_02_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_02_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_02_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSymbolAction(Handle, SymbolKind.Method); + } + + private void Handle(SymbolAnalysisContext context) + { + Assert.Equal("", context.Symbol.ToTestDisplayString()); + + switch (context.Symbol.DeclaringSyntaxReferences.Single().GetSyntax().ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_03() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_03_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_03_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_03_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSymbolStartAction(Handle, SymbolKind.Method); + } + + private void Handle(SymbolStartAnalysisContext context) + { + Assert.Equal("", context.Symbol.ToTestDisplayString()); + + switch (context.Symbol.DeclaringSyntaxReferences.Single().GetSyntax().ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_04() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_04_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(0, analyzer.FireCount4); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_04_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(1, analyzer.FireCount4); + } + + private class AnalyzerActions_04_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + public int FireCount4; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationAction(Handle1, OperationKind.Invocation); + context.RegisterOperationAction(Handle2, OperationKind.Block); + } + + private void Handle1(OperationAnalysisContext context) + { + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + Assert.Same(context.ContainingSymbol.DeclaringSyntaxReferences.Single().SyntaxTree, context.Operation.Syntax.SyntaxTree); + + Assert.Equal(SyntaxKind.InvocationExpression, context.Operation.Syntax.Kind()); + + switch (context.Operation.Syntax.ToString()) + { + case "System.Console.WriteLine(1)": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2)": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + + private void Handle2(OperationAnalysisContext context) + { + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + Assert.Same(context.ContainingSymbol.DeclaringSyntaxReferences.Single().GetSyntax(), context.Operation.Syntax); + Assert.Equal(SyntaxKind.CompilationUnit, context.Operation.Syntax.Kind()); + + switch (context.Operation.Syntax.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount3); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount4); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_05() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_05_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_05_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_05_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationBlockAction(Handle); + } + + private void Handle(OperationBlockAnalysisContext context) + { + Assert.Equal("", context.OwningSymbol.ToTestDisplayString()); + Assert.Equal(SyntaxKind.CompilationUnit, context.OperationBlocks.Single().Syntax.Kind()); + + switch (context.OperationBlocks.Single().Syntax.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_06() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_06_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_06_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_06_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationBlockStartAction(Handle); + } + + private void Handle(OperationBlockStartAnalysisContext context) + { + Assert.Equal("", context.OwningSymbol.ToTestDisplayString()); + Assert.Equal(SyntaxKind.CompilationUnit, context.OperationBlocks.Single().Syntax.Kind()); + + switch (context.OperationBlocks.Single().Syntax.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_07() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_07_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_07_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_07_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterCodeBlockAction(Handle); + } + + private void Handle(CodeBlockAnalysisContext context) + { + Assert.Equal("", context.OwningSymbol.ToTestDisplayString()); + Assert.Equal(SyntaxKind.CompilationUnit, context.CodeBlock.Kind()); + + switch (context.CodeBlock.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + + var model = context.SemanticModel; + var unit = (CompilationUnitSyntax)context.CodeBlock; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(unit)); + } + } + + [Fact] + public void AnalyzerActions_08() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_08_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_08_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + } + + private class AnalyzerActions_08_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterCodeBlockStartAction(Handle); + } + + private void Handle(CodeBlockStartAnalysisContext context) + { + Assert.Equal("", context.OwningSymbol.ToTestDisplayString()); + Assert.Equal(SyntaxKind.CompilationUnit, context.CodeBlock.Kind()); + + switch (context.CodeBlock.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + + var model = context.SemanticModel; + var unit = (CompilationUnitSyntax)context.CodeBlock; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(unit)); + } + } + + [Fact] + public void AnalyzerActions_09() + { + var text1 = @" +System.Console.WriteLine(""Hi!""); +"; + var text2 = @" +class Test +{ + void M() + { + M(); + } +} +"; + + var analyzer = new AnalyzerActions_09_Analyzer(); + var comp = CreateCompilation(text1 + text2, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(1, analyzer.FireCount4); + + analyzer = new AnalyzerActions_09_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(2, analyzer.FireCount4); + } + + private class AnalyzerActions_09_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + public int FireCount4; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSyntaxNodeAction(Handle1, SyntaxKind.InvocationExpression); + context.RegisterSyntaxNodeAction(Handle2, SyntaxKind.CompilationUnit); + } + + private void Handle1(SyntaxNodeAnalysisContext context) + { + var model = context.SemanticModel; + var node = (CSharpSyntaxNode)context.Node; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + switch (node.ToString()) + { + case @"System.Console.WriteLine(""Hi!"")": + Interlocked.Increment(ref FireCount1); + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + break; + + case "M()": + Interlocked.Increment(ref FireCount2); + Assert.Equal("void Test.M()", context.ContainingSymbol.ToTestDisplayString()); + break; + + default: + Assert.True(false); + break; + } + + var decl = (CSharpSyntaxNode)context.ContainingSymbol.DeclaringSyntaxReferences.Single().GetSyntax(); + + Assert.True(syntaxTreeModel.TestOnlyMemberModels.ContainsKey(decl)); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[decl]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(node).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(node)); + } + + private void Handle2(SyntaxNodeAnalysisContext context) + { + var model = context.SemanticModel; + var node = (CSharpSyntaxNode)context.Node; + var syntaxTreeModel = ((SyntaxTreeSemanticModel)model); + + switch (context.ContainingSymbol.ToTestDisplayString()) + { + case @"": + Interlocked.Increment(ref FireCount3); + + Assert.True(syntaxTreeModel.TestOnlyMemberModels.ContainsKey(node)); + + MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[node]; + + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(node).IsDefaultOrEmpty); + + Assert.Same(mm, syntaxTreeModel.GetMemberModel(node)); + break; + + case "": + Interlocked.Increment(ref FireCount4); + break; + + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_10() + { + var text1 = @" +[assembly: MyAttribute(1)] +"; + var text2 = @" +System.Console.WriteLine(""Hi!""); +"; + var text3 = @" +[MyAttribute(2)] +class Test +{ + [MyAttribute(3)] + void M() + { + } +} + +class MyAttribute : System.Attribute +{ + public MyAttribute(int x) {} +} +"; + + var analyzer = new AnalyzerActions_10_Analyzer(); + var comp = CreateCompilation(text1 + text2 + text3, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(1, analyzer.FireCount4); + Assert.Equal(1, analyzer.FireCount5); + + analyzer = new AnalyzerActions_10_Analyzer(); + comp = CreateCompilation(new[] { text1, text2, text3 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + Assert.Equal(1, analyzer.FireCount4); + Assert.Equal(3, analyzer.FireCount5); + } + + private class AnalyzerActions_10_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + public int FireCount4; + public int FireCount5; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSyntaxNodeAction(Handle1, SyntaxKind.Attribute); + context.RegisterSyntaxNodeAction(Handle2, SyntaxKind.CompilationUnit); + } + + private void Handle1(SyntaxNodeAnalysisContext context) + { + var node = (CSharpSyntaxNode)context.Node; + + switch (node.ToString()) + { + case @"MyAttribute(1)": + Interlocked.Increment(ref FireCount1); + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + break; + + case @"MyAttribute(2)": + Interlocked.Increment(ref FireCount2); + Assert.Equal("Test", context.ContainingSymbol.ToTestDisplayString()); + break; + + case @"MyAttribute(3)": + Interlocked.Increment(ref FireCount3); + Assert.Equal("void Test.M()", context.ContainingSymbol.ToTestDisplayString()); + break; + + default: + Assert.True(false); + break; + } + } + + private void Handle2(SyntaxNodeAnalysisContext context) + { + switch (context.ContainingSymbol.ToTestDisplayString()) + { + case @"": + Interlocked.Increment(ref FireCount4); + break; + + case @"": + Interlocked.Increment(ref FireCount5); + break; + + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_11() + { + var text1 = @" +System.Console.WriteLine(""Hi!""); +"; + var text2 = @" +namespace N1 +{} + +class C1 +{} +"; + + var analyzer = new AnalyzerActions_11_Analyzer(); + var comp = CreateCompilation(text1 + text2, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + + analyzer = new AnalyzerActions_11_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + } + + private class AnalyzerActions_11_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSymbolAction(Handle1, SymbolKind.Method); + context.RegisterSymbolAction(Handle2, SymbolKind.Namespace); + context.RegisterSymbolAction(Handle3, SymbolKind.NamedType); + } + + private void Handle1(SymbolAnalysisContext context) + { + Interlocked.Increment(ref FireCount1); + Assert.Equal("", context.Symbol.ToTestDisplayString()); + } + + private void Handle2(SymbolAnalysisContext context) + { + Interlocked.Increment(ref FireCount2); + Assert.Equal("N1", context.Symbol.ToTestDisplayString()); + } + + private void Handle3(SymbolAnalysisContext context) + { + Interlocked.Increment(ref FireCount3); + Assert.Equal("C1", context.Symbol.ToTestDisplayString()); + } + } + + [Fact] + public void AnalyzerActions_12() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_12_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_12_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(2, analyzer.FireCount3); + } + + private class AnalyzerActions_12_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationBlockStartAction(Handle1); + } + + private void Handle1(OperationBlockStartAnalysisContext context) + { + Interlocked.Increment(ref FireCount3); + context.RegisterOperationBlockEndAction(Handle2); + } + + private void Handle2(OperationBlockAnalysisContext context) + { + Assert.Equal("", context.OwningSymbol.ToTestDisplayString()); + Assert.Equal(SyntaxKind.CompilationUnit, context.OperationBlocks.Single().Syntax.Kind()); + + switch (context.OperationBlocks.Single().Syntax.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void AnalyzerActions_13() + { + var text1 = @"System.Console.WriteLine(1);"; + + var analyzer = new AnalyzerActions_13_Analyzer(); + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(0, analyzer.FireCount2); + Assert.Equal(1, analyzer.FireCount3); + + var text2 = @"System.Console.WriteLine(2);"; + + analyzer = new AnalyzerActions_13_Analyzer(); + comp = CreateCompilation(new[] { text1, text2 }, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); + + Assert.Equal(1, analyzer.FireCount1); + Assert.Equal(1, analyzer.FireCount2); + Assert.Equal(2, analyzer.FireCount3); + } + + private class AnalyzerActions_13_Analyzer : DiagnosticAnalyzer + { + public int FireCount1; + public int FireCount2; + public int FireCount3; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor("XY0000", "Test", "Test", "Test", DiagnosticSeverity.Warning, true, "Test", "Test"); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.RegisterOperationBlockStartAction(Handle1); + } + + private void Handle1(OperationBlockStartAnalysisContext context) + { + Interlocked.Increment(ref FireCount3); + context.RegisterOperationAction(Handle2, OperationKind.Block); + } + + private void Handle2(OperationAnalysisContext context) + { + Assert.Equal("", context.ContainingSymbol.ToTestDisplayString()); + Assert.Same(context.ContainingSymbol.DeclaringSyntaxReferences.Single().GetSyntax(), context.Operation.Syntax); + Assert.Equal(SyntaxKind.CompilationUnit, context.Operation.Syntax.Kind()); + + switch (context.Operation.Syntax.ToString()) + { + case "System.Console.WriteLine(1);": + Interlocked.Increment(ref FireCount1); + break; + case "System.Console.WriteLine(2);": + Interlocked.Increment(ref FireCount2); + break; + default: + Assert.True(false); + break; + } + } + } + + [Fact] + public void MissingTypes_01() + { + var text = @"return;"; + + var comp = CreateEmptyCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. + Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1), + // error CS0518: Predefined type 'System.Object' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Object").WithLocation(1, 1), + // error CS0518: Predefined type 'System.Void' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Void").WithLocation(1, 1), + // error CS0518: Predefined type 'System.String' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.String").WithLocation(1, 1) + ); + } + + [Fact] + public void MissingTypes_02() + { + var text = @"await Test();"; + + var comp = CreateCompilation(text, targetFramework: TargetFramework.Minimal, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Threading.Tasks.Task' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Threading.Tasks.Task").WithLocation(1, 1), + // (1,1): warning CS0028: '' has the wrong signature to be an entry point + // await Test(); + Diagnostic(ErrorCode.WRN_InvalidMainSig, "await Test();").WithArguments("").WithLocation(1, 1), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (1,7): error CS0103: The name 'Test' does not exist in the current context + // await Test(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Test").WithArguments("Test").WithLocation(1, 7) + ); + } + + [Fact] + public void MissingTypes_03() + { + var text = @" +System.Console.WriteLine(""Hi!""); +return 10; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.MakeTypeMissing(SpecialType.System_Int32); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32[missing]", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Int32' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Int32").WithLocation(1, 1), + // (3,8): error CS0518: Predefined type 'System.Int32' is not defined or imported + // return 10; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "10").WithArguments("System.Int32").WithLocation(3, 8) + ); + } + + [Fact] + public void MissingTypes_04() + { + var text = @" +await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); +return 11; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.MakeTypeMissing(SpecialType.System_Int32); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Int32' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Int32").WithLocation(1, 1), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (2,1): warning CS0028: '' has the wrong signature to be an entry point + // await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); + Diagnostic(ErrorCode.WRN_InvalidMainSig, @"await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); +return 11; +").WithArguments("").WithLocation(2, 1), + // (2,1): error CS0518: Predefined type 'System.Int32' is not defined or imported + // await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "await System.Threading.Tasks.Task.Factory.StartNew(() => 5L);").WithArguments("System.Int32").WithLocation(2, 1), + // (2,1): error CS0518: Predefined type 'System.Int32' is not defined or imported + // await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "await System.Threading.Tasks.Task.Factory.StartNew(() => 5L);").WithArguments("System.Int32").WithLocation(2, 1), + // (2,1): error CS0518: Predefined type 'System.Int32' is not defined or imported + // await System.Threading.Tasks.Task.Factory.StartNew(() => 5L); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "await System.Threading.Tasks.Task.Factory.StartNew(() => 5L);").WithArguments("System.Int32").WithLocation(2, 1), + // (3,8): error CS0518: Predefined type 'System.Int32' is not defined or imported + // return 11; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "11").WithArguments("System.Int32").WithLocation(3, 8) + ); + } + + [Fact] + public void MissingTypes_05() + { + var text = @" +await System.Threading.Tasks.Task.Factory.StartNew(() => ""5""); +return 11; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_Task_T); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task[missing]", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Threading.Tasks.Task`1' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Threading.Tasks.Task`1").WithLocation(1, 1), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (2,1): warning CS0028: '' has the wrong signature to be an entry point + // await System.Threading.Tasks.Task.Factory.StartNew(() => "5"); + Diagnostic(ErrorCode.WRN_InvalidMainSig, @"await System.Threading.Tasks.Task.Factory.StartNew(() => ""5""); +return 11; +").WithArguments("").WithLocation(2, 1) + ); + } + + [Fact] + public void MissingTypes_06() + { + var text = @" +await System.Threading.Tasks.Task.Factory.StartNew(() => ""5""); +return 11; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.MakeTypeMissing(SpecialType.System_Int32); + comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_Task_T); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task[missing]", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Threading.Tasks.Task`1' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Threading.Tasks.Task`1").WithLocation(1, 1), + // error CS0518: Predefined type 'System.Int32' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Int32").WithLocation(1, 1), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (2,1): warning CS0028: '' has the wrong signature to be an entry point + // await System.Threading.Tasks.Task.Factory.StartNew(() => "5"); + Diagnostic(ErrorCode.WRN_InvalidMainSig, @"await System.Threading.Tasks.Task.Factory.StartNew(() => ""5""); +return 11; +").WithArguments("").WithLocation(2, 1), + // (3,8): error CS0518: Predefined type 'System.Int32' is not defined or imported + // return 11; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "11").WithArguments("System.Int32").WithLocation(3, 8) + ); + } + + [Fact] + public void MissingTypes_07() + { + var text = @" +System.Console.WriteLine(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.MakeTypeMissing(SpecialType.System_String); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.String[missing][] args", entryPoint.Parameters.Single().ToTestDisplayString()); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.String' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.String").WithLocation(1, 1) + ); + } + + [Fact] + public void Return_01() + { + var text = @" +System.Console.WriteLine(args[0]); +return; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "Return_01", args: new[] { "Return_01" }); + + if (ExecutionConditionUtil.IsWindows) + { + _ = ConditionalSkipReason.NativePdbRequiresDesktop; + + comp.VerifyPdb("$Program.$Main", +@" + + + + + + + + + + + + + + + + + +", options: PdbValidationOptions.SkipConversionValidation); + } + } + + [Fact] + public void Return_02() + { + var text = @" +System.Console.WriteLine(args[0]); +return 10; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "Return_02", args: new[] { "Return_02" }, expectedReturnCode: 10); + + if (ExecutionConditionUtil.IsWindows) + { + _ = ConditionalSkipReason.NativePdbRequiresDesktop; + + comp.VerifyPdb("$Program.$Main", +@" + + + + + + + + + + + + + + + + + +", options: PdbValidationOptions.SkipConversionValidation); + } + } + + [Fact] + public void Return_03() + { + var text = @" +using System; +using System.Threading.Tasks; + +Console.Write(""hello ""); +await Task.Factory.StartNew(() => 5); +Console.Write(args[0]); +return; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "hello Return_03", args: new[] { "Return_03" }); + + if (ExecutionConditionUtil.IsWindows) + { + _ = ConditionalSkipReason.NativePdbRequiresDesktop; + + comp.VerifyPdb("$Program+<$Main>d__0.MoveNext", +@" + + + + + + + + + + + + + + + + + + + + + + + + +", options: PdbValidationOptions.SkipConversionValidation); + } + } + + [Fact] + public void Return_04() + { + var text = @" +using System; +using System.Threading.Tasks; + +Console.Write(""hello ""); +await Task.Factory.StartNew(() => 5); +Console.Write(args[0]); +return 11; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + AssertEntryPointParameter(entryPoint); + CompileAndVerify(comp, expectedOutput: "hello Return_04", args: new[] { "Return_04" }, expectedReturnCode: 11); + + if (ExecutionConditionUtil.IsWindows) + { + _ = ConditionalSkipReason.NativePdbRequiresDesktop; + + comp.VerifyPdb("$Program+<$Main>d__0.MoveNext", +@" + + + + + + + + + + + + + + + + + + + + + + + + + +", options: PdbValidationOptions.SkipConversionValidation); + } + } + + [Fact] + public void Return_05() + { + var text = @" +System.Console.WriteLine(""Hi!""); +return ""error""; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyDiagnostics( + // (3,8): error CS0029: Cannot implicitly convert type 'string' to 'int' + // return "error"; + Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""error""").WithArguments("string", "int").WithLocation(3, 8) + ); + } + + [Fact] + public void Return_06() + { + var text = @" +System.Func d = n => + { + System.Console.WriteLine(""Hi!""); + return n; + }; +d(0); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Return_07() + { + var text = @" +System.Func d = delegate(int n) + { + System.Console.WriteLine(""Hi!""); + return n; + }; +d(0); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Return_08() + { + var text = @" +System.Func d = (n) => + { + System.Console.WriteLine(""Hi!""); + return n; + }; +d(0); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Return_09() + { + var text = @" +int local(int n) +{ + System.Console.WriteLine(""Hi!""); + return n; +} + +local(0); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + Assert.True(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void Return_10() + { + var text = @" +bool b = true; +if (b) + return 0; +else + return; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyDiagnostics( + // (6,5): error CS0126: An object of a type convertible to 'int' is required + // return; + Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int").WithLocation(6, 5) + ); + } + + [Fact] + public void Return_11() + { + var text = @" +bool b = true; +if (b) + return; +else + return 0; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + comp.VerifyDiagnostics( + // (4,5): error CS0126: An object of a type convertible to 'int' is required + // return; + Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int").WithLocation(4, 5) + ); + } + + [Fact] + public void Return_12() + { + var text = @" +System.Console.WriteLine(1); +return; +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Void", entryPoint.ReturnType.ToTestDisplayString()); + CompileAndVerify(comp, expectedOutput: "1").VerifyDiagnostics( + // (4,1): warning CS0162: Unreachable code detected + // System.Console.WriteLine(2); + Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(4, 1) + ); + } + + [Fact] + public void Return_13() + { + var text = @" +System.Console.WriteLine(1); +return 13; +System.Console.WriteLine(2); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + CompileAndVerify(comp, expectedOutput: "1", expectedReturnCode: 13).VerifyDiagnostics( + // (4,1): warning CS0162: Unreachable code detected + // System.Console.WriteLine(2); + Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(4, 1) + ); + } + + [Fact] + public void Return_14() + { + var text = @" +System.Console.WriteLine(""Hi!""); +return default; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Int32", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "Hi!", expectedReturnCode: 0); + } + + [Fact] + public void Return_15() + { + var text = @" +using System; +using System.Threading.Tasks; + +Console.Write(""hello ""); +await Task.Factory.StartNew(() => 5); +Console.Write(""async main""); +return default; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + Assert.Equal("System.Threading.Tasks.Task", entryPoint.ReturnType.ToTestDisplayString()); + Assert.False(entryPoint.ReturnsVoid); + CompileAndVerify(comp, expectedOutput: "hello async main", expectedReturnCode: 0); + } + + [Fact] + public void Dll_01() + { + var text = @"System.Console.WriteLine(""Hi!"");"; + + var comp = CreateCompilation(text, options: TestOptions.DebugDll, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // error CS9004: Program using top-level statements must be an executable. + Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable).WithLocation(1, 1) + ); + } + + [Fact] + public void NetModule_01() + { + var text = @"System.Console.WriteLine(""Hi!"");"; + + var comp = CreateCompilation(text, options: TestOptions.ReleaseModule, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // error CS9004: Program using top-level statements must be an executable. + Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable).WithLocation(1, 1) + ); + } + + [Fact] + public void ExpressionStatement_01() + { + // Await expression is covered in other tests + var text = @" +new Test(0); // ObjectCreationExpression: +Test x; +x = new Test(1); // SimpleAssignmentExpression: +x += 1; // AddAssignmentExpression: +x -= 2; // SubtractAssignmentExpression: +x *= 3; // MultiplyAssignmentExpression: +x /= 4; // DivideAssignmentExpression: +x %= 5; // ModuloAssignmentExpression: +x &= 6; // AndAssignmentExpression: +x |= 7; // OrAssignmentExpression: +x ^= 8; // ExclusiveOrAssignmentExpression: +x <<= 9; // LeftShiftAssignmentExpression: +x >>= 10; // RightShiftAssignmentExpression: +x++; // PostIncrementExpression: +x--; // PostDecrementExpression: +++x; // PreIncrementExpression: +--x; // PreDecrementExpression: +System.Console.WriteLine(x.Count); // InvocationExpression: +x?.WhenNotNull(); // ConditionalAccessExpression: +x = null; +x ??= new Test(-1); // CoalesceAssignmentExpression: +System.Console.WriteLine(x.Count); // InvocationExpression: + +class Test +{ + public readonly int Count; + + public Test(int count) + { + Count = count; + if (count == 0) + { + System.Console.WriteLine(""Test..ctor""); + } + } + + public static Test operator +(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator -(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator *(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator /(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator %(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator &(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator |(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator ^(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator <<(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator >>(Test x, int y) + { + return new Test(x.Count + 1); + } + + public static Test operator ++(Test x) + { + return new Test(x.Count + 1); + } + + public static Test operator --(Test x) + { + return new Test(x.Count + 1); + } + + public void WhenNotNull() + { + System.Console.WriteLine(""WhenNotNull""); + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: +@"Test..ctor +15 +WhenNotNull +-1 +"); + } + + [Fact] + public void Block_01() + { + var text = @" +{ + System.Console.WriteLine(""Hi!""); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void EmptyStatement_01() + { + var text = @" +; +System.Console.WriteLine(""Hi!""); +; +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Hi!"); + } + + [Fact] + public void BreakStatement_01() + { + var text = @"break;"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (1,1): error CS0139: No enclosing loop out of which to break or continue + // break; + Diagnostic(ErrorCode.ERR_NoBreakOrCont, "break;").WithLocation(1, 1) + ); + } + + [Fact] + public void ContinueStatement_01() + { + var text = @"continue;"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (1,1): error CS0139: No enclosing loop out of which to break or continue + // continue; + Diagnostic(ErrorCode.ERR_NoBreakOrCont, "continue;").WithLocation(1, 1) + ); + } + + [Fact] + public void ThrowStatement_01() + { + var text = @"throw;"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (1,1): error CS0156: A throw statement with no arguments is not allowed outside of a catch clause + // throw; + Diagnostic(ErrorCode.ERR_BadEmptyThrow, "throw").WithLocation(1, 1) + ); + } + + [Fact] + public void ThrowStatement_02() + { + var text = @"throw null;"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp).VerifyIL("", sequencePoints: "$Program.$Main", source: text, expectedIL: +@" +{ + // Code size 2 (0x2) + .maxstack 1 + // sequence point: throw null; + IL_0000: ldnull + IL_0001: throw +} +"); + } + + [Fact] + public void DoStatement_01() + { + var text = @" +int i = 1; +do +{ + i++; +} while (i < 4); + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "4"); + } + + [Fact] + public void WhileStatement_01() + { + var text = @" +int i = 1; +while (i < 4) +{ + i++; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "4"); + } + + [Fact] + public void ForStatement_01() + { + var text = @" +int i = 1; +for (;i < 4;) +{ + i++; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "4"); + } + + [Fact] + public void CheckedStatement_01() + { + var text = @" +int i = 1; +i++; +checked +{ + i++; +} + +System.Console.WriteLine(i); +"; + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "3").VerifyIL("", sequencePoints: "$Program.$Main", source: text, expectedIL: +@" +{ + // Code size 20 (0x14) + .maxstack 2 + .locals init (int V_0) //i + // sequence point: int i = 1; + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + // sequence point: i++; + IL_0002: ldloc.0 + IL_0003: ldc.i4.1 + IL_0004: add + IL_0005: stloc.0 + // sequence point: { + IL_0006: nop + // sequence point: i++; + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: add.ovf + IL_000a: stloc.0 + // sequence point: } + IL_000b: nop + // sequence point: System.Console.WriteLine(i); + IL_000c: ldloc.0 + IL_000d: call ""void System.Console.WriteLine(int)"" + IL_0012: nop + IL_0013: ret +} +"); + } + + [Fact] + public void UncheckedStatement_01() + { + var text = @" +int i = 1; +i++; +unchecked +{ + i++; +} + +System.Console.WriteLine(i); +"; + var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithOverflowChecks(true), parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "3").VerifyIL("", sequencePoints: "$Program.$Main", source: text, expectedIL: +@" +{ + // Code size 20 (0x14) + .maxstack 2 + .locals init (int V_0) //i + // sequence point: int i = 1; + IL_0000: ldc.i4.1 + IL_0001: stloc.0 + // sequence point: i++; + IL_0002: ldloc.0 + IL_0003: ldc.i4.1 + IL_0004: add.ovf + IL_0005: stloc.0 + // sequence point: { + IL_0006: nop + // sequence point: i++; + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: add + IL_000a: stloc.0 + // sequence point: } + IL_000b: nop + // sequence point: System.Console.WriteLine(i); + IL_000c: ldloc.0 + IL_000d: call ""void System.Console.WriteLine(int)"" + IL_0012: nop + IL_0013: ret +} +"); + } + + [Fact] + public void UnsafeStatement_01() + { + var text = @" +unsafe +{ + int* p = (int*)0; + p++; + System.Console.WriteLine((int)p); +} +"; + var comp = CreateCompilation(text, options: TestOptions.UnsafeDebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "4", verify: Verification.Skipped); + } + + [Fact] + public void FixedStatement_01() + { + var text = @" +fixed(int *p = &new C().i) {} + +class C +{ + public int i = 2; +} +"; + var comp = CreateCompilation(text, options: TestOptions.UnsafeDebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // (2,1): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // fixed(int *p = &new C().i) {} + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "fixed(int *p = &new C().i) {}").WithLocation(2, 1), + // (2,7): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // fixed(int *p = &new C().i) {} + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int *").WithLocation(2, 7), + // (2,16): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // fixed(int *p = &new C().i) {} + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "&new C().i").WithLocation(2, 16) + ); + } + + [Fact] + public void LockStatement_01() + { + var text = @" +int i = 1; +lock (new object()) +{ + i++; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void IfStatement_01() + { + var text = @" +int i = 1; +if (i == 1) +{ + i++; +} +else +{ + i--; +} + +if (i != 2) +{ + i--; +} +else +{ + i++; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "3"); + } + + [Fact] + public void SwitchStatement_01() + { + var text = @" +int i = 1; +switch (i) +{ + case 1: + i++; + break; + default: + i--; + break; +} + +System.Console.WriteLine(i); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "2"); + } + + [Fact] + public void TryStatement_01() + { + var text = @" +try +{ + System.Console.Write(1); + throw null; +} +catch +{ + System.Console.Write(2); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "12"); + } + + [Fact] + public void Args_01() + { + var text = @" +#nullable enable +System.Console.WriteLine(args.Length == 0 ? 0 : -args[0].Length); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "0").VerifyDiagnostics(); + var entryPoint = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(comp); + AssertEntryPointParameter(entryPoint); + } + + [Fact] + public void Args_02() + { + var text1 = @" +using System.Linq; +_ = from args in new object[0] select args; +"; + + var comp = CreateCompilation(text1, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (3,10): error CS1931: The range variable 'args' conflicts with a previous declaration of 'args' + // _ = from args in new object[0] select args; + Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "args").WithArguments("args").WithLocation(3, 10) + ); + } + + [Fact] + public void Args_03() + { + var text = @" +local(); +void local() +{ + System.Console.WriteLine(args[0]); +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Args_03", args: new[] { "Args_03" }).VerifyDiagnostics(); + } + + [Fact] + public void Args_04() + { + var text = @" +System.Action lambda = () => System.Console.WriteLine(args[0]); +lambda(); +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + CompileAndVerify(comp, expectedOutput: "Args_04", args: new[] { "Args_04" }).VerifyDiagnostics(); + } + + [Fact] + public void Span_01() + { + var comp = CreateCompilationWithMscorlibAndSpan(@" +using System; + +Span span = default; +_ = new { Span = span }; + +", options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (5,11): error CS0828: Cannot assign 'Span' to anonymous type property + // _ = new { Span = span }; + Diagnostic(ErrorCode.ERR_AnonymousTypePropertyAssignedBadValue, "Span = span").WithArguments("System.Span").WithLocation(5, 11) + ); + } + + [Fact] + public void Span_02() + { + var comp = CreateCompilationWithMscorlibAndSpan(@" +using System; + +Span outer; +for (Span inner = stackalloc int[10];; inner = outer) +{ + outer = inner; +} +", options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + + comp.VerifyDiagnostics( + // (7,13): error CS8352: Cannot use local 'inner' in this context because it may expose referenced variables outside of their declaration scope + // outer = inner; + Diagnostic(ErrorCode.ERR_EscapeLocal, "inner").WithArguments("inner").WithLocation(7, 13) + ); + } + } +} diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs index d1c7c7eac608f..263d7096c3813 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs @@ -598,35 +598,35 @@ public void MetadataReferenceWithInvalidAlias() // use exported type with invalid alias comp = CSharpCompilation.Create("APP2", - options: TestOptions.ReleaseDll, + options: TestOptions.ReleaseExe, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}", - options: TestOptions.Regular) }, + options: TestOptions.RegularPreview) }, references: new MetadataReference[] { MscorlibRef, mtref } ); comp.VerifyDiagnostics( - // (1,19): error CS1002: ; expected - // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(1, 19), - // (1,20): error CS1031: Type expected - // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_TypeExpected, "*").WithLocation(1, 20), // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), - // (1,61): error CS8124: Tuple must contain at least two elements. - // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_TupleTooFewElements, "").WithLocation(1, 61), // (1,61): error CS1026: ) expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), - // (1,14): error CS0430: The extern alias 'Alias' was not specified in a /reference option + // (1,61): error CS1002: ; expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61), + // (1,14): error CS8112: Local function 'Alias()' must declare a body because it is not marked 'static extern'. + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "Alias").WithArguments("Alias()").WithLocation(1, 14), + // (1,8): error CS0246: The type or namespace name 'alias' could not be found (are you missing a using directive or an assembly reference?) // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_BadExternAlias, "Alias").WithArguments("Alias").WithLocation(1, 14), - // (1,1): hidden CS8020: Unused extern alias. + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias").WithArguments("alias").WithLocation(1, 8), + // (1,14): warning CS0626: Method, operator, or accessor 'Alias()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.HDN_UnusedExternAlias, "extern alias Alias").WithLocation(1, 1) + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Alias").WithArguments("Alias()").WithLocation(1, 14), + // (1,14): warning CS8321: The local function 'Alias' is declared but never used + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Alias").WithArguments("Alias").WithLocation(1, 14) ); } @@ -666,7 +666,7 @@ public void MetadataReferenceWithInvalidAliasWithCSharp6() // use exported type with invalid alias comp = CSharpCompilation.Create("APP2", - options: TestOptions.ReleaseDll, + options: TestOptions.ReleaseExe, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}", options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)) }, @@ -674,30 +674,36 @@ public void MetadataReferenceWithInvalidAliasWithCSharp6() ); comp.VerifyDiagnostics( - // (1,19): error CS1002: ; expected + // (1,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(1, 19), - // (1,19): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7.0 or greater. + Diagnostic(ErrorCode.ERR_FeatureInPreview, "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}").WithArguments("top-level statements").WithLocation(1, 1), + // (1,1): error CS8652: The feature 'extern local functions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(*#$@^%*&); class D : Alias(*#$@^%*&).C {}").WithArguments("tuples", "7.0").WithLocation(1, 19), - // (1,20): error CS1031: Type expected + Diagnostic(ErrorCode.ERR_FeatureInPreview, "extern").WithArguments("extern local functions").WithLocation(1, 1), + // (1,14): error CS8059: Feature 'local functions' is not available in C# 6. Please use language version 7.0 or greater. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_TypeExpected, "*").WithLocation(1, 20), + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "Alias").WithArguments("local functions", "7.0").WithLocation(1, 14), // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), - // (1,61): error CS8124: Tuple must contain at least two elements. - // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_TupleTooFewElements, "").WithLocation(1, 61), // (1,61): error CS1026: ) expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), - // (1,14): error CS0430: The extern alias 'Alias' was not specified in a /reference option + // (1,61): error CS1002: ; expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61), + // (1,14): error CS8112: Local function 'Alias()' must declare a body because it is not marked 'static extern'. + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "Alias").WithArguments("Alias()").WithLocation(1, 14), + // (1,8): error CS0246: The type or namespace name 'alias' could not be found (are you missing a using directive or an assembly reference?) + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias").WithArguments("alias").WithLocation(1, 8), + // (1,14): warning CS0626: Method, operator, or accessor 'Alias()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.ERR_BadExternAlias, "Alias").WithArguments("Alias").WithLocation(1, 14), - // (1,1): hidden CS8020: Unused extern alias. + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Alias").WithArguments("Alias()").WithLocation(1, 14), + // (1,14): warning CS8321: The local function 'Alias' is declared but never used // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} - Diagnostic(ErrorCode.HDN_UnusedExternAlias, "extern alias Alias").WithLocation(1, 1) + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Alias").WithArguments("Alias").WithLocation(1, 14) ); } @@ -1608,7 +1614,7 @@ static void Main() { } compilation.VerifyDiagnostics(); Assert.Null(compilation.GetEntryPoint(default(CancellationToken))); - Assert.Null(compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); + Assert.Same(CSharpCompilation.EntryPoint.None, compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); } [Fact] @@ -1624,7 +1630,7 @@ static void Main() { } compilation.VerifyDiagnostics(); Assert.Null(compilation.GetEntryPoint(default(CancellationToken))); - Assert.Null(compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); + Assert.Same(CSharpCompilation.EntryPoint.None, compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); } [Fact] diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoBrokenCodeTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoBrokenCodeTests.cs index 7249b10a2f8a7..9304d7a8df5d2 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoBrokenCodeTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoBrokenCodeTests.cs @@ -178,8 +178,8 @@ public void IsImplicitlyDeclared() var type = comp.GlobalNamespace.GetMember(TypeSymbol.ImplicitTypeName); Assert.True(type.IsImplicitlyDeclared); Symbol member; - member = type.GetMember("F"); - Assert.False(member.IsImplicitlyDeclared); + member = type.GetMember("F"); + Assert.Null(member); member = type.GetMember("P"); Assert.False(member.IsImplicitlyDeclared); member = type.GetMember("M"); @@ -195,11 +195,12 @@ public void Repro611177() var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); - var usingSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); - model.GetSymbolInfo(usingSyntax); + Assert.Empty(tree.GetCompilationUnitRoot().DescendantNodes().OfType()); - var identifierSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); - model.GetSymbolInfo(identifierSyntax); + foreach (var identifierSyntax in tree.GetCompilationUnitRoot().DescendantNodes().OfType()) + { + model.GetSymbolInfo(identifierSyntax); + } } [WorkItem(611177, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611177")] diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs index b3af847b28ae9..ddfa18e64107a 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs @@ -1578,9 +1578,7 @@ public void TopLevelIndexer() var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; - Assert.NotNull(symbol); - Assert.Equal(SymbolKind.Parameter, symbol.Kind); - Assert.Equal("E", symbol.Name); + Assert.Null(symbol); } [WorkItem(542360, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542360")] diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs index 8096c26c33df6..e7080f3e3a947 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs @@ -813,7 +813,7 @@ public class A var typeA = mems.Where(s => s.Name == "A").Select(s => s); Assert.Equal(1, typeA.Count()); - var invalid = mems.Where(s => s.Name == "").Select(s => s); + var invalid = mems.Where(s => s.Name == SimpleProgramNamedTypeSymbol.UnspeakableName).Select(s => s); Assert.Equal(1, invalid.Count()); } diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs index 1dc92a1972d2d..ec8d4e731c02c 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs @@ -3372,7 +3372,7 @@ void Goo(Func> f = w => x => 1) [Fact] public void TestGetDeclaredSymbolForIncompleteMemberNode() { - var compilation = CreateCompilation(@"u"); + var compilation = CreateCompilation(@"private"); var tree = compilation.SyntaxTrees[0]; var root = tree.GetCompilationUnitRoot(); @@ -3580,7 +3580,7 @@ class void Goo() var model = compilation.GetSemanticModel(tree); var methodDecl = tree.GetCompilationUnitRoot().FindToken(tree.GetCompilationUnitRoot().ToFullString().IndexOf("Goo", StringComparison.Ordinal)).Parent; - Assert.Equal(SyntaxKind.MethodDeclaration, methodDecl.Kind()); + Assert.Equal(SyntaxKind.LocalFunctionStatement, methodDecl.Kind()); var symbol = model.GetDeclaredSymbol(methodDecl); Assert.Equal(SymbolKind.Method, symbol.Kind); @@ -5119,7 +5119,7 @@ static void Main() [Fact] public void TestIncompleteMemberNode_Visitor() { - var compilation = CreateCompilation(@"u"); + var compilation = CreateCompilation(@"private"); var tree = compilation.SyntaxTrees[0]; var root = tree.GetCompilationUnitRoot(); @@ -5133,7 +5133,7 @@ public void TestIncompleteMemberNode_Visitor() var x = tree.FindNodeOrTokenByKind(SyntaxKind.IncompleteMember); Assert.Equal(SyntaxKind.IncompleteMember, x.Kind()); Assert.Equal("C#", x.Language); - Assert.Equal(1, x.Width); + Assert.Equal(7, x.Width); // This will call the Visitor Pattern Methods via the syntaxwalker var collector = new IncompleteSyntaxWalker(); diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs index a1683f9ff8367..c15ba20e16ed0 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs @@ -11359,14 +11359,7 @@ public void UnrecognizedGenericTypeReference() string sourceCode = "/**/C*/"; var semanticInfo = GetSemanticInfoForTest(sourceCode); var type = (INamedTypeSymbol)semanticInfo.Type; - Assert.Equal("C", type.ToTestDisplayString()); - Assert.Equal(2, type.TypeParameters.Length); - var typeParameter = type.TypeParameters[0]; - Assert.Equal(0, typeParameter.Ordinal); - Assert.Equal(string.Empty, typeParameter.Name); - typeParameter = type.TypeParameters[1]; - Assert.Equal(1, typeParameter.Ordinal); - Assert.Equal(string.Empty, typeParameter.Name); + Assert.Equal("System.Boolean", type.ToTestDisplayString()); } [WorkItem(542452, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542452")] diff --git a/src/Compilers/CSharp/Test/Symbol/DocumentationComments/CrefTests.cs b/src/Compilers/CSharp/Test/Symbol/DocumentationComments/CrefTests.cs index e3a0adc328530..775c992b293dd 100644 --- a/src/Compilers/CSharp/Test/Symbol/DocumentationComments/CrefTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/DocumentationComments/CrefTests.cs @@ -5472,7 +5472,7 @@ class C Func lookupSymbol = () => { - var factory = new BinderFactory(compilation, tree); + var factory = new BinderFactory(compilation, tree, ignoreAccessibility: false); var binder = factory.GetBinder(cref); var lookupResult = LookupResult.GetInstance(); HashSet useSiteDiagnostics = null; diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/ClsComplianceTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/ClsComplianceTests.cs index 1473732b0a9f5..ee61d56063015 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/ClsComplianceTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/ClsComplianceTests.cs @@ -2744,10 +2744,13 @@ public void TopLevelMethod_NoAssemblyAttribute() public void M() { } "; - CreateCompilation(source).VerifyDiagnostics( - // (5,13): error CS0116: A namespace does not directly contain members such as fields or methods + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (5,1): error CS0106: The modifier 'public' is not valid for this item + // public void M() { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "public").WithArguments("public").WithLocation(5, 1), + // (5,13): warning CS8321: The local function 'M' is declared but never used // public void M() { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "M")); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(5, 13)); } [Fact] @@ -2762,10 +2765,13 @@ public void TopLevelMethod_AttributeTrue() public void M() { } "; - CreateCompilation(source).VerifyDiagnostics( - // (5,13): error CS0116: A namespace does not directly contain members such as fields or methods + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (7,1): error CS0106: The modifier 'public' is not valid for this item // public void M() { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "M")); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "public").WithArguments("public").WithLocation(7, 1), + // (7,13): warning CS8321: The local function 'M' is declared but never used + // public void M() { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(7, 13)); } [Fact] @@ -2780,10 +2786,13 @@ public void TopLevelMethod_AttributeFalse() public void M() { } "; - CreateCompilation(source).VerifyDiagnostics( - // (7,13): error CS0116: A namespace does not directly contain members such as fields or methods + CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (7,1): error CS0106: The modifier 'public' is not valid for this item + // public void M() { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "public").WithArguments("public").WithLocation(7, 1), + // (7,13): warning CS8321: The local function 'M' is declared but never used // public void M() { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "M")); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(7, 13)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/TypeTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/TypeTests.cs index 31c2cefe0f6b0..012f20477da37 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/TypeTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/TypeTests.cs @@ -1450,9 +1450,9 @@ public void ErrorTypeTest01() var errSymbol = comp.SourceModule.GlobalNamespace.GetMembers().FirstOrDefault() as NamedTypeSymbol; Assert.NotNull(errSymbol); - Assert.Equal("", errSymbol.Name); + Assert.Equal(SimpleProgramNamedTypeSymbol.UnspeakableName, errSymbol.Name); Assert.False(errSymbol.IsErrorType(), "ErrorType"); - Assert.True(errSymbol.IsImplicitClass, "ImplicitClass"); + Assert.False(errSymbol.IsImplicitClass, "ImplicitClass"); } #region "Nullable" diff --git a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalErrorTests.cs b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalErrorTests.cs index 8b947baea54c3..48725a0762e79 100644 --- a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalErrorTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalErrorTests.cs @@ -368,22 +368,10 @@ class A ParserErrorMessageTests.ParseAndValidate(test,// (1,8): error CS1002: ; expected // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_SemicolonExpected, @"\u005C"), - // (1,14): error CS0116: A namespace does not directly contain members such as fields or methods - // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "u0065"), - // (1,22): error CS0116: A namespace does not directly contain members such as fields or methods - // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "System"), + Diagnostic(ErrorCode.ERR_SemicolonExpected, @"\u005C").WithLocation(1, 8), // (1,8): error CS1056: Unexpected character '\u005C' // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_UnexpectedCharacter, "").WithArguments(@"\u005C"), - // (1,20): error CS1022: Type or namespace definition, or end-of-file expected - // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_EOFExpected, "="), - // (1,28): error CS1022: Type or namespace definition, or end-of-file expected - // using S\u005Cu0065 = System; - Diagnostic(ErrorCode.ERR_EOFExpected, ";")); + Diagnostic(ErrorCode.ERR_UnexpectedCharacter, "").WithArguments(@"\u005C").WithLocation(1, 8)); } [Fact, WorkItem(536882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/536882")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index 2144b907f6964..eb322b4032bb5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -46,31 +46,6 @@ public void TestExternAlias() Assert.NotEqual(default, ea.SemicolonToken); } - [Fact] - public void TestExternWithoutAlias() - { - var text = "extern a;"; - var file = this.ParseFile(text); - - Assert.NotNull(file); - Assert.Equal(1, file.Externs.Count); - Assert.Equal(text, file.ToString()); - var errors = file.Errors(); - Assert.Equal(1, errors.Length); - Assert.Equal((int)ErrorCode.ERR_SyntaxError, errors[0].Code); - - var ea = file.Externs[0]; - - Assert.NotEqual(default, ea.ExternKeyword); - Assert.Equal(SyntaxKind.ExternKeyword, ea.ExternKeyword.Kind()); - Assert.NotEqual(default, ea.AliasKeyword); - Assert.Equal(SyntaxKind.AliasKeyword, ea.AliasKeyword.Kind()); - Assert.True(ea.AliasKeyword.IsMissing); - Assert.NotEqual(default, ea.Identifier); - Assert.Equal("a", ea.Identifier.ToString()); - Assert.NotEqual(default, ea.SemicolonToken); - } - [Fact] public void TestUsing() { @@ -7380,12 +7355,15 @@ class A : B : C // (2,15): error CS0116: A namespace cannot directly contain members such as fields or methods // class A : B : C Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "C").WithLocation(2, 15), - // (3,1): error CS1022: Type or namespace definition, or end-of-file expected + // (3,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // { + Diagnostic(ErrorCode.ERR_FeatureInPreview, @"{ +}").WithArguments("top-level statements").WithLocation(3, 1), + // (3,1): error CS9002: Top-level statements must precede namespace and type declarations. // { - Diagnostic(ErrorCode.ERR_EOFExpected, "{").WithLocation(3, 1), - // (4,1): error CS1022: Type or namespace definition, or end-of-file expected - // } - Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1)); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"{ +}").WithLocation(3, 1) + ); N(SyntaxKind.CompilationUnit); { @@ -7414,6 +7392,14 @@ class A : B : C N(SyntaxKind.IdentifierToken, "C"); } } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } N(SyntaxKind.EndOfFileToken); } EOF(); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs index c765edb3629bf..5c1d085e509a7 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs @@ -2380,55 +2380,58 @@ public void DiscardsInDeconstruction_01() var tree = UsingTree(@"void M() { var (x, _) = e; }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.ExpressionStatement); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.SimpleAssignmentExpression); + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); { - N(SyntaxKind.DeclarationExpression); + N(SyntaxKind.SimpleAssignmentExpression); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "var"); - } - N(SyntaxKind.ParenthesizedVariableDesignation); + N(SyntaxKind.DeclarationExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.SingleVariableDesignation); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.IdentifierToken, "var"); } - N(SyntaxKind.CommaToken); - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.ParenthesizedVariableDesignation); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } + N(SyntaxKind.CloseParenToken); } - N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); } } - N(SyntaxKind.EqualsToken); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); - } + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2442,68 +2445,71 @@ public void DiscardsInDeconstruction_02() var tree = UsingTree(@"void M() { (var x, var _) = e; }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.ExpressionStatement); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.SimpleAssignmentExpression); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); { - N(SyntaxKind.TupleExpression); + N(SyntaxKind.SimpleAssignmentExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.TupleExpression); { - N(SyntaxKind.DeclarationExpression); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "var"); - } - N(SyntaxKind.SingleVariableDesignation); + N(SyntaxKind.DeclarationExpression); { - N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } } } - } - N(SyntaxKind.CommaToken); - N(SyntaxKind.Argument); - { - N(SyntaxKind.DeclarationExpression); + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "var"); - } - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.DeclarationExpression); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); } - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsToken); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); } + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2517,53 +2523,56 @@ public void DiscardsInOut_01() var tree = UsingTree(@"void M() { M(out var _); }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.ExpressionStatement); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "M"); - } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.InvocationExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.DeclarationExpression); + N(SyntaxKind.IdentifierToken, "M"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "var"); - } - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.OutKeyword); + N(SyntaxKind.DeclarationExpression); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } } + N(SyntaxKind.CloseParenToken); } - N(SyntaxKind.CloseParenToken); } + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2577,53 +2586,56 @@ public void DiscardsInOut_02() var tree = UsingTree(@"void M() { M(out int _); }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.ExpressionStatement); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "M"); - } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.InvocationExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.DeclarationExpression); + N(SyntaxKind.IdentifierToken, "M"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.OutKeyword); + N(SyntaxKind.DeclarationExpression); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } } + N(SyntaxKind.CloseParenToken); } - N(SyntaxKind.CloseParenToken); } + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2637,52 +2649,55 @@ public void DiscardsInPattern_01() var tree = UsingTree(@"void M() { if (e is int _) {} }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); - { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.IfStatement); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.IfKeyword); N(SyntaxKind.OpenParenToken); - N(SyntaxKind.IsPatternExpression); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.IfStatement); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); - } - N(SyntaxKind.IsKeyword); - N(SyntaxKind.DeclarationPattern); + N(SyntaxKind.IfKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IsPatternExpression); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IntKeyword); + N(SyntaxKind.IdentifierToken, "e"); } - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.IsKeyword); + N(SyntaxKind.DeclarationPattern); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } } - N(SyntaxKind.CloseParenToken); - N(SyntaxKind.Block); - { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.CloseBraceToken); - } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2696,49 +2711,52 @@ public void DiscardsInPattern_02() var tree = UsingTree(@"void M() { if (e is var _) {} }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); - { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.IfStatement); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.IfKeyword); N(SyntaxKind.OpenParenToken); - N(SyntaxKind.IsPatternExpression); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.IfStatement); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); - } - N(SyntaxKind.IsKeyword); - N(SyntaxKind.VarPattern); + N(SyntaxKind.IfKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IsPatternExpression); { - N(SyntaxKind.VarKeyword, "var"); - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.VarPattern); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.VarKeyword, "var"); + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } } - N(SyntaxKind.CloseParenToken); - N(SyntaxKind.Block); - { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.CloseBraceToken); - } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2752,58 +2770,61 @@ public void DiscardsInPattern_03() var tree = UsingTree(@"void M() { switch (e) { case int _: break; } }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.SwitchStatement); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.SwitchKeyword); N(SyntaxKind.OpenParenToken); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); - } N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.SwitchSection); + N(SyntaxKind.SwitchStatement); { - N(SyntaxKind.CasePatternSwitchLabel); + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.CaseKeyword); - N(SyntaxKind.DeclarationPattern); + N(SyntaxKind.IdentifierToken, "e"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.DeclarationPattern); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.ColonToken); - } - N(SyntaxKind.BreakStatement); - { - N(SyntaxKind.BreakKeyword); - N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); @@ -2817,55 +2838,58 @@ public void DiscardsInPattern_04() var tree = UsingTree(@"void M() { switch (e) { case var _: break; } }"); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.MethodDeclaration); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } - N(SyntaxKind.IdentifierToken, "M"); - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.Block); + N(SyntaxKind.LocalFunctionStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.SwitchStatement); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.SwitchKeyword); N(SyntaxKind.OpenParenToken); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "e"); - } N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.SwitchSection); + N(SyntaxKind.SwitchStatement); { - N(SyntaxKind.CasePatternSwitchLabel); + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.CaseKeyword); - N(SyntaxKind.VarPattern); + N(SyntaxKind.IdentifierToken, "e"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); { - N(SyntaxKind.VarKeyword, "var"); - N(SyntaxKind.DiscardDesignation); + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.VarPattern); { - N(SyntaxKind.UnderscoreToken); + N(SyntaxKind.VarKeyword, "var"); + N(SyntaxKind.DiscardDesignation); + { + N(SyntaxKind.UnderscoreToken); + } } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.ColonToken); - } - N(SyntaxKind.BreakStatement); - { - N(SyntaxKind.BreakKeyword); - N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.EndOfFileToken); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index ddd5082664677..b682bead655a9 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -53,6 +53,15 @@ public static int Main() // (10,4): error CS1519: Invalid token '{' in class, struct, or interface member declaration // { Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "{").WithArguments("{").WithLocation(10, 4), + // (12,4): error CS9002: Top-level statements must precede namespace and type declarations. + // public static int Main() + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"public static int Main() + { + return 1; + }").WithLocation(12, 4), + // (12,4): error CS0106: The modifier 'public' is not valid for this item + // public static int Main() + Diagnostic(ErrorCode.ERR_BadMemberFlag, "public").WithArguments("public").WithLocation(12, 4), // (16,1): error CS1022: Type or namespace definition, or end-of-file expected // } Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(16, 1) @@ -179,21 +188,9 @@ public void CS0116ERR__NamespaceUnexpected() }"; // Extra errors ParseAndValidate(test, - // (1,1): error CS1022: Type or namespace definition, or end-of-file expected - // { - Diagnostic(ErrorCode.ERR_EOFExpected, "{").WithLocation(1, 1), - // (3,5): error CS1022: Type or namespace definition, or end-of-file expected - // { - Diagnostic(ErrorCode.ERR_EOFExpected, "{").WithLocation(3, 5), - // (2,5): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,8): error CS1002: ; expected // get - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "get").WithLocation(2, 5), - // (5,5): error CS1022: Type or namespace definition, or end-of-file expected - // } - Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(5, 5), - // (6,1): error CS1022: Type or namespace definition, or end-of-file expected - // } - Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(6, 1) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 8) ); } @@ -639,7 +636,7 @@ partial delegate E { } "; // Extra errors - CreateCompilation(test).VerifyDiagnostics( + CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'struct', 'interface', or 'void' // partial delegate E { } Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), @@ -655,12 +652,9 @@ partial delegate E { } // (2,20): error CS1002: ; expected // partial delegate E { } Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(2, 20), - // (2,20): error CS1022: Type or namespace definition, or end-of-file expected + // (2,20): error CS9002: Top-level statements must precede namespace and type declarations. // partial delegate E { } - Diagnostic(ErrorCode.ERR_EOFExpected, "{").WithLocation(2, 20), - // (2,22): error CS1022: Type or namespace definition, or end-of-file expected - // partial delegate E { } - Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(2, 22), + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "{ }").WithLocation(2, 20), // (2,20): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'struct', 'interface', or 'void' // partial delegate E { } Diagnostic(ErrorCode.ERR_PartialMisplaced, "").WithLocation(2, 20), @@ -2442,15 +2436,20 @@ public void CS1022ERR_EOFExpected02() { var test = @" > Roslyn.Utilities.dll! Basic"; - CreateCompilation(test).VerifyDiagnostics( - // (1,2): error CS1022: Type or namespace definition, or end-of-file expected - Diagnostic(ErrorCode.ERR_EOFExpected, ">").WithLocation(1, 2), - // (1,21): error CS0116: A namespace does not directly contain members such as fields or methods - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "dll").WithLocation(1, 21), - // (1,24): error CS1022: Type or namespace definition, or end-of-file expected - Diagnostic(ErrorCode.ERR_EOFExpected, "!").WithLocation(1, 24), - // (1,27): error CS0116: A namespace does not directly contain members such as fields or methods - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "Basic").WithLocation(1, 27)); + CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (1,2): error CS1525: Invalid expression term '>' + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ">").WithArguments(">").WithLocation(1, 2), + // (1,4): error CS0103: The name 'Roslyn' does not exist in the current context + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_NameNotInContext, "Roslyn").WithArguments("Roslyn").WithLocation(1, 4), + // (1,27): error CS1002: ; expected + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_SemicolonExpected, "Basic").WithLocation(1, 27), + // (1,27): error CS0116: A namespace cannot directly contain members such as fields or methods + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "Basic").WithLocation(1, 27) + ); } [Fact] @@ -3877,22 +3876,26 @@ public void CS1514ERR_LbraceExpected02() ParseAndValidate(test, // (1,15): error CS1514: { expected // public class S.D - Diagnostic(ErrorCode.ERR_LbraceExpected, "."), + Diagnostic(ErrorCode.ERR_LbraceExpected, ".").WithLocation(1, 15), // (1,15): error CS1513: } expected // public class S.D - Diagnostic(ErrorCode.ERR_RbraceExpected, "."), + Diagnostic(ErrorCode.ERR_RbraceExpected, ".").WithLocation(1, 15), // (1,15): error CS1022: Type or namespace definition, or end-of-file expected // public class S.D - Diagnostic(ErrorCode.ERR_EOFExpected, "."), - // (1,16): error CS0116: A namespace does not directly contain members such as fields or methods + Diagnostic(ErrorCode.ERR_EOFExpected, ".").WithLocation(1, 15), + // (1,16): error CS0116: A namespace cannot directly contain members such as fields or methods // public class S.D - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "D"), - // (2,1): error CS1022: Type or namespace definition, or end-of-file expected + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "D").WithLocation(1, 16), + // (2,1): error CS9002: Top-level statements must precede namespace and type declarations. + // { + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"{ +").WithLocation(2, 1), + // (2,2): error CS1513: } expected // { - Diagnostic(ErrorCode.ERR_EOFExpected, "{"), + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(2, 2), // (4,1): error CS1022: Type or namespace definition, or end-of-file expected // } - Diagnostic(ErrorCode.ERR_EOFExpected, "}")); + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1)); } [WorkItem(535932, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/535932")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs index 7ec217a8006b3..334c8a6c2576a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs @@ -432,13 +432,6 @@ class C var file = this.ParseTree(text); Assert.NotNull(file); Assert.Equal(text, file.ToFullString()); - Assert.Equal(1, file.Externs.Count); - Assert.Equal(1, file.Usings.Count); - Assert.Equal(1, file.AttributeLists.Count); - Assert.Equal(3, file.Members.Count); - Assert.Equal(SyntaxKind.ClassDeclaration, file.Members[0].Kind()); - Assert.Equal(SyntaxKind.IncompleteMember, file.Members[1].Kind()); - Assert.Equal(SyntaxKind.IncompleteMember, file.Members[2].Kind()); } [Fact] @@ -676,10 +669,6 @@ public void TestGlobalNamespaceWithOpenBraceBeforeNamespace() Assert.NotNull(file); Assert.Equal(text, file.ToFullString()); - Assert.Equal(1, file.Members.Count); - Assert.Equal(SyntaxKind.NamespaceDeclaration, file.Members[0].Kind()); - Assert.Equal(1, file.Errors().Length); - Assert.Equal((int)ErrorCode.ERR_EOFExpected, file.Errors()[0].Code); } [Fact] @@ -6529,23 +6518,12 @@ public void InsertOpenBraceBeforeCodes() }; }"; - SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(text); + SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(text, TestOptions.RegularPreview); Assert.Equal(text, syntaxTree.GetCompilationUnitRoot().ToFullString()); - Assert.Equal($"{{{Environment.NewLine}", syntaxTree.GetCompilationUnitRoot().GetLeadingTrivia().Node.ToFullString()); - // The issue (9391) was exhibited while enumerating the diagnostics Assert.True(syntaxTree.GetDiagnostics().Select(d => ((IFormattable)d).ToString(null, EnsureEnglishUICulture.PreferredOrNull)).SequenceEqual(new[] { - "(1,2): error CS1031: Type expected", - "(1,1): error CS1022: Type or namespace definition, or end-of-file expected", - "(2,13): error CS1003: Syntax error, '[' expected", - "(2,13): error CS1001: Identifier expected", - "(2,16): error CS1001: Identifier expected", - "(2,19): error CS1003: Syntax error, ',' expected", - "(2,20): error CS1003: Syntax error, ']' expected", - "(2,20): error CS1514: { expected", - "(3,6): error CS1597: Semicolon after method or accessor block is not valid", "(4,1): error CS1022: Type or namespace definition, or end-of-file expected", })); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs index c73994b3eea0f..7d2d53a99a84e 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs @@ -131,7 +131,7 @@ static async ref readonly Task M() } "; - ParseAndValidate(text, TestOptions.Regular, + ParseAndValidate(text, TestOptions.RegularPreview, // (9,27): error CS1003: Syntax error, '(' expected // ref readonly int Field; Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("(", ";").WithLocation(9, 27), @@ -150,6 +150,12 @@ static async ref readonly Task M() // (12,5): error CS1519: Invalid token '{' in class, struct, or interface member declaration // { Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "{").WithArguments("{").WithLocation(12, 5), + // (17,5): error CS9002: Top-level statements must precede namespace and type declarations. + // static async ref readonly Task M() + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"static async ref readonly Task M() + { + throw null; + }").WithLocation(17, 5), // (22,25): error CS1031: Type expected // public ref readonly virtual int* P1 => throw null; Diagnostic(ErrorCode.ERR_TypeExpected, "virtual").WithLocation(22, 25), diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs index fdc1ddb0350d0..c44b3c89c183f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs @@ -18,7 +18,7 @@ public class RoundTrippingTests internal static void ParseAndRoundTripping(string text, int errorCount = 0, int memberCount = 0) { - ParseAndRoundTripping(text, TestOptions.RegularWithDocumentationComments, errorCount, memberCount); + ParseAndRoundTripping(text, TestOptions.RegularWithDocumentationComments.WithLanguageVersion(LanguageVersion.Preview), errorCount, memberCount); } internal static void ParseAndRoundTripping(string text, CSharpParseOptions options, int errorCount = 0, int memberCount = 0) @@ -119,7 +119,7 @@ public void TestOptionalParamsArray() [Fact] public void TestNegInvalidExternAlias01() { - ParseAndRoundTripping(Resources.InvalidExternAlias01, -1); + ParseAndRoundTripping(Resources.InvalidExternAlias01, errorCount: 1); // Parsed as local with an initializer } [WorkItem(901348, "DevDiv/Personal")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index 2d5bb34053bda..69037f50089f3 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -2559,11 +2559,11 @@ public void Multiplication() { // pointer decl string test = @"a.b * c;"; - ParseAndValidate(test, TestOptions.Regular); + ParseAndValidate(test, TestOptions.RegularPreview); // pointer decl test = @"a.b * c"; - ParseAndValidate(test, TestOptions.Regular, new[] { new ErrorDescription { Code = (int)ErrorCode.ERR_SemicolonExpected, Line = 1, Column = 8 } }); // expected ';' + ParseAndValidate(test, TestOptions.RegularPreview, new[] { new ErrorDescription { Code = (int)ErrorCode.ERR_SemicolonExpected, Line = 1, Column = 8 } }); // expected ';' // multiplication test = @"a.b * c;"; diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs new file mode 100644 index 0000000000000..5558d8a42e777 --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs @@ -0,0 +1,2589 @@ +// 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 Roslyn.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + [CompilerTrait(CompilerFeature.TopLevelStatements)] + public sealed class TopLevelStatementsParsingTests : ParsingTests + { + public TopLevelStatementsParsingTests(ITestOutputHelper output) : base(output) { } + + protected override SyntaxTree ParseTree(string text, CSharpParseOptions options) + { + return SyntaxFactory.ParseSyntaxTree(text, options: options ?? TestOptions.RegularPreview); + } + + private SyntaxTree UsingTree(string text, params DiagnosticDescription[] expectedErrors) + { + var tree = base.UsingTree(text); + + var actualErrors = tree.GetDiagnostics(); + actualErrors.Verify(expectedErrors); + + return tree; + } + + [Fact] + public void InsertOpenBraceBeforeCodes() + { + UsingTree( +@"{ + this.I = i; + }; +}", + // (4,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.ThisExpression); + { + N(SyntaxKind.ThisKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "I"); + } + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "i"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestIncompleteGlobalMembers() + { + var text = @" +asas] +extern alias A; +asas +using System; +sadasdasd] + +[assembly: goo] + +class C +{ +} + + +[a]fod; +[b"; + UsingTree(text, + // (2,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // asas] + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "asas").WithLocation(2, 1), + // (2,5): error CS1022: Type or namespace definition, or end-of-file expected + // asas] + Diagnostic(ErrorCode.ERR_EOFExpected, "]").WithLocation(2, 5), + // (4,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // asas + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "asas").WithLocation(4, 1), + // (6,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // sadasdasd] + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "sadasdasd").WithLocation(6, 1), + // (6,10): error CS1022: Type or namespace definition, or end-of-file expected + // sadasdasd] + Diagnostic(ErrorCode.ERR_EOFExpected, "]").WithLocation(6, 10), + // (15,1): error CS9002: Top-level statements must precede namespace and type declarations. + // [a]fod; + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "[a]fod;").WithLocation(15, 1), + // (16,3): error CS1003: Syntax error, ']' expected + // [b + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("]", "").WithLocation(16, 3) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ExternAliasDirective); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.AliasKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.AttributeTargetSpecifier); + { + N(SyntaxKind.AssemblyKeyword); + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "goo"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "fod"); + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void IncompleteTopLevelOperator() + { + var text = @" +fg implicit// +class C { } +"; + UsingTree(text, + // (2,1): error CS1553: Declaration is not valid; use '+ operator (...' instead + // fg implicit// + Diagnostic(ErrorCode.ERR_BadOperatorSyntax, "fg").WithArguments("+").WithLocation(2, 1), + // (2,4): error CS1003: Syntax error, 'operator' expected + // fg implicit// + Diagnostic(ErrorCode.ERR_SyntaxError, "implicit").WithArguments("operator", "implicit").WithLocation(2, 4), + // (2,4): error CS1037: Overloadable operator expected + // fg implicit// + Diagnostic(ErrorCode.ERR_OvlOperatorExpected, "implicit").WithLocation(2, 4), + // (2,12): error CS1003: Syntax error, '(' expected + // fg implicit// + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("(", "class").WithLocation(2, 12), + // (2,12): error CS1026: ) expected + // fg implicit// + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(2, 12), + // (2,12): error CS1002: ; expected + // fg implicit// + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 12) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.OperatorDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "fg"); + } + M(SyntaxKind.OperatorKeyword); + M(SyntaxKind.PlusToken); + M(SyntaxKind.ParameterList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGlobalNamespaceWithOpenBraceBeforeNamespace() + { + var text = "{ namespace n { }"; + UsingTree(text, + // (1,3): error CS1513: } expected + // { namespace n { } + Diagnostic(ErrorCode.ERR_RbraceExpected, "namespace").WithLocation(1, 3) + ); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.NamespaceDeclaration); + { + N(SyntaxKind.NamespaceKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "n"); + } + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void CS1056ERR_UnexpectedCharacter_EscapedBackslash() + { + var test = @"using S\u005Cu0065 = System; +class A +{ +int x = 0; +} +"; + UsingTree(test, + // (1,8): error CS1002: ; expected + // using S\u005Cu0065 = System; + Diagnostic(ErrorCode.ERR_SemicolonExpected, @"\u005C").WithLocation(1, 8), + // (1,8): error CS1056: Unexpected character '\u005C' + // using S\u005Cu0065 = System; + Diagnostic(ErrorCode.ERR_UnexpectedCharacter, "").WithArguments(@"\u005C").WithLocation(1, 8) + ); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "u0065"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestNegInvalidExternAlias01() + { + UsingTree(Resources.InvalidExternAlias01, + // (1,1): error CS0106: The modifier 'extern' is not valid for this item + // extern alias libAlias=other_library.dll; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "extern").WithArguments("extern").WithLocation(1, 1) + ); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "libAlias"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "other_library"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dll"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "myClass"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void SeparatorsOfSeparatedSyntaxLists() + { + var test = "int goo(int a, int b, int c) {}"; + UsingTree(test); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "goo"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void GetDiagnosticsOnMissingToken() + { + var test = @"c1 Roslyn.Utilities.dll! Basic"; + UsingTree(test, + // (1,2): error CS1525: Invalid expression term '>' + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ">").WithArguments(">").WithLocation(1, 2), + // (1,27): error CS1002: ; expected + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_SemicolonExpected, "Basic").WithLocation(1, 27), + // (1,27): error CS0116: A namespace cannot directly contain members such as fields or methods + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "Basic").WithLocation(1, 27) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.GreaterThanExpression); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.SuppressNullableWarningExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Roslyn"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Utilities"); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "dll"); + } + } + N(SyntaxKind.ExclamationToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Basic"); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void CS0267ERR_PartialMisplaced_Delegate1() + { + var test = @" +partial delegate E { } +"; + UsingTree(test, + // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'struct', 'interface', or 'void' + // partial delegate E { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), + // (2,20): error CS1001: Identifier expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "{").WithLocation(2, 20), + // (2,20): error CS1003: Syntax error, '(' expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("(", "{").WithLocation(2, 20), + // (2,20): error CS1026: ) expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_CloseParenExpected, "{").WithLocation(2, 20), + // (2,20): error CS1002: ; expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(2, 20), + // (2,20): error CS9002: Top-level statements must precede namespace and type declarations. + // partial delegate E { } + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "{ }").WithLocation(2, 20) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.DelegateDeclaration); + { + N(SyntaxKind.PartialKeyword); + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + M(SyntaxKind.IdentifierToken); + M(SyntaxKind.ParameterList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem(543622, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543622")] + public void CS0116ERR__NamespaceUnexpected() + { + var test = @"{ + get + { + ParseDefaultDir(); + } +}"; + UsingTree(test, + // (2,8): error CS1002: ; expected + // get + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 8) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "get"); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ParseDefaultDir"); + } + 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 Multiplication() + { + // pointer decl + string test = @"a.b * c;"; + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + [Trait("Feature", "Directives")] + public void TestNegIfEndifDirectivesWithBadCode() + { + var test = +@"#if true +#else +#endif +aeu"; + UsingTree(test, + // (4,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // aeu + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "aeu").WithLocation(4, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "aeu"); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestExternWithoutAlias() + { + var test = "extern a;"; + UsingTree(test, + // (1,8): error CS0116: A namespace cannot directly contain members such as fields or methods + // extern a; + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "a").WithLocation(1, 8) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem(528655, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528655")] + public void ErrorSymbolForInvalidCode() + { + var test = @" +public class A +{ + int goo { void goo() {} } // Error + static int Main() { return 1; } +} +"; + UsingTree(test, + // (4,12): error CS1513: } expected + // int goo { void goo() {} } // Error + Diagnostic(ErrorCode.ERR_RbraceExpected, "void").WithLocation(4, 12), + // (5,2): error CS9002: Top-level statements must precede namespace and type declarations. + // static int Main() { return 1; } + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "static int Main() { return 1; }").WithLocation(5, 2), + // (6,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(6, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.PropertyDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "goo"); + N(SyntaxKind.AccessorList); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "goo"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "Main"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void InvalidAlias() + { + string test = +"extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}"; + + UsingTree(test, + // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), + // (1,61): error CS1026: ) expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), + // (1,61): error CS1002: ; expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + N(SyntaxKind.IdentifierToken, "Alias"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TopLevelIndexer() + { + var test = @" +this[double E] { get { return /**/E/**/; } } +"; + UsingTree(test, + // (2,6): error CS1525: Invalid expression term 'double' + // this[double E] { get { return /**/E/**/; } } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "double").WithArguments("double").WithLocation(2, 6), + // (2,13): error CS1003: Syntax error, ',' expected + // this[double E] { get { return /**/E/**/; } } + Diagnostic(ErrorCode.ERR_SyntaxError, "E").WithArguments(",", "").WithLocation(2, 13), + // (2,16): error CS1002: ; expected + // this[double E] { get { return /**/E/**/; } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(2, 16), + // (2,22): error CS1002: ; expected + // this[double E] { get { return /**/E/**/; } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(2, 22) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.ThisExpression); + { + N(SyntaxKind.ThisKeyword); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.DoubleKeyword); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "get"); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "E"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UnrecognizedGenericTypeReference() + { + string test = "/**/C*/"; + UsingTree(test, + // (1,13): error CS1525: Invalid expression term 'object' + // /**/C*/ + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "object").WithArguments("object").WithLocation(1, 13), + // (1,19): error CS1002: ; expected + // /**/C*/ + Diagnostic(ErrorCode.ERR_SemicolonExpected, ",").WithLocation(1, 19), + // (1,19): error CS1022: Type or namespace definition, or end-of-file expected + // /**/C*/ + Diagnostic(ErrorCode.ERR_EOFExpected, ",").WithLocation(1, 19), + // (1,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // /**/C*/ + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "string").WithLocation(1, 21) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void IncompleteOperator() + { + UsingTree(@"C operator +(C lhs, C rhs) {", + // (1,29): error CS1513: } expected + // C operator +(C lhs, C rhs) { + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(1, 29) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.OperatorDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.OperatorKeyword); + N(SyntaxKind.PlusToken); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "lhs"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "rhs"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void NewKeyword() + { + UsingTree(@"new ", + // (1,5): error CS1526: A new expression requires (), [], or {} after type + // new + Diagnostic(ErrorCode.ERR_BadNewExpr, "").WithLocation(1, 5), + // (1,5): error CS1002: ; expected + // new + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 5) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.ArgumentList); + { + M(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TupleUnsupportedInUsingStatement() + { + 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) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "VT2"); + } + N(SyntaxKind.EqualsToken); + } + 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, WorkItem(530131, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530131")] + public void MetadataReferenceWithInvalidAlias() + { + var test = "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}"; + + UsingTree(test, + // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), + // (1,61): error CS1026: ) expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), + // (1,61): error CS1002: ; expected + // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + N(SyntaxKind.IdentifierToken, "Alias"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void Identifier_01() + { + var test = "e"; + + UsingTree(test, + // (1,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // e + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "e").WithLocation(1, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void Identifier_02() + { + var test = +@" +[Flags] +e +"; + + UsingTree(test, + // (3,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // e + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "e").WithLocation(3, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Flags"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestSkippedTest() + { + var test = "abc using"; + + UsingTree(test, + // (1,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // abc using + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "abc").WithLocation(1, 1), + // (1,10): error CS1001: Identifier expected + // abc using + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 10), + // (1,10): error CS1002: ; expected + // abc using + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 10) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_01() + { + var test = "using var a = new MyDisposable();"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "a"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MyDisposable"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_02() + { + var test = "using static type name;"; + + UsingTree(test, + // (1,7): error CS0106: The modifier 'static' is not valid for this item + // using static type name; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(1, 7) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "name"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_03() + { + var test = "using volatile;"; + + UsingTree(test, + // (1,7): error CS0106: The modifier 'volatile' is not valid for this item + // using volatile; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "volatile").WithArguments("volatile").WithLocation(1, 7), + // (1,15): error CS1031: Type expected + // using volatile; + Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 15), + // (1,15): error CS1001: Identifier expected + // using volatile; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 15) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VolatileKeyword); + M(SyntaxKind.VariableDeclaration); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_04() + { + var test = "using const;"; + + UsingTree(test, + // (1,12): error CS1031: Type expected + // using const; + Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 12), + // (1,12): error CS1001: Identifier expected + // using const; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 12), + // (1,12): error CS0145: A const field requires a value to be provided + // using const; + Diagnostic(ErrorCode.ERR_ConstValueRequired, ";").WithLocation(1, 12) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.ConstKeyword); + M(SyntaxKind.VariableDeclaration); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_05() + { + var test = "using ref;"; + + UsingTree(test, + // (1,10): error CS1031: Type expected + // using ref; + Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 10), + // (1,10): error CS1001: Identifier expected + // using ref; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 10) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingLocalDeclaration_06() + { + var test = "using readonly;"; + + UsingTree(test, + // (1,7): error CS0106: The modifier 'readonly' is not valid for this item + // using readonly; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(1, 7), + // (1,15): error CS1031: Type expected + // using readonly; + Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 15), + // (1,15): error CS1001: Identifier expected + // using readonly; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 15) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.ReadOnlyKeyword); + M(SyntaxKind.VariableDeclaration); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_01() + { + var test = "using static type;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_02() + { + var test = "using type;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_03() + { + var test = "using alias = type;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_04() + { + var test = "using ns.type;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ns"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_05() + { + var test = "using static alias = type;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "type"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_06() + { + var test = "using int.Parse name = value;"; + + UsingTree(test, + // (1,10): error CS1001: Identifier expected + // using int.Parse name = value; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ".").WithLocation(1, 10), + // (1,10): error CS1003: Syntax error, ',' expected + // using int.Parse name = value; + Diagnostic(ErrorCode.ERR_SyntaxError, ".").WithArguments(",", ".").WithLocation(1, 10), + // (1,11): error CS1002: ; expected + // using int.Parse name = value; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "Parse").WithLocation(1, 11) + ); + + 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); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Parse"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "name"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "value"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_07() + { + var test = "using int (x, y)"; + + UsingTree(test, + // (1,11): error CS1001: Identifier expected + // using int (x, y) + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 11), + // (1,11): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // using int (x, y) + Diagnostic(ErrorCode.ERR_BadVarDecl, "(x, y").WithLocation(1, 11), + // (1,11): error CS1003: Syntax error, '[' expected + // using int (x, y) + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[", "(").WithLocation(1, 11), + // (1,16): error CS1003: Syntax error, ']' expected + // using int (x, y) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(1, 16), + // (1,17): error CS1002: ; expected + // using int (x, y) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 17) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + N(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void UsingDirective_08() + { + var test = "using int"; + + UsingTree(test, + // (1,10): error CS1001: Identifier expected + // using int + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 10), + // (1,10): error CS1002: ; expected + // using int + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").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); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [WorkItem(611177, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611177")] + [Fact] + public void Repro611177() + { + var test = @"[_<_[delegate using'"; + + UsingTree(test, + // (1,15): error CS1514: { expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_LbraceExpected, "using").WithLocation(1, 15), + // (1,15): error CS1003: Syntax error, ',' expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SyntaxError, "using").WithArguments(",", "using").WithLocation(1, 15), + // (1,15): error CS0443: Syntax error; value expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_ValueExpected, "").WithLocation(1, 15), + // (1,15): error CS1003: Syntax error, ']' expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SyntaxError, "using").WithArguments("]", "using").WithLocation(1, 15), + // (1,15): error CS1003: Syntax error, '>' expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SyntaxError, "using").WithArguments(">", "using").WithLocation(1, 15), + // (1,15): error CS1003: Syntax error, ']' expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SyntaxError, "using").WithArguments("]", "using").WithLocation(1, 15), + // (1,20): error CS1031: Type expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_TypeExpected, "'").WithLocation(1, 20), + // (1,20): error CS1001: Identifier expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_IdentifierExpected, "'").WithLocation(1, 20), + // (1,20): error CS1002: ; expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SemicolonExpected, "'").WithLocation(1, 20), + // (1,20): error CS1010: Newline in constant + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_NewlineInConst, "").WithLocation(1, 20), + // (1,20): error CS1011: Empty character literal + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_EmptyCharConst, "").WithLocation(1, 20), + // (1,21): error CS1002: ; expected + // [_<_[delegate using' + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 21) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "_"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "_"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.AnonymousMethodExpression); + { + N(SyntaxKind.DelegateKeyword); + M(SyntaxKind.Block); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + M(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.CloseBracketToken); + } + } + M(SyntaxKind.GreaterThanToken); + } + } + } + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.UsingKeyword); + M(SyntaxKind.VariableDeclaration); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.CharacterLiteralExpression); + { + N(SyntaxKind.CharacterLiteralToken); + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ConstructorLike_01() + { + var test = @"local() {}"; + + UsingTree(test, + // (1,9): error CS1002: ; expected + // local() {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 9) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ConstructorLike_02() + { + var test = @"static local() {}"; + + UsingTree(test, + // (1,13): error CS1001: Identifier expected + // static local() {} + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 13) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + M(SyntaxKind.IdentifierToken); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ConstructorLike_03() + { + var test = @"[attribute] local() {}"; + + UsingTree(test, + // (1,18): error CS1001: Identifier expected + // [attribute] local() {} + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 18) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "attribute"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + M(SyntaxKind.IdentifierToken); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + } +} diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNodeTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNodeTests.cs index 6b71cf610a4bf..108453c244adb 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNodeTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNodeTests.cs @@ -3021,8 +3021,8 @@ public void SeparatorsOfSeparatedSyntaxLists() var s1 = "int goo(int a, int b, int c) {}"; var tree = SyntaxFactory.ParseSyntaxTree(s1); - dynamic root = tree.GetCompilationUnitRoot(); - MethodDeclarationSyntax method = root.Members[0]; + var root = tree.GetCompilationUnitRoot(); + var method = (LocalFunctionStatementSyntax)((GlobalStatementSyntax)root.Members[0]).Statement; var list = (SeparatedSyntaxList)method.ParameterList.Parameters; @@ -3081,7 +3081,7 @@ public void ThrowIfUnderlyingNodeIsNullForList() [Fact] public void GetDiagnosticsOnMissingToken() { - var syntaxTree = SyntaxFactory.ParseSyntaxTree(@"c1 executableCodeBlocks, CancellationToken cancellationToken) + internal static DeclarationInfo GetDeclarationInfo(SemanticModel model, SyntaxNode node, bool getSymbol, IEnumerable? executableCodeBlocks, CancellationToken cancellationToken) { var declaredSymbol = GetDeclaredSymbol(model, node, getSymbol, cancellationToken); var codeBlocks = executableCodeBlocks?.Where(c => c != null).AsImmutableOrEmpty() ?? ImmutableArray.Empty; @@ -22,7 +24,7 @@ internal static DeclarationInfo GetDeclarationInfo(SemanticModel model, SyntaxNo internal static DeclarationInfo GetDeclarationInfo(SemanticModel model, SyntaxNode node, bool getSymbol, CancellationToken cancellationToken) { - return GetDeclarationInfo(model, node, getSymbol, (IEnumerable)null, cancellationToken); + return GetDeclarationInfo(model, node, getSymbol, (IEnumerable?)null, cancellationToken); } internal static DeclarationInfo GetDeclarationInfo(SemanticModel model, SyntaxNode node, bool getSymbol, SyntaxNode executableCodeBlock, CancellationToken cancellationToken) @@ -35,7 +37,7 @@ internal static DeclarationInfo GetDeclarationInfo(SemanticModel model, SyntaxNo return GetDeclarationInfo(model, node, getSymbol, executableCodeBlocks.AsEnumerable(), cancellationToken); } - private static ISymbol GetDeclaredSymbol(SemanticModel model, SyntaxNode node, bool getSymbol, CancellationToken cancellationToken) + private static ISymbol? GetDeclaredSymbol(SemanticModel model, SyntaxNode node, bool getSymbol, CancellationToken cancellationToken) { if (!getSymbol) { diff --git a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs index b1382750ea4f9..b4142c34365ea 100644 --- a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs +++ b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs @@ -873,7 +873,9 @@ public PreprocessingSymbolInfo GetPreprocessingSymbolInfo(SyntaxNode nameSyntax) /// /// Takes a node and returns a set of declarations that overlap the node's span. /// - internal abstract void ComputeDeclarationsInNode(SyntaxNode node, bool getSymbol, ArrayBuilder builder, CancellationToken cancellationToken, int? levelsToCompute = null); + internal abstract void ComputeDeclarationsInNode(SyntaxNode node, ISymbol associatedSymbol, bool getSymbol, ArrayBuilder builder, CancellationToken cancellationToken, int? levelsToCompute = null); + + internal virtual Func? GetSyntaxNodesToAnalyzeFilter(SyntaxNode declaredNode, ISymbol declaredSymbol) => null; /// /// Takes a Symbol and syntax for one of its declaring syntax reference and returns the topmost syntax node to be used by syntax analyzer. diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index e1d488a68d70e..f61f535551f75 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2239,7 +2239,7 @@ private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymb // We only care about the top level symbol declaration and its immediate member declarations. int? levelsToCompute = 2; var getSymbol = topmostNodeForAnalysis != declaringReferenceSyntax || declaredSymbol.Kind == SymbolKind.Namespace; - semanticModel.ComputeDeclarationsInNode(topmostNodeForAnalysis, getSymbol, builder, cancellationToken, levelsToCompute); + semanticModel.ComputeDeclarationsInNode(topmostNodeForAnalysis, declaredSymbol, getSymbol, builder, cancellationToken, levelsToCompute); } /// @@ -2538,7 +2538,9 @@ private static ImmutableArray GetSyntaxNodesToAnalyze( first = false; } - bool shouldAddNode(SyntaxNode node) => descendantDeclsToSkipOpt == null || !descendantDeclsToSkipOpt.Contains(node); + Func additionalFilterOpt = semanticModel.GetSyntaxNodesToAnalyzeFilter(declaredNode, declaredSymbol); + + bool shouldAddNode(SyntaxNode node) => (descendantDeclsToSkipOpt == null || !descendantDeclsToSkipOpt.Contains(node)) && (additionalFilterOpt is null || additionalFilterOpt(node)); var nodeBuilder = ArrayBuilder.GetInstance(); foreach (var node in declaredNode.DescendantNodesAndSelf(descendIntoChildren: shouldAddNode, descendIntoTrivia: true)) { diff --git a/src/Compilers/Core/Portable/Operations/OperationExtensions.cs b/src/Compilers/Core/Portable/Operations/OperationExtensions.cs index aec03024d2927..8aff08fa64363 100644 --- a/src/Compilers/Core/Portable/Operations/OperationExtensions.cs +++ b/src/Compilers/Core/Portable/Operations/OperationExtensions.cs @@ -36,7 +36,15 @@ public static partial class OperationExtensions } // if wrong compilation is given, GetSemanticModel will throw due to tree not belong to the given compilation. - var model = operation.SemanticModel ?? compilation.GetSemanticModel(operation.Syntax.SyntaxTree); + var model = operation.SemanticModel; + + // An IOperation tree for a simple program includes statements from all compilation units involved, + // but each model is tied to a single syntax tree. + if (model is null || model.SyntaxTree != operation.Syntax.SyntaxTree) + { + model = compilation.GetSemanticModel(operation.Syntax.SyntaxTree); + } + if (model.IsSpeculativeSemanticModel) { // GetDiagnostics not supported for speculative semantic model. diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index bbcd49af4e64b..ea2572cebcecd 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -889,7 +889,7 @@ public static SyntaxTree[] Parse(CSharpParseOptions options = null, params strin public static SyntaxTree ParseWithRoundTripCheck(string text, CSharpParseOptions options = null) { - var tree = Parse(text, options: options); + var tree = Parse(text, options: options ?? TestOptions.RegularPreview); var parsedText = tree.GetRoot(); // we validate the text roundtrips Assert.Equal(text, parsedText.ToFullString()); diff --git a/src/Compilers/Test/Utilities/CSharp/DiagnosticTestUtilities.cs b/src/Compilers/Test/Utilities/CSharp/DiagnosticTestUtilities.cs index eb0e4abd6948f..5cfbe70b8005b 100644 --- a/src/Compilers/Test/Utilities/CSharp/DiagnosticTestUtilities.cs +++ b/src/Compilers/Test/Utilities/CSharp/DiagnosticTestUtilities.cs @@ -76,7 +76,7 @@ public static CSharpCompilation VerifyErrorsAndGetCompilationWithMscorlib(string /// internal protected static CSharpCompilation VerifyErrorsAndGetCompilationWithMscorlib(string[] srcs, params ErrorDescription[] expectedErrorDesp) { - var comp = CSharpTestBase.CreateCompilation(srcs); + var comp = CSharpTestBase.CreateCompilation(srcs, parseOptions: TestOptions.RegularPreview); var actualErrors = comp.GetDiagnostics(); VerifyErrorCodes(actualErrors, expectedErrorDesp); return comp; diff --git a/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb b/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb index 44f2b7d29cb09..9b6276c38b1f4 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb @@ -3432,7 +3432,7 @@ _Default: VisualBasicDeclarationComputer.ComputeDeclarationsInSpan(Me, span, getSymbol, builder, cancellationToken) End Sub - Friend Overrides Sub ComputeDeclarationsInNode(node As SyntaxNode, getSymbol As Boolean, builder As ArrayBuilder(Of DeclarationInfo), cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing) + Friend Overrides Sub ComputeDeclarationsInNode(node As SyntaxNode, associatedSymbol As ISymbol, getSymbol As Boolean, builder As ArrayBuilder(Of DeclarationInfo), cancellationToken As CancellationToken, Optional levelsToCompute As Integer? = Nothing) VisualBasicDeclarationComputer.ComputeDeclarationsInNode(Me, node, getSymbol, builder, cancellationToken) End Sub diff --git a/src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs b/src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs index bd2282fc5cebc..0d984bdab02ce 100644 --- a/src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs +++ b/src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs @@ -6,7 +6,10 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.AddParameter; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; @@ -2587,5 +2590,51 @@ void TestFunc() void MyFunc(BaseClass param1, int newparam) { } }"); } + + [WorkItem(44271, "https://github.com/dotnet/roslyn/issues/44271")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)] + public async Task TopLevelStatement() + { + await TestInRegularAndScriptAsync(@" +[|local|](1, 2, 3); + +void local(int x, int y) +{ +} +", +@" +[|local|](1, 2, 3); + +void local(int x, int y, int v) +{ +} +", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } + + [WorkItem(44271, "https://github.com/dotnet/roslyn/issues/44271")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)] + public async Task TopLevelStatement_Nested() + { + await TestInRegularAndScriptAsync(@" +void outer() +{ + [|local|](1, 2, 3); + + void local(int x, int y) + { + } +} +", +@" +void outer() +{ + local(1, 2, 3); + + void local(int x, int y, int v) + { + } +} +"); + } } } diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs index 361453d41442c..94e09ad0ab0c6 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs @@ -20,7 +20,8 @@ public void Creation() Assert.NotNull(session); } - [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void String_TopLevel() { using var session = CreateSessionDoubleQuote("$$"); @@ -28,7 +29,8 @@ public void String_TopLevel() CheckStart(session.Session, expectValidSession: false); } - [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void VerbatimString_TopLevel() { using var session = CreateSessionDoubleQuote("@$$"); @@ -36,7 +38,8 @@ public void VerbatimString_TopLevel() CheckStart(session.Session, expectValidSession: false); } - [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void Char_TopLevel() { using var session = CreateSessionSingleQuote("$$"); @@ -44,7 +47,8 @@ public void Char_TopLevel() CheckStart(session.Session, expectValidSession: false); } - [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void String_TopLevel2() { using var session = CreateSessionDoubleQuote("using System;$$"); @@ -52,7 +56,8 @@ public void String_TopLevel2() CheckStart(session.Session, expectValidSession: false); } - [WpfFact, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void VerbatimString_TopLevel2() { using var session = CreateSessionDoubleQuote("using System;@$$"); diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs index b10628a6ad238..1e79297d22535 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs @@ -348,7 +348,8 @@ await TestInMethodAsync(code, Local("stuff")); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task VerbatimStringLiteral6() { await TestAsync( @@ -459,7 +460,8 @@ await TestInExpressionAsync(code, String(@"""bar""")); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task VarContextualKeywordAtNamespaceLevel() { var code = @"var goo = 2;"; @@ -472,7 +474,8 @@ await TestAsync(code, Punctuation.Semicolon); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task LinqKeywordsAtNamespaceLevel() { // the contextual keywords are actual keywords since we parse top level field declaration and only give a semantic error diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests_Preprocessor.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests_Preprocessor.cs index e5a01345c7978..271f0089e944d 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests_Preprocessor.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests_Preprocessor.cs @@ -372,7 +372,8 @@ await TestAsync(code, Identifier("aeu")); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task PP_If8() { var code = @@ -396,7 +397,8 @@ await TestAsync(code, Field("aeu")); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task PP_If9() { var code = diff --git a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests_Dynamic.cs b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests_Dynamic.cs index d5ccc554532b0..f40dec1282ed0 100644 --- a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests_Dynamic.cs +++ b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests_Dynamic.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; using static Microsoft.CodeAnalysis.Editor.UnitTests.Classification.FormattedClassifications; @@ -620,7 +621,8 @@ await TestInMethodAsync(@"typeof(dynamic)", Punctuation.CloseParen); } - [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Classification)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task DynamicAsArrayName() { await TestAsync( diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs index 47ab75120a60f..b3992949d9e1e 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs @@ -4744,5 +4744,19 @@ void NewMethod() await TestInRegularAndScript1Async(code, expected); } + + [WorkItem(44260, "https://github.com/dotnet/roslyn/issues/44260")] + [Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)] + public async Task TopLevelStatement_ArgumentInInvocation() + { + // ExtractLocalFunction currently disabled in the presence of top-level statements + // https://github.com/dotnet/roslyn/issues/44260 + + var code = @" +System.Console.WriteLine([|""string""|]); +"; + await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }, + new TestParameters(parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp8))); + } } } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs index 7d93166aef7bf..3244a83e481ac 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.InlineTemporary; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -5170,5 +5171,73 @@ C M2() } }"); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + public async Task Call_TopLevelStatement() + { + var code = @" +using System; + +int [||]x = 1 + 1; +x.ToString(); +"; + + var expected = @" +using System; + +(1 + 1).ToString(); +"; + + // Global statements in regular code are local variables, so Inline Temporary works. Script code is not + // tested because global statements in script code are field declarations, which are not considered + // temporary. + await TestAsync(code, expected, TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } + + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + public async Task TopLevelStatement() + { + // Note: we should simplify 'global' as well + // https://github.com/dotnet/roslyn/issues/44420 + var code = @" +int val = 0; +int [||]val2 = val + 1; +System.Console.WriteLine(val2); +"; + + var expected = @" +int val = 0; +global::System.Console.WriteLine(val + 1); +"; + + // Global statements in regular code are local variables, so Inline Temporary works. Script code is not + // tested because global statements in script code are field declarations, which are not considered + // temporary. + await TestAsync(code, expected, TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } + + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + public async Task TopLevelStatement_InScope() + { + // Note: we should simplify 'global' as well + // https://github.com/dotnet/roslyn/issues/44420 + await TestAsync(@" +{ + int val = 0; + int [||]val2 = val + 1; + System.Console.WriteLine(val2); +} +", +@" +{ + int val = 0; + global::System.Console.WriteLine(val + 1); +} +", + TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExternAliasCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExternAliasCompletionProviderTests.cs index c13793a32d26b..e117a26aceabf 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExternAliasCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExternAliasCompletionProviderTests.cs @@ -31,7 +31,8 @@ class C }"); } - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task ExternAlias() { var markup = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index 1d12aec898f8c..78494017f6773 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -34,36 +34,24 @@ internal override Type GetCompletionProviderType() protected override ComposableCatalog GetExportCatalog() => base.GetExportCatalog().WithPart(typeof(TestExperimentationService)); - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task EmptyFile() + [Theory, Trait(Traits.Feature, Traits.Features.Completion)] + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script)] + public async Task EmptyFile(SourceCodeKind sourceCodeKind) { - await VerifyItemIsAbsentAsync(@"$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); - await VerifyItemIsAbsentAsync(@"$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); + await VerifyItemIsAbsentAsync(@"$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind); + await VerifyItemExistsAsync(@"$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind); } - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task EmptyFile_Interactive() - { - await VerifyItemIsAbsentAsync(@"$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); - await VerifyItemExistsAsync(@"$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); - } - - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task EmptyFileWithUsing() - { - await VerifyItemIsAbsentAsync(@"using System; -$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); - await VerifyItemIsAbsentAsync(@"using System; -$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); - } - - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task EmptyFileWithUsing_Interactive() + [Theory, Trait(Traits.Feature, Traits.Features.Completion)] + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script)] + public async Task EmptyFileWithUsing(SourceCodeKind sourceCodeKind) { await VerifyItemExistsAsync(@"using System; -$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); +$$", @"String", expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind); await VerifyItemExistsAsync(@"using System; -$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); +$$", @"System", expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -632,7 +620,7 @@ public async Task NamespaceName_OnKeyword() { var source = @"name$$space System { }"; - await VerifyItemIsAbsentAsync(source, "System", sourceCodeKind: SourceCodeKind.Regular); + await VerifyItemExistsAsync(source, "System", sourceCodeKind: SourceCodeKind.Regular); } [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")] @@ -2281,7 +2269,14 @@ class R } } $$"; // At EOF - await VerifyItemIsAbsentAsync(markup, "Q", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); + + // Top-level statements are not allowed to follow classes, but we still offer it in completion for a few + // reasons: + // + // 1. The code is simpler + // 2. It's a relatively rare coding practice to define types outside of namespaces + // 3. It allows the compiler to produce a better error message when users type things in the wrong order + await VerifyItemExistsAsync(markup, "Q", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); await VerifyItemIsAbsentAsync(markup, "R", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular); } @@ -7467,7 +7462,8 @@ class N } [WorkItem(635957, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/635957")] - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task TildeOutsideClass() { var markup = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs index 7f75c22df31c8..936ca6a968299 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs @@ -64,11 +64,13 @@ public async Task SendEnterThroughToEditorTest() await VerifySendEnterThroughToEnterAsync("class C { void M() { System.Console.$$", "Beep", sendThroughEnterOption: EnterKeyRule.Always, expected: true); } - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task InvalidLocation1() => await VerifyItemIsAbsentAsync(@"System.Console.$$", @"Beep"); - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task InvalidLocation2() { await VerifyItemIsAbsentAsync(@"using System; diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs index c53da07c3ef1b..19b1ef007ab09 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs @@ -144,6 +144,29 @@ await VerifyTypeImportItemExistsAsync( inlineDescription: "Foo"); } + [InlineData("class", (int)Glyph.ClassPublic)] + [InlineData("struct", (int)Glyph.StructurePublic)] + [InlineData("enum", (int)Glyph.EnumPublic)] + [InlineData("interface", (int)Glyph.InterfacePublic)] + [Theory, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task Show_TopLevelStatement_NoImport_InProject(string typeKind, int glyph) + { + var file1 = $@" +namespace Foo +{{ + public {typeKind} Bar + {{}} +}}"; + var file2 = @" +$$ +"; + await VerifyTypeImportItemExistsAsync( + CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp), + "Bar", + glyph: glyph, + inlineDescription: "Foo"); + } + [InlineData("class")] [InlineData("struct")] [InlineData("enum")] @@ -756,6 +779,55 @@ class Bat await VerifyCustomCommitProviderAsync(markup, "Bar", expectedCodeAfterCommit, sourceCodeKind: kind); } + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script)] + [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task Commit_TopLevelStatement_NoImport_InProject(SourceCodeKind kind) + { + var file1 = $@" +namespace Foo +{{ + public class Bar + {{ + }} +}}"; + + var file2 = @" +$$ +"; + var expectedCodeAfterCommit = @"using Foo; +Bar$$ +"; + var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp); + await VerifyCustomCommitProviderAsync(markup, "Bar", expectedCodeAfterCommit, sourceCodeKind: kind); + } + + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script)] + [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task Commit_TopLevelStatement_UnrelatedImport_InProject(SourceCodeKind kind) + { + var file1 = $@" +namespace Foo +{{ + public class Bar + {{ + }} +}}"; + + var file2 = @" +using System; + +$$ +"; + var expectedCodeAfterCommit = @" +using System; +using Foo; +Bar$$ +"; + var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp); + await VerifyCustomCommitProviderAsync(markup, "Bar", expectedCodeAfterCommit, sourceCodeKind: kind); + } [InlineData(SourceCodeKind.Regular)] [InlineData(SourceCodeKind.Script)] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs index 4f4731454964c..016344265a552 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs @@ -459,7 +459,8 @@ public class goo } [WorkItem(775091, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775091")] - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] public async Task ParamRefNames() { await VerifyItemExistsAsync(@" @@ -472,7 +473,8 @@ static void Main(string[] args) ", "args"); } - [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task ParamNamesInEmptyAttribute() { await VerifyItemExistsAsync(@" diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs index 266ae8b4f7e54..b330f3572f6c2 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs @@ -3996,10 +3996,14 @@ class A [WorkItem(540766, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540766")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateType)] - public async Task TestMissingOnInvalidGlobalCode() + public async Task TestOnInvalidGlobalCode() { - await TestMissingAsync( -@"[|a|] test "); + await TestInRegularAndScriptAsync( +@"[|a|] test ", +@"[|a|] test internal class a +{ +}", +index: 1); } [WorkItem(539985, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539985")] diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs index 530e861f5ee3e..810650bdd9563 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs @@ -9766,7 +9766,8 @@ public void TupleType_LocalVariables() "Update [y = (3, 4)]@56 -> [y2 = (3, 4)]@96"); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423")] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void TupleElementName() { var src1 = @"(int a, int b) F();"; diff --git a/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/NamespaceContextTests.cs b/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/NamespaceContextTests.cs index 197f9ea25ad16..24c08d54257c5 100644 --- a/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/NamespaceContextTests.cs +++ b/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/NamespaceContextTests.cs @@ -16,7 +16,7 @@ protected override void CheckResult(bool validLocation, int position, SyntaxTree [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public void EmptyFile() - => VerifyFalse(@"$$"); + => VerifyTrue(@"$$"); [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public void UsingDirective() diff --git a/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/TypeContextTests.cs b/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/TypeContextTests.cs index b313c1f4b7035..ca2ae34d73060 100644 --- a/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/TypeContextTests.cs +++ b/src/EditorFeatures/CSharpTest/Extensions/ContextQuery/TypeContextTests.cs @@ -16,7 +16,7 @@ protected override void CheckResult(bool validLocation, int position, SyntaxTree [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public void EmptyFile() - => VerifyFalse(@"$$"); + => VerifyTrue(@"$$"); [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public void UsingDirective() diff --git a/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodTests.cs b/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodTests.cs index b3abe0fe98fe4..0f672ed2b6414 100644 --- a/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodTests.cs +++ b/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodTests.cs @@ -11182,6 +11182,45 @@ private static bool NewMethod() { return true; } +}"; + await TestExtractMethodAsync(code, expected); + } + + [WorkItem(44260, "https://github.com/dotnet/roslyn/issues/44260")] + [Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)] + public async Task TopLevelStatement_ValueInAssignment() + { + var code = @" +bool local; +local = [|true|]; +"; + var expected = @" +bool local; +local = NewMethod(); + +bool NewMethod() +{ + return true; +}"; + await TestExtractMethodAsync(code, expected); + } + + [WorkItem(44260, "https://github.com/dotnet/roslyn/issues/44260")] + [Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)] + public async Task TopLevelStatement_ArgumentInInvocation() + { + // Note: the cast should be simplified + // https://github.com/dotnet/roslyn/issues/44260 + + var code = @" +System.Console.WriteLine([|""string""|]); +"; + var expected = @" +System.Console.WriteLine((string)NewMethod()); + +string NewMethod() +{ + return ""string""; }"; await TestExtractMethodAsync(code, expected); } diff --git a/src/EditorFeatures/CSharpTest/FixInterpolatedVerbatimString/FixInterpolatedVerbatimStringCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/FixInterpolatedVerbatimString/FixInterpolatedVerbatimStringCommandHandlerTests.cs index fb3c63f24ded4..312c620baaef2 100644 --- a/src/EditorFeatures/CSharpTest/FixInterpolatedVerbatimString/FixInterpolatedVerbatimStringCommandHandlerTests.cs +++ b/src/EditorFeatures/CSharpTest/FixInterpolatedVerbatimString/FixInterpolatedVerbatimStringCommandHandlerTests.cs @@ -153,7 +153,8 @@ void M() }"); } - [WpfFact, Trait(Traits.Feature, Traits.Features.FixInterpolatedVerbatimString)] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.FixInterpolatedVerbatimString)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void TestMissingInEmptyFileAfterAtSignDollarSign() => TestNotHandled(@"@$[||]"); diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index c4268c2228e74..c31bb9ea331be 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -2115,8 +2115,9 @@ public async Task CharLiterals() await AutoFormatOnMarkerAsync(code, expected, SyntaxKind.CharacterLiteralToken, SyntaxKind.None); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423")] [Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task CharLiterals1() { var code = @"''';$$"; diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs index 06a337ad0c28c..701dceae84f2d 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs @@ -15,8 +15,9 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting.Indentation { public class SmartTokenFormatterFormatTokenTests : CSharpFormatterTestsBase { - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423)")] [Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task EmptyFile1() { var code = @"{"; diff --git a/src/EditorFeatures/CSharpTest/RemoveUnusedLocalFunction/RemoveUnusedLocalFunctionTests.cs b/src/EditorFeatures/CSharpTest/RemoveUnusedLocalFunction/RemoveUnusedLocalFunctionTests.cs index e7f9367e2fea3..ce13bf0c7af44 100644 --- a/src/EditorFeatures/CSharpTest/RemoveUnusedLocalFunction/RemoveUnusedLocalFunctionTests.cs +++ b/src/EditorFeatures/CSharpTest/RemoveUnusedLocalFunction/RemoveUnusedLocalFunctionTests.cs @@ -5,9 +5,11 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.RemoveUnusedLocalFunction; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnusedLocalFunction @@ -113,5 +115,16 @@ void Method() } }"); } + + [WorkItem(44272, "https://github.com/dotnet/roslyn/issues/44272")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedLocalFunction)] + public async Task TopLevelStatement() + { + await TestAsync(@" +void [|local()|] { } +", +@" +", TestOptions.Regular); + } } } diff --git a/src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs b/src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs index 7d15bf0a51bba..bda990e07161e 100644 --- a/src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs +++ b/src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.RemoveUnusedVariable; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; @@ -703,5 +704,16 @@ void Method() } }"); } + + [WorkItem(44273, "https://github.com/dotnet/roslyn/issues/44273")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedVariable)] + public async Task TopLevelStatement() + { + await TestAsync(@" +[|int i = 0|]; +", +@" +", TestOptions.Regular); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs index 713a626f71f41..975cf5a108611 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/AsyncKeywordRecommenderTests.cs @@ -154,67 +154,47 @@ class Goo }"); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(8616, "https://github.com/dotnet/roslyn/issues/8616")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] - public async Task TestLocalFunction() + public async Task TestLocalFunction(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Goo -{ - public void M() - { - $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(14525, "https://github.com/dotnet/roslyn/issues/14525")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] [Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLocalFunction2() + public async Task TestLocalFunction2(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Goo -{ - public void M() - { - unsafe $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"unsafe $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(14525, "https://github.com/dotnet/roslyn/issues/14525")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] [Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLocalFunction3() + public async Task TestLocalFunction3(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Goo -{ - public void M() - { - unsafe $$ void L() { } - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"unsafe $$ void L() { }", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(8616, "https://github.com/dotnet/roslyn/issues/8616")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] [Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLocalFunction4() + public async Task TestLocalFunction4(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Goo -{ - public void M() - { - $$ void L() { } - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"$$ void L() { }", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact] @@ -236,36 +216,26 @@ public void M(Action a) }"); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(8616, "https://github.com/dotnet/roslyn/issues/8616")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] [Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLocalFunction6() + public async Task TestLocalFunction6(bool topLevelStatement) { - await VerifyAbsenceAsync(@" -class Goo -{ - public void M() - { - int $$ - } -}"); + await VerifyAbsenceAsync(AddInsideMethod( +@"int $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact] + [Theory] + [CombinatorialData] [WorkItem(8616, "https://github.com/dotnet/roslyn/issues/8616")] [Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.LocalFunctions)] [Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLocalFunction7() + public async Task TestLocalFunction7(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Goo -{ - public void M() - { - static $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"static $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/AwaitKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/AwaitKeywordRecommenderTests.cs index c7ebc8609c708..014347f07097c 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/AwaitKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/AwaitKeywordRecommenderTests.cs @@ -21,162 +21,94 @@ class Program }"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInSynchronousMethod() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestStatementInMethod(bool isAsync, bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - void goo() - { - $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"$$", isAsync: isAsync, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestStatementInAsyncMethod() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestExpressionInAsyncMethod(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - $$ - } -}"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestExpressionInAsyncMethod() - { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - var z = $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"var z = $$", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestUsingStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestUsingStatement(bool topLevelStatement) { - await VerifyAbsenceAsync(@" -class Program -{ - void goo() - { - using $$ - } -}"); + await VerifyAbsenceAsync(AddInsideMethod( +@"using $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestUsingDirective() => await VerifyAbsenceAsync("using $$"); - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestForeachStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestForeachStatement(bool topLevelStatement) { - await VerifyAbsenceAsync(@" -class Program -{ - void goo() - { - foreach $$ - } -}"); + await VerifyAbsenceAsync(AddInsideMethod( +@"foreach $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInQuery() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInQuery(bool topLevelStatement) { - await VerifyAbsenceAsync(@" -class Program -{ - async void goo() - { - var z = from a in ""char"" - select $$ - } -}"); + await VerifyAbsenceAsync(AddInsideMethod( +@"var z = from a in ""char"" + select $$", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(907052, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/907052")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFinally() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFinally(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - try { } - finally { $$ } - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"try { } +finally { $$ }", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(907052, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/907052")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCatch() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCatch(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - try { } - catch { $$ } - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"try { } +catch { $$ }", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInLock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInLock(bool topLevelStatement) { - await VerifyAbsenceAsync(@" -class Program -{ - async void goo() - { - lock(this) { $$ } - } -}"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInAsyncLambdaInCatch() - { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - try { } - catch { var z = async () => $$ } - } -}"); + await VerifyAbsenceAsync(AddInsideMethod( +@"lock(this) { $$ }", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAwaitInLock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInAsyncLambdaInCatch(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - async void goo() - { - lock($$"); + await VerifyKeywordAsync(AddInsideMethod( +@"try { } +catch { var z = async () => $$ }", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInGlobalStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAwaitInLock(bool topLevelStatement) { - const string text = @"$$"; - await VerifyKeywordAsync(SourceCodeKind.Script, text); + await VerifyKeywordAsync(AddInsideMethod( +@"lock($$", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/BaseKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/BaseKeywordRecommenderTests.cs index a3dbb716b62da..aac3c727df842 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/BaseKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/BaseKeywordRecommenderTests.cs @@ -37,19 +37,19 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalStatement_Interactive() + public async Task TestNotAfterGlobalStatement() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"System.Console.WriteLine(); -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalVariableDeclaration_Interactive() + public async Task TestNotAfterGlobalVariableDeclaration() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"int i = 0; -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs index bf7bf2133a5df..13cc4ff28a180 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -13,10 +12,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class BoolKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { - await VerifyKeywordAsync(SourceCodeKind.Script, -@"$$"); + await VerifyKeywordAsync( +@"$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -28,19 +27,19 @@ await VerifyKeywordAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalStatement_Interactive() + public async Task TestAfterGlobalStatement() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"System.Console.WriteLine(); -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalVariableDeclaration_Interactive() + public async Task TestAfterGlobalVariableDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"int i = 0; -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -58,11 +57,12 @@ await VerifyKeywordAsync( int* goo = stackalloc $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFixedStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFixedStatement(bool topLevelStatement) { - await VerifyKeywordAsync( -@"fixed ($$"); + await VerifyKeywordAsync(AddInsideMethod( +@"fixed ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -89,74 +89,84 @@ await VerifyKeywordAsync( ref readonly $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConstInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterConstInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"const $$")); +@"const $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$")); +@"ref $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$")); +@"ref readonly $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConstLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterConstLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"const $$ int local;")); +@"const $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$ int local;")); +@"ref $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$ int local;")); +@"ref readonly $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefLocalFunction() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefLocalFunction(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$ int Function();")); +@"ref $$ int Function();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyLocalFunction() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyLocalFunction(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$ int Function();")); +@"ref readonly $$ int Function();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref int x = ref $$")); +@"ref int x = ref $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -166,32 +176,36 @@ await VerifyAbsenceAsync( @"enum E : $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInGenericType1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInGenericType1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"IList<$$")); +@"IList<$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInGenericType2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInGenericType2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"IList,$$")); +@"IList,$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -208,18 +222,20 @@ await VerifyKeywordAsync( @"class C : IList<$$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterIs() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterIs(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var v = goo is $$")); +@"var v = goo is $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAs() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAs(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var v = goo as $$")); +@"var v = goo as $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -381,40 +397,45 @@ await VerifyKeywordAsync(AddInsideMethod( @"$$")); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInForVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInForVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"for ($$")); +@"for ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInForeachVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInForeachVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"foreach ($$")); +@"foreach ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInUsingVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInUsingVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"using ($$")); +@"using ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFromVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFromVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var q = from $$")); +@"var q = from $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInJoinVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInJoinVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from a in b - join $$")); + join $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -568,25 +589,28 @@ await VerifyKeywordAsync( public static explicit operator $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterNewInExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterNewInExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new $$")); +@"new $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCastType() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCastType(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var str = (($$")); +@"var str = (($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCastType2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCastType2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var str = (($$)items) as string;")); +@"var str = (($$)items) as string;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -597,27 +621,30 @@ await VerifyKeywordAsync( } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInTypeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInTypeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"typeof($$")); +@"typeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInDefault() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInDefault(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"default($$")); +@"default($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInSizeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInSizeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"sizeof($$")); +@"sizeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(544219, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544219")] @@ -704,17 +731,12 @@ class Program } [WorkItem(14127, "https://github.com/dotnet/roslyn/issues/14127")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInTupleWithinMember() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInTupleWithinMember(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - void Method() - { - ($$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/BreakKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/BreakKeywordRecommenderTests.cs index bf0d15dd7a577..1b7e8f19881fa 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/BreakKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/BreakKeywordRecommenderTests.cs @@ -11,10 +11,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class BreakKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAtRoot_Interactive() + public async Task TestNotAtRoot() { - await VerifyAbsenceAsync(SourceCodeKind.Script, -@"$$"); + await VerifyAbsenceAsync( +@"$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -26,19 +26,19 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalStatement_Interactive() + public async Task TestNotAfterGlobalStatement() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"System.Console.WriteLine(); -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalVariableDeclaration_Interactive() + public async Task TestNotAfterGlobalVariableDeclaration() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"int i = 0; -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -48,131 +48,146 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestEmptyStatement(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBeforeStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBeforeStatement(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"$$ -return true;")); +return true;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterStatement(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"return true; -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBlock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBlock(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"if (true) { } -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterIf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterIf(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"if (true) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterDo() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterDo(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"do - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterWhile() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterWhile(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"while (true) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterFor() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterFor(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"for (int i = 0; i < 10; i++) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterForeach() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterForeach(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"foreach (var v in bar) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInsideLambda() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInsideLambda(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"foreach (var v in bar) { var d = () => { - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInsideAnonymousMethod() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInsideAnonymousMethod(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"foreach (var v in bar) { var d = delegate { - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInsideSwitch() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInsideSwitch(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"switch (a) { case 0: - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInsideSwitchWithLambda() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInsideSwitchWithLambda(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"switch (a) { case 0: var d = () => { - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInsideSwitchOutsideLambda() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInsideSwitchOutsideLambda(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"switch (a) { case 0: var d = () => { }; - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterBreak() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterBreak(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"break $$")); +@"break $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -184,33 +199,36 @@ await VerifyAbsenceAsync(@"class C }"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterYield() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterYield(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"yield $$")); +@"yield $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterSwitchInSwitch() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterSwitchInSwitch(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"switch (expr) { default: switch (expr) { } - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBlockInSwitch() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBlockInSwitch(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"switch (expr) { default: { } - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ByKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ByKeywordRecommenderTests.cs index 61d1927561e8d..f94050724f5ed 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ByKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ByKeywordRecommenderTests.cs @@ -11,10 +11,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class ByKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAtRoot_Interactive() + public async Task TestNotAtRoot() { - await VerifyAbsenceAsync(SourceCodeKind.Script, -@"$$"); + await VerifyAbsenceAsync( +@"$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -26,19 +26,19 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalStatement_Interactive() + public async Task TestNotAfterGlobalStatement() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"System.Console.WriteLine(); -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGlobalVariableDeclaration_Interactive() + public async Task TestNotAfterGlobalVariableDeclaration() { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync( @"int i = 0; -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -48,35 +48,39 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInEmptyStatement(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGroupExpr() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterGroupExpr(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - group a $$")); + group a $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterGroup() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterGroup(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"var q = from x in y - group $$")); + group $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterBy() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterBy(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( @"var q = from x in y - group a by $$")); + group a by $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs index 94a88324cba32..efecea03cbb44 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -13,10 +12,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class ByteKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { - await VerifyKeywordAsync(SourceCodeKind.Script, -@"$$"); + await VerifyKeywordAsync( +@"$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -28,19 +27,19 @@ await VerifyKeywordAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalStatement_Interactive() + public async Task TestAfterGlobalStatement() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"System.Console.WriteLine(); -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalVariableDeclaration_Interactive() + public async Task TestAfterGlobalVariableDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"int i = 0; -$$"); +$$", options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -58,11 +57,12 @@ await VerifyKeywordAsync( int* goo = stackalloc $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFixedStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFixedStatement(bool topLevelStatement) { - await VerifyKeywordAsync( -@"fixed ($$"); + await VerifyKeywordAsync(AddInsideMethod( +@"fixed ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -72,18 +72,20 @@ await VerifyKeywordAsync( @"public delegate $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCastType() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCastType(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var str = (($$")); +@"var str = (($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCastType2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCastType2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var str = (($$)items) as string;")); +@"var str = (($$)items) as string;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -110,74 +112,84 @@ await VerifyKeywordAsync( ref readonly $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConstInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterConstInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"const $$")); +@"const $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$")); +@"ref $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyInStatementContext() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyInStatementContext(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$")); +@"ref readonly $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConstLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterConstLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"const $$ int local;")); +@"const $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$ int local;")); +@"ref $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyLocalDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyLocalDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$ int local;")); +@"ref readonly $$ int local;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefLocalFunction() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefLocalFunction(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref $$ int Function();")); +@"ref $$ int Function();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefReadonlyLocalFunction() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefReadonlyLocalFunction(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref readonly $$ int Function();")); +@"ref readonly $$ int Function();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRefExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRefExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"ref int x = ref $$")); +@"ref int x = ref $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -187,32 +199,36 @@ await VerifyKeywordAsync( @"enum E : $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInGenericType1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInGenericType1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"IList<$$")); +@"IList<$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInGenericType2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInGenericType2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"IList,$$")); +@"IList,$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -229,18 +245,20 @@ await VerifyKeywordAsync( @"class C : IList<$$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterIs() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterIs(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var v = goo is $$")); +@"var v = goo is $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAs() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAs(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var v = goo as $$")); +@"var v = goo as $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -395,47 +413,53 @@ await VerifyKeywordAsync( static $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInLocalVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInLocalVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInForVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInForVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"for ($$")); +@"for ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInForeachVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInForeachVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"foreach ($$")); +@"foreach ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInUsingVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInUsingVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"using ($$")); +@"using ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFromVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFromVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var q = from $$")); +@"var q = from $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInJoinVariableDeclaration() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInJoinVariableDeclaration(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from a in b - join $$")); + join $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -589,35 +613,39 @@ await VerifyKeywordAsync( int this[int i, $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterNewInExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterNewInExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new $$")); +@"new $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInTypeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInTypeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"typeof($$")); +@"typeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInDefault() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInDefault(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"default($$")); +@"default($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInSizeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInSizeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"sizeof($$")); +@"sizeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(544219, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544219")] @@ -704,18 +732,12 @@ class Program } [WorkItem(14127, "https://github.com/dotnet/roslyn/issues/14127")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInTupleWithinMember() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInTupleWithinMember(bool topLevelStatement) { - await VerifyKeywordAsync(@" -class Program -{ - void Method() - { - ($$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } } } - diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ConstKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ConstKeywordRecommenderTests.cs index e8fc1bc4f0450..3142b22b45d96 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ConstKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ConstKeywordRecommenderTests.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations @@ -12,32 +11,32 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class ConstKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"$$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterClass_Interactive() + public async Task TestAfterClass() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"class C { } $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalStatement_Interactive() + public async Task TestAfterGlobalStatement() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"System.Console.WriteLine(); $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalVariableDeclaration_Interactive() + public async Task TestAfterGlobalVariableDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"int i = 0; $$"); } @@ -49,63 +48,39 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCompilationUnit() - => await VerifyAbsenceAsync(SourceCodeKind.Regular, @"$$"); - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterExtern() + public async Task TestAfterExtern() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"extern alias Goo; + await VerifyKeywordAsync(@"extern alias Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterExtern_Interactive() + public async Task TestAfterUsing() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"extern alias Goo; + await VerifyKeywordAsync(@"using Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterUsing() + public async Task TestAfterNamespace() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"using Goo; + await VerifyKeywordAsync(@"namespace N {} $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterUsing_Interactive() + public async Task TestAfterDelegateDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"using Goo; -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterNamespace() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"namespace N {} -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterTypeDeclaration() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"class C {} -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterDelegateDeclaration() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"delegate void Goo(); + await VerifyKeywordAsync(@"delegate void Goo(); $$"); } @@ -136,40 +111,34 @@ await VerifyKeywordAsync( $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotBeforeUsing() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [InlineData(SourceCodeKind.Regular)] + [InlineData(SourceCodeKind.Script, Skip = "https://github.com/dotnet/roslyn/issues/9880")] + public async Task TestNotBeforeUsing(SourceCodeKind sourceCodeKind) { - await VerifyAbsenceAsync(SourceCodeKind.Regular, -@"$$ -using Goo;"); - } - - [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/9880"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotBeforeUsing_Interactive() - { - await VerifyAbsenceAsync(SourceCodeKind.Script, + await VerifyAbsenceAsync(sourceCodeKind, @"$$ using Goo;"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterAssemblyAttribute() + public async Task TestAfterAssemblyAttribute() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[assembly: goo] + await VerifyKeywordAsync(@"[assembly: goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAssemblyAttribute_Interactive() + public async Task TestNotAfterRootAttribute() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] + await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterRootAttribute() + public async Task TestAfterRootAttribute_Interactive() { - await VerifyAbsenceAsync(@"[goo] + await VerifyKeywordAsync(SourceCodeKind.Script, @"[goo] $$"); } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/EventKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/EventKeywordRecommenderTests.cs index 06679277a07ac..72d7e5e869a3b 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/EventKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/EventKeywordRecommenderTests.cs @@ -169,7 +169,14 @@ await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotAfterRootAttribute() { - await VerifyAbsenceAsync(@"[goo] + await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[goo] +$$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterRootAttribute_Interactive() + { + await VerifyKeywordAsync(SourceCodeKind.Script, @"[goo] $$"); } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ExternKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ExternKeywordRecommenderTests.cs index 43938281c6fa4..bc35dd8ed8902 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ExternKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ExternKeywordRecommenderTests.cs @@ -11,32 +11,32 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class ExternKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { await VerifyKeywordAsync( @"$$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterClass_Interactive() + public async Task TestAfterClass() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"class C { } $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalStatement_Interactive() + public async Task TestAfterGlobalStatement() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"System.Console.WriteLine(); $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalVariableDeclaration_Interactive() + public async Task TestAfterGlobalVariableDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"int i = 0; $$"); } @@ -48,29 +48,33 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStaticInStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterStaticInStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"static $$")); +@"static $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAttributesInStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAttributesInStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"[Attr] $$")); +@"[Attr] $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAttributesInSwitchCase() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAttributesInSwitchCase(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"switch (c) @@ -78,73 +82,73 @@ await VerifyKeywordAsync(AddInsideMethod( case 0: [Foo] $$ -}")); +}", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAttributesAndStaticInStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAttributesAndStaticInStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"[Attr] static $$")); +@"[Attr] static $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBetweenAttributesAndReturnStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBetweenAttributesAndReturnStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"[Attr] $$ -return x;")); +return x;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBetweenAttributesAndLocalDeclarationStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBetweenAttributesAndLocalDeclarationStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"[Attr] $$ -x y = bar();")); +x y = bar();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBetweenAttributesAndAwaitExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBetweenAttributesAndAwaitExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"[Attr] $$ -await bar;")); +await bar;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBetweenAttributesAndAssignmentStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBetweenAttributesAndAssignmentStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"[Foo] $$ -y = bar();")); +y = bar();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBetweenAttributesAndCallStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBetweenAttributesAndCallStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"[Foo] $$ -bar();")); +bar();", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterExternInStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterExternInStatement(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"extern $$")); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot() - { - await VerifyKeywordAsync( -@"$$"); +@"extern $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -160,30 +164,16 @@ await VerifyKeywordAsync( } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterUsing() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"using Goo; -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterUsing_Interactive() - { - await VerifyKeywordAsync(SourceCodeKind.Script, @"using Goo; -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterNamespace() + public async Task TestAfterUsing() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"namespace N {} + await VerifyKeywordAsync(@"using Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterTypeDeclaration() + public async Task TestAfterNamespace() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"class C {} + await VerifyKeywordAsync(@"namespace N {} $$"); } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ForEachKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ForEachKeywordRecommenderTests.cs index 773858d715294..4239700a126aa 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ForEachKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ForEachKeywordRecommenderTests.cs @@ -17,6 +17,13 @@ await VerifyKeywordAsync(SourceCodeKind.Script, @"$$"); } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAtRoot_TopLevelStatement() + { + await VerifyKeywordAsync( +@"$$", options: CSharp9ParseOptions); + } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestAfterClass_Interactive() { @@ -33,6 +40,14 @@ await VerifyKeywordAsync(SourceCodeKind.Script, $$"); } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterStatement_TopLevelStatement() + { + await VerifyKeywordAsync( +@"System.Console.WriteLine(); +$$", options: CSharp9ParseOptions); + } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestAfterGlobalVariableDeclaration_Interactive() { @@ -41,6 +56,14 @@ await VerifyKeywordAsync(SourceCodeKind.Script, $$"); } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterVariableDeclaration_TopLevelStatement() + { + await VerifyKeywordAsync( +@"int i = 0; +$$", options: CSharp9ParseOptions); + } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotInUsingAlias() { @@ -48,116 +71,124 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAwait() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterAwait(bool topLevelStatement) { - await VerifyKeywordAsync( -@"class C -{ - async void M() - { - await $$ - } -}"); + await VerifyKeywordAsync(AddInsideMethod( +@"await $$", isAsync: true, topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBeforeStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBeforeStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"$$ -return true;")); +return 0;", returnType: "int", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"return true; -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBlock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBlock(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"if (true) { } -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInsideForEach() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInsideForEach(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"foreach (var v in c) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInsideForEachInsideForEach() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInsideForEachInsideForEach(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"foreach (var v in c) foreach (var v in c) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInsideForEachBlock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInsideForEachBlock(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"foreach (var v in c) { - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach1(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach $$")); +@"foreach $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach2(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach ($$")); +@"foreach ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach3() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach3(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach (var $$")); +@"foreach (var $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach4() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach4(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach (var v $$")); +@"foreach (var v $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach5() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach5(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach (var v in $$")); +@"foreach (var v in $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterForEach6() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterForEach6(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"foreach (var v in c $$")); +@"foreach (var v in c $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/NewKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/NewKeywordRecommenderTests.cs index 01cba27c375e5..47716af2aaedd 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/NewKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/NewKeywordRecommenderTests.cs @@ -12,32 +12,32 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class NewKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"$$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterClass_Interactive() + public async Task TestAfterClass() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"class C { } $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalStatement_Interactive() + public async Task TestAfterGlobalStatement() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"System.Console.WriteLine(); $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGlobalVariableDeclaration_Interactive() + public async Task TestAfterGlobalVariableDeclaration() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"int i = 0; $$"); } @@ -49,11 +49,12 @@ await VerifyAbsenceAsync( @"using Goo = $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -112,428 +113,488 @@ await VerifyKeywordAsync( @"class C where T : IGoo, $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestStartOfExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestStartOfExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var q = $$")); +@"var q = $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] [WorkItem(34324, "https://github.com/dotnet/roslyn/issues/34324")] - public async Task TestAfterNullCoalescingAssignment() + public async Task TestAfterNullCoalescingAssignment(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q ??= $$")); +@"q ??= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInParenthesizedExpression() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInParenthesizedExpression(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var q = ($$")); +@"var q = ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestPlusEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestPlusEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q += $$")); +@"q += $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestMinusEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestMinusEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q -= $$")); +@"q -= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestTimesEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestTimesEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q *= $$")); +@"q *= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestDivideEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestDivideEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q /= $$")); +@"q /= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestModEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestModEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q %= $$")); +@"q %= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestXorEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestXorEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q ^= $$")); +@"q ^= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAndEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAndEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q &= $$")); +@"q &= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestOrEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestOrEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q |= $$")); +@"q |= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLeftShiftEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestLeftShiftEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q <<= $$")); +@"q <<= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestRightShiftEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestRightShiftEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"q >>= $$")); +@"q >>= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterMinus() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterMinus(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"- $$")); +@"- $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterPlus() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterPlus(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"+ $$")); +@"+ $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterNot() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterNot(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"! $$")); +@"! $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterTilde() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterTilde(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"~ $$")); +@"~ $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryTimes() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryTimes(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a * $$")); +@"a * $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryDivide() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryDivide(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a / $$")); +@"a / $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryMod() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryMod(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a % $$")); +@"a % $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryPlus() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryPlus(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a + $$")); +@"a + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryMinus() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryMinus(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a - $$")); +@"a - $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryLeftShift() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryLeftShift(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a << $$")); +@"a << $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryRightShift() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryRightShift(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a >> $$")); +@"a >> $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryLessThan() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryLessThan(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a < $$")); +@"a < $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBinaryGreaterThan() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBinaryGreaterThan(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a > $$")); +@"a > $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterEqualsEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterEqualsEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a == $$")); +@"a == $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterNotEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterNotEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a != $$")); +@"a != $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterLessThanEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterLessThanEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a <= $$")); +@"a <= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGreaterThanEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterGreaterThanEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a >= $$")); +@"a >= $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterNullable() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterNullable(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a ?? $$")); +@"a ?? $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterArrayRankSpecifier1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterArrayRankSpecifier1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new int[ $$")); +@"new int[ $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterArrayRankSpecifier2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterArrayRankSpecifier2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new int[expr, $$")); +@"new int[expr, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConditional1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterConditional1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a ? $$")); +@"a ? $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterConditional2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [InlineData(false)] + [InlineData(true, Skip = "https://github.com/dotnet/roslyn/issues/44443")] + public async Task TestAfterConditional2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"a ? expr | $$")); +@"a ? expr | $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInArgument1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInArgument1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"Goo( $$")); +@"Goo( $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInArgument2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInArgument2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"Goo(expr, $$")); +@"Goo(expr, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInArgument3() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInArgument3(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new Goo( $$")); +@"new Goo( $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInArgument4() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInArgument4(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new Goo(expr, $$")); +@"new Goo(expr, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterRef() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterRef(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"Goo(ref $$")); +@"Goo(ref $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterOut() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterOut(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"Goo(out $$")); +@"Goo(out $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestLambda() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestLambda(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"Action a = i => $$")); +@"Action a = i => $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCollectionInitializer1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCollectionInitializer1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new System.Collections.Generic.List() { $$")); +@"new System.Collections.Generic.List() { $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInCollectionInitializer2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInCollectionInitializer2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"new System.Collections.Generic.List() { expr, $$")); +@"new System.Collections.Generic.List() { expr, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInForeachIn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInForeachIn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"foreach (var v in $$")); +@"foreach (var v in $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInAwaitForeachIn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInAwaitForeachIn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"await foreach (var v in $$")); +@"await foreach (var v in $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInFromIn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInFromIn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"var q = from x in $$")); +@"var q = from x in $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInJoinIn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInJoinIn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - join a in $$")); + join a in $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInJoinOn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInJoinOn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - join a in b on $$")); + join a in b on $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInJoinEquals() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInJoinEquals(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - join a in b on equals $$")); + join a in b on equals $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestWhere() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestWhere(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - where $$")); + where $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestOrderby1() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestOrderby1(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - orderby $$")); + orderby $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestOrderby2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestOrderby2(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - orderby a, $$")); + orderby a, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestOrderby3() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestOrderby3(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - orderby a ascending, $$")); + orderby a ascending, $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterSelect() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterSelect(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - select $$")); + select $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGroup() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterGroup(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - group $$")); + group $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterGroupBy() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterGroupBy(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"var q = from x in y - group expr by $$")); + group expr by $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterReturn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterReturn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"return $$")); +@"return $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterYieldReturn() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterYieldReturn(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"yield return $$")); +@"yield return $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -543,109 +604,87 @@ await VerifyAbsenceAsync( @"[return $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterThrow() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterThrow(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"throw $$")); +@"throw $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInWhile() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInWhile(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"while ($$")); +@"while ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInUsing() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInUsing(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"using ($$")); +@"using ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInAwaitUsing() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInAwaitUsing(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"await using ($$")); +@"await using ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInLock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInLock(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"lock ($$")); +@"lock ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInIf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInIf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"if ($$")); +@"if ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInSwitch() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInSwitch(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"switch ($$")); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCompilationUnit() - => await VerifyAbsenceAsync(SourceCodeKind.Regular, @"$$"); - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCompilationUnit_Interactive() - => await VerifyKeywordAsync(SourceCodeKind.Script, @"$$"); - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterExtern() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"extern alias Goo; -$$"); +@"switch ($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterExtern_Interactive() + public async Task TestAfterExtern() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"extern alias Goo; + await VerifyKeywordAsync(@"extern alias Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterUsing() + public async Task TestAfterUsing() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"using Goo; + await VerifyKeywordAsync(@"using Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterUsing_Interactive() + public async Task TestAfterNamespace() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"using Goo; + await VerifyKeywordAsync(@"namespace N {} $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterNamespace() + public async Task TestAfterDelegateDeclaration() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"namespace N {} -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterTypeDeclaration() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"class C {} -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterDelegateDeclaration() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"delegate void Goo(); + await VerifyKeywordAsync(@"delegate void Goo(); $$"); } @@ -693,23 +732,24 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterAssemblyAttribute() + public async Task TestAfterAssemblyAttribute() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[assembly: goo] + await VerifyKeywordAsync(@"[assembly: goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAssemblyAttribute_Interactive() + public async Task TestNotAfterRootAttribute() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] + await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterRootAttribute() + public async Task TestAfterRootAttribute_Interactive() { - await VerifyAbsenceAsync(@"[goo] + // The global function could be hiding a member inherited from System.Object. + await VerifyKeywordAsync(SourceCodeKind.Script, @"[goo] $$"); } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/PrivateKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/PrivateKeywordRecommenderTests.cs index 691c05be6ea2d..089c0146bd95b 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/PrivateKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/PrivateKeywordRecommenderTests.cs @@ -167,7 +167,14 @@ await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotAfterRootAttribute() { - await VerifyAbsenceAsync(@"[goo] + await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[goo] +$$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterRootAttribute_Interactive() + { + await VerifyKeywordAsync(SourceCodeKind.Script, @"[goo] $$"); } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs index 9f414c84c68a4..00ece020fdf1c 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs @@ -381,7 +381,8 @@ public async Task TestInRefStruct() public async Task TestInRefStructBeforeRef() => await VerifyKeywordAsync(SourceCodeKind.Regular, @"$$ ref struct { }"); - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task TestAfterNew() => await VerifyKeywordAsync(SourceCodeKind.Regular, @"new $$"); diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs index 70e32713b8db0..1194d801e5dcd 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs @@ -5,12 +5,14 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Roslyn.Test.Utilities; using Xunit; @@ -18,6 +20,8 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations { public abstract class RecommenderTests : TestBase { + protected static readonly CSharpParseOptions CSharp9ParseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersionExtensions.CSharp9); + protected string keywordText; internal Func>> RecommendKeywordsAsync; @@ -83,7 +87,7 @@ private async Task CheckResultAsync(bool absent, int position, CSharpSyntaxConte } else { - var result = (await RecommendKeywordsAsync(position, context)).SingleOrDefault(); + var result = (await RecommendKeywordsAsync(position, context))?.SingleOrDefault(); Assert.True(result != null, "No recommended keywords"); Assert.Equal(keywordText, result.Keyword); if (matchPriority != null) @@ -189,16 +193,52 @@ protected async Task VerifyAbsenceAsync(SourceCodeKind kind, string text) } } - protected string AddInsideMethod(string text) + protected string AddInsideMethod(string text, bool isAsync = false, string returnType = "void", bool topLevelStatement = false) { - return -@"class C -{ - void F() - { - " + text + -@" } -}"; + if (topLevelStatement) + { + return returnType switch + { + "void" => text, + "int" => text, + _ => throw new ArgumentException("Unsupported return type", nameof(returnType)), + }; + } + + var builder = new StringBuilder(); + if (isAsync && returnType != "void") + { + builder.AppendLine("using System.Threading.Tasks;"); + } + + builder.AppendLine("class C"); + builder.AppendLine("{"); + builder.Append(" "); + + if (isAsync) + { + builder.Append("async "); + if (returnType == "void") + { + builder.Append("Task"); + } + else + { + builder.Append($"Task<{returnType}>"); + } + } + else + { + builder.Append(returnType); + } + + builder.AppendLine(" F()"); + builder.AppendLine(" {"); + builder.Append(" ").Append(text); + builder.AppendLine(" }"); + builder.Append("}"); + + return builder.ToString(); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/RefKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/RefKeywordRecommenderTests.cs index 53b878a6230ce..762fd1e60995a 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/RefKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/RefKeywordRecommenderTests.cs @@ -713,7 +713,8 @@ await VerifyKeywordWithRefsAsync(SourceCodeKind.Regular, @"$$ readonly struct { }"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public async Task TestAfterNew() { await VerifyKeywordWithRefsAsync(SourceCodeKind.Regular, diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UsingKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UsingKeywordRecommenderTests.cs index b42c2c08e9a0b..0e82170cbba71 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/UsingKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UsingKeywordRecommenderTests.cs @@ -19,9 +19,9 @@ await VerifyAbsenceAsync( } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterClass_Interactive() + public async Task TestAfterClass() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"class C { } $$"); } @@ -42,11 +42,12 @@ await VerifyKeywordAsync(SourceCodeKind.Script, $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInEmptyStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInEmptyStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"$$")); +@"$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -118,13 +119,6 @@ await VerifyKeywordAsync( $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterTypeDeclaration() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"class C {} -$$"); - } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotAfterNestedTypeDeclaration() { @@ -199,76 +193,84 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, extern alias Goo;"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestBeforeStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestBeforeStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"$$ -return true;")); +return true;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStatement() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterStatement(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"return true; -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterBlock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterBlock(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"if (true) { } -$$")); +$$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterIf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterIf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"if (true) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterDo() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterDo(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"do - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterWhile() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterWhile(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"while (true) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterFor() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterFor(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"for (int i = 0; i < 10; i++) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterForeach() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestAfterForeach(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"foreach (var v in bar) - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotAfterUsing() { - await VerifyAbsenceAsync(AddInsideMethod( -@"using $$")); + await VerifyAbsenceAsync( +@"using $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -283,10 +285,10 @@ await VerifyAbsenceAsync(@"class C [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestBetweenUsings() { - await VerifyKeywordAsync(AddInsideMethod( + await VerifyKeywordAsync( @"using Goo; $$ -using Bar;")); +using Bar;"); } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/VoidKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/VoidKeywordRecommenderTests.cs index 79e7ad4e954e7..820ec66cc3016 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/VoidKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/VoidKeywordRecommenderTests.cs @@ -12,16 +12,16 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations public class VoidKeywordRecommenderTests : KeywordRecommenderTests { [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAtRoot_Interactive() + public async Task TestAtRoot() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"$$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterClass_Interactive() + public async Task TestAfterClass() { - await VerifyKeywordAsync(SourceCodeKind.Script, + await VerifyKeywordAsync( @"class C { } $$"); } @@ -71,77 +71,55 @@ await VerifyKeywordAsync( @"public delegate $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCastType() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInCastType(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"var str = (($$")); +@"var str = (($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCastType2() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInCastType2(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"var str = (($$)items) as string;")); +@"var str = (($$)items) as string;", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInTypeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInTypeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"typeof($$")); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInCompilationUnit() - => await VerifyAbsenceAsync(SourceCodeKind.Regular, @"$$"); - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterExtern() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"extern alias Goo; -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterExtern_Interactive() - { - await VerifyKeywordAsync(SourceCodeKind.Script, @"extern alias Goo; -$$"); - } - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterUsing() - { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"using Goo; -$$"); +@"typeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterUsing_Interactive() + public async Task TestAfterExtern() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"using Goo; + await VerifyKeywordAsync(@"extern alias Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterNamespace() + public async Task TestAfterUsing() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"namespace N {} + await VerifyKeywordAsync(@"using Goo; $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterTypeDeclaration() + public async Task TestAfterNamespace() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"class C {} + await VerifyKeywordAsync(@"namespace N {} $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterDelegateDeclaration() + public async Task TestAfterDelegateDeclaration() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"delegate void Goo(); + await VerifyKeywordAsync(@"delegate void Goo(); $$"); } @@ -189,23 +167,23 @@ await VerifyAbsenceAsync(SourceCodeKind.Script, } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterAssemblyAttribute() + public async Task TestAfterAssemblyAttribute() { - await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[assembly: goo] + await VerifyKeywordAsync(@"[assembly: goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAssemblyAttribute_Interactive() + public async Task TestAfterRootAttribute() { - await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] + await VerifyKeywordAsync(@"[goo] $$"); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterRootAttribute() + public async Task TestAfterMultipleRootAttributes() { - await VerifyAbsenceAsync(@"[goo] + await VerifyKeywordAsync(@"[goo][goo] $$"); } @@ -348,15 +326,11 @@ await VerifyKeywordAsync( } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterStatic() - => await VerifyAbsenceAsync(SourceCodeKind.Regular, @"static $$"); - - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStatic_Interactive() - => await VerifyKeywordAsync(SourceCodeKind.Script, @"static $$"); + public async Task TestAfterStatic() + => await VerifyKeywordAsync(@"static $$"); [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterStatic() + public async Task TestAfterStaticInClass() { await VerifyKeywordAsync( @"class C { @@ -386,11 +360,12 @@ await VerifyKeywordAsync( @"delegate $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotAfterAnonymousDelegate() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotAfterAnonymousDelegate(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"var q = delegate $$")); +@"var q = delegate $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -424,12 +399,13 @@ await VerifyKeywordAsync( new $$"); } - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInUnsafeBlock() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInUnsafeBlock(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( @"unsafe { - $$")); + $$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -567,19 +543,21 @@ unsafe int this[int i] { } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestNotInDefault() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestNotInDefault(bool topLevelStatement) { await VerifyAbsenceAsync(AddInsideMethod( -@"default($$")); +@"default($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(538804, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538804")] - [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestInSizeOf() + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [CombinatorialData] + public async Task TestInSizeOf(bool topLevelStatement) { await VerifyKeywordAsync(AddInsideMethod( -@"sizeof($$")); +@"sizeof($$", topLevelStatement: topLevelStatement), options: CSharp9ParseOptions); } [WorkItem(544347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544347")] diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/VolatileKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/VolatileKeywordRecommenderTests.cs index db11b726258d3..effbc78f50ba7 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/VolatileKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/VolatileKeywordRecommenderTests.cs @@ -169,7 +169,14 @@ await VerifyKeywordAsync(SourceCodeKind.Script, @"[assembly: goo] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestNotAfterRootAttribute() { - await VerifyAbsenceAsync(@"[goo] + await VerifyAbsenceAsync(SourceCodeKind.Regular, @"[goo] +$$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterRootAttribute_Interactive() + { + await VerifyKeywordAsync(SourceCodeKind.Script, @"[goo] $$"); } diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index 1c7ee6ad4d855..1b3bdf811b3e4 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -74,13 +74,59 @@ namespace N$$.P $$, showCompletionInArgumentLists:=showCompletionInArgumentLists) - state.SendTypeChars("us") + state.SendTypeChars("usi") state.SendTab() Await state.AssertNoCompletionSession() Assert.Contains("using", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) End Using End Function + + + + Public Async Function TestSelectUsingOverUshort(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + +$$ + , + showCompletionInArgumentLists:=showCompletionInArgumentLists) + + ' 'us' should select 'using' instead of 'ushort' (even though 'ushort' sorts higher in the list textually). + state.SendTypeChars("us") + Await state.AssertSelectedCompletionItem(displayText:="using", isHardSelected:=True) + Await state.AssertCompletionItemsContain("ushort", "") + + ' even after 'ushort' is selected, deleting the 'h' should still take us back to 'using'. + state.SendTypeChars("h") + Await state.AssertSelectedCompletionItem(displayText:="ushort", isHardSelected:=True) + state.SendBackspace() + Await state.AssertSelectedCompletionItem(displayText:="using", isHardSelected:=True) + End Using + End Function + + + + + Public Async Function TestSelectUshortOverUsingOnceInMRU(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + +$$ + , + showCompletionInArgumentLists:=showCompletionInArgumentLists) + + state.SendTypeChars("ush") + Await state.AssertCompletionItemsContain("ushort", "") + state.SendTab() + Assert.Contains("ushort", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + + state.SendDeleteWordToLeft() + + ' 'ushort' should be in the MRU now. so typing 'us' should select it instead of 'using'. + state.SendTypeChars("us") + Await state.AssertSelectedCompletionItem(displayText:="ushort", isHardSelected:=True) + End Using + End Function + Public Async Function TestDeletingWholeWordResetCompletionToTheDefaultItem(showCompletionInArgumentLists As Boolean) As Task diff --git a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb index 1f40702f77231..e69c2df5b57b3 100644 --- a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb +++ b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb @@ -58,6 +58,33 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename End Using End Function + + + Public Async Function RenameLocalVariableInTopLevelStatement(host As TestHost) As Task + Using workspace = CreateWorkspaceWithWaiter( + + + + object [|$$test|] = new object(); + var other = [|test|]; + + + , host) + + Dim session = StartSession(workspace) + + ' Type a bit in the file + Dim caretPosition = workspace.Documents.Single(Function(d) d.CursorPosition.HasValue).CursorPosition.Value + Dim textBuffer = workspace.Documents.Single().GetTextBuffer() + + textBuffer.Insert(caretPosition, "renamed") + + session.Commit() + + Await VerifyTagsAreCorrect(workspace, "renamedtest") + End Using + End Function + Public Async Function RenameLambdaDiscard(host As TestHost) As Task diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 72461877b09f6..5d2d6a1d89711 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -498,7 +498,7 @@ internal async Task VerifyCustomCommitWorkerAsync( var actualCodeAfterCommit = textBuffer.CurrentSnapshot.AsText().ToString(); var caretPosition = commit.NewPosition ?? textView.Caret.Position.BufferPosition.Position; - Assert.Equal(actualExpectedCode, actualCodeAfterCommit); + AssertEx.EqualOrDiff(actualExpectedCode, actualCodeAfterCommit); Assert.Equal(expectedCaretPosition, caretPosition); } @@ -780,6 +780,7 @@ private async Task VerifyItemWithReferenceWorkerAsync( if (expectedSymbols >= 1) { + Assert.NotNull(completionList); AssertEx.Any(completionList.Items, c => CompareItems(c.DisplayText, expectedItem)); var item = completionList.Items.First(c => CompareItems(c.DisplayText, expectedItem)); diff --git a/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs index 46c6b328811f6..dc4d571ab8cf0 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs @@ -366,6 +366,11 @@ private static SyntaxNode GetScope(VariableDeclaratorSyntax variableDeclarator) scope = parentExpressions.LastOrDefault().Parent; } + if (scope.IsKind(SyntaxKind.GlobalStatement)) + { + scope = scope.Parent; + } + return scope; } @@ -439,6 +444,12 @@ private static SyntaxNode RemoveDeclaratorFromScope(VariableDeclaratorSyntax var return newScope.ReplaceNode(labeledStatement, newLabeledStatement); } + // If the local is parented by a global statement, we need to remove the parent global statement. + if (newLocalDeclaration.IsParentKind(SyntaxKind.GlobalStatement, out GlobalStatementSyntax globalStatement)) + { + return newScope.RemoveNode(globalStatement, SyntaxRemoveOptions.KeepNoTrivia); + } + return newScope.RemoveNode(newLocalDeclaration, SyntaxRemoveOptions.KeepNoTrivia); } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs index 9fbb3aa56cff7..80f2f350d9749 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/ExtensionMethodImportCompletionProvider.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion.Providers; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; @@ -44,5 +45,18 @@ protected override ImmutableArray GetImportedNamespaces( protected override Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken) => ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken); + + protected override bool IsFinalSemicolonOfUsingOrExtern(SyntaxNode directive, SyntaxToken token) + { + if (token.IsKind(SyntaxKind.None) || token.IsMissing) + return false; + + return directive switch + { + UsingDirectiveSyntax usingDirective => usingDirective.SemicolonToken == token, + ExternAliasDirectiveSyntax externAliasDirective => externAliasDirective.SemicolonToken == token, + _ => false, + }; + } } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs index 96b9d30f0f9ae..419e23d7255bc 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ImportCompletion/TypeImportCompletionProvider.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion.Providers; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; @@ -42,5 +43,18 @@ protected override ImmutableArray GetImportedNamespaces( protected override Task CreateContextAsync(Document document, int position, CancellationToken cancellationToken) => ImportCompletionProviderHelper.CreateContextAsync(document, position, cancellationToken); + + protected override bool IsFinalSemicolonOfUsingOrExtern(SyntaxNode directive, SyntaxToken token) + { + if (token.IsKind(SyntaxKind.None) || token.IsMissing) + return false; + + return directive switch + { + UsingDirectiveSyntax usingDirective => usingDirective.SemicolonToken == token, + ExternAliasDirectiveSyntax externAliasDirective => externAliasDirective.SemicolonToken == token, + _ => false, + }; + } } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/EventKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/EventKeywordRecommender.cs index fd70e29f1a395..7176b5b398c8c 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/EventKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/EventKeywordRecommender.cs @@ -6,6 +6,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { @@ -41,7 +42,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context { var syntaxTree = context.SyntaxTree; return - context.IsGlobalStatementContext || + (context.IsGlobalStatementContext && syntaxTree.IsScript()) || syntaxTree.IsGlobalMemberDeclarationContext(position, SyntaxKindSet.AllGlobalMemberModifiers, cancellationToken) || context.IsMemberDeclarationContext(validModifiers: s_validClassModifiers, validTypeDeclarations: SyntaxKindSet.ClassInterfaceTypeDeclarations, canBePartial: false, cancellationToken: cancellationToken) || context.IsMemberDeclarationContext(validModifiers: s_validStructModifiers, validTypeDeclarations: SyntaxKindSet.StructOnlyTypeDeclarations, canBePartial: false, cancellationToken: cancellationToken) || diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ExternKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ExternKeywordRecommender.cs index 284b59ee00586..6703694059277 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ExternKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ExternKeywordRecommender.cs @@ -6,6 +6,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { @@ -51,7 +52,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context var syntaxTree = context.SyntaxTree; return IsExternAliasContext(context) || - context.IsGlobalStatementContext || + (context.IsGlobalStatementContext && syntaxTree.IsScript()) || syntaxTree.IsGlobalMemberDeclarationContext(position, s_validGlobalModifiers, cancellationToken) || context.IsMemberDeclarationContext( validModifiers: s_validModifiers, diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/PrivateKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/PrivateKeywordRecommender.cs index 4b74cdb9665e1..288d5729461d1 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/PrivateKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/PrivateKeywordRecommender.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { @@ -19,7 +20,7 @@ public PrivateKeywordRecommender() protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { return - context.IsGlobalStatementContext || + (context.IsGlobalStatementContext && context.SyntaxTree.IsScript()) || IsValidContextForAccessor(context) || IsValidContextForType(context, cancellationToken) || IsValidContextForMember(context, cancellationToken); diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VoidKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VoidKeywordRecommender.cs index 6376159a4233b..3e7dca7cd473e 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VoidKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VoidKeywordRecommender.cs @@ -48,6 +48,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context IsUnsafeCastTypeContext(context) || IsUnsafeDefaultExpressionContext(context) || context.IsFixedVariableDeclarationContext || + context.SyntaxTree.IsGlobalMemberDeclarationContext(position, SyntaxKindSet.AllGlobalMemberModifiers, cancellationToken) || context.SyntaxTree.IsLocalFunctionDeclarationContext(position, SyntaxKindSet.AllLocalFunctionModifiers, cancellationToken); } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VolatileKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VolatileKeywordRecommender.cs index aad687e23673d..c5e11dd4eb25b 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VolatileKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/VolatileKeywordRecommender.cs @@ -6,6 +6,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { @@ -29,7 +30,7 @@ public VolatileKeywordRecommender() protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { return - context.IsGlobalStatementContext || + (context.IsGlobalStatementContext && context.SyntaxTree.IsScript()) || context.SyntaxTree.IsGlobalMemberDeclarationContext(context.Position, SyntaxKindSet.AllGlobalMemberModifiers, cancellationToken) || context.IsMemberDeclarationContext( validModifiers: s_validMemberModifiers, diff --git a/src/Features/CSharp/Portable/RemoveUnusedLocalFunction/CSharpRemoveUnusedLocalFunctionCodeFixProvider.cs b/src/Features/CSharp/Portable/RemoveUnusedLocalFunction/CSharpRemoveUnusedLocalFunctionCodeFixProvider.cs index 43a7effac394f..792058c78fd29 100644 --- a/src/Features/CSharp/Portable/RemoveUnusedLocalFunction/CSharpRemoveUnusedLocalFunctionCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/RemoveUnusedLocalFunction/CSharpRemoveUnusedLocalFunctionCodeFixProvider.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -58,7 +59,7 @@ protected override Task FixAllAsync(Document document, ImmutableArray AddParameterAsync( var generator = editor.Generator; foreach (var methodDeclaration in documentLookup) { - var methodNode = syntaxRoot.FindNode(methodDeclaration.Locations[0].SourceSpan); + var methodNode = syntaxRoot.FindNode(methodDeclaration.Locations[0].SourceSpan, getInnermostNodeForTie: true); var existingParameters = generator.GetParameters(methodNode); var insertionIndex = newParameterIndex ?? existingParameters.Count; diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs index 212fac2fe923b..7541fcc84c8d9 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs @@ -28,6 +28,7 @@ internal abstract class AbstractImportCompletionProvider : LSPCompletionProvider protected abstract ImmutableArray GetImportedNamespaces(SyntaxNode location, SemanticModel semanticModel, CancellationToken cancellationToken); protected abstract bool ShouldProvideCompletion(Document document, SyntaxContext syntaxContext); protected abstract Task AddCompletionItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, HashSet namespacesInScope, bool isExpandedCompletion, CancellationToken cancellationToken); + protected abstract bool IsFinalSemicolonOfUsingOrExtern(SyntaxNode directive, SyntaxToken token); // For telemetry reporting protected abstract void LogCommit(); @@ -85,7 +86,11 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC private HashSet GetNamespacesInScope(Document document, SyntaxContext syntaxContext, CancellationToken cancellationToken) { var semanticModel = syntaxContext.SemanticModel; - var importedNamespaces = GetImportedNamespaces(syntaxContext.LeftToken.Parent!, semanticModel, cancellationToken); + + // The location is the containing node of the LeftToken, or the compilation unit itsef if LeftToken + // indicates the beginning of the document (i.e. no parent). + var location = syntaxContext.LeftToken.Parent ?? syntaxContext.SyntaxTree.GetRoot(cancellationToken); + var importedNamespaces = GetImportedNamespaces(location, semanticModel, cancellationToken); // This hashset will be used to match namespace names, so it must have the same case-sensitivity as the source language. var syntaxFacts = document.GetRequiredLanguageService(); @@ -191,12 +196,13 @@ async Task ShouldCompleteWithFullyQualifyTypeName() } } - private static async Task IsInImportsDirectiveAsync(Document document, int position, CancellationToken cancellationToken) + private async Task IsInImportsDirectiveAsync(Document document, int position, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService(); var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var leftToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives: true); - return leftToken.GetAncestor(syntaxFacts.IsUsingOrExternOrImport) != null; + return leftToken.GetAncestor(syntaxFacts.IsUsingOrExternOrImport) is { } node + && !IsFinalSemicolonOfUsingOrExtern(node, leftToken); } protected static bool IsAddingImportsSupported(Document document) diff --git a/src/Features/Core/Portable/ExtractMethod/AbstractExtractMethodService.cs b/src/Features/Core/Portable/ExtractMethod/AbstractExtractMethodService.cs index c7109609061fe..d6508d799e4fb 100644 --- a/src/Features/Core/Portable/ExtractMethod/AbstractExtractMethodService.cs +++ b/src/Features/Core/Portable/ExtractMethod/AbstractExtractMethodService.cs @@ -4,7 +4,9 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.ExtractMethod @@ -36,6 +38,15 @@ public async Task ExtractMethodAsync( return new FailedExtractMethodResult(selectionResult.Status); } + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var syntaxFacts = document.GetLanguageService(); + if (localFunction && syntaxFacts.ContainsGlobalStatement(root)) + { + // ExtractLocalFunction doesn't yet support local functions in top-level statements + // https://github.com/dotnet/roslyn/issues/44260 + return new FailedExtractMethodResult(OperationStatus.FailedWithUnknownReason); + } + cancellationToken.ThrowIfCancellationRequested(); // extract method diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb index a4b57da1c0500..8a44546cb396d 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/ExtensionMethodImportCompletionProvider.vb @@ -44,5 +44,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Protected Overrides Function GetImportedNamespaces(location As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As ImmutableArray(Of String) Return ImportCompletionProviderHelper.GetImportedNamespaces(location, semanticModel) End Function + + Protected Overrides Function IsFinalSemicolonOfUsingOrExtern(directive As SyntaxNode, token As SyntaxToken) As Boolean + Return False + End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb index 26c15b2d50561..93c03422c18ca 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImportCompletionProvider/TypeImportCompletionProvider.vb @@ -38,5 +38,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Protected Overrides Function GetImportedNamespaces(location As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As ImmutableArray(Of String) Return ImportCompletionProviderHelper.GetImportedNamespaces(location, semanticModel) End Function + + Protected Overrides Function IsFinalSemicolonOfUsingOrExtern(directive As SyntaxNode, token As SyntaxToken) As Boolean + Return False + End Function End Class End Namespace diff --git a/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs b/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs index 0f5dc59e48b6e..7ef2fa44446eb 100644 --- a/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs +++ b/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs @@ -181,7 +181,7 @@ internal static void VerifyOperationTree(this Compilation compilation, string sy SyntaxNode root = tree.GetRoot(); SemanticModel model = compilation.GetSemanticModel(tree); var declarationsBuilder = ArrayBuilder.GetInstance(); - model.ComputeDeclarationsInNode(root, getSymbol: true, builder: declarationsBuilder, cancellationToken: CancellationToken.None); + model.ComputeDeclarationsInNode(root, associatedSymbol: null, getSymbol: true, builder: declarationsBuilder, cancellationToken: CancellationToken.None); var actualTextBuilder = new StringBuilder(); foreach (DeclarationInfo declaration in declarationsBuilder.ToArrayAndFree().Where(d => d.DeclaredSymbol != null).OrderBy(d => d.DeclaredSymbol.ToTestDisplayString())) diff --git a/src/Test/Utilities/Portable/Traits/CompilerFeature.cs b/src/Test/Utilities/Portable/Traits/CompilerFeature.cs index 618e811949382..2021e0068183f 100644 --- a/src/Test/Utilities/Portable/Traits/CompilerFeature.cs +++ b/src/Test/Utilities/Portable/Traits/CompilerFeature.cs @@ -35,5 +35,6 @@ public enum CompilerFeature DefaultInterfaceImplementation, LambdaDiscardParameters, StatementAttributes, + TopLevelStatements, } } diff --git a/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb b/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb index 08459991d4437..bc7e79971d46b 100644 --- a/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb +++ b/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb @@ -166,7 +166,8 @@ using G= H.I; Await TestSnippetAddImportsAsync(originalCode, namespacesToAdd, placeSystemNamespaceFirst:=True, expectedUpdatedCode:=expectedUpdatedCode) End Function - + + Public Async Function TestAddImport_BadNamespaceGetsAdded() As Task Dim originalCode = "" Dim namespacesToAdd = {"$system"} diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs index ba9343764fd31..0fb21ad0d28e3 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs @@ -161,7 +161,7 @@ public void CtrlAltSpaceOption(bool showCompletionInArgumentLists) VisualStudio.Editor.SetUseSuggestionMode(false); - VisualStudio.Editor.SendKeys("nam"); + VisualStudio.Editor.SendKeys("names"); Assert.True(VisualStudio.Editor.IsCompletionActive()); VisualStudio.Editor.SendKeys(" Goo"); diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs index 2e7a738fb0564..380ab7ee34ac6 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs @@ -108,6 +108,12 @@ protected override TDeclarationNode AddField(TDeclarationNode protected override TDeclarationNode AddMethod(TDeclarationNode destination, IMethodSymbol method, CodeGenerationOptions options, IList availableIndices) { + // https://github.com/dotnet/roslyn/issues/44425: Add handling for top level statements + if (destination is GlobalStatementSyntax) + { + return destination; + } + CheckDeclarationNode(destination); options = options.With(options: options.Options ?? Workspace.Options); diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs index 1377236e694aa..96f7138f09045 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs @@ -1649,7 +1649,8 @@ static void Main(string[] args) } [WorkItem(542546, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542546")] - [Fact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Formatting)] public async Task FormatInvalidCode_1() { var content = @"> Roslyn.Utilities.dll! Basic"; @@ -1657,7 +1658,8 @@ public async Task FormatInvalidCode_1() } [WorkItem(542546, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542546")] - [Fact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423"), Trait(Traits.Feature, Traits.Features.Formatting)] public async Task FormatInvalidCode_2() { var content = @"> Roslyn.Utilities.dll! Line 43 + 0x5 bytes Basic"; diff --git a/src/Workspaces/CoreTest/LinkedFileDiffMerging/LinkedFileDiffMergingTests.TextMerging.cs b/src/Workspaces/CoreTest/LinkedFileDiffMerging/LinkedFileDiffMergingTests.TextMerging.cs index 6ad9abb438f51..e4deebee38b2a 100644 --- a/src/Workspaces/CoreTest/LinkedFileDiffMerging/LinkedFileDiffMergingTests.TextMerging.cs +++ b/src/Workspaces/CoreTest/LinkedFileDiffMerging/LinkedFileDiffMergingTests.TextMerging.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.UnitTests.LinkedFileDiffMerging @@ -43,8 +44,9 @@ public void TestIsolatedChangesInBothFiles() LanguageNames.CSharp); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423")] [Trait(Traits.Feature, Traits.Features.LinkedFileDiffMerging)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void TestIdenticalEditAfterIsolatedChanges() { TestLinkedFileSet( @@ -126,8 +128,9 @@ public void TestTwoConflictsOnAdjacentLines() LanguageNames.CSharp); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/44423")] [Trait(Traits.Feature, Traits.Features.LinkedFileDiffMerging)] + [WorkItem(44423, "https://github.com/dotnet/roslyn/issues/44423")] public void TestTwoConflictsOnSeparatedLines() { TestLinkedFileSet( diff --git a/src/Workspaces/CoreTestUtilities/SolutionUtilities.cs b/src/Workspaces/CoreTestUtilities/SolutionUtilities.cs index 9b5a78b41dcf9..9cf0b9b64ebb3 100644 --- a/src/Workspaces/CoreTestUtilities/SolutionUtilities.cs +++ b/src/Workspaces/CoreTestUtilities/SolutionUtilities.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.Shared.Extensions; +using Xunit; namespace Microsoft.CodeAnalysis.UnitTests { @@ -16,7 +17,12 @@ public class SolutionUtilities public static ProjectChanges GetSingleChangedProjectChanges(Solution oldSolution, Solution newSolution) { var solutionDifferences = newSolution.GetChanges(oldSolution); - var projectId = solutionDifferences.GetProjectChanges().Single().ProjectId; + var projectChanges = solutionDifferences.GetProjectChanges(); + + Assert.NotNull(projectChanges); + Assert.NotEmpty(projectChanges); + + var projectId = projectChanges.Single().ProjectId; var oldProject = oldSolution.GetRequiredProject(projectId); var newProject = newSolution.GetRequiredProject(projectId); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/StatementSyntaxExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/StatementSyntaxExtensions.cs index a4352efbe332a..e40a7baf712bb 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/StatementSyntaxExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/StatementSyntaxExtensions.cs @@ -29,10 +29,16 @@ public static StatementSyntax GetNextStatement(this StatementSyntax statement) if (statement != null) { var nextToken = statement.GetLastToken().GetNextToken(); - return nextToken.GetAncestors().FirstOrDefault(s => s.Parent == statement.Parent); + return nextToken.GetAncestors().FirstOrDefault(s => s.Parent == statement.Parent || AreInSiblingTopLevelStatements(s, statement)); } return null; + + static bool AreInSiblingTopLevelStatements(StatementSyntax one, StatementSyntax other) + { + return one.IsParentKind(SyntaxKind.GlobalStatement) && + other.IsParentKind(SyntaxKind.GlobalStatement); + } } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs index 9257590c909a5..48ffc62e37279 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs @@ -1701,7 +1701,7 @@ public SyntaxNode FindInnermostCommonExecutableBlock(IEnumerable nod => nodes.FindInnermostCommonNode(node => IsExecutableBlock(node)); public bool IsStatementContainer(SyntaxNode node) - => IsExecutableBlock(node) || node.IsEmbeddedStatementOwner(); + => IsExecutableBlock(node) || node.IsEmbeddedStatementOwner() || node.IsKind(SyntaxKind.GlobalStatement); public IReadOnlyList GetStatementContainerStatements(SyntaxNode node) => IsExecutableBlock(node) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs index d478acc0a172b..19068c7cfd8b1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs @@ -87,5 +87,6 @@ public TSyntaxKind Convert(int kind) where TSyntaxKind : struct public int VariableDeclarator => (int)SyntaxKind.VariableDeclarator; public int TypeArgumentList => (int)SyntaxKind.TypeArgumentList; + public int? GlobalStatement => (int)SyntaxKind.GlobalStatement; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs index d0d4fb999bfa6..dc3bdfb0c0167 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs @@ -372,6 +372,9 @@ public static bool IsThisExpression(this ISyntaxFacts syntaxFacts, [NotNullWhen( public static bool IsTupleExpression(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) => node?.RawKind == syntaxFacts.SyntaxKinds.TupleExpression; + public static bool ContainsGlobalStatement(this ISyntaxFacts syntaxFacts, SyntaxNode node) + => node.ChildNodes().Any(c => c.RawKind == syntaxFacts.SyntaxKinds.GlobalStatement); + #endregion #region statements diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs index 5eae938de7671..57769b66c2cf9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs @@ -39,6 +39,7 @@ internal interface ISyntaxKinds int AwaitKeyword { get; } int GlobalKeyword { get; } int IfKeyword { get; } + int? GlobalStatement { get; } #endregion diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb index ebe335d404adb..f53501d167039 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb @@ -87,5 +87,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices Public ReadOnly Property VariableDeclarator As Integer = SyntaxKind.VariableDeclarator Implements ISyntaxKinds.VariableDeclarator Public ReadOnly Property TypeArgumentList As Integer = SyntaxKind.TypeArgumentList Implements ISyntaxKinds.TypeArgumentList + Public ReadOnly Property GlobalStatement As Integer? = Nothing Implements ISyntaxKinds.GlobalStatement End Class End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs index f8e9e67c8bec9..92c96b676c0bd 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs @@ -380,7 +380,25 @@ internal bool IsAwaitStatementContext(int position, CancellationToken cancellati { var leftToken = this.SyntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); var targetToken = leftToken.GetPreviousTokenIfTouchingWord(position); - return targetToken.Kind() == SyntaxKind.AwaitKeyword && targetToken.GetPreviousToken().IsBeginningOfStatementContext(); + if (targetToken.IsKind(SyntaxKind.AwaitKeyword)) + { + var previousToken = targetToken.GetPreviousToken(); + if (previousToken.IsBeginningOfStatementContext()) + { + return true; + } + + return SyntaxTree.IsGlobalStatementContext(targetToken.SpanStart, cancellationToken); + } + else if (SyntaxTree.IsScript() + && targetToken.IsKind(SyntaxKind.IdentifierToken) + && targetToken.HasMatchingText(SyntaxKind.AwaitKeyword)) + { + // The 'await' keyword is parsed as an identifier in C# script + return SyntaxTree.IsGlobalStatementContext(targetToken.SpanStart, cancellationToken); + } + + return false; } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs index 861c0aa7ab3fa..3be1121d3075f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs @@ -78,11 +78,22 @@ public static bool IsGlobalMemberDeclarationContext( var tokenOnLeftOfPosition = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); var token = tokenOnLeftOfPosition.GetPreviousTokenIfTouchingWord(position); + var parent = token.Parent; var modifierTokens = syntaxTree.GetPrecedingModifiers(position, tokenOnLeftOfPosition); if (modifierTokens.IsEmpty()) { - return false; + if (token.IsKind(SyntaxKind.CloseBracketToken) + && parent.IsKind(SyntaxKind.AttributeList, out AttributeListSyntax attributeList) + && !IsGlobalAttributeList(attributeList)) + { + // Allow empty modifier tokens if we have an attribute list + parent = attributeList.Parent; + } + else + { + return false; + } } if (modifierTokens.IsSubsetOf(validModifiers)) @@ -90,15 +101,28 @@ public static bool IsGlobalMemberDeclarationContext( // the parent is the member // the grandparent is the container of the member // in interactive, it's possible that there might be an intervening "incomplete" member for partially - // typed declarations that parse ambiguously. For example, "internal e". - if (token.Parent.IsKind(SyntaxKind.CompilationUnit) || - (token.Parent.IsKind(SyntaxKind.IncompleteMember) && token.Parent.IsParentKind(SyntaxKind.CompilationUnit))) + // typed declarations that parse ambiguously. For example, "internal e". It's also possible for a + // complete member to be parsed based on data after the caret, e.g. "unsafe $$ void L() { }". + if (parent.IsKind(SyntaxKind.CompilationUnit) || + (parent is MemberDeclarationSyntax && parent.IsParentKind(SyntaxKind.CompilationUnit))) { return true; } } return false; + + // Local functions + static bool IsGlobalAttributeList(AttributeListSyntax attributeList) + { + if (attributeList.Target is { Identifier: { RawKind: var kind } }) + { + return kind == (int)SyntaxKind.AssemblyKeyword + || kind == (int)SyntaxKind.ModuleKeyword; + } + + return false; + } } public static bool IsMemberDeclarationContext( @@ -303,8 +327,10 @@ public static bool IsLocalFunctionDeclarationContext( var leftToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); var token = leftToken.GetPreviousTokenIfTouchingWord(position); - // Local functions are always valid in a statement context - if (syntaxTree.IsStatementContext(position, leftToken, cancellationToken)) + // Local functions are always valid in a statement context. They are also valid for top-level statements (as + // opposed to global functions which are defined in the global statement context of scripts). + if (syntaxTree.IsStatementContext(position, leftToken, cancellationToken) + || (!syntaxTree.IsScript() && syntaxTree.IsGlobalStatementContext(position, cancellationToken))) { return true; } @@ -328,7 +354,17 @@ public static bool IsLocalFunctionDeclarationContext( leftToken = syntaxTree.FindTokenOnLeftOfPosition(beforeModifiersPosition, cancellationToken); token = leftToken.GetPreviousTokenIfTouchingWord(beforeModifiersPosition); - return syntaxTree.IsStatementContext(beforeModifiersPosition, token, cancellationToken); + // If one or more attribute lists are present before the caret, check to see if those attribute lists + // were written in a local function declaration context. + while (token.IsKind(SyntaxKind.CloseBracketToken) && token.Parent.IsKind(SyntaxKind.AttributeList, out AttributeListSyntax attributeList)) + { + beforeModifiersPosition = attributeList.OpenBracketToken.SpanStart; + leftToken = syntaxTree.FindTokenOnLeftOfPosition(beforeModifiersPosition, cancellationToken); + token = leftToken.GetPreviousTokenIfTouchingWord(beforeModifiersPosition); + } + + return syntaxTree.IsStatementContext(beforeModifiersPosition, token, cancellationToken) + || (!syntaxTree.IsScript() && syntaxTree.IsGlobalStatementContext(beforeModifiersPosition, cancellationToken)); } return false; @@ -728,6 +764,7 @@ public static bool IsTypeContext( syntaxTree.IsParameterTypeContext(position, tokenOnLeftOfPosition) || syntaxTree.IsPossibleLambdaOrAnonymousMethodParameterTypeContext(position, tokenOnLeftOfPosition, cancellationToken) || syntaxTree.IsStatementContext(position, tokenOnLeftOfPosition, cancellationToken) || + syntaxTree.IsGlobalStatementContext(position, cancellationToken) || syntaxTree.IsTypeParameterConstraintContext(position, tokenOnLeftOfPosition) || syntaxTree.IsUsingAliasContext(position, cancellationToken) || syntaxTree.IsUsingStaticContext(position, cancellationToken) || @@ -1876,11 +1913,6 @@ public static bool IsStatementContext(this SyntaxTree syntaxTree, int position, public static bool IsGlobalStatementContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken) { - if (!syntaxTree.IsScript()) - { - return false; - } - #if false if (syntaxTree.IsInPreprocessorDirectiveContext(position, cancellationToken)) {