Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
e54c35a
Initial support for "Simple Programs" feature. (#41706)
AlekseyTs Feb 24, 2020
63eb387
Support multi-unit Simple Programs. (#41926)
AlekseyTs Feb 28, 2020
8da805e
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_04
AlekseyTs Feb 29, 2020
c798ced
Temporarily disable tests broken by the integartion.
AlekseyTs Mar 2, 2020
0aa7a00
Merge pull request #42032 from AlekseyTs/SimplePrograms_04
AlekseyTs Mar 2, 2020
c6dbaec
Report diagnostics when top level statements are used out of order. (…
AlekseyTs Mar 3, 2020
da19941
Adjustments to the parser behavior for a Simple Program (#42147)
AlekseyTs Mar 5, 2020
fb2092e
Share nullable rewritten root between semantic models targeting diffe…
AlekseyTs Mar 6, 2020
8331ee3
Adjust enclosing binder used to to create top-level locals in a Simpl…
AlekseyTs Mar 10, 2020
7848fa7
Enable pattern matching tests in context of a Simple Program. (#42328)
AlekseyTs Mar 11, 2020
1efabcd
Support `using` local declarations in a Simple Program. (#42385)
AlekseyTs Mar 16, 2020
8436989
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_10
AlekseyTs Mar 16, 2020
207c68f
Follow-up on merge from master, strengthen code to suppress a nullabl…
AlekseyTs Mar 16, 2020
64cd5ac
Merge 'master' into SimplePrograms
AlekseyTs Mar 16, 2020
c7d7f9b
Support `await using/foreach` statements in a Simple Program. (#42485)
AlekseyTs Mar 17, 2020
d127e7c
Limit top-level statements to a single compilation unit within a prog…
AlekseyTs Mar 24, 2020
2e681ab
Support SemanticModel that ignores accessibility for top level statem…
AlekseyTs Mar 26, 2020
83c5dee
Enable analyzer actions for a Simple Program. (#43038)
AlekseyTs Apr 6, 2020
020f49d
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_15
AlekseyTs Apr 6, 2020
915c14a
Adjust test base-line with Simple Programs feature in mind and tempor…
AlekseyTs Apr 7, 2020
951b49f
Merge master into SimplePrograms
AlekseyTs Apr 7, 2020
ac5d505
Misc. changes related to Simple Programs (#43213)
AlekseyTs Apr 13, 2020
dde3cab
Finalize the story around instrumentation for top-level statements in…
AlekseyTs Apr 13, 2020
3ce85f8
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_18
AlekseyTs Apr 16, 2020
e91921c
Follow up on merge from master
AlekseyTs Apr 16, 2020
04956be
Merge master into SimplePrograms
AlekseyTs Apr 17, 2020
d1cb0b1
Support returning an integer from a Simple Program (#43451)
AlekseyTs Apr 20, 2020
2f91f7f
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_20
AlekseyTs Apr 23, 2020
f5ce72c
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_20
AlekseyTs Apr 24, 2020
0008dee
Merge master into SimplePrograms
AlekseyTs Apr 25, 2020
2412d11
Ensure a program with top level statements is an executable. (#43738)
AlekseyTs Apr 29, 2020
467d7cc
Add tests for remaining statements as top-level statements. (#43814)
AlekseyTs May 1, 2020
254e92f
Follow up on feature rename from "Simple programs" to "Top-level stat…
AlekseyTs May 7, 2020
dbdcab2
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_24
AlekseyTs May 8, 2020
fa63e84
Follow up on merge from master
AlekseyTs May 8, 2020
b9c1266
Merge pull request #44082 from AlekseyTs/SimplePrograms_24
May 8, 2020
a80a092
Provide access to command line arguments within top-level statements …
AlekseyTs May 13, 2020
585e5ba
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_27
AlekseyTs May 16, 2020
0cfc27f
Follow up on merge from master
AlekseyTs May 16, 2020
c265cd5
Merge pull request #44317 from AlekseyTs/SimplePrograms_27
May 16, 2020
9be1ef7
Misc. changes for Top-level statements (#44305)
AlekseyTs May 18, 2020
c525b54
Fix 'foreach' completion in top-level statements
sharwell May 19, 2020
8371309
Add keyword recommender tests 'async' through 'byte'
sharwell May 19, 2020
2aa4319
Fix completion of unimported types with top-level statements
sharwell May 20, 2020
31e5ccd
Add test for renaming a local variable in a top-level statement
sharwell May 20, 2020
57f8a72
Implement Inline Temporary support for top-level statements
sharwell May 20, 2020
66bbe82
Follow-up on Test Plan review for Top-level statements (#44419)
AlekseyTs May 20, 2020
a118521
Block some refactorings/fixes on top-level statements (#44410)
jcouv May 20, 2020
db52875
Move PROTOTYPE comments for "Top-level statements" to issues (#44426)
AlekseyTs May 20, 2020
0b043dd
Merge pull request #44421 from sharwell/inline-temp
sharwell May 20, 2020
5e967a6
Update Add Parameter to support global statements
sharwell May 20, 2020
366bae9
Fix 'Use Throw Expression' in top-level statements
sharwell May 20, 2020
f8850ae
Update tests for top-level statements
sharwell May 20, 2020
b167379
Merge pull request #44417 from sharwell/rename-test
sharwell May 21, 2020
5a28f74
Merge pull request #44456 from sharwell/use-throw
sharwell May 21, 2020
a17d627
Merge pull request #44445 from sharwell/add-parameter
sharwell May 21, 2020
dd7bbcb
Few more IDE scenarios for top-level statements (#44455)
jcouv May 21, 2020
731ece3
Document location node
sharwell May 26, 2020
dd96998
Replace IsTerminator with a feature-specific abstract method
sharwell May 26, 2020
068054a
Treat [module: ...] as a global attribute list
sharwell May 26, 2020
75a87bc
Merge remote-tracking branch 'dotnet/master' into SimplePrograms_31
AlekseyTs May 27, 2020
7779f1a
Follow up on merge from master
AlekseyTs May 27, 2020
772e024
Merge pull request #44402 from sharwell/completion-fixes
sharwell May 27, 2020
79c941f
Merge pull request #44585 from AlekseyTs/SimplePrograms_31
May 27, 2020
527068c
Merge remote-tracking branch 'dotnet/features/SimplePrograms'
AlekseyTs May 28, 2020
a4c0276
Adjust Roslyn.VisualStudio.IntegrationTests.CSharp.CSharpIntelliSense…
AlekseyTs May 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/features/TopLevelStatements.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,21 @@ public static void ComputeDeclarationsInSpan(
ArrayBuilder<DeclarationInfo> 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<DeclarationInfo> 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)
Expand All @@ -51,6 +52,7 @@ private static bool InvalidLevel(int? level)

private static void ComputeDeclarations(
SemanticModel model,
ISymbol associatedSymbol,
SyntaxNode node,
Func<SyntaxNode, int?, bool> shouldSkip,
bool getSymbol,
Expand All @@ -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);
Expand All @@ -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));
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ internal virtual QuickAttributeChecker QuickAttributeChecker
}
}

internal virtual Imports GetImports(ConsList<TypeSymbol> basesBeingResolved)
internal virtual Imports GetImports(ConsList<TypeSymbol>? basesBeingResolved)
{
RoslynDebug.Assert(Next is object);
return Next.GetImports(basesBeingResolved);
Expand Down
Loading