From c3ee6a325f670e8d1ce654b39c0d74f8328a1951 Mon Sep 17 00:00:00 2001 From: JohanLarsson Date: Sat, 26 Jan 2019 13:14:48 +0100 Subject: [PATCH] Tweak doc test perf. --- .paket/Paket.Restore.targets | 10 +- .../Documentation/Tests.cs | 130 ++++++++++++------ AspNetCoreAnalyzers.sln.DotSettings | 1 + 3 files changed, 97 insertions(+), 44 deletions(-) diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets index b4f593e..52f41c6 100644 --- a/.paket/Paket.Restore.targets +++ b/.paket/Paket.Restore.targets @@ -62,6 +62,9 @@ true true + + + True @@ -102,7 +105,11 @@ true - + + true @@ -183,6 +190,7 @@ runtime runtime true + true diff --git a/AspNetCoreAnalyzers.Tests/Documentation/Tests.cs b/AspNetCoreAnalyzers.Tests/Documentation/Tests.cs index 08d74c8..426b070 100644 --- a/AspNetCoreAnalyzers.Tests/Documentation/Tests.cs +++ b/AspNetCoreAnalyzers.Tests/Documentation/Tests.cs @@ -4,6 +4,7 @@ namespace AspNetCoreAnalyzers.Tests.Documentation { using System; + using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -27,24 +28,27 @@ public class Tests .ToArray(); private static readonly IReadOnlyList DescriptorInfos = Analyzers - .SelectMany(DescriptorInfo.Create) - .ToArray(); + .SelectMany(DescriptorInfo.Create) + .ToArray(); - private static IReadOnlyList DescriptorsWithDocs => DescriptorInfos.Where(d => d.DocExists).ToArray(); + private static IReadOnlyList DescriptorsWithDocs => DescriptorInfos.Where(d => d.DocumentationFile.Exists) + .ToArray(); - private static DirectoryInfo SolutionDirectory => SolutionFile.Find("AspNetCoreAnalyzers.sln").Directory; + private static DirectoryInfo SolutionDirectory => SolutionFile.Find("AspNetCoreAnalyzers.sln") + .Directory; - private static DirectoryInfo DocumentsDirectory => SolutionDirectory.EnumerateDirectories("documentation", SearchOption.TopDirectoryOnly).Single(); + private static DirectoryInfo DocumentsDirectory => SolutionDirectory.EnumerateDirectories("documentation", SearchOption.TopDirectoryOnly) + .Single(); [TestCaseSource(nameof(DescriptorInfos))] public void MissingDocs(DescriptorInfo descriptorInfo) { - if (!descriptorInfo.DocExists) + if (!descriptorInfo.DocumentationFile.Exists) { var descriptor = descriptorInfo.Descriptor; var id = descriptor.Id; DumpIfDebug(CreateStub(descriptorInfo)); - File.WriteAllText(descriptorInfo.DocFileName + ".generated", CreateStub(descriptorInfo)); + File.WriteAllText(descriptorInfo.DocumentationFile.Name + ".generated", CreateStub(descriptorInfo)); Assert.Fail($"Documentation is missing for {id}"); } } @@ -52,14 +56,17 @@ public void MissingDocs(DescriptorInfo descriptorInfo) [TestCaseSource(nameof(DescriptorsWithDocs))] public void TitleId(DescriptorInfo descriptorInfo) { - Assert.AreEqual($"# {descriptorInfo.Descriptor.Id}", File.ReadLines(descriptorInfo.DocFileName).First()); + Assert.AreEqual($"# {descriptorInfo.Descriptor.Id}", descriptorInfo.DocumentationFile.AllLines[0]); } [TestCaseSource(nameof(DescriptorsWithDocs))] public void Title(DescriptorInfo descriptorInfo) { var expected = $"## {descriptorInfo.Descriptor.Title}"; - var actual = File.ReadLines(descriptorInfo.DocFileName).Skip(1).First().Replace("`", string.Empty, StringComparison.Ordinal); + var actual = descriptorInfo.DocumentationFile.AllLines + .Skip(1) + .First() + .Replace("`", string.Empty, StringComparison.Ordinal); Assert.AreEqual(expected, actual); } @@ -71,11 +78,11 @@ public void Description(DescriptorInfo descriptorInfo) .ToString(CultureInfo.InvariantCulture) .Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries) .First(); - var actual = File.ReadLines(descriptorInfo.DocFileName) - .SkipWhile(l => !l.StartsWith("## Description", StringComparison.OrdinalIgnoreCase)) - .Skip(1) - .FirstOrDefault(l => !string.IsNullOrWhiteSpace(l)) - ?.Replace("`", string.Empty, StringComparison.Ordinal); + var actual = descriptorInfo.DocumentationFile.AllLines + .SkipWhile(l => !l.StartsWith("## Description", StringComparison.OrdinalIgnoreCase)) + .Skip(1) + .FirstOrDefault(l => !string.IsNullOrWhiteSpace(l)) + ?.Replace("`", string.Empty, StringComparison.Ordinal); DumpIfDebug(expected); DumpIfDebug(actual); @@ -87,7 +94,7 @@ public void Table(DescriptorInfo descriptorInfo) { var expected = GetTable(CreateStub(descriptorInfo)); DumpIfDebug(expected); - var actual = GetTable(File.ReadAllText(descriptorInfo.DocFileName)); + var actual = GetTable(descriptorInfo.DocumentationFile.AllText); CodeAssert.AreEqual(expected, actual); } @@ -96,14 +103,16 @@ public void ConfigSeverity(DescriptorInfo descriptorInfo) { var expected = GetConfigSeverity(CreateStub(descriptorInfo)); DumpIfDebug(expected); - var actual = GetConfigSeverity(File.ReadAllText(descriptorInfo.DocFileName)); + var actual = GetConfigSeverity(descriptorInfo.DocumentationFile.AllText); CodeAssert.AreEqual(expected, actual); } [TestCaseSource(nameof(DescriptorInfos))] public void UniqueIds(DescriptorInfo descriptorInfo) { - Assert.AreEqual(1, DescriptorInfos.Select(x => x.Descriptor).Distinct().Count(d => d.Id == descriptorInfo.Descriptor.Id)); + Assert.AreEqual(1, DescriptorInfos.Select(x => x.Descriptor) + .Distinct() + .Count(d => d.Id == descriptorInfo.Descriptor.Id)); } [Test] @@ -112,7 +121,9 @@ public void Index() var builder = new StringBuilder(); builder.AppendLine("") .AppendLine(""); - foreach (var descriptor in DescriptorsWithDocs.Select(x => x.Descriptor).Distinct().OrderBy(x => x.Id)) + foreach (var descriptor in DescriptorsWithDocs.Select(x => x.Descriptor) + .Distinct() + .OrderBy(x => x.Id)) { builder.AppendLine(" ") .AppendLine($@" ") @@ -201,7 +212,7 @@ Or put this at the top of the file to disable all instances. if (Analyzers.Count(x => x.SupportedDiagnostics.Any(d => d.Id == descriptor.Id)) == 1) { return stub.AssertReplace("", descriptorInfo.Analyzer.GetType().Name) - .AssertReplace("", descriptorInfo.CodeFileUri); + .AssertReplace("", descriptorInfo.AnalyzerFile.Uri); } var builder = StringBuilderPool.Borrow(); @@ -209,7 +220,7 @@ Or put this at the top of the file to disable all instances. { _ = builder.AppendLine(" ") .AppendLine($" \r\n".Length ? "Code" : string.Empty)}") - .AppendLine($" ") + .AppendLine($" ") .AppendLine(" "); } @@ -249,36 +260,17 @@ private DescriptorInfo(DiagnosticAnalyzer analyzer, DiagnosticDescriptor descrip { this.Analyzer = analyzer; this.Descriptor = descriptor; - this.DocFileName = Path.Combine(DocumentsDirectory.FullName, descriptor.Id + ".md"); - this.CodeFileName = Directory.EnumerateFiles( - SolutionDirectory.FullName, - analyzer.GetType().Name + ".cs", - SearchOption.AllDirectories) - .FirstOrDefault(); - this.CodeFileUri = GetCodeFileUri(analyzer); + this.DocumentationFile = new MarkdownFile(Path.Combine(DocumentsDirectory.FullName, descriptor.Id + ".md")); + this.AnalyzerFile = CodeFile.Find(analyzer.GetType()); } public DiagnosticAnalyzer Analyzer { get; } - public bool DocExists => File.Exists(this.DocFileName); - public DiagnosticDescriptor Descriptor { get; } - public string DocFileName { get; } - - public string CodeFileName { get; } + public MarkdownFile DocumentationFile { get; } - public string CodeFileUri { get; } - - public static string GetCodeFileUri(DiagnosticAnalyzer analyzer) - { - var fileName = Directory.EnumerateFiles(SolutionDirectory.FullName, analyzer.GetType().Name + ".cs", SearchOption.AllDirectories) - .FirstOrDefault(); - return fileName != null - ? "https://github.com/DotNetAnalyzers/AspNetCoreAnalyzers/blob/master" + - fileName.Substring(SolutionDirectory.FullName.Length).Replace("\\", "/", StringComparison.Ordinal) - : "missing"; - } + public CodeFile AnalyzerFile { get; } public static IEnumerable Create(DiagnosticAnalyzer analyzer) { @@ -290,5 +282,57 @@ public static IEnumerable Create(DiagnosticAnalyzer analyzer) public override string ToString() => this.Descriptor.Id; } + + public class MarkdownFile + { + public MarkdownFile(string name) + { + this.Name = name; + if (File.Exists(name)) + { + this.AllText = File.ReadAllText(name); + this.AllLines = File.ReadAllLines(name); + } + } + + public string Name { get; } + + public bool Exists => File.Exists(this.Name); + + public string AllText { get; } + + public IReadOnlyList AllLines { get; } + } + + public class CodeFile + { + private static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(); + + public CodeFile(string name) + { + this.Name = name; + } + + public string Name { get; } + + public string Uri => "https://github.com/DotNetAnalyzers/AspNetCoreAnalyzers/blob/master" + this.Name.Substring(SolutionDirectory.FullName.Length) + .Replace("\\", "/", StringComparison.Ordinal); + + public static CodeFile Find(Type type) + { + return Cache.GetOrAdd(type, x => FindCore(x.Name + ".cs")); + } + + private static CodeFile FindCore(string name) + { + var fileName = Cache.Values.Select(x => Path.GetDirectoryName(x.Name)) + .Distinct() + .SelectMany(d => Directory.EnumerateFiles(d, name, SearchOption.TopDirectoryOnly)) + .FirstOrDefault() ?? + Directory.EnumerateFiles(SolutionDirectory.FullName, name, SearchOption.AllDirectories) + .First(); + return new CodeFile(fileName); + } + } } } diff --git a/AspNetCoreAnalyzers.sln.DotSettings b/AspNetCoreAnalyzers.sln.DotSettings index a22b317..3a9f3e0 100644 --- a/AspNetCoreAnalyzers.sln.DotSettings +++ b/AspNetCoreAnalyzers.sln.DotSettings @@ -72,5 +72,6 @@ True True True + True True True \ No newline at end of file
{descriptor.Id}
{(builder.Length <= "
{analyzer.GetType().Name}{analyzer.GetType().Name}