Skip to content

Commit

Permalink
Trim unnessasary leading lines when removing usings (#60672)
Browse files Browse the repository at this point in the history
  • Loading branch information
DoctorKrolic authored Apr 11, 2022
1 parent 3e091ab commit ea8b494
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1984,5 +1984,144 @@ static void Main(string[] args)
LanguageVersion = LanguageVersion.CSharp10,
}.RunAsync();
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)]
[WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")]
public async Task TestUsingGroups_DeleteLeadingBlankLinesIfFirstGroupWasDeleted_SingleUsing()
{
await new VerifyCS.Test
{
TestCode =
@"[|{|IDE0005:using System;|}
using System.Collections.Generic;|]
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
",
FixedCode =
@"using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
"
}.RunAsync();
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)]
[WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")]
public async Task TestUsingGroups_DeleteLeadingBlankLinesIfFirstGroupWasDeleted_MultipleUsings()
{
await new VerifyCS.Test
{
TestCode =
@"[|{|IDE0005:using System;
using System.Threading.Tasks;|}
using System.Collections.Generic;|]
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
",
FixedCode =
@"using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
"
}.RunAsync();
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)]
[WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")]
public async Task TestUsingGroups_NotAllFirstGroupIsDeleted()
{
await new VerifyCS.Test
{
TestCode =
@"[|{|IDE0005:using System;|}
using System.Threading.Tasks;
using System.Collections.Generic;|]
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
Task task = null;
}
}
",
FixedCode =
@"using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
Task task = null;
}
}
"
}.RunAsync();
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)]
[WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")]
public async Task TestUsingGroups_AllLastGroupIsDeleted()
{
await new VerifyCS.Test
{
TestCode =
@"[|using System.Collections.Generic;
{|IDE0005:using System;
using System.Threading.Tasks;|}|]
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
",
FixedCode =
@"using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var argList = new List<string>(args);
}
}
"
}.RunAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1214,5 +1214,108 @@ Imports System
Event E()
End Class|]")
End Function

<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)>
<WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")>
Public Async Function TestImportGroup_DeleteLeadingBlankLinesIfFirstGroupWasDeleted_SingleImport() As Task
Await TestInRegularAndScript1Async(
"[|Imports System.Threading.Tasks

Imports System|]

Class C
Function Test()
Console.WriteLine()
End Function
End Class
",
"Imports System

Class C
Function Test()
Console.WriteLine()
End Function
End Class
")
End Function

<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)>
<WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")>
Public Async Function TestImportGroup_DeleteLeadingBlankLinesIfFirstGroupWasDeleted_MultipleImports() As Task
Await TestInRegularAndScript1Async(
"[|Imports System.Threading.Tasks
Imports System.Collections.Generic

Imports System|]

Class C
Function Test()
Console.WriteLine()
End Function
End Class
",
"Imports System

Class C
Function Test()
Console.WriteLine()
End Function
End Class
")
End Function

<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)>
<WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")>
Public Async Function TestImportGroup_NotAllFirstGroupIsDeleted() As Task
Await TestInRegularAndScript1Async(
"[|Imports System.Threading.Tasks
Imports System.Collections.Generic

Imports System|]

Class C
Function Test()
Console.WriteLine()
Dim list As List(Of Integer) = Nothing
End Function
End Class
",
"Imports System.Collections.Generic

Imports System

Class C
Function Test()
Console.WriteLine()
Dim list As List(Of Integer) = Nothing
End Function
End Class
")
End Function

<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)>
<WorkItem(45866, "https://github.com/dotnet/roslyn/issues/45866")>
Public Async Function TestImportGroup_AllLastGroupIsDeleted() As Task
Await TestInRegularAndScript1Async(
"[|Imports System

Imports System.Threading.Tasks
Imports System.Collections.Generic|]

Class C
Function Test()
Console.WriteLine()
End Function
End Class
",
"Imports System

Class C
Function Test()
Console.WriteLine()
End Function
End Class
")
End Function
End Class
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
Expand Down Expand Up @@ -48,6 +47,8 @@ private static void ProcessUsings(
out SyntaxTriviaList finalTrivia)
{
var currentUsings = new List<UsingDirectiveSyntax>(usings);
var firstUsingNotBeingRemoved = true;
var passedLeadngTrivia = false;

finalTrivia = default;
for (var i = 0; i < usings.Count; i++)
Expand Down Expand Up @@ -83,13 +84,40 @@ private static void ProcessUsings(
// want to preserve.
currentUsings[nextIndex] = nextUsing.WithLeadingTrivia(leadingTrivia);
}

passedLeadngTrivia = true;
}
else
{
finalTrivia = leadingTrivia;
}
}
}
else if (firstUsingNotBeingRemoved)
{
// 1) We only apply this logic for not first using, that is saved:
// ===================
// namespace N;
//
// using System; <- if we save this using, we don't need to cut leading lines
// ===================
// 2) If leading trivia was saved from the previous using, that was removed,
// we don't bother cutting blank lines as well:
// ===================
// namespace N;
//
// using System; <- need to delete this using
// using System.Collections.Generic; <- this using is saved, no need to eat the line,
// otherwise https://github.com/dotnet/roslyn/issues/58972 will happen
if (i > 0 && !passedLeadngTrivia)
{
var currentUsing = currentUsings[i];
var currentUsingLeadingTrivia = currentUsing.GetLeadingTrivia();
currentUsings[i] = currentUsing.WithLeadingTrivia(currentUsingLeadingTrivia.WithoutLeadingBlankLines());
}

firstUsingNotBeingRemoved = false;
}
}

finalUsings = currentUsings.WhereNotNull().ToSyntaxList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports

Private Function ProcessImports(compilationUnit As CompilationUnitSyntax) As CompilationUnitSyntax
Dim oldImports = compilationUnit.Imports.ToList()
Dim firstImportNotBeingRemoved = True
Dim passedLeadingTrivia = False

Dim remainingTrivia As SyntaxTriviaList = Nothing
For i = 0 To oldImports.Count - 1
Expand All @@ -65,6 +67,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
' want to preserve.
oldImports(nextIndex) = nextImport.WithLeadingTrivia(leadingTrivia)
End If

passedLeadingTrivia = True
Else
remainingTrivia = leadingTrivia
End If
Expand All @@ -85,6 +89,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
oldImports(index) = previousImport.WithTrailingTrivia(trailingTrivia)
End If
End If
ElseIf firstImportNotBeingRemoved Then
' 1) We only apply this logic for Not first using, that is saved:
' ===================
' #Const A = 1
'
' Imports System <- if we save this import, we don't need to cut leading lines
' ===================
' 2) If leading trivia was saved from the previous import, that was removed,
' we don't bother cutting blank lines as well:
' ===================
' #Const A = 1
'
' Imports System <- need to delete this import
' Imports System.Collections.Generic <- this import is saved, no need to eat the line,
' otherwise https://github.com/dotnet/roslyn/issues/58972 will happen
If i > 0 AndAlso Not passedLeadingTrivia Then
Dim currentImport = oldImports(i)
Dim currentImportLeadingTrivia = currentImport.GetLeadingTrivia()
oldImports(i) = currentImport.WithLeadingTrivia(currentImportLeadingTrivia.WithoutLeadingWhitespaceOrEndOfLine())
End If

firstImportNotBeingRemoved = False
End If
Next

Expand Down

0 comments on commit ea8b494

Please sign in to comment.