From 5a8875e0cd043ad9fb388417740be9a60112b123 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Thu, 23 Feb 2017 21:46:56 -0800 Subject: [PATCH 1/3] Pass per-document options when organizing imports or usings --- .../Organizing/OrganizeUsingsTests.cs | 85 ++++++++++--------- .../OrganizeDocumentCommandHandler.cs | 2 +- .../Organizing/OrganizeImportsTests.vb | 72 +++++++++------- .../CSharpOrganizeImportsService.cs | 5 +- .../IOrganizeImportsService.cs | 2 +- .../OrganizeImports/OrganizeImportsService.cs | 4 +- .../VisualBasicOrganizeImportsService.vb | 4 +- .../XamlOrganizeImportsService.cs | 7 +- 8 files changed, 102 insertions(+), 79 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs index 39e5952dd8bc2..714f1c0f7d3a9 100644 --- a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs +++ b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs @@ -3,7 +3,9 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.OrganizeImports; using Roslyn.Test.Utilities; using Xunit; @@ -12,12 +14,19 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Organizing { public class OrganizeUsingsTests { - protected async Task CheckAsync(string initial, string final, bool specialCaseSystem, CSharpParseOptions options = null) + protected async Task CheckAsync(string initial, string final, bool? placeSystemNamespaceFirst = null, CSharpParseOptions options = null) { using (var workspace = await TestWorkspace.CreateCSharpAsync(initial)) { var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); - var newRoot = await (await OrganizeImportsService.OrganizeImportsAsync(document, specialCaseSystem)).GetSyntaxRootAsync(); + if (placeSystemNamespaceFirst != null) + { + var workspaceOptions = workspace.Options; + var newOptionSet = workspaceOptions.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst.Value); + workspace.Options = newOptionSet; + } + + var newRoot = await (await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync(); Assert.Equal(final.NormalizeLineEndings(), newRoot.ToFullString()); } } @@ -25,7 +34,7 @@ protected async Task CheckAsync(string initial, string final, bool specialCaseSy [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] public async Task EmptyFile() { - await CheckAsync(string.Empty, string.Empty, true); + await CheckAsync(string.Empty, string.Empty); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -33,7 +42,7 @@ public async Task SingleUsingStatement() { var initial = @"using A;"; var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -52,7 +61,7 @@ public async Task AliasesAtBottom() using D = E; "; - await CheckAsync(initial, final, false); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -77,7 +86,7 @@ public async Task UsingStaticsBetweenUsingsAndAliases() using D = E; "; - await CheckAsync(initial, final, false); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -162,7 +171,7 @@ namespace N5 using N; } }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -180,7 +189,7 @@ public async Task SpecialCaseSystem() using M1; using M2; "; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -202,7 +211,7 @@ public async Task SpecialCaseSystemWithUsingStatic() using static System.BitConverter; using static Microsoft.Win32.Registry; "; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -221,7 +230,7 @@ public async Task DoNotSpecialCaseSystem() using System.Linq; "; - await CheckAsync(initial, final, false); + await CheckAsync(initial, final, placeSystemNamespaceFirst: false); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -242,7 +251,7 @@ public async Task DoNotSpecialCaseSystemWithUsingStatics() using System.Linq; using static Microsoft.Win32.Registry; using static System.BitConverter;"; - await CheckAsync(initial, final, false); + await CheckAsync(initial, final, placeSystemNamespaceFirst: false); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -276,7 +285,7 @@ namespace U { } namespace V.W { } namespace X.Y.Z { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -302,7 +311,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -328,7 +337,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -354,7 +363,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [WorkItem(2480, "https://github.com/dotnet/roslyn/issues/2480")] @@ -379,7 +388,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [WorkItem(2480, "https://github.com/dotnet/roslyn/issues/2480")] @@ -404,7 +413,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [WorkItem(2480, "https://github.com/dotnet/roslyn/issues/2480")] @@ -429,7 +438,7 @@ namespace B { }"; namespace A { } namespace B { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [WorkItem(2480, "https://github.com/dotnet/roslyn/issues/2480")] @@ -454,7 +463,7 @@ public async Task CommentsNotAtTheStartOfTheFile1() using System.Text; }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [WorkItem(2480, "https://github.com/dotnet/roslyn/issues/2480")] @@ -481,7 +490,7 @@ public async Task CommentsNotAtTheStartOfTheFile2() using System.Text; }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -502,7 +511,7 @@ namespace C { } namespace D { }"; var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -582,7 +591,7 @@ struct T { } } }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -594,7 +603,7 @@ public async Task DuplicateUsings() var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -614,7 +623,7 @@ public async Task InlineComments() /*00*/using/*01*/D/*02*/;/*03*/ /*16*/"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -628,7 +637,7 @@ public async Task AllOnOneLine() using B; using C; "; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -655,7 +664,7 @@ class Class1 { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -670,7 +679,7 @@ public async Task NestedRegionBlock() var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -687,7 +696,7 @@ public async Task MultipleRegionBlocks() var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -709,7 +718,7 @@ class D { }"; class D { }"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -729,7 +738,7 @@ public async Task InsideIfEndIfBlock() using C; #endif"; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -746,7 +755,7 @@ public async Task IfEndIfBlockAbove() using E;"; var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -766,7 +775,7 @@ public async Task IfEndIfBlockMiddle() using G;"; var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -783,7 +792,7 @@ public async Task IfEndIfBlockBelow() #endif"; var final = initial; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -822,7 +831,7 @@ public async Task Korean() using 하; "; - await CheckAsync(initial, final, true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -851,7 +860,7 @@ public async Task DoNotSpecialCaseSystem1() using SystemZ; "; - await CheckAsync(initial, final, specialCaseSystem: false); + await CheckAsync(initial, final, placeSystemNamespaceFirst: false); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -894,7 +903,7 @@ public async Task DoNotSpecialCaseSystem2() using Z = System.Int32; "; - await CheckAsync(initial, final, specialCaseSystem: false); + await CheckAsync(initial, final, placeSystemNamespaceFirst: false); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -987,7 +996,7 @@ public async Task CaseSensitivity1() // If Kana is sensitive あ != ア, if Kana is insensitive あ == ア. // If Width is sensitiveア != ア, if Width is insensitive ア == ア."; - await CheckAsync(initial, final, specialCaseSystem: true); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -1022,7 +1031,7 @@ public async Task CaseSensitivity2() using ああ; "; - await CheckAsync(initial, final, specialCaseSystem: true); + await CheckAsync(initial, final); } } } diff --git a/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs b/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs index 27568973b04b0..3ee9a18780fe4 100644 --- a/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs @@ -123,7 +123,7 @@ private void SortAndRemoveUnusedImports(ITextBuffer subjectBuffer, CancellationT if (document != null) { var newDocument = document.GetLanguageService().RemoveUnnecessaryImportsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); - newDocument = OrganizeImportsService.OrganizeImportsAsync(newDocument, subjectBuffer.GetFeatureOnOffOption(GenerationOptions.PlaceSystemNamespaceFirst), cancellationToken).WaitAndGetResult(cancellationToken); + newDocument = OrganizeImportsService.OrganizeImportsAsync(newDocument, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); diff --git a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb index a8bde6aa545b5..25956b81494d8 100644 --- a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb @@ -1,38 +1,44 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Xml.Linq +Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.OrganizeImports Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Organizing Public Class OrganizeImportsTests - Private Async Function CheckAsync(initial As XElement, final As XElement, specialCaseSystem As Boolean) As Threading.Tasks.Task + Private Async Function CheckAsync(initial As XElement, final As XElement, Optional placeSystemNamespaceFirst As Boolean? = Nothing) As Task Using workspace = Await TestWorkspace.CreateVisualBasicAsync(initial.NormalizedValue) Dim document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id) - Dim newRoot = Await (Await OrganizeImportsService.OrganizeImportsAsync(document, specialCaseSystem)).GetSyntaxRootAsync() - + If placeSystemNamespaceFirst IsNot Nothing Then + Dim workspaceOptions = workspace.Options + Dim newOptionSet = workspaceOptions.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst.Value) + workspace.Options = newOptionSet + End If + Dim newRoot = Await (Await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync() Assert.Equal(final.NormalizedValue, newRoot.ToFullString()) End Using End Function Public Async Function TestEmptyFile() As Task - Await CheckAsync(, , True) + Await CheckAsync(, ) End Function Public Async Function TestSingleImportsStatement() As Task Dim initial = Imports A Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function Public Async Function TestMultipleClauses() As Task Dim initial = Imports C, B, A Dim final = Imports A, B, C - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -50,7 +56,7 @@ Imports A = B Imports D = E - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -65,7 +71,7 @@ Imports D Imports E Imports F - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -82,7 +88,7 @@ Imports System.Linq Imports M1 Imports M2 - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -100,7 +106,7 @@ Imports System Imports System.Linq - Await CheckAsync(initial, final, False) + Await CheckAsync(initial, final, placeSystemNamespaceFirst:=False) End Function @@ -115,7 +121,7 @@ Imports A Imports A Imports B - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -140,7 +146,7 @@ Imports B namespace A { } namespace B { } - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -165,7 +171,7 @@ Imports B namespace A { } namespace B { } - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -194,7 +200,7 @@ end namespace namespace B end namespace - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -218,7 +224,7 @@ Imports B namespace A { } namespace B { } - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -242,7 +248,7 @@ Imports B namespace A { } namespace B { } - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -266,7 +272,7 @@ Imports B namespace A { } namespace B { } - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -286,7 +292,7 @@ namespace C { } namespace D { } Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -297,7 +303,7 @@ Imports A Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -316,7 +322,7 @@ Imports C '/*07*/ Imports D '/*03*/ - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -336,7 +342,7 @@ Imports C #endregion - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -350,7 +356,7 @@ Imports B Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -366,7 +372,7 @@ Imports B Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -389,7 +395,7 @@ Imports C class D end class - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -408,7 +414,7 @@ Imports B Imports C #end if - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -424,7 +430,7 @@ Imports A Imports E Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -443,7 +449,7 @@ Imports E Imports G Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -459,7 +465,7 @@ Imports F #end if Dim final = initial - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -497,7 +503,7 @@ Imports 파 Imports 하 - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -525,7 +531,7 @@ Imports System.Collections.Generic Imports SystemZ - Await CheckAsync(initial, final, False) + Await CheckAsync(initial, final, placeSystemNamespaceFirst:=False) End Function @@ -548,7 +554,7 @@ Imports Imports ]]> - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -640,7 +646,7 @@ Imports ああ // If Kana is sensitive あ != ア, if Kana is insensitive あ == ア. // If Width is sensitiveア != ア, if Width is insensitive ア == ア. - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function @@ -674,7 +680,7 @@ Imports あア Imports ああ - Await CheckAsync(initial, final, True) + Await CheckAsync(initial, final) End Function End Class End Namespace diff --git a/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs b/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs index 3a4c1141ab85c..dd3f152d509b1 100644 --- a/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs +++ b/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs @@ -3,6 +3,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.OrganizeImports; @@ -11,9 +12,11 @@ namespace Microsoft.CodeAnalysis.CSharp.OrganizeImports [ExportLanguageService(typeof(IOrganizeImportsService), LanguageNames.CSharp), Shared] internal partial class CSharpOrganizeImportsService : IOrganizeImportsService { - public async Task OrganizeImportsAsync(Document document, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) + public async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); var rewriter = new Rewriter(placeSystemNamespaceFirst); var newRoot = rewriter.Visit(root); diff --git a/src/Features/Core/Portable/OrganizeImports/IOrganizeImportsService.cs b/src/Features/Core/Portable/OrganizeImports/IOrganizeImportsService.cs index 1b5972bc8728f..42b988fa84095 100644 --- a/src/Features/Core/Portable/OrganizeImports/IOrganizeImportsService.cs +++ b/src/Features/Core/Portable/OrganizeImports/IOrganizeImportsService.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.OrganizeImports { internal interface IOrganizeImportsService : ILanguageService { - Task OrganizeImportsAsync(Document document, bool placeSystemNamespaceFirst, CancellationToken cancellationToken); + Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken); string SortAndRemoveUnusedImportsDisplayStringWithAccelerator { get; } } diff --git a/src/Features/Core/Portable/OrganizeImports/OrganizeImportsService.cs b/src/Features/Core/Portable/OrganizeImports/OrganizeImportsService.cs index 713301dd9cc7c..253226483b329 100644 --- a/src/Features/Core/Portable/OrganizeImports/OrganizeImportsService.cs +++ b/src/Features/Core/Portable/OrganizeImports/OrganizeImportsService.cs @@ -8,9 +8,9 @@ namespace Microsoft.CodeAnalysis.OrganizeImports { internal static partial class OrganizeImportsService { - public static Task OrganizeImportsAsync(Document document, bool placeSystemNamespaceFirst = true, CancellationToken cancellationToken = default(CancellationToken)) + public static Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken = default(CancellationToken)) { - return document.GetLanguageService().OrganizeImportsAsync(document, placeSystemNamespaceFirst, cancellationToken); + return document.GetLanguageService().OrganizeImportsAsync(document, cancellationToken); } } } diff --git a/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb b/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb index c2c646b2c4974..763578aa102e1 100644 --- a/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb +++ b/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb @@ -4,6 +4,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.OrganizeImports Imports System.Composition +Imports Microsoft.CodeAnalysis.Editing Namespace Microsoft.CodeAnalysis.VisualBasic.OrganizeImports @@ -11,9 +12,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.OrganizeImports Implements IOrganizeImportsService Public Async Function OrganizeImportsAsync(document As Document, - placeSystemNamespaceFirst As Boolean, cancellationToken As CancellationToken) As Task(Of Document) Implements IOrganizeImportsService.OrganizeImportsAsync Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) + Dim options = Await document.GetOptionsAsync(cancellationToken).ConfigureAwait(False) + Dim placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language) Dim rewriter = New Rewriter(placeSystemNamespaceFirst) Dim newRoot = rewriter.Visit(root) Return document.WithSyntaxRoot(newRoot) diff --git a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs index b78dcc7f6f137..92fa90785b967 100644 --- a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs +++ b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs @@ -3,6 +3,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.Xaml.Features.OrganizeImports; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.OrganizeImports; @@ -21,9 +22,11 @@ public XamlOrganizeImportsService(IXamlOrganizeNamespacesService organizeService _organizeService = organizeService; } - public Task OrganizeImportsAsync(Document document, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) + public async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken) { - return _organizeService.OrganizeNamespacesAsync(document, placeSystemNamespaceFirst, cancellationToken) ?? Task.FromResult(document); + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); + return await _organizeService.OrganizeNamespacesAsync(document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false) ?? document; } public string SortAndRemoveUnusedImportsDisplayStringWithAccelerator From 5cb106385ff6836d654767c4ce62430c4e60a87a Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 24 Feb 2017 12:53:22 -0800 Subject: [PATCH 2/3] small test case changes --- .../Organizing/OrganizeUsingsTests.cs | 20 ++++++++----------- .../Organizing/OrganizeImportsTests.vb | 12 +++++------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs index 714f1c0f7d3a9..9723dc28770f7 100644 --- a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs +++ b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs @@ -14,18 +14,14 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Organizing { public class OrganizeUsingsTests { - protected async Task CheckAsync(string initial, string final, bool? placeSystemNamespaceFirst = null, CSharpParseOptions options = null) + protected async Task CheckAsync(string initial, string final, bool placeSystemNamespaceFirst = false, CSharpParseOptions options = null) { using (var workspace = await TestWorkspace.CreateCSharpAsync(initial)) { var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); - if (placeSystemNamespaceFirst != null) - { - var workspaceOptions = workspace.Options; - var newOptionSet = workspaceOptions.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst.Value); - workspace.Options = newOptionSet; - } - + var workspaceOptions = workspace.Options; + var newOptionSet = workspaceOptions.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst); + workspace.Options = newOptionSet; var newRoot = await (await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync(); Assert.Equal(final.NormalizeLineEndings(), newRoot.ToFullString()); } @@ -189,7 +185,7 @@ public async Task SpecialCaseSystem() using M1; using M2; "; - await CheckAsync(initial, final); + await CheckAsync(initial, final, placeSystemNamespaceFirst: true); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -211,7 +207,7 @@ public async Task SpecialCaseSystemWithUsingStatic() using static System.BitConverter; using static Microsoft.Win32.Registry; "; - await CheckAsync(initial, final); + await CheckAsync(initial, final, placeSystemNamespaceFirst: true); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -230,7 +226,7 @@ public async Task DoNotSpecialCaseSystem() using System.Linq; "; - await CheckAsync(initial, final, placeSystemNamespaceFirst: false); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] @@ -251,7 +247,7 @@ public async Task DoNotSpecialCaseSystemWithUsingStatics() using System.Linq; using static Microsoft.Win32.Registry; using static System.BitConverter;"; - await CheckAsync(initial, final, placeSystemNamespaceFirst: false); + await CheckAsync(initial, final); } [Fact, Trait(Traits.Feature, Traits.Features.Organizing)] diff --git a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb index 25956b81494d8..f2d730eb433a8 100644 --- a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb @@ -9,14 +9,12 @@ Imports Microsoft.CodeAnalysis.OrganizeImports Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Organizing Public Class OrganizeImportsTests - Private Async Function CheckAsync(initial As XElement, final As XElement, Optional placeSystemNamespaceFirst As Boolean? = Nothing) As Task + Private Async Function CheckAsync(initial As XElement, final As XElement, Optional placeSystemNamespaceFirst As Boolean = False) As Task Using workspace = Await TestWorkspace.CreateVisualBasicAsync(initial.NormalizedValue) Dim document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id) - If placeSystemNamespaceFirst IsNot Nothing Then - Dim workspaceOptions = workspace.Options - Dim newOptionSet = workspaceOptions.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst.Value) - workspace.Options = newOptionSet - End If + Dim workspaceOptions = workspace.Options + Dim newOptionSet = workspaceOptions.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst) + workspace.Options = newOptionSet Dim newRoot = Await (Await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync() Assert.Equal(final.NormalizedValue, newRoot.ToFullString()) End Using @@ -88,7 +86,7 @@ Imports System.Linq Imports M1 Imports M2 - Await CheckAsync(initial, final) + Await CheckAsync(initial, final, placeSystemNamespaceFirst:=True) End Function From f533a9b6a5b9cac4015cfddde37b1c88ee1b1051 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 24 Feb 2017 13:58:00 -0800 Subject: [PATCH 3/3] fixing up some PR feedback from cyrus --- .../CSharpTest/Organizing/OrganizeUsingsTests.cs | 4 +--- .../Organizing/OrganizeDocumentCommandHandler.cs | 2 -- .../VisualBasicTest/Organizing/OrganizeImportsTests.vb | 4 +--- .../OrganizeImports/CSharpOrganizeImportsService.cs | 2 +- .../OrganizeImports/VisualBasicOrganizeImportsService.vb | 6 +++--- .../Features/OrganizeImports/XamlOrganizeImportsService.cs | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs index 9723dc28770f7..12d783f3e1a2f 100644 --- a/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs +++ b/src/EditorFeatures/CSharpTest/Organizing/OrganizeUsingsTests.cs @@ -19,9 +19,7 @@ protected async Task CheckAsync(string initial, string final, bool placeSystemNa using (var workspace = await TestWorkspace.CreateCSharpAsync(initial)) { var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); - var workspaceOptions = workspace.Options; - var newOptionSet = workspaceOptions.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst); - workspace.Options = newOptionSet; + workspace.Options = workspace.Options.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst); var newRoot = await (await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync(); Assert.Equal(final.NormalizeLineEndings(), newRoot.ToFullString()); } diff --git a/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs b/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs index 3ee9a18780fe4..0ec49809cea3a 100644 --- a/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/Organizing/OrganizeDocumentCommandHandler.cs @@ -3,7 +3,6 @@ using System; using System.ComponentModel.Composition; using System.Threading; -using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Shared; @@ -12,7 +11,6 @@ using Microsoft.CodeAnalysis.Organizing; using Microsoft.CodeAnalysis.RemoveUnnecessaryImports; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Shared.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Text; using Roslyn.Utilities; diff --git a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb index f2d730eb433a8..56c7f1bae8541 100644 --- a/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Organizing/OrganizeImportsTests.vb @@ -12,9 +12,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Organizing Private Async Function CheckAsync(initial As XElement, final As XElement, Optional placeSystemNamespaceFirst As Boolean = False) As Task Using workspace = Await TestWorkspace.CreateVisualBasicAsync(initial.NormalizedValue) Dim document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id) - Dim workspaceOptions = workspace.Options - Dim newOptionSet = workspaceOptions.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst) - workspace.Options = newOptionSet + workspace.Options = workspace.Options.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst) Dim newRoot = Await (Await OrganizeImportsService.OrganizeImportsAsync(document)).GetSyntaxRootAsync() Assert.Equal(final.NormalizedValue, newRoot.ToFullString()) End Using diff --git a/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs b/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs index dd3f152d509b1..2e780be9e89ef 100644 --- a/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs +++ b/src/Features/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs @@ -16,7 +16,7 @@ public async Task OrganizeImportsAsync(Document document, Cancellation { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); + var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst); var rewriter = new Rewriter(placeSystemNamespaceFirst); var newRoot = rewriter.Visit(root); diff --git a/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb b/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb index 763578aa102e1..6064935cc4844 100644 --- a/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb +++ b/src/Features/VisualBasic/Portable/OrganizeImports/VisualBasicOrganizeImportsService.vb @@ -1,10 +1,10 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports System.Composition Imports System.Threading +Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.OrganizeImports -Imports System.Composition -Imports Microsoft.CodeAnalysis.Editing Namespace Microsoft.CodeAnalysis.VisualBasic.OrganizeImports @@ -15,7 +15,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.OrganizeImports cancellationToken As CancellationToken) As Task(Of Document) Implements IOrganizeImportsService.OrganizeImportsAsync Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Dim options = Await document.GetOptionsAsync(cancellationToken).ConfigureAwait(False) - Dim placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language) + Dim placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst) Dim rewriter = New Rewriter(placeSystemNamespaceFirst) Dim newRoot = rewriter.Visit(root) Return document.WithSyntaxRoot(newRoot) diff --git a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs index 92fa90785b967..93f6f1329760a 100644 --- a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs +++ b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs @@ -25,7 +25,7 @@ public XamlOrganizeImportsService(IXamlOrganizeNamespacesService organizeService public async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken) { var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); + var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst); return await _organizeService.OrganizeNamespacesAsync(document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false) ?? document; }