diff --git a/src/Workspaces/Core/Portable/IOrderableMetadata.cs b/src/Workspaces/Core/Portable/IOrderableMetadata.cs deleted file mode 100644 index 79b336468bf17dea7fef70f0716627f4e7086704..0000000000000000000000000000000000000000 --- a/src/Workspaces/Core/Portable/IOrderableMetadata.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.CodeAnalysis -{ - /// - /// This interface exists purely to enable some shared code that operates over orderable metadata. - /// This interface should not be used directly with MEF, used OrderableMetadata instead. - /// - internal interface IOrderableMetadata - { - IEnumerable After { get; } - IEnumerable Before { get; } - string Name { get; } - } -} diff --git a/src/Workspaces/Core/Portable/OrderableMetadata.cs b/src/Workspaces/Core/Portable/OrderableMetadata.cs index 0be32975b317840a58b885775b9e9546f697a7ae..ede4dcb6201e877a3c25c48adf6dbcb0671db2ac 100644 --- a/src/Workspaces/Core/Portable/OrderableMetadata.cs +++ b/src/Workspaces/Core/Portable/OrderableMetadata.cs @@ -1,37 +1,35 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.ComponentModel; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { - internal class OrderableMetadata : IOrderableMetadata + internal class OrderableMetadata { [DefaultValue(new string[] { })] - public object After { get; } + public object? After { get; } [DefaultValue(new string[] { })] - public object Before { get; } + public object? Before { get; } internal IEnumerable AfterTyped { get; set; } internal IEnumerable BeforeTyped { get; set; } - public string Name { get; } - - IEnumerable IOrderableMetadata.After => AfterTyped; - - IEnumerable IOrderableMetadata.Before => BeforeTyped; + public string? Name { get; } public OrderableMetadata(IDictionary data) { var readOnlyData = (IReadOnlyDictionary)data; this.AfterTyped = readOnlyData.GetEnumerableMetadata("After").WhereNotNull(); this.BeforeTyped = readOnlyData.GetEnumerableMetadata("Before").WhereNotNull(); - this.Name = (string)data.GetValueOrDefault("Name"); + this.Name = (string?)data.GetValueOrDefault("Name"); } - public OrderableMetadata(string name, IEnumerable after = null, IEnumerable before = null) + public OrderableMetadata(string? name, IEnumerable? after = null, IEnumerable? before = null) { this.AfterTyped = after ?? SpecializedCollections.EmptyEnumerable(); this.BeforeTyped = before ?? SpecializedCollections.EmptyEnumerable(); diff --git a/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.Graph.cs b/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.Graph.cs index bbf1d9e134a369daab013eba64e3937e7e0dc91c..9493d839fb260ec3d5697e1daa85e675387a5da9 100644 --- a/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.Graph.cs +++ b/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.Graph.cs @@ -1,21 +1,25 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Linq; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Utilities { internal partial class ExtensionOrderer { private class Graph - where TMetadata : IOrderableMetadata + where TMetadata : OrderableMetadata { public readonly Dictionary, Node> Nodes = new Dictionary, Node>(); public IEnumerable> FindExtensions(string name) { + Contract.ThrowIfNull(name); return this.Nodes.Keys.Where(k => k.Metadata.Name == name); } diff --git a/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.cs b/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.cs index 49d06851274668ed2ba506fb38e5647b289ee0b4..282738ca3d2d03aaec7a93d4c5526933cb49e5b5 100644 --- a/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.cs +++ b/src/Workspaces/Core/Portable/Shared/Utilities/ExtensionOrderer.cs @@ -1,9 +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. +#nullable enable + using System; using System.Collections.Generic; using System.Linq; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Utilities { @@ -11,7 +12,7 @@ internal static partial class ExtensionOrderer { internal static IList> Order( IEnumerable> extensions) - where TMetadata : IOrderableMetadata + where TMetadata : OrderableMetadata { var graph = GetGraph(extensions); return graph.TopologicalSort(); @@ -19,7 +20,7 @@ internal static partial class ExtensionOrderer private static Graph GetGraph( IEnumerable> extensions) - where TMetadata : IOrderableMetadata + where TMetadata : OrderableMetadata { var list = extensions.ToList(); var graph = new Graph(); @@ -32,7 +33,7 @@ internal static partial class ExtensionOrderer foreach (var extension in list) { var extensionNode = graph.Nodes[extension]; - foreach (var before in Before(extension)) + foreach (var before in extension.Metadata.BeforeTyped) { foreach (var beforeExtension in graph.FindExtensions(before)) { @@ -41,7 +42,7 @@ internal static partial class ExtensionOrderer } } - foreach (var after in After(extension)) + foreach (var after in extension.Metadata.AfterTyped) { foreach (var afterExtension in graph.FindExtensions(after)) { @@ -54,18 +55,6 @@ internal static partial class ExtensionOrderer return graph; } - private static IEnumerable Before(Lazy extension) - where TMetadata : IOrderableMetadata - { - return extension.Metadata.Before ?? SpecializedCollections.EmptyEnumerable(); - } - - private static IEnumerable After(Lazy extension) - where TMetadata : IOrderableMetadata - { - return extension.Metadata.After ?? SpecializedCollections.EmptyEnumerable(); - } - internal static class TestAccessor { /// @@ -75,7 +64,7 @@ internal static class TestAccessor /// A cycle was detected in the extension ordering. internal static void CheckForCycles( IEnumerable> extensions) - where TMetadata : IOrderableMetadata + where TMetadata : OrderableMetadata { var graph = GetGraph(extensions); graph.CheckForCycles(); diff --git a/src/Workspaces/CoreTest/ExtensionOrdererTests.cs b/src/Workspaces/CoreTest/ExtensionOrdererTests.cs index f160298e198b2b8e198552bcb2407866d8ded474..d84014f0e3ae3ecd6d5de6a2f2c5283c96fcac9b 100644 --- a/src/Workspaces/CoreTest/ExtensionOrdererTests.cs +++ b/src/Workspaces/CoreTest/ExtensionOrdererTests.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -9,24 +11,10 @@ namespace Microsoft.CodeAnalysis.UnitTests { - public class ExtensionOrdererTests : TestBase + public class ExtensionOrdererTests { private class Extension { } - private class ExtensionMetadata : IOrderableMetadata - { - public string Name { get; } - public IEnumerable Before { get; } - public IEnumerable After { get; } - - public ExtensionMetadata(string name = null, IEnumerable before = null, IEnumerable after = null) - { - this.Name = name; - this.Before = before; - this.After = after; - } - } - [Fact] public void TestNoCycle1() { @@ -36,7 +24,7 @@ public void TestNoCycle1() var d = CreateExtension(name: "d", before: new[] { "e" }); var e = CreateExtension(name: "e"); - var extensions = new List>() { d, b, a, c, e }; + var extensions = new List>() { d, b, a, c, e }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException if cycle is detected. ExtensionOrderer.TestAccessor.CheckForCycles(extensions); @@ -53,7 +41,7 @@ public void TestNoCycle2() var d = CreateExtension(name: "d", after: new[] { "e" }); var e = CreateExtension(name: "e"); - var extensions = new List>() { d, b, a, c, e }; + var extensions = new List>() { d, b, a, c, e }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException if cycle is detected. ExtensionOrderer.TestAccessor.CheckForCycles(extensions); @@ -70,7 +58,7 @@ public void TestNoCycle3() var d = CreateExtension(name: "d", before: new[] { "e" }, after: new[] { "c", "b", "a" }); var e = CreateExtension(name: "e", after: new[] { "d", "c", "b", "a" }); - var extensions = new List>() { d, b, a, c, e }; + var extensions = new List>() { d, b, a, c, e }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException if cycle is detected. ExtensionOrderer.TestAccessor.CheckForCycles(extensions); @@ -87,7 +75,7 @@ public void TestCycle1() var d = CreateExtension(name: "d", before: new[] { "e" }); var e = CreateExtension(name: "e", before: new[] { "a" }); - var extensions = new List>() { a, b, c, d, e }; + var extensions = new List>() { a, b, c, d, e }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -104,7 +92,7 @@ public void TestCycle2() var d = CreateExtension(name: "d", after: new[] { "e" }); var e = CreateExtension(name: "e", after: new[] { "a" }); - var extensions = new List>() { a, b, c, d, e }; + var extensions = new List>() { a, b, c, d, e }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -119,7 +107,7 @@ public void TestCycle3() var b = CreateExtension(name: "b", before: new[] { "a" }, after: new[] { "a" }); var c = CreateExtension(name: "c"); - var extensions = new List>() { a, b, c }; + var extensions = new List>() { a, b, c }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -134,7 +122,7 @@ public void TestCycle4() var b = CreateExtension(name: "b", before: new[] { "b" }, after: new[] { "b" }); var c = CreateExtension(name: "c"); - var extensions = new List>() { a, b, c }; + var extensions = new List>() { a, b, c }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -153,7 +141,7 @@ public void TestCycle5() var f = CreateExtension(name: "f", before: new[] { "g" }); var g = CreateExtension(name: "g"); - var extensions = new List>() { a, b, c, d, e, f, g }; + var extensions = new List>() { a, b, c, d, e, f, g }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -172,7 +160,7 @@ public void TestCycle6() var f = CreateExtension(name: "f", before: new[] { "g" }); var g = CreateExtension(name: "g"); - var extensions = new List>() { a, b, c, d, e, f, g }; + var extensions = new List>() { a, b, c, d, e, f, g }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -190,7 +178,7 @@ public void TestCycle7() var e = CreateExtension(name: "e", before: new[] { "f" }); var f = CreateExtension(name: "f", before: new[] { "d" }); - var extensions = new List>() { a, b, c, d, e, f }; + var extensions = new List>() { a, b, c, d, e, f }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -208,7 +196,7 @@ public void TestCycle8() var e = CreateExtension(name: "e", before: new[] { "f" }); var f = CreateExtension(name: "f", before: new[] { "a" }); - var extensions = new List>() { a, b, c, d, e, f }; + var extensions = new List>() { a, b, c, d, e, f }; // ExtensionOrderer.TestAccessor.CheckForCycles() will throw ArgumentException when cycle is detected. Assert.Throws(() => ExtensionOrderer.TestAccessor.CheckForCycles(extensions)); @@ -217,28 +205,23 @@ public void TestCycle8() } #region Helpers - private Lazy CreateExtension(string name = null, IEnumerable before = null, IEnumerable after = null) - { - return new Lazy(new ExtensionMetadata(name, before, after)); - } - private IEnumerable GetNames(IEnumerable> actual) + private Lazy CreateExtension(string? name = null, IEnumerable? before = null, IEnumerable? after = null) { - return actual.Select(i => i.Metadata.Name); + return new Lazy(new OrderableMetadata(name, before: before, after: after)); } - private void VerifyOrder(IEnumerable expected, IEnumerable> actual) + private IEnumerable GetNames(IEnumerable> actual) { - var expectedOrder = string.Join(string.Empty, expected); - var actualOrder = string.Join(string.Empty, GetNames(actual)); - Assert.Equal(expectedOrder, actualOrder); + return actual.Select(i => i.Metadata.Name); } - private void VerifyOrder(string expected, IEnumerable> actual) + private void VerifyOrder(string expected, IEnumerable> actual) { var actualOrder = string.Join(string.Empty, GetNames(actual)); Assert.Equal(expected, actualOrder); } + #endregion } }