diff --git a/.editorconfig b/.editorconfig index 3129802f..6a35e9e3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -81,6 +81,10 @@ dotnet_code_quality.CA1062.null_check_validation_methods = ThrowIfNull|ThrowIfNu # These rules represent Dave Glick's preferences and enforce consistent code quality guidelines. [*.{cs,vb}] +dotnet_diagnostic.CA1506.severity = none +dotnet_diagnostic.CA1724.severity = none +dotnet_diagnostic.CS1591.severity = none + dotnet_diagnostic.CA1020.severity = warning dotnet_diagnostic.CA1021.severity = warning dotnet_diagnostic.CA1040.severity = warning @@ -89,7 +93,6 @@ dotnet_diagnostic.CA1062.severity = warning dotnet_diagnostic.CA1501.severity = warning dotnet_diagnostic.CA1504.severity = warning dotnet_diagnostic.CA1505.severity = warning -dotnet_diagnostic.CA1506.severity = none dotnet_diagnostic.CA1700.severity = warning dotnet_diagnostic.CA1701.severity = warning dotnet_diagnostic.CA1702.severity = warning @@ -108,34 +111,24 @@ dotnet_diagnostic.CA1719.severity = warning dotnet_diagnostic.CA1720.severity = warning dotnet_diagnostic.CA1721.severity = warning dotnet_diagnostic.CA1722.severity = warning -dotnet_diagnostic.CA1724.severity = none dotnet_diagnostic.CA1725.severity = warning dotnet_diagnostic.CA1726.severity = warning dotnet_diagnostic.CA2204.severity = warning -dotnet_diagnostic.CS1591.severity = none + dotnet_diagnostic.IDE0007.severity = none dotnet_diagnostic.IDE0007WithoutSuggestion.severity = none dotnet_diagnostic.IDE0008.severity = warning -dotnet_diagnostic.RCS1001.severity = suggestion -dotnet_diagnostic.RCS1002.severity = none -dotnet_diagnostic.RCS1003.severity = suggestion + dotnet_diagnostic.RCS1004.severity = none -dotnet_diagnostic.RCS1005.severity = silent -dotnet_diagnostic.RCS1006.severity = silent +dotnet_diagnostic.RCS1002.severity = none dotnet_diagnostic.RCS1007.severity = none -dotnet_diagnostic.RCS1008.severity = warning -dotnet_diagnostic.RCS1009.severity = warning +dotnet_diagnostic.RCS1008.severity = none # Use explicit instead of 'var' dotnet_diagnostic.RCS1010.severity = none -dotnet_diagnostic.RCS1012.severity = warning dotnet_diagnostic.RCS1013.severity = none dotnet_diagnostic.RCS1014.severity = none -dotnet_diagnostic.RCS1015.severity = suggestion dotnet_diagnostic.RCS1016.severity = none dotnet_diagnostic.RCS1017.severity = none -dotnet_diagnostic.RCS1018.severity = suggestion dotnet_diagnostic.RCS1019.severity = none -dotnet_diagnostic.RCS1020.severity = suggestion -dotnet_diagnostic.RCS1021.severity = suggestion dotnet_diagnostic.RCS1022.severity = none dotnet_diagnostic.RCS1023.severity = none dotnet_diagnostic.RCS1024.severity = none @@ -143,80 +136,139 @@ dotnet_diagnostic.RCS1025.severity = none dotnet_diagnostic.RCS1026.severity = none dotnet_diagnostic.RCS1027.severity = none dotnet_diagnostic.RCS1028.severity = none -dotnet_diagnostic.RCS1029.severity = suggestion dotnet_diagnostic.RCS1030.severity = none -dotnet_diagnostic.RCS1031.severity = suggestion -dotnet_diagnostic.RCS1032.severity = suggestion -dotnet_diagnostic.RCS1033.severity = suggestion -dotnet_diagnostic.RCS1034.severity = silent dotnet_diagnostic.RCS1035.severity = none -dotnet_diagnostic.RCS1036.severity = suggestion -dotnet_diagnostic.RCS1037.severity = suggestion -dotnet_diagnostic.RCS1038.severity = suggestion -dotnet_diagnostic.RCS1039.severity = silent -dotnet_diagnostic.RCS1040.severity = silent -dotnet_diagnostic.RCS1041.severity = suggestion -dotnet_diagnostic.RCS1042.severity = silent -dotnet_diagnostic.RCS1043.severity = silent -dotnet_diagnostic.RCS1044.severity = warning dotnet_diagnostic.RCS1045.severity = none dotnet_diagnostic.RCS1046.severity = none -dotnet_diagnostic.RCS1047.severity = suggestion -dotnet_diagnostic.RCS1048.severity = suggestion -dotnet_diagnostic.RCS1049.severity = suggestion dotnet_diagnostic.RCS1050.severity = none dotnet_diagnostic.RCS1051.severity = none dotnet_diagnostic.RCS1052.severity = none dotnet_diagnostic.RCS1053.severity = none -dotnet_diagnostic.RCS1054.severity = silent -dotnet_diagnostic.RCS1055.severity = silent dotnet_diagnostic.RCS1056.severity = none -dotnet_diagnostic.RCS1057.severity = suggestion -dotnet_diagnostic.RCS1058.severity = suggestion -dotnet_diagnostic.RCS1059.severity = warning dotnet_diagnostic.RCS1060.severity = none -dotnet_diagnostic.RCS1061.severity = silent -dotnet_diagnostic.RCS1062.severity = silent -dotnet_diagnostic.RCS1063.severity = suggestion dotnet_diagnostic.RCS1064.severity = none dotnet_diagnostic.RCS1065.severity = none -dotnet_diagnostic.RCS1066.severity = silent dotnet_diagnostic.RCS1067.severity = none -dotnet_diagnostic.RCS1068.severity = suggestion +dotnet_diagnostic.RCS1075.severity = none +dotnet_diagnostic.RCS1078.severity = none +dotnet_diagnostic.RCS1079.severity = none +dotnet_diagnostic.RCS1081.severity = none +dotnet_diagnostic.RCS1086.severity = none +dotnet_diagnostic.RCS1087.severity = none +dotnet_diagnostic.RCS1088.severity = none +dotnet_diagnostic.RCS1092.severity = none +dotnet_diagnostic.RCS1094.severity = none +dotnet_diagnostic.RCS1100.severity = none +dotnet_diagnostic.RCS1101.severity = none +dotnet_diagnostic.RCS1102.severity = none +dotnet_diagnostic.RCS1111.severity = none +dotnet_diagnostic.RCS1122.severity = none +dotnet_diagnostic.RCS1126.severity = none +dotnet_diagnostic.RCS1139.severity = none +dotnet_diagnostic.RCS1153.severity = none +dotnet_diagnostic.RCS1162.severity = none +dotnet_diagnostic.RCS1168.severity = none +dotnet_diagnostic.RCS1174.severity = none +dotnet_diagnostic.RCS1176.severity = none +dotnet_diagnostic.RCS1177.severity = none +dotnet_diagnostic.RCS1184.severity = none +dotnet_diagnostic.RCS1185.severity = none +dotnet_diagnostic.RCS1194.severity = none +dotnet_diagnostic.RCS1198.severity = none +dotnet_diagnostic.RCS1208.severity = none +dotnet_diagnostic.RCS1219.severity = none +dotnet_diagnostic.RCS1223.severity = none + +dotnet_diagnostic.RCS1005.severity = silent +dotnet_diagnostic.RCS1006.severity = silent +dotnet_diagnostic.RCS1039.severity = silent +dotnet_diagnostic.RCS1040.severity = silent +dotnet_diagnostic.RCS1042.severity = silent +dotnet_diagnostic.RCS1043.severity = silent +dotnet_diagnostic.RCS1034.severity = silent +dotnet_diagnostic.RCS1054.severity = silent +dotnet_diagnostic.RCS1055.severity = silent +dotnet_diagnostic.RCS1061.severity = silent +dotnet_diagnostic.RCS1062.severity = silent +dotnet_diagnostic.RCS1066.severity = silent dotnet_diagnostic.RCS1069.severity = silent dotnet_diagnostic.RCS1070.severity = silent dotnet_diagnostic.RCS1071.severity = silent -dotnet_diagnostic.RCS1072.severity = suggestion -dotnet_diagnostic.RCS1073.severity = suggestion dotnet_diagnostic.RCS1074.severity = silent -dotnet_diagnostic.RCS1075.severity = none dotnet_diagnostic.RCS1076.severity = silent +dotnet_diagnostic.RCS1091.severity = silent +dotnet_diagnostic.RCS1115.severity = silent +dotnet_diagnostic.RCS1116.severity = silent +dotnet_diagnostic.RCS1117.severity = silent +dotnet_diagnostic.RCS1124.severity = silent +dotnet_diagnostic.RCS1125.severity = silent +dotnet_diagnostic.RCS1129.severity = silent +dotnet_diagnostic.RCS1131.severity = silent +dotnet_diagnostic.RCS1133.severity = silent +dotnet_diagnostic.RCS1134.severity = silent +dotnet_diagnostic.RCS1136.severity = silent +dotnet_diagnostic.RCS1137.severity = silent +dotnet_diagnostic.RCS1140.severity = silent +dotnet_diagnostic.RCS1141.severity = silent +dotnet_diagnostic.RCS1142.severity = silent +dotnet_diagnostic.RCS1143.severity = silent +dotnet_diagnostic.RCS1144.severity = silent +dotnet_diagnostic.RCS1145.severity = silent +dotnet_diagnostic.RCS1147.severity = silent +dotnet_diagnostic.RCS1148.severity = silent +dotnet_diagnostic.RCS1149.severity = silent +dotnet_diagnostic.RCS1151.severity = silent +dotnet_diagnostic.RCS1152.severity = silent +dotnet_diagnostic.RCS1161.severity = silent +dotnet_diagnostic.RCS1165.severity = silent +dotnet_diagnostic.RCS1167.severity = silent +dotnet_diagnostic.RCS1181.severity = silent +dotnet_diagnostic.RCS1182.severity = silent +dotnet_diagnostic.RCS1183.severity = silent +dotnet_diagnostic.RCS1186.severity = silent +dotnet_diagnostic.RCS1188.severity = silent +dotnet_diagnostic.RCS1189.severity = silent +dotnet_diagnostic.RCS1201.severity = silent +dotnet_diagnostic.RCS1207.severity = silent +dotnet_diagnostic.RCS1211.severity = silent +dotnet_diagnostic.RCS1217.severity = silent +dotnet_diagnostic.RCS1228.severity = silent + +dotnet_diagnostic.RCS1001.severity = suggestion +dotnet_diagnostic.RCS1003.severity = suggestion +dotnet_diagnostic.RCS1015.severity = suggestion +dotnet_diagnostic.RCS1018.severity = suggestion +dotnet_diagnostic.RCS1020.severity = suggestion +dotnet_diagnostic.RCS1021.severity = suggestion +dotnet_diagnostic.RCS1029.severity = suggestion +dotnet_diagnostic.RCS1031.severity = suggestion +dotnet_diagnostic.RCS1032.severity = suggestion +dotnet_diagnostic.RCS1033.severity = suggestion +dotnet_diagnostic.RCS1036.severity = suggestion +dotnet_diagnostic.RCS1037.severity = suggestion +dotnet_diagnostic.RCS1038.severity = suggestion +dotnet_diagnostic.RCS1041.severity = suggestion +dotnet_diagnostic.RCS1047.severity = suggestion +dotnet_diagnostic.RCS1048.severity = suggestion +dotnet_diagnostic.RCS1049.severity = suggestion +dotnet_diagnostic.RCS1057.severity = suggestion +dotnet_diagnostic.RCS1058.severity = suggestion +dotnet_diagnostic.RCS1063.severity = suggestion +dotnet_diagnostic.RCS1068.severity = suggestion +dotnet_diagnostic.RCS1072.severity = suggestion +dotnet_diagnostic.RCS1073.severity = suggestion dotnet_diagnostic.RCS1077.severity = suggestion -dotnet_diagnostic.RCS1078.severity = none -dotnet_diagnostic.RCS1079.severity = none dotnet_diagnostic.RCS1080.severity = suggestion -dotnet_diagnostic.RCS1081.severity = none -dotnet_diagnostic.RCS1082.severity = warning -dotnet_diagnostic.RCS1083.severity = warning dotnet_diagnostic.RCS1084.severity = suggestion dotnet_diagnostic.RCS1085.severity = suggestion -dotnet_diagnostic.RCS1086.severity = none -dotnet_diagnostic.RCS1087.severity = none -dotnet_diagnostic.RCS1088.severity = none dotnet_diagnostic.RCS1089.severity = suggestion dotnet_diagnostic.RCS1090.severity = suggestion -dotnet_diagnostic.RCS1091.severity = silent -dotnet_diagnostic.RCS1092.severity = none dotnet_diagnostic.RCS1093.severity = suggestion -dotnet_diagnostic.RCS1094.severity = none dotnet_diagnostic.RCS1095.severity = suggestion dotnet_diagnostic.RCS1096.severity = suggestion dotnet_diagnostic.RCS1097.severity = suggestion dotnet_diagnostic.RCS1098.severity = suggestion dotnet_diagnostic.RCS1099.severity = suggestion -dotnet_diagnostic.RCS1100.severity = none -dotnet_diagnostic.RCS1101.severity = none -dotnet_diagnostic.RCS1102.severity = none dotnet_diagnostic.RCS1103.severity = suggestion dotnet_diagnostic.RCS1104.severity = suggestion dotnet_diagnostic.RCS1105.severity = suggestion @@ -225,127 +277,88 @@ dotnet_diagnostic.RCS1107.severity = suggestion dotnet_diagnostic.RCS1108.severity = suggestion dotnet_diagnostic.RCS1109.severity = suggestion dotnet_diagnostic.RCS1110.severity = suggestion -dotnet_diagnostic.RCS1111.severity = none dotnet_diagnostic.RCS1112.severity = suggestion dotnet_diagnostic.RCS1113.severity = suggestion dotnet_diagnostic.RCS1114.severity = suggestion -dotnet_diagnostic.RCS1115.severity = silent -dotnet_diagnostic.RCS1116.severity = silent -dotnet_diagnostic.RCS1117.severity = silent dotnet_diagnostic.RCS1118.severity = suggestion dotnet_diagnostic.RCS1119.severity = suggestion dotnet_diagnostic.RCS1120.severity = suggestion dotnet_diagnostic.RCS1121.severity = suggestion -dotnet_diagnostic.RCS1122.severity = none dotnet_diagnostic.RCS1123.severity = suggestion -dotnet_diagnostic.RCS1124.severity = silent -dotnet_diagnostic.RCS1125.severity = silent -dotnet_diagnostic.RCS1126.severity = none dotnet_diagnostic.RCS1127.severity = suggestion dotnet_diagnostic.RCS1128.severity = suggestion -dotnet_diagnostic.RCS1129.severity = silent dotnet_diagnostic.RCS1130.severity = suggestion -dotnet_diagnostic.RCS1131.severity = silent dotnet_diagnostic.RCS1132.severity = suggestion -dotnet_diagnostic.RCS1133.severity = silent -dotnet_diagnostic.RCS1134.severity = silent dotnet_diagnostic.RCS1135.severity = suggestion -dotnet_diagnostic.RCS1136.severity = silent -dotnet_diagnostic.RCS1137.severity = silent -dotnet_diagnostic.RCS1138.severity = warning -dotnet_diagnostic.RCS1139.severity = none -dotnet_diagnostic.RCS1140.severity = silent -dotnet_diagnostic.RCS1141.severity = silent -dotnet_diagnostic.RCS1142.severity = silent -dotnet_diagnostic.RCS1143.severity = silent -dotnet_diagnostic.RCS1144.severity = silent -dotnet_diagnostic.RCS1145.severity = silent dotnet_diagnostic.RCS1146.severity = suggestion -dotnet_diagnostic.RCS1147.severity = silent -dotnet_diagnostic.RCS1148.severity = silent -dotnet_diagnostic.RCS1149.severity = silent dotnet_diagnostic.RCS1150.severity = suggestion -dotnet_diagnostic.RCS1151.severity = silent -dotnet_diagnostic.RCS1152.severity = silent -dotnet_diagnostic.RCS1153.severity = none dotnet_diagnostic.RCS1154.severity = suggestion -dotnet_diagnostic.RCS1155.severity = warning dotnet_diagnostic.RCS1156.severity = suggestion dotnet_diagnostic.RCS1157.severity = suggestion dotnet_diagnostic.RCS1158.severity = suggestion dotnet_diagnostic.RCS1159.severity = suggestion dotnet_diagnostic.RCS1160.severity = suggestion -dotnet_diagnostic.RCS1161.severity = silent -dotnet_diagnostic.RCS1162.severity = none dotnet_diagnostic.RCS1163.severity = suggestion dotnet_diagnostic.RCS1164.severity = suggestion -dotnet_diagnostic.RCS1165.severity = silent dotnet_diagnostic.RCS1166.severity = suggestion -dotnet_diagnostic.RCS1167.severity = silent -dotnet_diagnostic.RCS1168.severity = none dotnet_diagnostic.RCS1169.severity = suggestion dotnet_diagnostic.RCS1170.severity = suggestion dotnet_diagnostic.RCS1171.severity = suggestion -dotnet_diagnostic.RCS1172.severity = warning dotnet_diagnostic.RCS1173.severity = suggestion -dotnet_diagnostic.RCS1174.severity = none dotnet_diagnostic.RCS1175.severity = suggestion -dotnet_diagnostic.RCS1176.severity = none -dotnet_diagnostic.RCS1177.severity = none dotnet_diagnostic.RCS1178.severity = suggestion dotnet_diagnostic.RCS1179.severity = suggestion dotnet_diagnostic.RCS1180.severity = suggestion -dotnet_diagnostic.RCS1181.severity = silent -dotnet_diagnostic.RCS1182.severity = silent -dotnet_diagnostic.RCS1183.severity = silent -dotnet_diagnostic.RCS1184.severity = none -dotnet_diagnostic.RCS1185.severity = none -dotnet_diagnostic.RCS1186.severity = silent dotnet_diagnostic.RCS1187.severity = suggestion -dotnet_diagnostic.RCS1188.severity = silent -dotnet_diagnostic.RCS1189.severity = silent dotnet_diagnostic.RCS1190.severity = suggestion dotnet_diagnostic.RCS1191.severity = suggestion dotnet_diagnostic.RCS1192.severity = suggestion -dotnet_diagnostic.RCS1193.severity = warning -dotnet_diagnostic.RCS1194.severity = none dotnet_diagnostic.RCS1195.severity = suggestion dotnet_diagnostic.RCS1196.severity = suggestion dotnet_diagnostic.RCS1197.severity = suggestion -dotnet_diagnostic.RCS1198.severity = none dotnet_diagnostic.RCS1199.severity = suggestion dotnet_diagnostic.RCS1200.severity = suggestion -dotnet_diagnostic.RCS1201.severity = silent dotnet_diagnostic.RCS1202.severity = suggestion -dotnet_diagnostic.RCS1203.severity = warning dotnet_diagnostic.RCS1204.severity = suggestion dotnet_diagnostic.RCS1205.severity = suggestion dotnet_diagnostic.RCS1206.severity = suggestion -dotnet_diagnostic.RCS1207.severity = silent -dotnet_diagnostic.RCS1208.severity = none dotnet_diagnostic.RCS1209.severity = suggestion -dotnet_diagnostic.RCS1210.severity = warning -dotnet_diagnostic.RCS1211.severity = silent dotnet_diagnostic.RCS1212.severity = suggestion dotnet_diagnostic.RCS1213.severity = suggestion dotnet_diagnostic.RCS1214.severity = suggestion -dotnet_diagnostic.RCS1215.severity = warning dotnet_diagnostic.RCS1216.severity = suggestion -dotnet_diagnostic.RCS1217.severity = silent dotnet_diagnostic.RCS1218.severity = suggestion -dotnet_diagnostic.RCS1219.severity = none dotnet_diagnostic.RCS1220.severity = suggestion dotnet_diagnostic.RCS1221.severity = suggestion dotnet_diagnostic.RCS1222.severity = suggestion -dotnet_diagnostic.RCS1223.severity = none dotnet_diagnostic.RCS1224.severity = suggestion dotnet_diagnostic.RCS1225.severity = suggestion dotnet_diagnostic.RCS1226.severity = suggestion dotnet_diagnostic.RCS1227.severity = suggestion -dotnet_diagnostic.RCS1228.severity = silent dotnet_diagnostic.RCS1229.severity = suggestion dotnet_diagnostic.RCS1230.severity = suggestion dotnet_diagnostic.RCS1231.severity = suggestion + +dotnet_diagnostic.RCS1009.severity = warning +dotnet_diagnostic.RCS1012.severity = warning +dotnet_diagnostic.RCS1044.severity = warning +dotnet_diagnostic.RCS1059.severity = warning +dotnet_diagnostic.RCS1082.severity = warning +dotnet_diagnostic.RCS1083.severity = warning +dotnet_diagnostic.RCS1009.severity = warning +dotnet_diagnostic.RCS1012.severity = warning +dotnet_diagnostic.RCS1044.severity = warning +dotnet_diagnostic.RCS1059.severity = warning +dotnet_diagnostic.RCS1082.severity = warning +dotnet_diagnostic.RCS1083.severity = warning +dotnet_diagnostic.RCS1138.severity = warning +dotnet_diagnostic.RCS1155.severity = warning +dotnet_diagnostic.RCS1172.severity = warning +dotnet_diagnostic.RCS1193.severity = warning +dotnet_diagnostic.RCS1203.severity = warning +dotnet_diagnostic.RCS1210.severity = warning +dotnet_diagnostic.RCS1215.severity = warning + dotnet_diagnostic.SA1101.severity = none dotnet_diagnostic.SA1118.severity = none dotnet_diagnostic.SA1200.severity = none @@ -373,4 +386,5 @@ dotnet_diagnostic.SA1623.severity = none dotnet_diagnostic.SA1633.severity = none dotnet_diagnostic.SA1642.severity = none dotnet_diagnostic.SA1648.severity = none + dotnet_diagnostic.SX1309.severity = warning \ No newline at end of file diff --git a/src/Buildalyzer/AnalyzerResult.cs b/src/Buildalyzer/AnalyzerResult.cs index bbf77c74..c2a5a230 100644 --- a/src/Buildalyzer/AnalyzerResult.cs +++ b/src/Buildalyzer/AnalyzerResult.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.IO; using Buildalyzer.Construction; using Buildalyzer.Logging; @@ -9,21 +10,8 @@ public class AnalyzerResult : IAnalyzerResult private readonly Dictionary _properties = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _items = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Guid _projectGuid; - private readonly List _assemblyObjects = new List - { - "vbc.exe", - "vbc.dll", - "csc.exe", - "csc.dll", - "fsc.exe", - "fsc.dll" - }; - private List<(string, string)> _cscCommandLineArguments; - private List<(string, string)> _fscCommandLineArguments; - private List<(string, string)> _vbcCommandLineArguments; - private string _command; - private string[] _compilerArguments; - private string _compilerFilePath; + + public CompilerCommand CompilerCommand { get; private set; } internal AnalyzerResult(string projectFilePath, AnalyzerManager manager, ProjectAnalyzer analyzer) { @@ -58,13 +46,13 @@ internal AnalyzerResult(string projectFilePath, AnalyzerManager manager, Project public Guid ProjectGuid => _projectGuid; /// - public string Command => _command; + public string Command => CompilerCommand?.Text ?? string.Empty; /// - public string CompilerFilePath => _compilerFilePath; + public string CompilerFilePath => CompilerCommand?.CompilerLocation?.ToString() ?? string.Empty; /// - public string[] CompilerArguments => _compilerArguments; + public string[] CompilerArguments => CompilerCommand?.Arguments.ToArray() ?? []; /// public string GetProperty(string name) => @@ -78,67 +66,18 @@ public string GetProperty(string name) => .FirstOrDefault(); public string[] SourceFiles => - _cscCommandLineArguments - ?.Where(x => x.Item1 == null - && !string.Equals(Path.GetFileName(x.Item2), "csc.dll", StringComparison.OrdinalIgnoreCase) - && !string.Equals(Path.GetFileName(x.Item2), "csc.exe", StringComparison.OrdinalIgnoreCase)) - .Select(x => AnalyzerManager.NormalizePath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), x.Item2))) - .ToArray() ?? _fscCommandLineArguments - ?.Where(x => x.Item1 == null - && x.Item2?.Contains("fsc.dll") == false - && x.Item2?.Contains("fsc.exe") == false) - .Select(x => AnalyzerManager.NormalizePath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), x.Item2))) - .ToArray() ?? _vbcCommandLineArguments - ?.Where(x => x.Item1 == null && !_assemblyObjects.Contains(Path.GetFileName(x.Item2), StringComparer.OrdinalIgnoreCase)) - .Select(x => AnalyzerManager.NormalizePath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), x.Item2))) - .ToArray() ?? Array.Empty(); + CompilerCommand?.SourceFiles.Select(file => file.ToString()).ToArray() ?? []; public string[] References => - _cscCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("reference", StringComparison.OrdinalIgnoreCase)) - .Select(x => x.Item2) - .ToArray() - ?? _fscCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("r", StringComparison.OrdinalIgnoreCase)) - .Select(x => x.Item2) - .ToArray() - ?? _vbcCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("reference", StringComparison.OrdinalIgnoreCase)) - .Select(x => x.Item2) - .ToArray() - ?? Array.Empty(); + CompilerCommand?.MetadataReferences.ToArray() ?? []; public string[] AnalyzerReferences => - _cscCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("analyzer", StringComparison.OrdinalIgnoreCase)) - .Select(x => x.Item2) - .ToArray() ?? Array.Empty(); + CompilerCommand?.AnalyzerReferences.Select(r => r.ToString()).ToArray() ?? []; - public string[] PreprocessorSymbols => - _cscCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("define", StringComparison.OrdinalIgnoreCase)) - .SelectMany(x => x.Item2.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) - .Select(x => x.Trim()) - .ToArray() - ?? _vbcCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("define", StringComparison.OrdinalIgnoreCase)) - .SelectMany(x => x.Item2.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) - .Select(x => x.Trim()) - .ToArray() - ?? Array.Empty(); + public string[] PreprocessorSymbols => CompilerCommand?.PreprocessorSymbolNames.ToArray() ?? []; public string[] AdditionalFiles => - _cscCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("additionalfile", StringComparison.OrdinalIgnoreCase)) - .SelectMany(x => x.Item2.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) - .Select(x => x.Trim()) - .ToArray() - ?? _vbcCommandLineArguments - ?.Where(x => x.Item1 is object && x.Item1.Equals("additionalfile", StringComparison.OrdinalIgnoreCase)) - .SelectMany(x => x.Item2.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) - .Select(x => x.Trim()) - .ToArray() - ?? Array.Empty(); + CompilerCommand?.AdditionalFiles.Select(file => file.ToString()).ToArray() ?? []; public IEnumerable ProjectReferences => Items.TryGetValue("ProjectReference", out IProjectItem[] items) @@ -171,292 +110,21 @@ internal void ProcessProject(PropertiesAndItems propertiesAndItems) internal void ProcessCscCommandLine(string commandLine, bool coreCompile) { // Some projects can have multiple Csc calls (see #92) so if this is the one inside CoreCompile use it, otherwise use the first - if (string.IsNullOrWhiteSpace(commandLine) || (_cscCommandLineArguments != null && !coreCompile)) + if (string.IsNullOrWhiteSpace(commandLine) || (CompilerCommand != null && !coreCompile)) { return; } - ProcessedCommandLine cmd = ProcessCscCommandLine(commandLine); - _command = cmd.Command; - _compilerFilePath = cmd.FileName; - _compilerArguments = cmd.Arguments.ToArray(); - _cscCommandLineArguments = cmd.ProcessedArguments; - } - - internal static ProcessedCommandLine ProcessCscCommandLine(string commandLine) - { - return ProcessCommandLine(commandLine, "csc."); - } - - internal struct ProcessedCommandLine - { - public string Command; - public string FileName; - public List Arguments; - public List<(string, string)> ProcessedArguments; - } - - internal static ProcessedCommandLine ProcessCommandLine(string commandLine, string initialCommandEnd) - { - ProcessedCommandLine cmd; - cmd.Command = commandLine; - cmd.FileName = string.Empty; - cmd.Arguments = new List(); - cmd.ProcessedArguments = new List<(string, string)>(); - - using (IEnumerator enumerator = EnumerateCommandLineParts(commandLine, initialCommandEnd).GetEnumerator()) - { - if (!enumerator.MoveNext()) - { - return cmd; - } - - // Initial command (csc) - cmd.ProcessedArguments.Add((null, enumerator.Current)); - cmd.FileName = enumerator.Current; - - // Iterate the rest of parts - while (enumerator.MoveNext()) - { - string part = enumerator.Current; - cmd.Arguments.Add(part); - - if (part[0] == '/') - { - int valueStart = part.IndexOf(':'); - if (valueStart >= 0 && valueStart < part.Length - 1) - { - // Argument with a value - cmd.ProcessedArguments.Add((part.Substring(1, valueStart - 1), part.Substring(valueStart + 1))); - } - else - { - // Switch - cmd.ProcessedArguments.Add((valueStart >= 0 ? part.Substring(1, valueStart - 1) : part.Substring(1), null)); - } - } - else - { - // Argument, not a switch - cmd.ProcessedArguments.Add((null, part)); - } - } - } - - return cmd; + CompilerCommand = Compiler.CommandLine.Parse(new FileInfo(ProjectFilePath).Directory, commandLine, CompilerLanguage.CSharp); } internal void ProcessVbcCommandLine(string commandLine) { - ProcessedCommandLine cmd = ProcessCommandLine(commandLine, "vbc."); - - // vbc comma delimits the references, enumerate and replace - int referencesIdx = cmd.ProcessedArguments.FindIndex(x => x.Item1 == "reference"); - if (referencesIdx >= 0) - { - (string, string) references = cmd.ProcessedArguments[referencesIdx]; - cmd.Arguments.RemoveAt(referencesIdx); - cmd.ProcessedArguments.RemoveAt(referencesIdx); - foreach (string r in references.Item2.Split(',')) - { - cmd.Arguments.Add("/reference:\"" + r + "\""); - cmd.ProcessedArguments.Add((references.Item1, r)); - } - } - - _command = cmd.Command; - _compilerFilePath = cmd.FileName; - _compilerArguments = cmd.Arguments.ToArray(); - _vbcCommandLineArguments = cmd.ProcessedArguments; - } - - public bool HasFscArguments() - { - return _fscCommandLineArguments?.Count > 0; - } - - private static IEnumerable EnumerateCommandLineParts(string commandLine, string initialCommandEnd) - { - StringBuilder part = new StringBuilder(); - bool isInQuote = false; - bool initialCommand = true; - - using (StringReader reader = new StringReader(commandLine)) - { - while (reader.Read() is int c && c >= 0) - { - switch (c) - { - case '\\': - int next = reader.Read(); - if (next == '"') - { - // Escaped quote - part.Append('"'); - } - else - { - // Not an escape - part.Append((char)c); - - if (next >= 0) - { - part.Append((char)next); - } - } - break; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - if (isInQuote || initialCommand) - { - // Treat as a normal char - part.Append((char)c); - } - else if (part.Length > 0) - { - // End of the part - yield return part.ToString(); - part.Clear(); - } - break; - case '"': - isInQuote = !isInQuote; - break; - default: - part.Append((char)c); - break; - } - - if (initialCommand && part.ToString().EndsWith(initialCommandEnd, StringComparison.InvariantCultureIgnoreCase)) - { - initialCommand = false; - } - } - } - - if (part.Length > 0) - { - yield return part.ToString(); - } + CompilerCommand = Compiler.CommandLine.Parse(new FileInfo(ProjectFilePath).Directory, commandLine, CompilerLanguage.VisualBasic); } internal void ProcessFscCommandLine(string commandLine) { - _command = commandLine; - - List<(string, string)> processedArguments = new List<(string, string)>(); - List arguments = new List(); - - bool initialCommand = true; - using (IEnumerator enumerator = EnumerateCommandLinePartsFsc(commandLine, initialCommand).GetEnumerator()) - { - // Initial command (fsc) - processedArguments.Add((null, enumerator.Current)); - _compilerFilePath = enumerator.Current; - initialCommand = false; - - // Iterate the rest of parts - while (enumerator.MoveNext()) - { - string part = enumerator.Current; - arguments.Add(part); - - if (part[0] == '-') - { - int valueStart = part.IndexOf(':'); - if (valueStart >= 0 && valueStart < part.Length - 1) - { - // Argument with a value - processedArguments.Add((part.Substring(1, valueStart - 1), part.Substring(valueStart + 1))); - } - else - { - // Switch - processedArguments.Add((valueStart >= 0 ? part.Substring(1, valueStart - 1) : part.Substring(1), null)); - } - } - else - { - // Argument, not a switch - processedArguments.Add((null, part)); - } - } - } - - _fscCommandLineArguments = processedArguments; - _compilerArguments = arguments.ToArray(); - } - - private static IEnumerable EnumerateCommandLinePartsFsc(string commandLine, bool initialCommand) - { - StringBuilder part = new StringBuilder(); - bool isInQuote = false; - - using (StringReader reader = new StringReader(commandLine)) - { - while (reader.Read() is int c && c >= 0) - { - switch (c) - { - case '\\': - int next = reader.Read(); - if (next == '"') - { - // Escaped quote - part.Append('"'); - } - else - { - // Not an escape - part.Append((char)c); - - if (next >= 0) - { - part.Append((char)next); - } - } - break; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - if (isInQuote || initialCommand) - { - // Treat as a normal char - part.Append((char)c); - } - else if (reader.Read() == '\n') - { - // End of the part - yield return part.ToString(); - part.Clear(); - } - break; - - // case ' ': - case '"': - isInQuote = !isInQuote; - break; - default: - part.Append((char)c); - break; - } - - if (initialCommand && part.ToString().EndsWith("fsc.", StringComparison.InvariantCultureIgnoreCase)) - { - initialCommand = false; - } - } - } - - if (part.Length > 0) - { - yield return part.ToString(); - } + CompilerCommand = Compiler.CommandLine.Parse(new FileInfo(ProjectFilePath).Directory, commandLine, CompilerLanguage.FSharp); } private class ProjectItemItemSpecEqualityComparer : IEqualityComparer diff --git a/src/Buildalyzer/Buildalyzer.csproj b/src/Buildalyzer/Buildalyzer.csproj index bbe2f109..9c391be9 100644 --- a/src/Buildalyzer/Buildalyzer.csproj +++ b/src/Buildalyzer/Buildalyzer.csproj @@ -7,6 +7,8 @@ + + diff --git a/src/Buildalyzer/Compiler/CSharpCompilerCommand.cs b/src/Buildalyzer/Compiler/CSharpCompilerCommand.cs new file mode 100644 index 00000000..c2f8f6d9 --- /dev/null +++ b/src/Buildalyzer/Compiler/CSharpCompilerCommand.cs @@ -0,0 +1,11 @@ +#nullable enable + +using Microsoft.CodeAnalysis.CSharp; + +namespace Buildalyzer; + +public sealed record CSharpCompilerCommand : RoslynBasedCompilerCommand +{ + /// + public override CompilerLanguage Language => CompilerLanguage.CSharp; +} \ No newline at end of file diff --git a/src/Buildalyzer/Compiler/Compiler.cs b/src/Buildalyzer/Compiler/Compiler.cs new file mode 100644 index 00000000..998fa454 --- /dev/null +++ b/src/Buildalyzer/Compiler/Compiler.cs @@ -0,0 +1,121 @@ +#nullable enable + +using System.IO; +using Buildalyzer.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.VisualBasic; + +namespace Buildalyzer; + +public static class Compiler +{ + public static class CommandLine + { + [Pure] + public static string[]? SplitCommandLineIntoArguments(string? commandLine, CompilerLanguage language) => language switch + { + CompilerLanguage.CSharp => RoslynCommandLineParser.SplitCommandLineIntoArguments(commandLine, "csc.dll", "csc.exe"), + CompilerLanguage.VisualBasic => RoslynCommandLineParser.SplitCommandLineIntoArguments(commandLine, "vbc.dll", "vbc.exe"), + CompilerLanguage.FSharp => FSharpCommandLineParser.SplitCommandLineIntoArguments(commandLine), + _ => throw new NotSupportedException($"The {language} language is not supported."), + }; + + [Pure] + public static CompilerCommand Parse(DirectoryInfo? baseDir, string commandLine, CompilerLanguage language) + { + var tokens = SplitCommandLineIntoArguments(commandLine, language) ?? throw new FormatException("Commandline could not be parsed."); + var location = new FileInfo(tokens[0]); + var args = tokens[1..]; + + return Parse(baseDir?.ToString(), location.Directory?.ToString(), args, language) with + { + Text = commandLine, + CompilerLocation = location, + Arguments = args.ToImmutableArray(), + }; + + CompilerCommand Parse(string? baseDir, string? root, string[] args, CompilerLanguage language) + { + return language switch + { + CompilerLanguage.CSharp => CSharpParser.Parse(args, baseDir, root), + CompilerLanguage.VisualBasic => VisualBasicParser.Parse(args, baseDir, root), + CompilerLanguage.FSharp => FSharpParser.Parse(args), + _ => throw new NotSupportedException($"The {language} language is not supported."), + }; + } + } + } + + private static class CSharpParser + { + [Pure] + public static CSharpCompilerCommand Parse(string[] args, string? baseDir, string? root) + { + var arguments = CSharpCommandLineParser.Default.Parse(args, baseDir, root); + var command = new CSharpCompilerCommand() + { + CommandLineArguments = arguments, + }; + return RoslynParser.Enrich(command, arguments); + } + } + + private static class VisualBasicParser + { + [Pure] + public static VisualBasicCompilerCommand Parse(string[] args, string? baseDir, string? root) + { + var arguments = VisualBasicCommandLineParser.Default.Parse(args, baseDir, root); + var command = new VisualBasicCompilerCommand() + { + CommandLineArguments = arguments, + PreprocessorSymbols = arguments.ParseOptions.PreprocessorSymbols.ToImmutableDictionary(), + }; + return RoslynParser.Enrich(command, arguments); + } + } + + private static class FSharpParser + { + [Pure] + public static FSharpCompilerCommand Parse(string[] args) + { + var sourceFiles = args.Where(a => a[0] != '-').Select(IOPath.Parse); + var preprocessorSymbolNames = args.Where(a => a.StartsWith("--define:")).Select(a => a[9..]); + var metadataReferences = args.Where(a => a.StartsWith("-r:")).Select(a => a[3..]); + + return new() + { + MetadataReferences = metadataReferences.ToImmutableArray(), + PreprocessorSymbolNames = preprocessorSymbolNames.ToImmutableArray(), + SourceFiles = sourceFiles.ToImmutableArray(), + }; + } + } + + private static class RoslynParser + { + public static TCommand Enrich(TCommand command, CommandLineArguments arguments) + where TCommand : CompilerCommand + + => command with + { + AnalyzerReferences = arguments.AnalyzerReferences.Select(AsIOPath).ToImmutableArray(), + AnalyzerConfigPaths = arguments.AnalyzerConfigPaths.Select(IOPath.Parse).ToImmutableArray(), + MetadataReferences = arguments.MetadataReferences.Select(m => m.Reference).ToImmutableArray(), + PreprocessorSymbolNames = arguments.ParseOptions.PreprocessorSymbolNames.ToImmutableArray(), + + SourceFiles = arguments.SourceFiles.Select(AsIOPath).ToImmutableArray(), + AdditionalFiles = arguments.AdditionalFiles.Select(AsIOPath).ToImmutableArray(), + EmbeddedFiles = arguments.EmbeddedFiles.Select(AsIOPath).ToImmutableArray(), + }; + } + + [Pure] + internal static IOPath AsIOPath(CommandLineAnalyzerReference file) => IOPath.Parse(file.FilePath); + + [Pure] + internal static IOPath AsIOPath(CommandLineSourceFile file) => IOPath.Parse(file.Path); +} diff --git a/src/Buildalyzer/Compiler/CompilerCommand.cs b/src/Buildalyzer/Compiler/CompilerCommand.cs new file mode 100644 index 00000000..69b6e6aa --- /dev/null +++ b/src/Buildalyzer/Compiler/CompilerCommand.cs @@ -0,0 +1,51 @@ +#nullable enable + +using System.IO; +using Buildalyzer.IO; +using Microsoft.CodeAnalysis; + +namespace Buildalyzer; + +[DebuggerDisplay("{Language.Display()}: {Text}")] +public abstract record CompilerCommand +{ + /// The compiler lanuague. + public abstract CompilerLanguage Language { get; } + + /// The original text of the compiler command. + public string Text { get; init; } = string.Empty; + + /// The parsed command line arguments. + public ImmutableArray Arguments { get; init; } + + /// The location of the used compiler. + public FileInfo? CompilerLocation { get; init; } + + /// + public ImmutableArray Errors { get; init; } + + /// + public ImmutableArray SourceFiles { get; init; } + + /// + public ImmutableArray AdditionalFiles { get; init; } + + /// + public ImmutableArray EmbeddedFiles { get; init; } + + /// + public ImmutableArray AnalyzerReferences { get; init; } + + /// + public ImmutableArray AnalyzerConfigPaths { get; init; } + + /// + public ImmutableArray PreprocessorSymbolNames { get; init; } + + /// + public ImmutableArray MetadataReferences { get; init; } + + /// + [Pure] + public override string ToString() => Text ?? string.Empty; +} diff --git a/src/Buildalyzer/Compiler/CompilerLanguage.cs b/src/Buildalyzer/Compiler/CompilerLanguage.cs new file mode 100644 index 00000000..afd76cf7 --- /dev/null +++ b/src/Buildalyzer/Compiler/CompilerLanguage.cs @@ -0,0 +1,17 @@ +namespace Buildalyzer; + +/// The compiler language. +public enum CompilerLanguage +{ + /// None. + None = 0, + + /// C#. + CSharp = 1, + + /// VB.NET. + VisualBasic = 2, + + /// F#. + FSharp = 3, +} diff --git a/src/Buildalyzer/Compiler/FSharpCommandLineParser.cs b/src/Buildalyzer/Compiler/FSharpCommandLineParser.cs new file mode 100644 index 00000000..54b913bb --- /dev/null +++ b/src/Buildalyzer/Compiler/FSharpCommandLineParser.cs @@ -0,0 +1,59 @@ +#nullable enable + +namespace Buildalyzer; + +internal static class FSharpCommandLineParser +{ + [Pure] + public static string[]? SplitCommandLineIntoArguments(string? commandLine) + => commandLine?.Split(Splitters, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries) is { Length: > 0 } args + && First(args[0]).ToArray() is { Length: >= 1 } first + ? first.Concat(args[1..]).ToArray() + : null; + + [Pure] + private static IEnumerable First(string arg) + => Tokenize(arg) + .SkipWhile(NotCompilerLocation) + .Select(a => a.Trim()) + .Where(a => a.Length > 0); + + [Pure] + private static IEnumerable Tokenize(string arg) + { + var first = 0; + var cursor = 0; + var quote = false; + + foreach (var ch in arg) + { + if (ch == '"') + { + if (quote) + { + quote = false; + yield return arg[first..cursor]; + } + else + { + quote = true; + } + first = cursor + 1; + } + else if (ch == ' ' && cursor >= first && !quote) + { + yield return arg[first..cursor]; + first = cursor + 1; + } + cursor++; + } + yield return arg[first..]; + } + + [Pure] + public static bool NotCompilerLocation(string s) + => !s.EndsWith("fsc.dll", StringComparison.OrdinalIgnoreCase) + && !s.EndsWith("fsc.exe", StringComparison.OrdinalIgnoreCase); + + private static readonly char[] Splitters = ['\r', '\n']; +} diff --git a/src/Buildalyzer/Compiler/FSharpCompilerCommand.cs b/src/Buildalyzer/Compiler/FSharpCompilerCommand.cs new file mode 100644 index 00000000..398b177f --- /dev/null +++ b/src/Buildalyzer/Compiler/FSharpCompilerCommand.cs @@ -0,0 +1,10 @@ +using Buildalyzer.IO; +using Microsoft.CodeAnalysis; + +namespace Buildalyzer; + +public sealed record FSharpCompilerCommand : CompilerCommand +{ + /// + public override CompilerLanguage Language => CompilerLanguage.FSharp; +} diff --git a/src/Buildalyzer/Compiler/RoslynBasedCompilerCommand.cs b/src/Buildalyzer/Compiler/RoslynBasedCompilerCommand.cs new file mode 100644 index 00000000..edee04d1 --- /dev/null +++ b/src/Buildalyzer/Compiler/RoslynBasedCompilerCommand.cs @@ -0,0 +1,12 @@ +#nullable enable + +using Microsoft.CodeAnalysis; + +namespace Buildalyzer; + +public abstract record RoslynBasedCompilerCommand : CompilerCommand + where TArguments : CommandLineArguments +{ + /// The Roslyn comppiler arguments. + public TArguments? CommandLineArguments { get; init; } +} diff --git a/src/Buildalyzer/Compiler/RoslynCommandLineParser.cs b/src/Buildalyzer/Compiler/RoslynCommandLineParser.cs new file mode 100644 index 00000000..dbbed201 --- /dev/null +++ b/src/Buildalyzer/Compiler/RoslynCommandLineParser.cs @@ -0,0 +1,28 @@ +#nullable enable + +using Microsoft.CodeAnalysis; + +namespace Buildalyzer; + +internal static class RoslynCommandLineParser +{ + [Pure] + public static string[]? SplitCommandLineIntoArguments(string? commandLine, params string[] execs) + => Split(CommandLineParser.SplitCommandLineIntoArguments(commandLine ?? string.Empty, removeHashComments: true).ToArray(), execs); + + [Pure] + private static string[]? Split(string[] args, string[] execs) + { + foreach (var exec in execs) + { + for (var i = 0; i < args.Length - 1; i++) + { + if (args[i].EndsWith(exec, StringComparison.OrdinalIgnoreCase)) + { + return args[i..]; + } + } + } + return null; + } +} diff --git a/src/Buildalyzer/Compiler/VisualBasicCompilerCommand.cs b/src/Buildalyzer/Compiler/VisualBasicCompilerCommand.cs new file mode 100644 index 00000000..cfc5e89d --- /dev/null +++ b/src/Buildalyzer/Compiler/VisualBasicCompilerCommand.cs @@ -0,0 +1,14 @@ +#nullable enable + +using Microsoft.CodeAnalysis.VisualBasic; + +namespace Buildalyzer; + +public sealed record VisualBasicCompilerCommand : RoslynBasedCompilerCommand +{ + /// + public override CompilerLanguage Language => CompilerLanguage.VisualBasic; + + /// + public ImmutableDictionary? PreprocessorSymbols { get; init; } +} diff --git a/src/Buildalyzer/Extensions/CompilerLanguageExtensions.cs b/src/Buildalyzer/Extensions/CompilerLanguageExtensions.cs new file mode 100644 index 00000000..1f4e6ed6 --- /dev/null +++ b/src/Buildalyzer/Extensions/CompilerLanguageExtensions.cs @@ -0,0 +1,14 @@ +namespace Buildalyzer; + +internal static class CompilerLanguageExtensions +{ + /// Represents the as (DEBUG) display string. + [Pure] + public static string Display(this CompilerLanguage language) => language switch + { + CompilerLanguage.CSharp => "C#", + CompilerLanguage.FSharp => "F#", + CompilerLanguage.VisualBasic => "VB.NET", + _ => language.ToString(), + }; +} diff --git a/src/Buildalyzer/Guard.cs b/src/Buildalyzer/Guard.cs new file mode 100644 index 00000000..69cc1a6c --- /dev/null +++ b/src/Buildalyzer/Guard.cs @@ -0,0 +1,42 @@ +#nullable enable + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Buildalyzer; + +/// Supplies parameter guarding for methods and constructors. +/// +/// Advised usage: +/// * Change the namespace to maximum shared namespace amongst the using projects +/// * Keep it internal and use [assembly: InternalsVisibleTo] to open up access +/// * Add specific Guard methods if you software needs them. +/// * Keep the checks cheap so that you also can run them in production code. +/// +[ExcludeFromCodeCoverage] +internal static class Guard +{ + /// Guards the parameter if not null, otherwise throws an argument (null) exception. + /// The type to guard; cannot be a structure. + /// The parameter to guard. + /// The name of the parameter. + /// + /// The guarded parameter. + /// + [DebuggerStepThrough] + public static T NotNull([ValidatedNotNull] T? parameter, [CallerArgumentExpression(nameof(parameter))] string? paramName = null) + where T : class + => parameter ?? throw new ArgumentNullException(paramName); + + /// Marks the NotNull argument as being validated for not being null, to satisfy the static code analysis. + /// + /// Notice that it does not matter what this attribute does, as long as + /// it is named ValidatedNotNullAttribute. + /// + /// It is marked as conditional, as does not add anything to have the attribute compiled. + /// + [Conditional("Analysis")] + [AttributeUsage(AttributeTargets.Parameter)] + private sealed class ValidatedNotNullAttribute : Attribute { } +} diff --git a/src/Buildalyzer/Logging/EventProcessor.cs b/src/Buildalyzer/Logging/EventProcessor.cs index c78e4ecd..7a5e3f9d 100644 --- a/src/Buildalyzer/Logging/EventProcessor.cs +++ b/src/Buildalyzer/Logging/EventProcessor.cs @@ -156,7 +156,7 @@ private void MessageRaised(object sender, BuildMessageEventArgs e) if (e.SenderName?.Equals("Fsc", StringComparison.OrdinalIgnoreCase) == true && !string.IsNullOrWhiteSpace(e.Message) && _targetStack.Any(x => x.TargetName == "CoreCompile") - && !result.HasFscArguments()) + && result.CompilerCommand is null) { result.ProcessFscCommandLine(e.Message); } diff --git a/tests/Buildalyzer.Tests/AnalyzerResultFixture.cs b/tests/Buildalyzer.Tests/AnalyzerResultFixture.cs deleted file mode 100644 index 53a0ee81..00000000 --- a/tests/Buildalyzer.Tests/AnalyzerResultFixture.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using NUnit.Framework; -using Shouldly; - -namespace Buildalyzer.Tests; - -[TestFixture] -public class AnalyzerResultFixture -{ - private const string CscOptions = "/noconfig /unsafe- /checked- /nowarn:1701,1702,1701,1702,1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE;DEBUG;NETCOREAPP;NETCOREAPP2_1 "; - private const string VbcOptions = "/noconfig /imports:Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Diagnostics,System.Linq,System.Xml.Linq,System.Threading.Tasks /optioncompare:Binary /optionexplicit+ /optionstrict:custom /nowarn:41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 /nosdkpath /optioninfer+ /nostdlib /errorreport:prompt /rootnamespace:ConsoleApp21 /highentropyva+ /define:CONFIG=Debug,DEBUG=-1 /warnaserror+:NU1605 "; - - [TestCase("foo.cs", new[] { "foo.cs" })] - [TestCase("foo.cs bar.cs", new[] { "foo.cs", "bar.cs" })] - [TestCase("\"foo.cs\"", new[] { "foo.cs" })] - [TestCase("\"fizz buzz.cs\"", new[] { "fizz buzz.cs" })] - [TestCase("foo.cs \"fizz buzz.cs\"", new[] { "foo.cs", "fizz buzz.cs" })] - [TestCase("\"fizz - buzz.cs\"", new[] { "fizz - buzz.cs" })] // #89 - [TestCase("\"f oo.cs\"", new[] { "f oo.cs" })] - [TestCase("\" foo.cs\"", new[] { " foo.cs" })] - [TestCase("\"foo.cs \"", new[] { "foo.cs " })] - [TestCase("\"foo.cs\\\"\"", new[] { "foo.cs\"" })] - [TestCase("\"f oo.cs\" bar.cs", new[] { "f oo.cs", "bar.cs" })] - [TestCase("\" foo.cs\" bar.cs", new[] { " foo.cs", "bar.cs" })] - [TestCase("\"foo.cs \" bar.cs", new[] { "foo.cs ", "bar.cs" })] - [TestCase("\"foo.cs\\\"\" bar.cs", new[] { "foo.cs\"", "bar.cs" })] - [TestCase("\"fo\\\"o.cs\" bar.cs", new[] { "fo\"o.cs", "bar.cs" })] - [TestCase("bar.cs \"f oo.cs\"", new[] { "bar.cs", "f oo.cs" })] - [TestCase("bar.cs \" foo.cs\"", new[] { "bar.cs", " foo.cs" })] - [TestCase("bar.cs \"foo.cs\\\"\"", new[] { "bar.cs", "foo.cs\"" })] - [TestCase("\"foo.cs\\\" bar.cs\"", new[] { "foo.cs\" bar.cs" })] - public void ParsesCscCommandLineSourceFiles(string commandLine, string[] sourceFiles) - { - // Given - commandLine = Path.Combine("/", "Fizz", "Buzz", "csc.exe") + " " - + CscOptions - + commandLine; - - // When - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCscCommandLine(commandLine); - - // Then - result.Command.ShouldBe(commandLine); - result.FileName.ShouldBe(Path.Combine("/", "Fizz", "Buzz", "csc.exe")); - result.Arguments.ShouldBe(CscOptions.Split(' ', StringSplitOptions.RemoveEmptyEntries).Concat(sourceFiles)); - result.ProcessedArguments.Where(x => x.Item1 == null).Select(x => x.Item2).Skip(1).ShouldBe(sourceFiles); - } - - [TestCase("foo.cs bar.cs csc.dll", new[] { "foo.cs", "bar.cs" })] - [TestCase("foo.cs csc.exe bar.cs", new[] { "foo.cs", "bar.cs" })] - [TestCase("foo.cs bar.cs", new[] { "foo.cs", "bar.cs" })] - [SuppressMessage("CA1062", "CA1062:Validate arguments of public methods", Justification = "Test")] - public void RemovesCscAssembliesFromSourceFiles(string input, string[] sourceFiles) - { - // Given - string commandLine = Path.Combine("/", "Fizz", "Buzz", "csc.exe") + " " - + CscOptions - + input; - string projectFilePath = Path.Combine("/", "Code", "Project", "project.csproj"); - AnalyzerResult result = new AnalyzerResult(projectFilePath, null, null); - - // When - result.ProcessCscCommandLine(commandLine, false); - - // Then - result.Command.ShouldBe(commandLine); - result.CompilerFilePath.ShouldBe(Path.Combine("/", "Fizz", "Buzz", "csc.exe")); - result.CompilerArguments.ShouldBe(CscOptions.Split(' ', StringSplitOptions.RemoveEmptyEntries).Concat(input.Split(' ', StringSplitOptions.RemoveEmptyEntries))); - result.SourceFiles.ShouldBe(sourceFiles.Select(x => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), x)))); - } - - [Test] - public void ParsesCscCommandLineWithAliasReference() - { - // Given - string commandLine = Path.Combine("/", "Fizz", "Buzz", "csc.exe") - + @" /reference:Data1=""C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll"""; - - // When - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCscCommandLine(commandLine); - - // Then - result.Command.ShouldBe(commandLine); - result.FileName.ShouldBe(Path.Combine("/", "Fizz", "Buzz", "csc.exe")); - result.Arguments.ShouldBe(new[] { @"/reference:Data1=C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll" }); - result.ProcessedArguments.Count.ShouldBe(2); - result.ProcessedArguments.Where(x => x.Item1 == "reference") - .Select(x => x.Item2) - .Single() - .ShouldBe(@"Data1=C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll"); - } - - [TestCase("C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\MSBuild\\Current\\Bin\\Roslyn\\csc.exe /noconfig")] - [TestCase("/one two/three/csc.dll /noconfig")] - [SuppressMessage("CA1062", "CA1062:Validate arguments of public methods", Justification = "Test")] - public void TreatsCscCommandAsSingleArg(string commandLine) - { - // Given, When - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCscCommandLine(commandLine); - - // Then - result.Command.ShouldBe(commandLine); - result.FileName.ShouldBe(commandLine.Replace(" /noconfig", string.Empty)); - result.Arguments.ShouldBe(new[] { "/noconfig" }); - result.ProcessedArguments.Count.ShouldBe(2); - } - - [TestCase("foo.vb", new[] { "foo.vb" })] - [TestCase("foo.vb bar.vb", new[] { "foo.vb", "bar.vb" })] - [TestCase("\"foo.vb\"", new[] { "foo.vb" })] - [TestCase("\"fizz buzz.vb\"", new[] { "fizz buzz.vb" })] - [TestCase("foo.vb \"fizz buzz.vb\"", new[] { "foo.vb", "fizz buzz.vb" })] - [TestCase("\"fizz - buzz.vb\"", new[] { "fizz - buzz.vb" })] // #89 - [TestCase("\"f oo.vb\"", new[] { "f oo.vb" })] - [TestCase("\" foo.vb\"", new[] { " foo.vb" })] - [TestCase("\"foo.vb \"", new[] { "foo.vb " })] - [TestCase("\"foo.vb\\\"\"", new[] { "foo.vb\"" })] - [TestCase("\"f oo.vb\" bar.vb", new[] { "f oo.vb", "bar.vb" })] - [TestCase("\" foo.vb\" bar.vb", new[] { " foo.vb", "bar.vb" })] - [TestCase("\"foo.vb \" bar.vb", new[] { "foo.vb ", "bar.vb" })] - [TestCase("\"foo.vb\\\"\" bar.vb", new[] { "foo.vb\"", "bar.vb" })] - [TestCase("\"fo\\\"o.vb\" bar.vb", new[] { "fo\"o.vb", "bar.vb" })] - [TestCase("bar.vb \"f oo.vb\"", new[] { "bar.vb", "f oo.vb" })] - [TestCase("bar.vb \" foo.vb\"", new[] { "bar.vb", " foo.vb" })] - [TestCase("bar.vb \"foo.vb\\\"\"", new[] { "bar.vb", "foo.vb\"" })] - [TestCase("\"foo.vb\\\" bar.vb\"", new[] { "foo.vb\" bar.vb" })] - public void ParsesVbcCommandLineSourceFiles(string input, string[] sourceFiles) - { - // Given - string commandLine = Path.Combine("/", "Fizz", "Buzz", "vbc.exe") + " " - + VbcOptions - + input; - - // When - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCommandLine(commandLine, "vbc."); - - // Then - result.Command.ShouldBe(commandLine); - result.FileName.ShouldBe(Path.Combine("/", "Fizz", "Buzz", "vbc.exe")); - result.Arguments.ShouldBe(VbcOptions.Split(' ', StringSplitOptions.RemoveEmptyEntries).Concat(sourceFiles)); - result.ProcessedArguments.Where(x => x.Item1 == null).Select(x => x.Item2).Skip(1).ShouldBe(sourceFiles); - } - - [TestCase("foo.vb bar.vb vbc.dll", new[] { "foo.vb", "bar.vb" })] - [TestCase("foo.vb vbc.exe bar.vb", new[] { "foo.vb", "bar.vb" })] - [TestCase("foo.vb bar.vb", new[] { "foo.vb", "bar.vb" })] - public void RemovesVbcAssembliesFromSourceFiles(string commandLine, string[] sourceFiles) - { - // Given - commandLine = Path.Combine("/", "Fizz", "Buzz", "vbc.exe") + " " - + VbcOptions - + commandLine; - string projectFilePath = Path.Combine("/", "Code", "Project", "project.vbproj"); - AnalyzerResult result = new AnalyzerResult(projectFilePath, null, null); - - // When - result.ProcessVbcCommandLine(commandLine); - - // Then - result.SourceFiles.ShouldBe(sourceFiles.Select(x => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), x)))); - } - - [Test] - public void ParsesVbcCommandLineWithAliasReference() - { - // Given - string commandLine = Path.Combine("/", "Fizz", "Buzz", "vbc.exe") - + @" /reference:Data1=""C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll"""; - - // When - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCommandLine(commandLine, "vbc."); - - // Then - result.Command.ShouldBe(commandLine); - result.FileName.ShouldBe(Path.Combine("/", "Fizz", "Buzz", "vbc.exe")); - result.Arguments.ShouldBe(new[] { @"/reference:Data1=C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll" }); - result.ProcessedArguments.Count.ShouldBe(2); - result.ProcessedArguments.Where(x => x.Item1 == "reference") - .Select(x => x.Item2) - .Single() - .ShouldBe(@"Data1=C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll"); - } - - [TestCase("C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\MSBuild\\Current\\Bin\\Roslyn\\vbc.exe /noconfig")] - [TestCase("/one two/three/vbc.dll /noconfig")] - public void TreatsVbcCommandAsSingleArg(string commandLine) - { - AnalyzerResult.ProcessedCommandLine result = AnalyzerResult.ProcessCommandLine(commandLine, "vbc."); - result.ProcessedArguments.Count.ShouldBe(2); - } - - [Test] - public void ParseVbcCommandLineWithMultipleReferences() - { - // Given - string commandLine = Path.Combine("/", "Fizz", "Buzz", "vbc.exe") - + @" /reference:""C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\System.Data.dll"", ""C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\Facades\System.Collections.dll"""; - - string projectFilePath = Path.Combine("/", "Code", "Project", "project.vbproj"); - AnalyzerResult result = new AnalyzerResult(projectFilePath, null, null); - - // When - result.ProcessVbcCommandLine(commandLine); - - // Then - result.References.Length.ShouldBe(2); - } -} diff --git a/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj b/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj index 9a6751c4..551e8b71 100644 --- a/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj +++ b/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj @@ -5,6 +5,12 @@ 12 + + + + + + diff --git a/tests/Buildalyzer.Tests/Compiler/CompilerCommandFixture.cs b/tests/Buildalyzer.Tests/Compiler/CompilerCommandFixture.cs new file mode 100644 index 00000000..466d258c --- /dev/null +++ b/tests/Buildalyzer.Tests/Compiler/CompilerCommandFixture.cs @@ -0,0 +1,154 @@ +using System.Collections.Immutable; +using Buildalyzer.IO; +using FluentAssertions; +using FSharp.Compiler.CodeAnalysis; +using Microsoft.CodeAnalysis; +using Microsoft.FSharp.Collections; + +namespace Buildalyzer.Tests.Compiler; + +[TestFixture] +public class CompilerCommandFixture +{ + [Test] + public void Parse_CS() + { + string commandline = string.Empty + + "C:\\Program Files\\dotnet\\dotnet.exe exec \"C:\\Program Files\\dotnet\\sdk\\8.0.101\\Roslyn\\bincore\\csc.dll\" " + + "/noconfig " + + "/unsafe- " + + "/checked- " + + "/nowarn:1701,1702,1701,1702 " + + "/fullpaths " + + "/nostdlib+ " + + "/errorreport:prompt " + + "/warn:3 " + + "/define:TRACE;DEBUG;NETCOREAPP;NETCOREAPP3_1;NETCOREAPP1_0_OR_GREATER;NETCOREAPP1_1_OR_GREATER;NETCOREAPP2_0_OR_GREATER;NETCOREAPP2_1_OR_GREATER;NETCOREAPP2_2_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER " + + "/preferreduilang:en-US " + + "/highentropyva+ " + + "/debug:portable " + + "/filealign:512 " + + "/optimize- " + + "/warnaserror- " + + "/utf8output " + + "/deterministic+ " + + "/langversion:8.0 " + + "/analyzerconfig:code\\buildalyzer\\.editorconfig " + + "/analyzerconfig:code\\buildalyzer\\tests\\.editorconfig " + + "Program.cs " + + "Startup.cs " + + "/warnaserror+:NU1605"; + + var command = Buildalyzer.Compiler.CommandLine.Parse(new("."), commandline, CompilerLanguage.CSharp); + + command.Should().BeEquivalentTo(new + { + Text = commandline, + Language = CompilerLanguage.CSharp, + PreprocessorSymbolNames = new[] { "TRACE", "DEBUG", "NETCOREAPP", "NETCOREAPP3_1", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP2_1_OR_GREATER", "NETCOREAPP2_2_OR_GREATER", "NETCOREAPP3_0_OR_GREATER", "NETCOREAPP3_1_OR_GREATER" }, + SourceFiles = Files(".\\Program.cs", ".\\Startup.cs"), + AnalyzerConfigPaths = Files(".\\code\\buildalyzer\\.editorconfig", ".\\code\\buildalyzer\\tests\\.editorconfig"), + }); + } + + [Test] + public void Parse_VB() + { + string commandline = string.Empty + + "C:\\Program Files\\dotnet\\dotnet.exe exec \"C:\\Program Files\\dotnet\\sdk\\8.0.200\\Roslyn\\bincore\\vbc.dll\" " + + "/noconfig " + + @"/imports:Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Diagnostics,System.Linq,System.Xml.Linq,System.Threading.Tasks /optioncompare:Binary /optionexplicit+ /optionstrict:custom /nowarn:41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 /nosdkpath /optioninfer+ /nostdlib /errorreport:prompt /rootnamespace:VisualBasicNetConsoleApp /preferreduilang:en-US /highentropyva+ /vbruntime:""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.VisualBasic.dll"" /define:""CONFIG=\""Debug\"",DEBUG=-1,TRACE=-1,PLATFORM=\""AnyCPU\"",NET=-1,NET6_0=-1,NETCOREAPP=-1,_MyType=\""Empty\"",NET5_0_OR_GREATER=-1,NET6_0_OR_GREATER=-1,NETCOREAPP1_0_OR_GREATER=-1,NETCOREAPP1_1_OR_GREATER=-1,NETCOREAPP2_0_OR_GREATER=-1,NETCOREAPP2_1_OR_GREATER=-1,NETCOREAPP2_2_OR_GREATER=-1,NETCOREAPP3_0_OR_GREATER=-1,NETCOREAPP3_1_OR_GREATER=-1"" /reference:C:\Users\c.nobel\.nuget\packages\bouncycastle.netcore\1.8.10\lib\netstandard2.0\BouncyCastle.Crypto.dll,""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Antiforgery.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authentication.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authentication.Cookies.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authentication.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authentication.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authentication.OAuth.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authorization.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Authorization.Policy.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Components.Authorization.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Components.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Components.Forms.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Components.Server.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Components.Web.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Connections.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.CookiePolicy.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Cors.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Cryptography.Internal.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.DataProtection.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.DataProtection.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Diagnostics.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Diagnostics.HealthChecks.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.HostFiltering.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Hosting.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Hosting.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Html.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Connections.Common.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Connections.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Features.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Http.Results.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.HttpLogging.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.HttpOverrides.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.HttpsPolicy.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Identity.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Localization.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Localization.Routing.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Metadata.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Cors.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Formatters.Xml.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Localization.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.Razor.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.RazorPages.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll"",C:\Users\c.nobel\.nuget\packages\microsoft.aspnetcore.owin\6.0.4\lib\net6.0\Microsoft.AspNetCore.Owin.dll,""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Razor.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Razor.Runtime.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.ResponseCaching.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.ResponseCompression.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Rewrite.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Routing.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Routing.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.HttpSys.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.IIS.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.IISIntegration.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.Kestrel.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.Session.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.SignalR.Common.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.SignalR.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.SignalR.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.StaticFiles.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.WebSockets.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.AspNetCore.WebUtilities.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.CSharp.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Caching.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Caching.Memory.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.Binder.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.CommandLine.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.FileExtensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.Ini.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.KeyPerFile.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.UserSecrets.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Configuration.Xml.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.DependencyInjection.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Diagnostics.HealthChecks.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Features.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.FileProviders.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.FileProviders.Composite.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.FileProviders.Embedded.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.FileProviders.Physical.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.FileSystemGlobbing.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Hosting.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Hosting.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Http.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Identity.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Identity.Stores.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Localization.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Localization.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.Abstractions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.Configuration.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.Console.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.Debug.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.EventLog.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.EventSource.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Logging.TraceSource.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.ObjectPool.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Options.DataAnnotations.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Options.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Extensions.WebEncoders.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.JSInterop.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Net.Http.Headers.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.VisualBasic.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.VisualBasic.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Win32.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\Microsoft.Win32.Registry.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\mscorlib.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\netstandard.dll"",C:\Users\c.nobel\.nuget\packages\newtonsoft.json\13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll,""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.AppContext.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Buffers.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Collections.Concurrent.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Collections.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Collections.Immutable.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Collections.NonGeneric.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Collections.Specialized.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.Annotations.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.DataAnnotations.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.EventBasedAsync.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ComponentModel.TypeConverter.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Configuration.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Console.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Core.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Data.Common.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Data.DataSetExtensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Data.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.Contracts.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.Debug.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.DiagnosticSource.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.EventLog.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.FileVersionInfo.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.Process.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.StackTrace.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.TextWriterTraceListener.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.Tools.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.TraceSource.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Diagnostics.Tracing.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Drawing.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Drawing.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Dynamic.Runtime.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Formats.Asn1.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Globalization.Calendars.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Globalization.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Globalization.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Compression.Brotli.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Compression.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Compression.FileSystem.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Compression.ZipFile.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.FileSystem.AccessControl.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.FileSystem.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.FileSystem.DriveInfo.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.FileSystem.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.FileSystem.Watcher.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.IsolatedStorage.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.MemoryMappedFiles.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\System.IO.Pipelines.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Pipes.AccessControl.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.Pipes.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.IO.UnmanagedMemoryStream.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Linq.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Linq.Expressions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Linq.Parallel.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Linq.Queryable.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Memory.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Http.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Http.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.HttpListener.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Mail.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.NameResolution.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.NetworkInformation.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Ping.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Requests.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Security.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.ServicePoint.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.Sockets.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.WebClient.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.WebHeaderCollection.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.WebProxy.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.WebSockets.Client.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Net.WebSockets.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Numerics.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Numerics.Vectors.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ObjectModel.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.DispatchProxy.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Emit.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Emit.ILGeneration.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Emit.Lightweight.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Metadata.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Reflection.TypeExtensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Resources.Reader.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Resources.ResourceManager.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Resources.Writer.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.CompilerServices.Unsafe.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.CompilerServices.VisualC.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Handles.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.InteropServices.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.InteropServices.RuntimeInformation.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Intrinsics.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Loader.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Numerics.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Serialization.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Serialization.Formatters.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Serialization.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Serialization.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Runtime.Serialization.Xml.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.AccessControl.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Claims.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Algorithms.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Cng.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Csp.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Encoding.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.OpenSsl.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Primitives.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.X509Certificates.dll"",""C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\6.0.27\ref\net6.0\System.Security.Cryptography.Xml.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.dll"",C:\Users\c.nobel\.nuget\packages\system.security.permissions\4.5.0\ref\netstandard2.0\System.Security.Permissions.dll,""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Principal.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.Principal.Windows.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Security.SecureString.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ServiceModel.Web.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ServiceProcess.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.Encoding.CodePages.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.Encoding.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.Encoding.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.Encodings.Web.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.Json.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Text.RegularExpressions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Channels.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Overlapped.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Tasks.Dataflow.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Tasks.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Tasks.Extensions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Tasks.Parallel.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Thread.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.ThreadPool.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Threading.Timer.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Transactions.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Transactions.Local.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.ValueTuple.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Web.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Web.HttpUtility.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Windows.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.Linq.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.ReaderWriter.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.Serialization.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.XDocument.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.XmlDocument.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.XmlSerializer.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.XPath.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\System.Xml.XPath.XDocument.dll"",""C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.27\ref\net6.0\WindowsBase.dll"" /debug+ /debug:portable /filealign:512 /optimize- /out:obj\Debug\net6.0\VisualBasicNetConsoleApp.dll /refout:obj\Debug\net6.0\refint\VisualBasicNetConsoleApp.dll /target:exe /warnaserror- /utf8output /deterministic+ " + + @"/analyzerconfig:code\buildalyzer\.editorconfig /analyzerconfig:code\buildalyzer\tests\.editorconfig " + + @"/analyzer:""C:\Program Files\dotnet\sdk\8.0.200\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers.dll"" " + + @"/analyzer:""C:\Program Files\dotnet\sdk\8.0.200\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.NetAnalyzers.dll"" " + + "Configuration.vb " + + "Program.vb " + + "\"obj\\Debug\\net6.0\\.NETCoreApp,Version=v6.0.AssemblyAttributes.vb\" " + + "\"obj\\Debug\\net6.0\\VisualBasicNetConsoleApp.AssemblyInfo.vb\" " + + "/warnaserror+:NU1605"; + + var command = Buildalyzer.Compiler.CommandLine.Parse(new("."), commandline, CompilerLanguage.VisualBasic); + + command.Should().BeEquivalentTo(new + { + Text = commandline, + Language = CompilerLanguage.VisualBasic, + PreprocessorSymbolNames = new[] { "TRACE", "NETCOREAPP2_2_OR_GREATER", "NETCOREAPP1_0_OR_GREATER", "NET6_0", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP3_0_OR_GREATER", "_MyType", "NETCOREAPP", "NETCOREAPP2_1_OR_GREATER", "NET6_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "CONFIG", "NET", "PLATFORM", "NETCOREAPP3_1_OR_GREATER", "DEBUG", "NET5_0_OR_GREATER", "VBC_VER", "TARGET" }, + SourceFiles = Files(".\\Configuration.vb", ".\\Program.vb", ".\\obj\\Debug\\net6.0\\.NETCoreApp,Version=v6.0.AssemblyAttributes.vb", ".\\obj\\Debug\\net6.0\\VisualBasicNetConsoleApp.AssemblyInfo.vb"), + AnalyzerReferences = Files("C:\\Program Files\\dotnet\\sdk\\8.0.200\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\analyzers\\Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers.dll", "C:\\Program Files\\dotnet\\sdk\\8.0.200\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\analyzers\\Microsoft.CodeAnalysis.NetAnalyzers.dll"), + AnalyzerConfigPaths = Files(".\\code\\buildalyzer\\.editorconfig", ".\\code\\buildalyzer\\tests\\.editorconfig"), + }); + } + + [Test] + public void Parse_FSharp() + { + string commandLine = @"C:\Program Files\dotnet\dotnet.exe ""C:\Program Files\dotnet\sdk\8.0.200\FSharp\fsc.dll"" -o:obj\Debug\netcoreapp3.1\FSharpProject.dll +-g +--debug:portable +--noframework +--define:TRACE +--define:DEBUG +--define:NETCOREAPP +--define:NETCOREAPP3_1 +--define:NETCOREAPP1_0_OR_GREATER +--define:NETCOREAPP1_1_OR_GREATER +--define:NETCOREAPP2_0_OR_GREATER +--define:NETCOREAPP2_1_OR_GREATER +--define:NETCOREAPP2_2_OR_GREATER +--define:NETCOREAPP3_0_OR_GREATER +--define:NETCOREAPP3_1_OR_GREATER +--optimize- +--tailcalls- +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.CSharp.dll +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.VisualBasic.Core.dll +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.VisualBasic.dll +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.Win32.Primitives.dll +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\mscorlib.dll +-r:C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\netstandard.dll +--target:exe +--warn:3 +--warnaserror:3239 +--preferreduilang:en-US +--fullpaths +--flaterrors +--highentropyva+ +--targetprofile:netcore +--nocopyfsharpcore +--deterministic+ +--simpleresolution +obj\Debug\netcoreapp3.1\.NETCoreApp,Version=v3.1.AssemblyAttributes.fs +obj\Debug\netcoreapp3.1\FSharpProject.AssemblyInfo.fs +Program.fs"; + + var command = Buildalyzer.Compiler.CommandLine.Parse(new("."), commandLine, CompilerLanguage.FSharp); + var options = GetFSharpParsingOptions(commandLine); + + command.Should().BeEquivalentTo(new + { + Text = commandLine, + Language = CompilerLanguage.FSharp, + PreprocessorSymbolNames = new[] { "NETCOREAPP3_1_OR_GREATER", "NETCOREAPP3_0_OR_GREATER", "NETCOREAPP2_2_OR_GREATER", "NETCOREAPP2_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP3_1", "NETCOREAPP", "DEBUG", "TRACE" }, + SourceFiles = Files("obj\\Debug\\netcoreapp3.1\\.NETCoreApp,Version=v3.1.AssemblyAttributes.fs", "obj\\Debug\\netcoreapp3.1\\FSharpProject.AssemblyInfo.fs", "Program.fs"), + MetadataReferences = Array("C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\Microsoft.CSharp.dll", "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\Microsoft.VisualBasic.Core.dll", "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\Microsoft.VisualBasic.dll", "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\Microsoft.Win32.Primitives.dll", "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\mscorlib.dll", "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1\\netstandard.dll"), + }); + + command.SourceFiles.Should().BeEquivalentTo(Files(options.SourceFiles)); + + // INTERACTIVE is added by the F# checker. TODO: based on being interactive or not, INTERACTIVE or COMPILED should be added by the parser. + command.PreprocessorSymbolNames.Concat(["INTERACTIVE"]).Should().BeEquivalentTo(options.ConditionalDefines); + + static FSharpParsingOptions GetFSharpParsingOptions(string commandLine) + { + var checker = FSharpChecker.Instance; + var result = checker.GetParsingOptionsFromCommandLineArgs(ListModule.OfArray(FSharpCommandLineParser.SplitCommandLineIntoArguments(commandLine)), isInteractive: true, isEditing: false); + return result.Item1; + } + } + + private static ImmutableArray Files(params string[] files) + => files.Select(f => IOPath.Parse(f)).ToImmutableArray(); + + private static ImmutableArray Array(params string[] references) + => references.ToImmutableArray(); +} diff --git a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs index 04cf5978..ab171e66 100644 --- a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs +++ b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Compression; -using System.Linq; using Buildalyzer.Environment; -using NUnit.Framework; +using FluentAssertions; using Shouldly; namespace Buildalyzer.Tests.Integration; @@ -153,13 +150,14 @@ public void GetsReferences( // When IAnalyzerResults results = analyzer.Build(options); + IEnumerable references = results.SelectMany(r => r.References.Select(Path.GetFileName)); // Then - results.ShouldAllBe(x => x.References != null, log.ToString()); - results.Any(x => x.References.Any(r => r.Contains("mscorlib"))).ShouldBeTrue(log.ToString()); + references.Should().Contain("mscorlib.dll", because: log.ToString()); + if (projectFile.Contains("PackageReference")) { - results.Any(x => x.References.Any(r => r.EndsWith("NodaTime.dll"))).ShouldBeTrue(log.ToString()); + references.Should().Contain("NodaTime.dll", because: log.ToString()); } } @@ -692,11 +690,11 @@ public void GetsAdditionalCscFiles() StringWriter log = new StringWriter(); IProjectAnalyzer analyzer = GetProjectAnalyzer(@"RazorClassLibraryTest\RazorClassLibraryTest.csproj", log); - // When - IEnumerable additionalFiles = analyzer.Build().First().AdditionalFiles; - - // Then - additionalFiles.ShouldBe(new[] { "_Imports.razor", "Component1.razor" }, log.ToString()); + // When + then + analyzer.Build().First().AdditionalFiles.Select(Path.GetFileName) + .Should().BeEquivalentTo( + "_Imports.razor", + "Component1.razor"); } [Test] @@ -706,11 +704,10 @@ public void GetsAdditionalFile() StringWriter log = new StringWriter(); IProjectAnalyzer analyzer = GetProjectAnalyzer(@"ProjectWithAdditionalFile\ProjectWithAdditionalFile.csproj", log); - // When - IEnumerable additionalFiles = analyzer.Build().First().AdditionalFiles; + // When + then + analyzer.Build().First().AdditionalFiles.Select(Path.GetFileName) + .Should().BeEquivalentTo("message.txt"); - // Then - additionalFiles.ShouldBe(new[] { "message.txt" }, log.ToString()); } private static IProjectAnalyzer GetProjectAnalyzer(string projectFile, StringWriter log)