-
Notifications
You must be signed in to change notification settings - Fork 508
/
StyleCopDiagnosticVerifier`1.cs
179 lines (155 loc) · 7.33 KB
/
StyleCopDiagnosticVerifier`1.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace StyleCop.Analyzers.Test.Verifiers
{
using System;
using System.Threading;
using System.Threading.Tasks;
using global::LightJson;
using global::LightJson.Serialization;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
using StyleCop.Analyzers.Settings.ObjectModel;
using TestHelper;
internal static class StyleCopDiagnosticVerifier<TAnalyzer>
where TAnalyzer : DiagnosticAnalyzer, new()
{
internal static DiagnosticResult[] EmptyDiagnosticResults
=> DiagnosticVerifier<TAnalyzer>.EmptyDiagnosticResults;
internal static DiagnosticResult Diagnostic(string diagnosticId = null)
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(diagnosticId);
internal static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(descriptor);
internal static DiagnosticResult CompilerError(string errorIdentifier)
=> DiagnosticVerifier<TAnalyzer>.CompilerError(errorIdentifier);
internal static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult expected, CancellationToken cancellationToken)
=> VerifyCSharpDiagnosticAsync(source, new[] { expected }, cancellationToken);
internal static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
{
var test = new CSharpTest
{
TestCode = source,
};
test.ExpectedDiagnostics.AddRange(expected);
return test.RunAsync(cancellationToken);
}
internal class CSharpTest : DiagnosticVerifier<TAnalyzer>.CSharpTest
{
private const int DefaultIndentationSize = 4;
private const int DefaultTabSize = 4;
private const bool DefaultUseTabs = false;
public CSharpTest()
{
this.OptionsTransforms.Add(options =>
options
.WithChangedOption(FormattingOptions.IndentationSize, this.Language, this.IndentationSize)
.WithChangedOption(FormattingOptions.TabSize, this.Language, this.TabSize)
.WithChangedOption(FormattingOptions.UseTabs, this.Language, this.UseTabs));
this.SolutionTransforms.Add((solution, projectId) =>
{
var settings = this.Settings;
StyleCopSettings defaultSettings = new StyleCopSettings();
if (this.IndentationSize != defaultSettings.Indentation.IndentationSize
|| this.UseTabs != defaultSettings.Indentation.UseTabs
|| this.TabSize != defaultSettings.Indentation.TabSize)
{
var indentationSettings = $@"
{{
""settings"": {{
""indentation"": {{
""indentationSize"": {this.IndentationSize},
""useTabs"": {this.UseTabs.ToString().ToLowerInvariant()},
""tabSize"": {this.TabSize}
}}
}}
}}
";
if (string.IsNullOrEmpty(settings))
{
settings = indentationSettings;
}
else
{
JsonObject indentationObject = JsonReader.Parse(indentationSettings).AsJsonObject;
JsonObject settingsObject = JsonReader.Parse(settings).AsJsonObject;
JsonObject mergedSettings = MergeJsonObjects(settingsObject, indentationObject);
using (var writer = new JsonWriter(pretty: true))
{
settings = writer.Serialize(mergedSettings);
}
}
}
if (!string.IsNullOrEmpty(settings))
{
var documentId = DocumentId.CreateNewId(projectId);
solution = solution.AddAdditionalDocument(documentId, this.SettingsFileName, settings);
}
return solution;
});
}
/// <summary>
/// Gets or sets the value of the <see cref="FormattingOptions.IndentationSize"/> to apply to the test
/// workspace.
/// </summary>
/// <value>
/// The value of the <see cref="FormattingOptions.IndentationSize"/> to apply to the test workspace.
/// </value>
public int IndentationSize { get; set; } = DefaultIndentationSize;
/// <summary>
/// Gets or sets a value indicating whether the <see cref="FormattingOptions.UseTabs"/> option is applied to the
/// test workspace.
/// </summary>
/// <value>
/// The value of the <see cref="FormattingOptions.UseTabs"/> to apply to the test workspace.
/// </value>
public bool UseTabs { get; set; } = DefaultUseTabs;
/// <summary>
/// Gets or sets the value of the <see cref="FormattingOptions.TabSize"/> to apply to the test workspace.
/// </summary>
/// <value>
/// The value of the <see cref="FormattingOptions.TabSize"/> to apply to the test workspace.
/// </value>
public int TabSize { get; set; } = DefaultTabSize;
/// <summary>
/// Gets or sets the content of the settings file to use.
/// </summary>
/// <value>
/// The content of the settings file to use.
/// </value>
public string Settings { get; set; } = null;
/// <summary>
/// Gets or sets the name of the settings file to use.
/// </summary>
/// <value>
/// The name of the settings file to use.
/// </value>
public string SettingsFileName { get; set; } = SettingsHelper.SettingsFileName;
private static JsonObject MergeJsonObjects(JsonObject priority, JsonObject fallback)
{
foreach (var pair in priority)
{
if (pair.Value.IsJsonObject)
{
switch (fallback[pair.Key].Type)
{
case JsonValueType.Null:
fallback[pair.Key] = pair.Value;
break;
case JsonValueType.Object:
fallback[pair.Key] = MergeJsonObjects(pair.Value.AsJsonObject, fallback[pair.Key].AsJsonObject);
break;
default:
throw new InvalidOperationException($"Cannot merge objects of type '{pair.Value.Type}' and '{fallback[pair.Key].Type}'.");
}
}
else
{
fallback[pair.Key] = pair.Value;
}
}
return fallback;
}
}
}
}