|
' 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.
Imports System.Threading
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.VisualBasic.Formatting
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.Options
Imports Roslyn.Test.Utilities
Imports Xunit
Imports Microsoft.CodeAnalysis.[Shared].Extensions
Imports Microsoft.CodeAnalysis.OrganizeImports
Imports Microsoft.CodeAnalysis.UnitTests
Namespace Microsoft.CodeAnalysis.VisualBasic.Workspaces.UnitTests.OrganizeImports
<[UseExportProvider]>
<Trait(Traits.Feature, Traits.Features.Organizing)>
Public Class OrganizeImportsTests
Private Shared Async Function CheckAsync(initial As XElement, final As XElement,
Optional placeSystemNamespaceFirst As Boolean = False,
Optional separateImportGroups As Boolean = False,
Optional endOfLine As String = Nothing) As Task
Using workspace = New AdhocWorkspace()
Dim project = workspace.CurrentSolution.AddProject("Project", "Project.dll", LanguageNames.VisualBasic)
Dim document = project.AddDocument("Document", SourceText.From(initial.Value.ReplaceLineEndings(If(endOfLine, Environment.NewLine))))
Dim service = document.GetRequiredLanguageService(Of IOrganizeImportsService)
Dim options = New OrganizeImportsOptions() With
{
.PlaceSystemNamespaceFirst = placeSystemNamespaceFirst,
.SeparateImportDirectiveGroups = separateImportGroups,
.NewLine = If(endOfLine, OrganizeImportsOptions.Default.NewLine)
}
Dim newDocument = Await service.OrganizeImportsAsync(document, options, CancellationToken.None)
Dim newRoot = Await newDocument.GetSyntaxRootAsync()
Assert.Equal(final.Value.ReplaceLineEndings(If(endOfLine, Environment.NewLine)), newRoot.ToFullString())
End Using
End Function
Private Shared Async Function CheckWithFormatAsync(initial As XElement, final As XElement,
Optional placeSystemNamespaceFirst As Boolean = False,
Optional separateImportGroups As Boolean = False) As Task
Using workspace = New AdhocWorkspace()
Dim project = workspace.CurrentSolution.AddProject("Project", "Project.dll", LanguageNames.VisualBasic)
Dim document = project.AddDocument("Document", SourceText.From(initial.Value.NormalizeLineEndings()))
Dim formattingOptions = New VisualBasicSyntaxFormattingOptions() With
{
.SeparateImportDirectiveGroups = separateImportGroups
}
Dim organizeOptions = New OrganizeImportsOptions() With
{
.PlaceSystemNamespaceFirst = placeSystemNamespaceFirst,
.SeparateImportDirectiveGroups = separateImportGroups
}
Dim service = document.GetRequiredLanguageService(Of IOrganizeImportsService)
Dim organizedDocument = Await service.OrganizeImportsAsync(document, organizeOptions, CancellationToken.None)
Dim formattedDocument = Await Formatter.FormatAsync(organizedDocument, formattingOptions, CancellationToken.None)
Dim newRoot = Await formattedDocument.GetSyntaxRootAsync()
Assert.Equal(final.Value.NormalizeLineEndings(), newRoot.ToFullString())
End Using
End Function
<Fact>
Public Async Function TestEmptyFile() As Task
Await CheckAsync(<content></content>, <content></content>)
End Function
<Fact>
Public Async Function TestSingleImportsStatement() As Task
Dim initial = <content>Imports A</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestMultipleClauses() As Task
Dim initial = <content>Imports C, B, A</content>
Dim final = <content>Imports A, B, C</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestAliasesAtBottom() As Task
Dim initial =
<content>Imports A = B
Imports C
Imports D = E
Imports F</content>
Dim final =
<content>Imports C
Imports F
Imports A = B
Imports D = E
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestMultipleStatementsMultipleClauses() As Task
Dim initial =
<content>Imports F
Imports E
Imports D
Imports C, B, A</content>
Dim final = <content>Imports A, B, C
Imports D
Imports E
Imports F
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestSpecialCaseSystem() As Task
Dim initial =
<content>Imports M2
Imports M1
Imports System.Linq
Imports System</content>
Dim final =
<content>Imports System
Imports System.Linq
Imports M1
Imports M2
</content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=True)
End Function
<Fact>
Public Async Function TestDoNotSpecialCaseSystem() As Task
Dim initial =
<content>Imports M2
Imports M1
Imports System.Linq
Imports System</content>
Dim final =
<content>Imports M1
Imports M2
Imports System
Imports System.Linq
</content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=False)
End Function
<Fact>
Public Async Function TestMissingNames() As Task
Dim initial =
<content>Imports B
Imports
Imports A</content>
Dim final =
<content>Imports
Imports A
Imports B
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDoNotTouchCommentsAtBeginningOfFile1() As Task
Dim initial =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
' I like namespace A
Imports A
namespace A { }
namespace B { }</content>
Dim final =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
' I like namespace A
Imports A
Imports B
namespace A { }
namespace B { }</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDoNotTouchCommentsAtBeginningOfFile2() As Task
Dim initial =
<content>'' Copyright (c) Microsoft Corporation. All rights reserved. */
Imports B
'' I like namespace A */
Imports A
namespace A { }
namespace B { }</content>
Dim final =
<content>'' Copyright (c) Microsoft Corporation. All rights reserved. */
'' I like namespace A */
Imports A
Imports B
namespace A { }
namespace B { }</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDoNotTouchCommentsAtBeginningOfFile3() As Task
Dim initial =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
''' I like namespace A
Imports A
namespace A
end namespace
namespace B
end namespace</content>
Dim final =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
''' I like namespace A
Imports A
Imports B
namespace A
end namespace
namespace B
end namespace</content>
Await CheckAsync(initial, final)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33251")>
Public Async Function TestDoNotTouchCommentsAtBeginningOfFile4() As Task
Dim initial =
<content>''' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
''' I like namespace A
Imports A
namespace A
end namespace
namespace B
end namespace</content>
Dim final =
<content>''' Copyright (c) Microsoft Corporation. All rights reserved.
''' I like namespace A
Imports A
Imports B
namespace A
end namespace
namespace B
end namespace</content>
Await CheckAsync(initial, final)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2480")>
Public Async Function TestDoTouchCommentsAtBeginningOfFile1() As Task
Dim initial =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
' I like namespace A
Imports A
namespace A { }
namespace B { }</content>
Dim final =
<content>' Copyright (c) Microsoft Corporation. All rights reserved.
' I like namespace A
Imports A
Imports B
namespace A { }
namespace B { }</content>
Await CheckAsync(initial, final)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2480")>
Public Async Function TestDoTouchCommentsAtBeginningOfFile2() As Task
Dim initial =
<content>'' Copyright (c) Microsoft Corporation. All rights reserved. */
Imports B
'' I like namespace A */
Imports A
namespace A { }
namespace B { }</content>
Dim final =
<content>'' Copyright (c) Microsoft Corporation. All rights reserved. */
'' I like namespace A */
Imports A
Imports B
namespace A { }
namespace B { }</content>
Await CheckAsync(initial, final)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2480")>
Public Async Function TestDoTouchCommentsAtBeginningOfFile3() As Task
Dim initial =
<content>''' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
''' I like namespace A
Imports A
namespace A { }
namespace B { }</content>
Dim final =
<content>''' I like namespace A
Imports A
''' Copyright (c) Microsoft Corporation. All rights reserved.
Imports B
namespace A { }
namespace B { }</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDoNotSortIfEndIfBlocks() As Task
Dim initial =
<content>Imports D
#If MYCONFIG Then
Imports C
#Else
Imports B
#End If
Imports A
namespace A { }
namespace B { }
namespace C { }
namespace D { }</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDuplicateUsings() As Task
Dim initial =
<content>Imports A
Imports A</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestTrailingComments() As Task
Dim initial =
<content>Imports D '/*03*/
Imports C '/*07*/
Imports A '/*11*/
Imports B '/*15*/
</content>
Dim final =
<content>Imports A '/*11*/
Imports B '/*15*/
Imports C '/*07*/
Imports D '/*03*/
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestInsideRegionBlock() As Task
Dim initial =
<content>#region Using directives
Imports C
Imports A
Imports B
#endregion
</content>
Dim final =
<content>#region Using directives
Imports A
Imports B
Imports C
#endregion
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestNestedRegionBlock() As Task
Dim initial =
<content>Imports C
#region Z
Imports A
#endregion
Imports B</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestMultipleRegionBlocks() As Task
Dim initial =
<content>#region Using directives
Imports C
#region Z
Imports A
#endregion
Imports B
#endregion</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestInterleavedNewlines() As Task
Dim initial =
<content>Imports B
Imports A
Imports C
class D
end class</content>
Dim final =
<content>Imports A
Imports B
Imports C
class D
end class</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestInsideIfEndIfBlock() As Task
Dim initial =
<content>#if not X
Imports B
Imports A
Imports C
#end if</content>
Dim final =
<content>#if not X
Imports A
Imports B
Imports C
#end if</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestIfEndIfBlockAbove() As Task
Dim initial =
<content>#if not X
Imports C
Imports B
Imports F
#end if
Imports D
Imports A
Imports E</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestIfEndIfBlockMiddle() As Task
Dim initial =
<content>Imports D
Imports A
Imports H
#if not X
Imports C
Imports B
Imports I
#End If
Imports F
Imports E
Imports G</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestIfEndIfBlockBelow() As Task
Dim initial =
<content>Imports D
Imports A
Imports E
#if not X
Imports C
Imports B
Imports F
#end if</content>
Dim final = initial
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestKorean() As Task
Dim initial =
<content>Imports 하
Imports 파
Imports 타
Imports 카
Imports 차
Imports 자
Imports 아
Imports 사
Imports 바
Imports 마
Imports 라
Imports 다
Imports 나
Imports 가</content>
Dim final =
<content>Imports 가
Imports 나
Imports 다
Imports 라
Imports 마
Imports 바
Imports 사
Imports 아
Imports 자
Imports 차
Imports 카
Imports 타
Imports 파
Imports 하
</content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestDoNotSpecialCaseSystem1() As Task
Dim initial =
<content>Imports B
Imports System.Collections.Generic
Imports C
Imports _System
Imports SystemZ
Imports D.System
Imports System
Imports System.Collections
Imports A</content>
Dim final =
<content>Imports _System
Imports A
Imports B
Imports C
Imports D.System
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports SystemZ
</content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=False)
End Function
<Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538367")>
Public Async Function TestXml() As Task
Dim initial =
<content><![CDATA[Imports System
Imports <xmlns="http://DefaultNamespace">
Imports System.Collections.Generic
Imports <xmlns:ab="http://NewNamespace">
Imports System.Linq
Imports <xmlns:zz="http://NextNamespace">]]></content>
Dim final =
<content><![CDATA[Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports <xmlns="http://DefaultNamespace">
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestCaseSensitivity1() As Task
Dim initial =
<content>Imports Bb
Imports B
Imports bB
Imports b
Imports Aa
Imports a
Imports A
Imports aa
Imports aA
Imports AA
Imports bb
Imports BB
Imports bBb
Imports bbB
Imports あ
Imports ア
Imports ア
Imports ああ
Imports あア
Imports あア
Imports アあ
Imports cC
Imports Cc
Imports アア
Imports アア
Imports アあ
Imports アア
Imports アア
Imports BBb
Imports BbB
Imports bBB
Imports BBB
Imports c
Imports C
Imports bbb
Imports Bbb
Imports cc
Imports cC
Imports CC
</content>
Dim final As XElement
If GlobalizationUtilities.ICUMode() Then
final =
<content>Imports a
Imports A
Imports aa
Imports aA
Imports Aa
Imports AA
Imports b
Imports B
Imports bb
Imports bB
Imports Bb
Imports BB
Imports bbb
Imports bbB
Imports bBb
Imports bBB
Imports Bbb
Imports BbB
Imports BBb
Imports BBB
Imports c
Imports C
Imports cc
Imports cC
Imports cC
Imports Cc
Imports CC
Imports あ
Imports ア
Imports ああ
Imports あア
Imports アあ
Imports アア
Imports あア
Imports アア
Imports ア
Imports アあ
Imports アア
Imports アア
</content>
Else
final =
<content>Imports a
Imports A
Imports aa
Imports aA
Imports Aa
Imports AA
Imports b
Imports B
Imports bb
Imports bB
Imports Bb
Imports BB
Imports bbb
Imports bbB
Imports bBb
Imports bBB
Imports Bbb
Imports BbB
Imports BBb
Imports BBB
Imports c
Imports C
Imports cc
Imports cC
Imports cC
Imports Cc
Imports CC
Imports ア
Imports ア
Imports あ
Imports アア
Imports アア
Imports アア
Imports アア
Imports アあ
Imports アあ
Imports あア
Imports あア
Imports ああ
</content>
End If
Await CheckAsync(initial, final)
End Function
<Fact>
Public Async Function TestCaseSensitivity2() As Task
Dim initial =
<content>Imports あ
Imports ア
Imports ア
Imports ああ
Imports あア
Imports あア
Imports アあ
Imports アア
Imports アア
Imports アあ
Imports アア
Imports アア</content>
Dim final As XElement
If GlobalizationUtilities.ICUMode() Then
final =
<content>Imports あ
Imports ア
Imports ああ
Imports あア
Imports アあ
Imports アア
Imports あア
Imports アア
Imports ア
Imports アあ
Imports アア
Imports アア
</content>
Else
final =
<content>Imports ア
Imports ア
Imports あ
Imports アア
Imports アア
Imports アア
Imports アア
Imports アあ
Imports アあ
Imports あア
Imports あア
Imports ああ
</content>
End If
Await CheckAsync(initial, final)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20988")>
Public Async Function TestGrouping() As Task
Dim initial =
<content><![CDATA[' Banner
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Dim final =
<content><![CDATA[' Banner
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=True, separateImportGroups:=True)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20988")>
Public Async Function TestGrouping2() As Task
' Make sure we don't insert extra newlines if they're already there.
Dim initial =
<content><![CDATA[' Banner
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Dim final =
<content><![CDATA[' Banner
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=True, separateImportGroups:=True)
End Function
<Theory, WorkItem("https://github.com/dotnet/roslyn/issues/19306")>
<InlineData(vbLf)>
<InlineData(vbCrLf)>
Public Async Function TestGrouping3(endOfLine As String) As Task
Dim initial =
<content><![CDATA[' Banner
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Dim final =
<content><![CDATA[' Banner
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.CSharp.Extensions
Imports Microsoft.CodeAnalysis.CSharp.Syntax
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Roslyn.Utilities
Imports IntList = System.Collections.Generic.List(Of Integer)
Imports <xmlns:ab="http://NewNamespace">
Imports <xmlns="http://DefaultNamespace">
Imports <xmlns:zz="http://NextNamespace">
]]></content>
Await CheckAsync(initial, final, placeSystemNamespaceFirst:=True, separateImportGroups:=True, endOfLine:=endOfLine)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36984")>
Public Async Function TestGroupingWithFormat() As Task
Dim initial =
<content><![CDATA[Imports M
Imports System
Class Program
Console.WriteLine("Hello World!")
New Goo()
End Class
Namespace M
Class Goo
End Class
End Namespace
]]></content>
Dim final =
<content><![CDATA[Imports M
Imports System
Class Program
Console.WriteLine("Hello World!")
New Goo()
End Class
Namespace M
Class Goo
End Class
End Namespace
]]></content>
Await CheckWithFormatAsync(initial, final, placeSystemNamespaceFirst:=False, separateImportGroups:=True)
End Function
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36984")>
Public Async Function TestSortingAndGroupingWithFormat() As Task
Dim initial =
<content><![CDATA[Imports M
Imports System
Class Program
Console.WriteLine("Hello World!")
New Goo()
End Class
Namespace M
Class Goo
End Class
End Namespace
]]></content>
Dim final =
<content><![CDATA[Imports System
Imports M
Class Program
Console.WriteLine("Hello World!")
New Goo()
End Class
Namespace M
Class Goo
End Class
End Namespace
]]></content>
Await CheckWithFormatAsync(initial, final, placeSystemNamespaceFirst:=True, separateImportGroups:=True)
End Function
End Class
End Namespace
|