Skip to content

Commit

Permalink
Tweak doc test perf.
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanLarsson committed Jan 26, 2019
1 parent e34d309 commit c3ee6a3
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 44 deletions.
10 changes: 9 additions & 1 deletion .paket/Paket.Restore.targets
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
<!-- see https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1032-fsharp-in-dotnet-sdk.md -->
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
<DisableImplicitSystemValueTupleReference>true</DisableImplicitSystemValueTupleReference>

<!-- Disable Paket restore under NCrunch build -->
<PaketRestoreDisabled Condition="'$(NCrunch)' == '1'">True</PaketRestoreDisabled>
</PropertyGroup>

<Target Name="PaketBootstrapping" Condition="Exists('$(PaketToolsPath)paket.bootstrapper.proj')">
Expand Down Expand Up @@ -102,7 +105,11 @@
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
</PropertyGroup>

<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.174.2' ">
<!--
This value should match the version in the props generated by paket
If they differ, this means we need to do a restore in order to ensure correct dependencies
-->
<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.185.3' ">
<PaketRestoreRequired>true</PaketRestoreRequired>
</PropertyGroup>

Expand Down Expand Up @@ -183,6 +190,7 @@
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' == '6' And %(PaketReferencesFileLinesInfo.CopyLocal) == 'false'">runtime</ExcludeAssets>
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' != '6' And %(PaketReferencesFileLinesInfo.AllPrivateAssets) == 'exclude'">runtime</ExcludeAssets>
<Publish Condition=" '$(PackAsTool)' == 'true' ">true</Publish>
<AllowExplicitVersion>true</AllowExplicitVersion>
</PackageReference>
</ItemGroup>

Expand Down
130 changes: 87 additions & 43 deletions AspNetCoreAnalyzers.Tests/Documentation/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace AspNetCoreAnalyzers.Tests.Documentation
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
Expand All @@ -27,39 +28,45 @@ public class Tests
.ToArray();

private static readonly IReadOnlyList<DescriptorInfo> DescriptorInfos = Analyzers
.SelectMany(DescriptorInfo.Create)
.ToArray();
.SelectMany(DescriptorInfo.Create)
.ToArray();

private static IReadOnlyList<DescriptorInfo> DescriptorsWithDocs => DescriptorInfos.Where(d => d.DocExists).ToArray();
private static IReadOnlyList<DescriptorInfo> 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}");
}
}

[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);
}

Expand All @@ -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);
Expand All @@ -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);
}

Expand All @@ -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]
Expand All @@ -112,7 +121,9 @@ public void Index()
var builder = new StringBuilder();
builder.AppendLine("<!-- start generated table -->")
.AppendLine("<table>");
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(" <tr>")
.AppendLine($@" <td><a href=""{descriptor.HelpLinkUri}"">{descriptor.Id}</a></td>")
Expand Down Expand Up @@ -201,15 +212,15 @@ 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("<TYPENAME>", descriptorInfo.Analyzer.GetType().Name)
.AssertReplace("<URL>", descriptorInfo.CodeFileUri);
.AssertReplace("<URL>", descriptorInfo.AnalyzerFile.Uri);
}

var builder = StringBuilderPool.Borrow();
foreach (var analyzer in Analyzers.Where(x => x.SupportedDiagnostics.Any(d => d.Id == descriptor.Id)))
{
_ = builder.AppendLine(" <tr>")
.AppendLine($" <td>{(builder.Length <= " <tr>\r\n".Length ? "Code" : string.Empty)}</td>")
.AppendLine($" <td><a href=\"{DescriptorInfo.GetCodeFileUri(analyzer)}\">{analyzer.GetType().Name}</a></td>")
.AppendLine($" <td><a href=\"{CodeFile.Find(analyzer.GetType()).Uri}\">{analyzer.GetType().Name}</a></td>")
.AppendLine(" </tr>");
}

Expand Down Expand Up @@ -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<DescriptorInfo> Create(DiagnosticAnalyzer analyzer)
{
Expand All @@ -290,5 +282,57 @@ public static IEnumerable<DescriptorInfo> 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<string> AllLines { get; }
}

public class CodeFile
{
private static readonly ConcurrentDictionary<Type, CodeFile> Cache = new ConcurrentDictionary<Type, CodeFile>();

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);
}
}
}
}
1 change: 1 addition & 0 deletions AspNetCoreAnalyzers.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Multicast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nameof/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=parameterless/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ruleset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Struct/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Templated/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

0 comments on commit c3ee6a3

Please sign in to comment.