Skip to content

Commit a3df2ff

Browse files
committed
Refactor StaticAnalysis to use Tools.Common
1 parent 5fdc9b7 commit a3df2ff

40 files changed

+526
-1164
lines changed

tools/StaticAnalysis/BreakingChangeAnalyzer/BreakingChangeAnalyzer.cs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
using System.Runtime.Serialization.Formatters.Binary;
2424
using System.Threading.Tasks;
2525
using System.Xml.Serialization;
26+
using Tools.Common.Helpers;
27+
using Tools.Common.Issues;
28+
using Tools.Common.Loaders;
29+
using Tools.Common.Loggers;
30+
using Tools.Common.Models;
2631

2732
namespace StaticAnalysis.BreakingChangeAnalyzer
2833
{
@@ -41,7 +46,7 @@ public BreakingChangeAnalyzer()
4146
}
4247

4348
/// <summary>
44-
/// Given a set of directory paths containing PowerShell module folders,
49+
/// Given a set of directory paths containing PowerShell module folders,
4550
/// analyze the breaking changes in the modules and report any issues
4651
/// </summary>
4752
/// <param name="cmdletProbingDirs">Set of directory paths containing PowerShell module folders to be checked for breaking changes.</param>
@@ -53,7 +58,7 @@ public void Analyze(IEnumerable<string> cmdletProbingDirs)
5358
/// <summary>
5459
/// Given a set of directory paths containing PowerShell module folders,
5560
/// analyze the breaking changes in the modules and report any issues
56-
///
61+
///
5762
/// Filters can be added to find breaking changes for specific modules
5863
/// </summary>
5964
/// <param name="cmdletProbingDirs">Set of directory paths containing PowerShell module folders to be checked for breaking changes.</param>
@@ -73,7 +78,7 @@ public void Analyze(
7378
cmdletProbingDirs = directoryFilter(cmdletProbingDirs);
7479
}
7580

