-
Notifications
You must be signed in to change notification settings - Fork 222
/
SonarLintXmlReader.cs
123 lines (106 loc) · 5.47 KB
/
SonarLintXmlReader.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
/*
* SonarAnalyzer for .NET
* Copyright (C) 2015-2023 SonarSource SA
* mailto: contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.CodeAnalysis.Text;
namespace SonarAnalyzer.Helpers;
public class SonarLintXmlReader
{
public static readonly SonarLintXmlReader Empty = new(null);
private readonly SonarLintXml sonarLintXml;
public string[] Exclusions { get; private set; }
public string[] Inclusions { get; private set; }
public string[] GlobalExclusions { get; private set; }
public string[] TestExclusions { get; private set; }
public string[] TestInclusions { get; private set; }
public string[] GlobalTestExclusions { get; private set; }
public List<SonarLintXmlRule> ParametrizedRules { get; private set; }
private bool? ignoreHeaderCommentsCS;
private bool? ignoreHeaderCommentsVB;
public bool IgnoreHeaderComments(string language) =>
language switch
{
LanguageNames.CSharp => ignoreHeaderCommentsCS ??= ReadBoolean(ReadSettingsProperty("sonar.cs.ignoreHeaderComments")),
LanguageNames.VisualBasic => ignoreHeaderCommentsVB ??= ReadBoolean(ReadSettingsProperty("sonar.vbnet.ignoreHeaderComments")),
_ => throw new UnexpectedLanguageException(language)
};
private bool? analyzeGeneratedCodeCS;
private bool? analyzeGeneratedCodeVB;
public bool AnalyzeGeneratedCode(string language) =>
language switch
{
LanguageNames.CSharp => analyzeGeneratedCodeCS ??= ReadBoolean(ReadSettingsProperty("sonar.cs.analyzeGeneratedCode")),
LanguageNames.VisualBasic => analyzeGeneratedCodeVB ??= ReadBoolean(ReadSettingsProperty("sonar.vbnet.analyzeGeneratedCode")),
_ => throw new UnexpectedLanguageException(language)
};
public SonarLintXmlReader(SourceText sonarLintXml)
{
this.sonarLintXml = sonarLintXml == null ? SonarLintXml.Empty : ParseContent(sonarLintXml);
Exclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.exclusions"));
Inclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.inclusions"));
GlobalExclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.global.exclusions"));
TestExclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.test.exclusions"));
TestInclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.test.inclusions"));
GlobalTestExclusions = ReadCommaSeparatedArray(ReadSettingsProperty("sonar.global.test.exclusions"));
ParametrizedRules = ReadRuleParameters();
}
public bool IsFileIncluded(string filePath, bool isTestProject) =>
isTestProject
? IsFileIncluded(TestInclusions, TestExclusions, GlobalTestExclusions, filePath)
: IsFileIncluded(Inclusions, Exclusions, GlobalExclusions, filePath);
private static bool IsFileIncluded(string[] inclusions, string[] exclusions, string[] globalExclusions, string filePath) =>
IsIncluded(inclusions, filePath)
&& !IsExcluded(exclusions, filePath)
&& !IsExcluded(globalExclusions, filePath);
private static bool IsIncluded(string[] inclusions, string filePath) =>
inclusions is { Length: 0 } || inclusions.Any(x => WildcardPatternMatcher.IsMatch(x, filePath, true));
private static bool IsExcluded(string[] exclusions, string filePath) =>
exclusions.Any(x => WildcardPatternMatcher.IsMatch(x, filePath, false));
private static SonarLintXml ParseContent(SourceText sonarLintXml)
{
try
{
var serializer = new XmlSerializer(typeof(SonarLintXml));
var byteArray = Encoding.UTF8.GetBytes(sonarLintXml.ToString());
var stream = new MemoryStream(byteArray);
using var sr = new StreamReader(stream, Encoding.UTF8, false);
using var reader = XmlReader.Create(sr);
return (SonarLintXml)serializer.Deserialize(reader);
}
catch
{
return SonarLintXml.Empty;
}
}
private List<SonarLintXmlRule> ReadRuleParameters() =>
sonarLintXml is { Rules: { } rules }
? rules.Where(x => x.Parameters.Any()).ToList()
: new();
private string ReadSettingsProperty(string property) =>
sonarLintXml is { Settings: { } settings }
? settings.Where(x => x.Key.Equals(property)).Select(x => x.Value).FirstOrDefault()
: null;
private static string[] ReadCommaSeparatedArray(string str) =>
string.IsNullOrEmpty(str) ? Array.Empty<string>() : str.Split(',');
private static bool ReadBoolean(string str, bool defaultValue = false) =>
bool.TryParse(str, out var propertyValue) ? propertyValue : defaultValue;
}