This repository has been archived by the owner on Mar 22, 2023. It is now read-only.
/
RubberduckInspections.cs
109 lines (94 loc) · 4.32 KB
/
RubberduckInspections.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Linq;
using Octokit;
namespace RubberduckWeb.Models
{
public static class RubberduckInspections
{
private const string GitHubOrg = "rubberduck-vba";
private const string RepositoryName = "Rubberduck";
private const string AssetName = "Rubberduck.CodeAnalysis.xml";
public static async Task InvalidateAsync()
{
Inspections = /*await*/ RequestInspectionsAsync();
if (Inspections != null)
{
_lastInvalalidated = DateTime.UtcNow;
}
}
public static bool ShouldInvalidate => Inspections == null || DateTime.UtcNow > _lastInvalalidated.AddDays(1);
private static DateTime _lastInvalalidated;
public static IDictionary<string, InspectionInfo> Inspections { get; private set; }
private static /*async Task<*/IDictionary<string, InspectionInfo>/*>*/ RequestInspectionsAsync()
{
var client = new GitHubClient(new ProductHeaderValue("rubberduck-vba_RubberduckWEB"));
var masterTask = /*await*/ Task.Run(async () => await client.Repository.Release.GetLatest(GitHubOrg, RepositoryName));
masterTask.Wait();
if (masterTask.IsFaulted)
{
var e = masterTask.Exception;
}
var master = masterTask.Result;
var masterUrl = master.Assets.SingleOrDefault(a => a.Name == AssetName)?.BrowserDownloadUrl;
var nextTask = /*await*/ Task.Run(async () => await client.Repository.Release.GetAll(GitHubOrg, RepositoryName));
nextTask.Wait();
if (nextTask.IsFaulted)
{
var e = nextTask.Exception;
}
var next = nextTask.Result.FirstOrDefault(tag => tag.Prerelease);
var nextUrl = next?.Assets.SingleOrDefault(a => a.Name == AssetName)?.BrowserDownloadUrl;
var masterDocsTask = /*await*/ Task.Run(async () => await DownloadXmlDocAssetAsync(masterUrl, isPreRelease: false));
masterDocsTask.Wait();
if (masterDocsTask.IsFaulted)
{
var e = masterDocsTask.Exception;
}
var masterDocs = masterDocsTask.Result;
var nextDocsTask = /*await*/ Task.Run(async () => await DownloadXmlDocAssetAsync(nextUrl, isPreRelease: masterDocs.Any()));
nextDocsTask.Wait();
var nextDocs = nextDocsTask.Result;
if (nextDocsTask.IsFaulted)
{
var e = nextDocsTask.Exception;
}
return masterDocs.AsEnumerable()
.Concat(nextDocs.AsEnumerable().Where(kvp => !masterDocs.ContainsKey(kvp.Key)))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
private static async Task<IDictionary<string, InspectionInfo>> DownloadXmlDocAssetAsync(string assetUrl, bool isPreRelease)
{
if (string.IsNullOrEmpty(assetUrl))
{
return new Dictionary<string, InspectionInfo>();
}
using (var client = new HttpClient())
{
var uri = new Uri(assetUrl);
var response = await client.GetAsync(uri);
var xml = await response.Content.ReadAsStreamAsync();
var document = XDocument.Load(xml);
var result = GetInspectionDocs(document, isPreRelease).ToDictionary(info => info.InspectionName, info => info);
return result;
}
}
private static IEnumerable<InspectionInfo> GetInspectionDocs(XDocument doc, bool isPreRelease) =>
from node in doc.Descendants("member")
let name = GetInspectionNameOrDefault(node)
where !string.IsNullOrEmpty(name)
select new InspectionInfo(name, node, isPreRelease);
private static string GetInspectionNameOrDefault(XElement memberNode)
{
var name = memberNode.Attribute("name")?.Value;
if (name == null || !name.StartsWith("T:") || !name.EndsWith("Inspection"))
{
return default(string);
}
return name.Substring(name.LastIndexOf(".", StringComparison.Ordinal) + 1);
}
}
}