76-
foreach (var baseDirectory in cmdletProbingDirs.Where(s => !s.Contains("ServiceManagement") &&
81+
foreach (var baseDirectory in cmdletProbingDirs.Where(s => !s.Contains("ServiceManagement") &&
7782
!s.Contains("Stack") && Directory.Exists(Path.GetFullPath(s))))
7883
{
7984
List<string> probingDirectories = new List<string>();
@@ -99,34 +104,44 @@ public void Analyze(
99104
}
100105

101106
var psd1 = manifestFiles.FirstOrDefault();
102-
103-
var parentDirectory = Directory.GetParent(psd1);
107+
var parentDirectory = Directory.GetParent(psd1).FullName;
104108
var psd1FileName = Path.GetFileName(psd1);
105-
109+
IEnumerable<string> nestedModules = null;
110+
List<string> requiredModules = null;
106111
PowerShell powershell = PowerShell.Create();
107-
powershell.AddScript("Import-LocalizedData -BaseDirectory " + parentDirectory +
108-
" -FileName " + psd1FileName +
109-
" -BindingVariable ModuleMetadata; $ModuleMetadata.NestedModules");
110-
112+
powershell.AddScript("Import-LocalizedData -BaseDirectory " + parentDirectory +
113+
" -FileName " + psd1FileName +
114+
" -BindingVariable ModuleMetadata; $ModuleMetadata.NestedModules; $ModuleMetadata.RequiredModules | % { $_[\"ModuleName\"] };");
111115
var cmdletResult = powershell.Invoke();
112-
var cmdletFiles = cmdletResult.Select(c => c.ToString().Substring(2));
116+
nestedModules = cmdletResult.Where(c => c.ToString().StartsWith(".")).Select(c => c.ToString().Substring(2));
117+
requiredModules = cmdletResult.Where(c => !c.ToString().StartsWith(".")).Select(c => c.ToString()).ToList();
113118

114-
if (cmdletFiles.Any())
119+
if (nestedModules.Any())
115120
{
116-
foreach (var cmdletFileName in cmdletFiles)
121+
Directory.SetCurrentDirectory(directory);
122+
123+
requiredModules = requiredModules.Join(cmdletProbingDirs,
124+
module => 1,
125+
dir => 1,
126+
(module, dir) => Path.Combine(dir, module))
127+
.Where(f => Directory.Exists(f))
128+
.ToList();
129+
130+
requiredModules.Add(directory);
131+
132+
foreach (var nestedModule in nestedModules)
117133
{
118-
var cmdletFileFullPath = Path.Combine(directory, Path.GetFileName(cmdletFileName));
119-
120-
if (File.Exists(cmdletFileFullPath))
134+
var assemblyFile = Directory.GetFiles(parentDirectory, nestedModule, SearchOption.AllDirectories).FirstOrDefault();
135+
var assemblyFileName = Path.GetFileName(assemblyFile);
136+
if (File.Exists(assemblyFile))
121137
{
122-
issueLogger.Decorator.AddDecorator(a => a.AssemblyFileName = cmdletFileFullPath, "AssemblyFileName");
123-
processedHelpFiles.Add(cmdletFileName);
124-
var proxy =
125-
EnvironmentHelpers.CreateProxy<CmdletBreakingChangeLoader>(directory, out _appDomain);
126-
var newModuleMetadata = proxy.GetModuleMetadata(cmdletFileFullPath);
127-
128-
string fileName = cmdletFileName + ".json";
129-
string executingPath =
138+
issueLogger.Decorator.AddDecorator(a => a.AssemblyFileName = assemblyFileName, "AssemblyFileName");
139+
processedHelpFiles.Add(assemblyFileName);
140+
var proxy = EnvironmentHelpers.CreateProxy<CmdletLoader>(directory, out _appDomain);
141+
var newModuleMetadata = proxy.GetModuleMetadata(assemblyFile, requiredModules);
142+
143+
string fileName = assemblyFileName + ".json";
144+
string executingPath =
130145
Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
131146

132147
string filePath = executingPath + "\\SerializedCmdlets\\" + fileName;
@@ -150,7 +165,7 @@ public void Analyze(
150165
string output = string.Format("Before filter\nOld module cmdlet count: {0}\nNew module cmdlet count: {1}",
151166
oldModuleMetadata.Cmdlets.Count, newModuleMetadata.Cmdlets.Count);
152167

153-
output += string.Format("\nCmdlet file: {0}", cmdletFileFullPath);
168+
output += string.Format("\nCmdlet file: {0}", assemblyFileName);
154169

155170
oldModuleMetadata.FilterCmdlets(cmdletFilter);
156171
newModuleMetadata.FilterCmdlets(cmdletFilter);
@@ -173,6 +188,8 @@ public void Analyze(
173188

174189
RunBreakingChangeChecks(oldModuleMetadata, newModuleMetadata, issueLogger);
175190
}
191+
192+
AppDomain.Unload(_appDomain);
176193
}
177194
}
178195
}
@@ -249,7 +266,7 @@ public AnalysisReport GetAnalysisReport()
249266
public static class LogExtensions
250267
{
251268
public static void LogBreakingChangeIssue(
252-
this ReportLogger<BreakingChangeIssue> issueLogger, CmdletBreakingChangeMetadata cmdlet,
269+
this ReportLogger<BreakingChangeIssue> issueLogger, CmdletMetadata cmdlet,
253270
string description, string remediation, int severity, int problemId)
254271
{
255272
issueLogger.LogRecord(new BreakingChangeIssue

tools/StaticAnalysis/BreakingChangeAnalyzer/BreakingChangeIssue.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
using System;
1616
using System.Text.RegularExpressions;
17+
using Tools.Common.Issues;
1718

1819
namespace StaticAnalysis.BreakingChangeAnalyzer
1920
{

tools/StaticAnalysis/BreakingChangeAnalyzer/CmdletBreakingChangeMetadata.cs

Lines changed: 0 additions & 92 deletions
This file was deleted.

tools/StaticAnalysis/BreakingChangeAnalyzer/CmdletMetadataHelper.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
using System;
1616
using System.Collections.Generic;
1717
using System.Linq;
18-
using System.Text;
1918
using System.Text.RegularExpressions;
20-
using System.Threading.Tasks;
19+
using Tools.Common.Loggers;
20+
using Tools.Common.Models;
2121

2222
namespace StaticAnalysis.BreakingChangeAnalyzer
2323
{
2424
/// <summary>
25-
/// This class is responsible for comparing CmdletBreakingChangeMetadata and
25+
/// This class is responsible for comparing CmdletMetadata and
2626
/// checking for breaking changes between old (serialized) metadata and new metadata.
2727
/// </summary>
2828
public class CmdletMetadataHelper
@@ -47,29 +47,29 @@ public CmdletMetadataHelper(TypeMetadataHelper typeMetadataHelper)
4747

4848
/// <summary>
4949
/// Compares the metadata of cmdlets with the same name (or alias) for any breaking changes.
50-
///
50+
///
5151
/// Breaking changes for cmdlets include
5252
/// - Removing a cmdlet
5353
/// - Removing an alias to a cmdlet
5454
/// - Removing SupportsShouldProcess
5555
/// - Removing SupportsPaging
5656
/// - Output type (or any of its properties) of cmdlet has changed
5757
/// - Default parameter set has changed
58-
///
58+
///
5959
/// This method will also check for breaking changes in the cmdlets' parameters and
6060
/// parameter sets using the appropriate helpers.
6161
/// </summary>
6262
/// <param name="oldCmdlets">The list of cmdlets from the old (serialized) metadata.</param>
6363
/// <param name="newCmdlets">The list of cmdlets from the new metadata.</param>
6464
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
6565
public void CompareCmdletMetadata(
66-
List<CmdletBreakingChangeMetadata> oldCmdlets,
67-
List<CmdletBreakingChangeMetadata> newCmdlets,
66+
List<CmdletMetadata> oldCmdlets,
67+
List<CmdletMetadata> newCmdlets,
6868
ReportLogger<BreakingChangeIssue> issueLogger)
6969
{
7070
// This dictionary will map a cmdlet name (or alias) to the corresponding metadata
71-
Dictionary<string, CmdletBreakingChangeMetadata> cmdletDictionary =
72-
new Dictionary<string, CmdletBreakingChangeMetadata>();
71+
Dictionary<string, CmdletMetadata> cmdletDictionary =
72+
new Dictionary<string, CmdletMetadata>();
7373

7474
// Add each cmdlet and its aliases to the dictionary
7575
foreach (var newCmdlet in newCmdlets)
@@ -125,8 +125,8 @@ public void CompareCmdletMetadata(
125125
/// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param>
126126
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
127127
private void CheckForRemovedCmdletAlias(
128-
CmdletBreakingChangeMetadata oldCmdlet,
129-
CmdletBreakingChangeMetadata newCmdlet,
128+
CmdletMetadata oldCmdlet,
129+
CmdletMetadata newCmdlet,
130130
ReportLogger<BreakingChangeIssue> issueLogger)
131131
{
132132
// This set will contain all of the aliases in the new metadata
@@ -164,8 +164,8 @@ private void CheckForRemovedCmdletAlias(
164164
/// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param>
165165
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
166166
private void CheckForRemovedSupportsShouldProcess(
167-
CmdletBreakingChangeMetadata oldCmdlet,
168-
CmdletBreakingChangeMetadata newCmdlet,
167+
CmdletMetadata oldCmdlet,
168+
CmdletMetadata newCmdlet,
169169
ReportLogger<BreakingChangeIssue> issueLogger)
170170
{
171171
// If the old cmdlet implements SupportsShouldProcess and the new cmdlet does not, log an issue
@@ -187,8 +187,8 @@ private void CheckForRemovedSupportsShouldProcess(
187187
/// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param>
188188
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
189189
private void CheckForRemovedSupportsPaging(
190-
CmdletBreakingChangeMetadata oldCmdlet,
191-
CmdletBreakingChangeMetadata newCmdlet,
190+
CmdletMetadata oldCmdlet,
191+
CmdletMetadata newCmdlet,
192192
ReportLogger<BreakingChangeIssue> issueLogger)
193193
{
194194
// If the old cmdlet implements SupportsPaging and the new cmdlet does not, log an issue
@@ -211,8 +211,8 @@ private void CheckForRemovedSupportsPaging(
211211
/// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param>
212212
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
213213
private void CheckForChangedOutputType(
214-
CmdletBreakingChangeMetadata oldCmdlet,
215-
CmdletBreakingChangeMetadata newCmdlet,
214+
CmdletMetadata oldCmdlet,
215+
CmdletMetadata newCmdlet,
216216
ReportLogger<BreakingChangeIssue> issueLogger)
217217
{
218218
// This dictionary will map an output type name to the corresponding type metadata
@@ -262,8 +262,8 @@ private void CheckForChangedOutputType(
262262
/// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param>
263263
/// <param name="issueLogger">ReportLogger that will keep track of issues found.</param>
264264
private void CheckDefaultParameterName(
265-
CmdletBreakingChangeMetadata oldCmdlet,
266-
CmdletBreakingChangeMetadata newCmdlet,
265+
CmdletMetadata oldCmdlet,
266+
CmdletMetadata newCmdlet,
267267
ReportLogger<BreakingChangeIssue> issueLogger)
268268
{
269269
// If the default parameter name hasn't changed, or if there wasn't a
@@ -315,7 +315,7 @@ private void CheckDefaultParameterName(
315315
}
316316

317317
/// <summary>
318-
/// Comparer for assebly qualified names. Parses of the PublicKeyToken, so that types from signed and unsigned assemblies match
318+
/// Comparer for assebly qualified names. Parses of the PublicKeyToken, so that types from signed and unsigned assemblies match
319319
/// </summary>
320320
class TypeNameComparer : IEqualityComparer<string>
321321
{

0 commit comments

Comments
 (0)