Skip to content

Commit 2ab81d4

Browse files
authored
Improve where file-level directives are added (#50956)
1 parent 161caf7 commit 2ab81d4

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

src/Cli/dotnet/Commands/Run/FileBasedAppSourceEditor.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ private TextChange DetermineAddChange(CSharpDirective directive)
8686
{
8787
// Find one that has the same kind and name.
8888
// If found, we will replace it with the new directive.
89-
if (directive is CSharpDirective.Named named &&
89+
var named = directive as CSharpDirective.Named;
90+
if (named != null &&
9091
Directives.OfType<CSharpDirective.Named>().FirstOrDefault(d => NamedDirectiveComparer.Instance.Equals(d, named)) is { } toReplace)
9192
{
9293
return new TextChange(toReplace.Info.Span, newText: directive.ToString() + NewLine);
@@ -99,6 +100,14 @@ private TextChange DetermineAddChange(CSharpDirective directive)
99100
{
100101
if (existingDirective.GetType() == directive.GetType())
101102
{
103+
// Add named directives in sorted order.
104+
if (named != null &&
105+
existingDirective is CSharpDirective.Named existingNamed &&
106+
string.CompareOrdinal(existingNamed.Name, named.Name) > 0)
107+
{
108+
break;
109+
}
110+
102111
addAfter = existingDirective;
103112
}
104113
else if (addAfter != null)
@@ -120,7 +129,7 @@ private TextChange DetermineAddChange(CSharpDirective directive)
120129
var result = tokenizer.ParseNextToken();
121130
var leadingTrivia = result.Token.LeadingTrivia;
122131

123-
// If there is a comment at the top of the file, we add the directive after it
132+
// If there is a comment or #! at the top of the file, we add the directive after it
124133
// (the comment might be a license which should always stay at the top).
125134
int insertAfterIndex = -1;
126135
int trailingNewLines = 0;
@@ -161,6 +170,11 @@ private TextChange DetermineAddChange(CSharpDirective directive)
161170
}
162171
break;
163172

173+
case SyntaxKind.ShebangDirectiveTrivia:
174+
trailingNewLines = 1; // shebang trivia has one newline embedded in its structure
175+
insertAfterIndex = i;
176+
break;
177+
164178
case SyntaxKind.EndOfLineTrivia:
165179
if (insertAfterIndex >= 0)
166180
{

test/dotnet.Tests/CommandTests/Run/FileBasedAppSourceEditorTests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,45 @@ public void GroupWithoutSpace()
347347
"""));
348348
}
349349

350+
/// <summary>
351+
/// New package directive should be sorted into the correct location in the package group.
352+
/// </summary>
353+
[Fact]
354+
public void Sort()
355+
{
356+
Verify(
357+
"""
358+
#:property X=Y
359+
#:package B@C
360+
#:package X@Y
361+
#:project D
362+
#:package E
363+
364+
Console.WriteLine();
365+
""",
366+
(static editor => editor.Add(new CSharpDirective.Package(default) { Name = "Test", Version = "1.0.0" }),
367+
"""
368+
#:property X=Y
369+
#:package B@C
370+
371+
#:package X@Y
372+
#:project D
373+
#:package E
374+
375+
Console.WriteLine();
376+
"""),
377+
(static editor => editor.Remove(editor.Directives[2]),
378+
"""
379+
#:property X=Y
380+
#:package B@C
381+
#:package X@Y
382+
#:project D
383+
#:package E
384+
385+
Console.WriteLine();
386+
"""));
387+
}
388+
350389
[Fact]
351390
public void OtherDirectives()
352391
{
@@ -371,6 +410,33 @@ public void OtherDirectives()
371410
"""));
372411
}
373412

413+
/// <summary>
414+
/// Shebang directive should always stay first.
415+
/// </summary>
416+
[Fact]
417+
public void Shebang()
418+
{
419+
Verify(
420+
"""
421+
#!/test
422+
Console.WriteLine();
423+
""",
424+
(static editor => editor.Add(new CSharpDirective.Package(default) { Name = "MyPackage", Version = "1.0.0" }),
425+
"""
426+
#!/test
427+
428+
429+
430+
Console.WriteLine();
431+
"""),
432+
(static editor => editor.Remove(editor.Directives[1]),
433+
"""
434+
#!/test
435+
436+
Console.WriteLine();
437+
"""));
438+
}
439+
374440
[Fact]
375441
public void AfterTokens()
376442
{

0 commit comments

Comments
 (0)