public void Analyze(IEnumerable<string> directories) { if (directories == null) { throw new ArgumentNullException("directories"); } _versionConflictLogger = Logger.CreateLogger<AssemblyVersionConflict>("AssemblyVersionConflict.csv"); _sharedConflictLogger = Logger.CreateLogger<SharedAssemblyConflict>("SharedAssemblyConflict.csv"); _missingAssemblyLogger = Logger.CreateLogger<MissingAssembly>("MissingAssemblies.csv"); _extraAssemblyLogger = Logger.CreateLogger<ExtraAssembly>("ExtraAssemblies.csv"); foreach (var baseDirectory in directories) { foreach (var directoryPath in Directory.EnumerateDirectories(baseDirectory)) { if (!Directory.Exists(directoryPath)) { throw new InvalidOperationException("Please pass a valid directory name as the first parameter"); } Logger.WriteMessage("Processing Directory {0}", directoryPath); _assemblies.Clear(); _versionConflictLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _missingAssemblyLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _extraAssemblyLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); ProcessDirectory(directoryPath); _versionConflictLogger.Decorator.Remove("Directory"); _missingAssemblyLogger.Decorator.Remove("Directory"); _extraAssemblyLogger.Decorator.Remove("Directory"); } } }
public static IList<string> GetHelpTopics(string helpPath, ReportLogger<HelpIssue> logger) { IList<string> cmdlets = new List<string>(); try { XDocument document = XDocument.Parse(File.ReadAllText(helpPath)); var root = document.Root; foreach (var command in root.GetChildElements("command")) { if (command.ContainsChildElement("details")) { var details = command.GetChildElement("details"); if (details.ContainsChildElement("name")) { cmdlets.Add(details.GetChildElement("name").Value.Trim()); } else { logger.LogRecord(new HelpIssue { HelpFile = helpPath, Severity = 0, ProblemId = MissingCommandName, Description = string.Format("Missing command:name element for file {0}", helpPath), Remediation = "Correct the xml format of the help file" }); } } else { logger.LogRecord(new HelpIssue { HelpFile = helpPath, Severity = 0, ProblemId = MissingCommandDetails, Description = string.Format("Missing command:details element for file {0}", helpPath), Remediation = "Correct the xml format of the help file" }); } } } catch (Exception e) { logger.LogRecord(new HelpIssue { HelpFile = helpPath, Severity = 0, ProblemId = InvalidHelpFile, Description = string.Format("Parsing error for help file {0}: {1}", helpPath, e.ToString()), Remediation = "Correct the xml format of the help file" }); } return cmdlets; }
private void ValidateHelpRecords(IList<CmdletHelpMetadata> cmdlets, IList<string> helpRecords, ReportLogger<HelpIssue> helpLogger) { foreach (var cmdlet in cmdlets) { if (!helpRecords.Contains(cmdlet.CmdletName, StringComparer.OrdinalIgnoreCase)) { helpLogger.LogRecord(new HelpIssue { Target = cmdlet.ClassName, Severity = 1, Description = string.Format("Help missing for cmdlet {0} implemented by class {1}", cmdlet.CmdletName, cmdlet.ClassName), Remediation = string.Format("Add Help record for cmdlet {0} to help file.", cmdlet.CmdletName) }); } } }
private void ValidateHelpRecords(IList <CmdletMetadata> cmdlets, IList <string> helpRecords, ReportLogger <HelpIssue> helpLogger) { foreach (var cmdlet in cmdlets) { if (!helpRecords.Contains(cmdlet.Name, StringComparer.OrdinalIgnoreCase)) { helpLogger.LogRecord(new HelpIssue { Target = cmdlet.ClassName, Severity = 1, ProblemId = MissingHelp, Description = string.Format("Help missing for cmdlet {0} implemented by class {1}", cmdlet.Name, cmdlet.ClassName), Remediation = string.Format("Add Help record for cmdlet {0} to help file.", cmdlet.Name) }); } } }
public void Analyze(IEnumerable <string> directories, IEnumerable <String> modulesToAnalyze) { if (directories == null) { throw new ArgumentNullException("directories"); } _versionConflictLogger = Logger.CreateLogger <AssemblyVersionConflict>("AssemblyVersionConflict.csv"); _sharedConflictLogger = Logger.CreateLogger <SharedAssemblyConflict>("SharedAssemblyConflict.csv"); _missingAssemblyLogger = Logger.CreateLogger <MissingAssembly>("MissingAssemblies.csv"); _extraAssemblyLogger = Logger.CreateLogger <ExtraAssembly>("ExtraAssemblies.csv"); _dependencyMapLogger = Logger.CreateLogger <DependencyMap>("DependencyMap.csv"); foreach (var baseDirectory in directories) { foreach (var directoryPath in Directory.EnumerateDirectories(baseDirectory)) { if (modulesToAnalyze != null && modulesToAnalyze.Any() && !modulesToAnalyze.Any(m => directoryPath.EndsWith(m))) { continue; } if (!Directory.Exists(directoryPath)) { throw new InvalidOperationException("Please pass a valid directory name as the first parameter"); } Logger.WriteMessage("Processing Directory {0}", directoryPath); _assemblies.Clear(); _versionConflictLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _missingAssemblyLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _extraAssemblyLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _dependencyMapLogger.Decorator.AddDecorator(r => { r.Directory = directoryPath; }, "Directory"); _isNetcore = directoryPath.Contains("Az."); ProcessDirectory(directoryPath); _versionConflictLogger.Decorator.Remove("Directory"); _missingAssemblyLogger.Decorator.Remove("Directory"); _extraAssemblyLogger.Decorator.Remove("Directory"); _dependencyMapLogger.Decorator.Remove("Directory"); } } }
/// <summary> /// Check if the given types are arrays, and if so, see if their element types are the same. If not, log an issue. /// </summary> /// <param name="cmdlet">The cmdlet metadata currently being checked.</param> /// <param name="oldTypeMetadata">The type metadata from the old (serialized) assembly.</param> /// <param name="newTypeMetadata">The type metadata from the new assembly.</param> /// <param name="problemId">The problemId used for logging if there is an issue.</param> /// <param name="description">The description used for logging if there is an issue.</param> /// <param name="remediation">The remediation used for logging if there is an issue.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> private bool IsElementType( CmdletMetadata cmdlet, TypeMetadata oldTypeMetadata, TypeMetadata newTypeMetadata, int problemId, string description, string remediation, ReportLogger <BreakingChangeIssue> issueLogger) { // Check if the type is an array if (oldTypeMetadata.ElementType != null && newTypeMetadata.ElementType != null) { // Check if the element of the array is the same in the old and new metadata if (oldTypeMetadata.ElementType.Equals(newTypeMetadata.ElementType, StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this element type, // run this method on the type if (!_typeSet.Contains(oldTypeMetadata.ElementType)) { _typeSet.Add(oldTypeMetadata.ElementType); var oldElementType = _oldTypeDictionary[oldTypeMetadata.ElementType]; var newElementType = _newTypeDictionary[newTypeMetadata.ElementType]; CompareTypeMetadata(cmdlet, oldElementType, newElementType, issueLogger); } } // If the element type has changed, log an issue else { issueLogger?.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: problemId, description: description, remediation: remediation); } return(true); } return(false); }
/// <summary> /// Check if the OutputType of the cmdlet has been removed, or if any property /// of the OutputType has been removed or changed /// </summary> /// <param name="oldCmdlet">The cmdlet metadata from the old (serialized) assembly.</param> /// <param name="newCmdlet">The cmdlet metadata from the new assembly.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> private void CheckForChangedOutputType( CmdletBreakingChangeMetadata oldCmdlet, CmdletBreakingChangeMetadata newCmdlet, ReportLogger <BreakingChangeIssue> issueLogger) { // This dictionary will map an output type name to the corresponding type metadata Dictionary <string, TypeMetadata> outputDictionary = new Dictionary <string, TypeMetadata>(); // Add each output in the new metadata to the dictionary foreach (var newOutput in newCmdlet.OutputTypes) { if (!outputDictionary.ContainsKey(newOutput.Type.AssemblyQualifiedName)) { outputDictionary.Add(newOutput.Type.AssemblyQualifiedName, newOutput.Type); } } // For each output in the old metadata, see if it // exists in the new metadata foreach (var oldOutput in oldCmdlet.OutputTypes) { // If the output can be found, use the TypeMetadataHelper to // check the type for any breaking changes if (outputDictionary.ContainsKey(oldOutput.Type.AssemblyQualifiedName)) { var newOutputType = outputDictionary[oldOutput.Type.AssemblyQualifiedName]; _typeMetadataHelper.CheckOutputType(oldCmdlet, oldOutput.Type, newOutputType, issueLogger); } // If the output cannot be found, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: oldCmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedOutputType, description: string.Format(Properties.Resources.ChangedOutputTypeDescription, oldCmdlet.Name, oldOutput.Type.Name), remediation: string.Format(Properties.Resources.ChangedOutputTypeRemediation, oldCmdlet.Name, oldOutput.Type.Name)); } } }
public override bool Export(ReportLogger reportLogger) { _reportLogger = reportLogger; SetupExport(); int stepId = reportLogger.AddStep(); try { FileInfo fileInfo = new FileInfo(PathAndFileName); FileInfo serverPathAndFile = new FileInfo(_serverPath + fileInfo.Name); FileInfo serverPath = new FileInfo(_serverPath); FileInfo tempDirectory = new FileInfo(_serverPath + @"Temp\"); string filename = fileInfo.Name.Split('.')[0]; XmlExport(fileInfo); if (File.Exists(serverPathAndFile.FullName)) { File.Delete(serverPathAndFile.FullName); } File.Move(tempDirectory + filename + _extension, serverPathAndFile.FullName); if (CoreDataLib.IsLive()) { if (ExportItem.ExportItemFtpId > 0) { FileFtp.FtpFile(serverPathAndFile, reportLogger, ExportItem); } } reportLogger.EndStep(stepId); } catch (Exception exception) { _reportLogger.EndStep(stepId, exception); return(false); } return(true); }
/// <summary> /// Check if the parameter now supports the ValidateNotNullOrEmpty attribute /// </summary> /// <param name="cmdlet">The cmdlet whose parameter metadata is currently being checked.</param> /// <param name="oldParameter">The parameter metadata from the old (serialized) assembly.</param> /// <param name="newParameter">The parameter metadata from new assembly</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> private void CheckForValidateNotNullOrEmpty( CmdletBreakingChangeMetadata cmdlet, ParameterMetadata oldParameter, ParameterMetadata newParameter, ReportLogger <BreakingChangeIssue> issueLogger) { // If the parameter didn't have the ValidateNotNullOrEmpty attribute in the // old assembly, but has it in the new assembly, log an issue if (!oldParameter.ValidateNotNullOrEmpty && newParameter.ValidateNotNullOrEmpty) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.AddedValidateNotNullOrEmpty, description: string.Format(Properties.Resources.AddedValidateNotNullOrEmptyDescription, oldParameter.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.AddedValidateNotNullOrEmptyRemediation, oldParameter.Name)); } }
public static void ImportRunFtp() { ReportLogger importRunFtpLogger = new ReportLogger("ImportRunFtpLogger"); importRunFtpLogger.StartLog("Start of Run"); try { SaveCriteria(importRunFtpLogger); UpdateIncludeTable(importRunFtpLogger); LoadFlightCostCache(importRunFtpLogger); LoadPropertyPriceCache(importRunFtpLogger); CreateAllOutputFiles(importRunFtpLogger); SendEmails("Dear All, the InternationalOfferLoader has successfully completed an import and load run for"); importRunFtpLogger.EndLog(); } catch (Exception e) { importRunFtpLogger.EndLog(e); } }
internal static void CheckQueItems() { List <string> queItems = CoreDataLibrary.Data.Get.GetQueItems(); Parallel.ForEach(queItems, currentExportItem => { ReportLogger reportLogger = new ReportLogger(currentExportItem); try { ExportItem exportItem = Get.GetExportItem(currentExportItem); reportLogger = new ReportLogger(exportItem.ExportItemName); reportLogger.StartLog("Exporting : " + exportItem.ExportItemName); exportItem.Export(reportLogger); reportLogger.EndLog(exportItem.ExportItemName + " : Exported"); } catch (Exception e) { reportLogger.EndLog(e); Emailer.SendEmail("*****@*****.**", "CoreDataReportService", "MainProcess->Run", e); } }); }
/// <summary> /// Run all of the different breaking change checks that we have for the tool /// </summary> /// <param name="oldModuleMetadata">Information about the module from the old (serialized) assembly.</param> /// <param name="newModuleMetadata">Information about the module from the new assembly.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> private void RunBreakingChangeChecks( ModuleMetadata oldModuleMetadata, ModuleMetadata newModuleMetadata, ReportLogger <BreakingChangeIssue> issueLogger) { // Get the list of cmdlet metadata from each module var oldCmdlets = oldModuleMetadata.Cmdlets; var newCmdlets = newModuleMetadata.Cmdlets; // Get the type dictionary from each module var oldTypeDictionary = oldModuleMetadata.TypeDictionary; var newTypeDictionary = newModuleMetadata.TypeDictionary; // Initialize a TypeMetadataHelper object that knows how to compare types var typeMetadataHelper = new TypeMetadataHelper(oldTypeDictionary, newTypeDictionary); // Initialize a CmdletMetadataHelper object that knows how to compare cmdlets var cmdletMetadataHelper = new CmdletMetadataHelper(typeMetadataHelper); // Compare the cmdlet metadata cmdletMetadataHelper.CompareCmdletMetadata(oldCmdlets, newCmdlets, issueLogger); }
private static void ProcessLongOutput(string fileName, ReportLogger reportLogger) { int stepId = reportLogger.AddStep("International Offer Loader - " + fileName); try { using (SqlConnection conn = new SqlConnection(DataConnection.InternationalOfferLoaderConnection)) { SqlCommand cmd = new SqlCommand("dbo.uspOutputLong", conn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@psFileName", fileName); cmd.CommandTimeout = 72000; conn.Open(); cmd.ExecuteNonQuery(); reportLogger.EndStep(stepId); } } catch (Exception e) { reportLogger.EndStep(stepId, e); } }
public override bool Run() { if (DueToRun()) { ReportLogger.AddMessage("Trello", "Passed Due To Run."); ReportLogger reportLogger = new ReportLogger(Name); int stepId = reportLogger.AddStep(); try { ReportLogger.AddMessage("Trello", "Running"); List <TrelloList> lists = GetLists(key, token); //Returns list of ids etc in correct order as per on screen ReportLogger.AddMessage("Trello", "GetList"); Dictionary <string, string> contacts = Get.Contacts(); foreach (KeyValuePair <string, string> contact in contacts) { string message = Emailer.EmailContent(lists, contact.Value); Emailer.SendEmail(contact.Key, "LCTG - Daily Business Priorities", message, false, "*****@*****.**"); ReportLogger.AddMessage("Trello", "Email sent."); } reportLogger.EndStep(stepId); ReportLogger.AddMessage("Trello", "Completed"); } catch (Exception ex) { reportLogger.EndStep(stepId, ex); return(false); } reportLogger.EndLog(); return(true); } return(false); }
public override bool DueToRun() { if (QuedToRun) { QuedToRun = false; return(true); } //ReportLogger.AddMessage("Trello", "Due To Run"); ReadFromDb(); //ReportLogger.AddMessage("Trello", "ReadFrom Db() completed."); var dateTime = DateTime.Now; var timeSpan = dateTime - LastRun; //ReportLogger.AddMessage("Trello", "Check Timespan to see if it is due to run."); if (timeSpan.TotalMinutes >= 60 && dateTime.Hour == 7) { ReportLogger.AddMessage("Trello", "Due To Run."); LastRun = dateTime; return(true); } return(false); }
public bool RunReport() { ReportLogger reportLogger = new ReportLogger(ReportName); int stepId = reportLogger.AddStep(); try { if (DueToRun()) { OfferLoader.FirstLoad(); LastRun = DateTime.Now; reportLogger.EndStep(stepId); } reportLogger.EndStep(stepId); } catch (Exception e) { reportLogger.EndStep(stepId, e); return(false); } return(true); }
private void ValidateHelpRecords(IList <CmdletMetadata> cmdlets, IList <string> helpRecords, ReportLogger <HelpIssue> helpLogger) { var cmdletDict = new Dictionary <string, CmdletMetadata>(); foreach (var cmdlet in cmdlets) { cmdletDict.Add(cmdlet.Name, cmdlet); if (!helpRecords.Contains(cmdlet.Name, StringComparer.OrdinalIgnoreCase)) { HelpIssue issue = new HelpIssue { Target = cmdlet.ClassName, Severity = 1, ProblemId = MissingHelp, Remediation = string.Format("Add Help record for cmdlet {0} to help file.", cmdlet.Name) }; if (cmdlet.ClassName != null) { issue.Description = $"Help missing for cmdlet {cmdlet.Name} implemented by class {cmdlet.ClassName}"; } else { issue.Description = $"Help missing for cmdlet {cmdlet.Name} implemented by functions"; } helpLogger.LogRecord(issue); } } foreach (var helpRecord in helpRecords) { if (!cmdletDict.ContainsKey(helpRecord)) { Console.Error.WriteLine($"Help record {helpRecord} has no cmdlet."); } } }
/// <summary> /// Check if the arguments of a generic type are the same. If they are not, log an issue. /// </summary> /// <param name="cmdlet">The cmdlet metadata currently being checked.</param> /// <param name="oldArgument">The old argument from the generic.</param> /// <param name="newArgument">The new argument from the generic</param> /// <param name="target">Target of the generic type breaking change.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> private bool CheckGenericTypeArguments( CmdletBreakingChangeMetadata cmdlet, string oldArgument, string newArgument, string target, ReportLogger <BreakingChangeIssue> issueLogger) { if (oldArgument.Equals(newArgument, StringComparison.OrdinalIgnoreCase)) { return(true); } // If the generic type arguments aren't the same, log an issue issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedGenericTypeArgument, description: string.Format(Properties.Resources.ChangedGenericTypeArgumentDescription, target, oldArgument, newArgument), remediation: string.Format(Properties.Resources.ChangedGenericTypeArgumentRemediation, target, oldArgument)); return(false); }
private void AnalyzeMarkdownHelp( IEnumerable <string> scopes, string directory, ReportLogger <HelpIssue> helpLogger, List <string> processedHelpFiles, string savedDirectory) { var helpFolder = Directory.EnumerateDirectories(directory, "help").FirstOrDefault(); var service = Path.GetFileName(directory); if (helpFolder == null) { helpLogger.LogRecord(new HelpIssue() { Assembly = service, Description = string.Format("{0} has no matching help folder", service), Severity = 0, Remediation = string.Format("Make sure a help folder for {0} exists and it is " + "being copied to the output directory.", service), Target = service, HelpFile = service + "/folder", ProblemId = MissingHelpFile }); return; } var helpFiles = Directory.EnumerateFiles(helpFolder, "*.md").Select(Path.GetFileNameWithoutExtension).ToList(); // Assume all cmdlets markdown file following format of VERB-AzResource. Dash is required. helpFiles = helpFiles.Where(c => c.Contains("-")).ToList(); if (!helpFiles.Any()) { return; } Directory.SetCurrentDirectory(directory); var manifestFiles = Directory.EnumerateFiles(directory, "*.psd1").ToList(); if (manifestFiles.Count > 1) { manifestFiles = manifestFiles.Where(f => Path.GetFileName(f).IndexOf(service) >= 0).ToList(); } if (manifestFiles.Count == 0) { return; } var psd1 = manifestFiles.FirstOrDefault(); var parentDirectory = Directory.GetParent(psd1).FullName; var psd1FileName = Path.GetFileName(psd1); var powershell = PowerShell.Create(); var script = $"Import-LocalizedData -BaseDirectory {parentDirectory} -FileName {psd1FileName} -BindingVariable ModuleMetadata; $ModuleMetadata.NestedModules"; powershell.AddScript(script); var cmdletResult = powershell.Invoke(); var nestedModules = new List <string>(); foreach (var module in cmdletResult) { if (module != null && module.ToString().StartsWith(".")) { nestedModules.Add(module.ToString().Substring(2)); } else if (module != null) { nestedModules.Add(module.ToString()); } } script = $"Import-LocalizedData -BaseDirectory {parentDirectory} -FileName {psd1FileName}" + " -BindingVariable ModuleMetadata; $ModuleMetadata.RequiredModules | % { $_[\"ModuleName\"] };"; cmdletResult = PowerShell.Create().AddScript(script).Invoke(); var requiredModules = cmdletResult.Where(c => c != null && !c.ToString().StartsWith(".")).Select(c => c.ToString()).ToList(); var allCmdlets = new List <CmdletMetadata>(); if (nestedModules.Any()) { Directory.SetCurrentDirectory(directory); requiredModules = requiredModules.Join(scopes, module => 1, dir => 1, (module, dir) => Path.Combine(dir, module)) .Where(Directory.Exists) .ToList(); requiredModules.Add(directory); foreach (var nestedModule in nestedModules) { var assemblyFile = Directory.GetFiles(parentDirectory, nestedModule, SearchOption.AllDirectories).FirstOrDefault(); if (!File.Exists(assemblyFile)) { continue; } var assemblyFileName = Path.GetFileName(assemblyFile); helpLogger.Decorator.AddDecorator(h => { h.HelpFile = assemblyFileName; h.Assembly = assemblyFileName; }, "Cmdlet"); processedHelpFiles.Add(assemblyFileName); // TODO: Remove IfDef #if NETSTANDARD var proxy = new CmdletLoader(); #else var proxy = EnvironmentHelpers.CreateProxy <CmdletLoader>(directory, out _appDomain); #endif var module = proxy.GetModuleMetadata(assemblyFile, requiredModules); var cmdlets = module.Cmdlets; allCmdlets.AddRange(cmdlets); helpLogger.Decorator.Remove("Cmdlet"); // TODO: Remove IfDef code #if !NETSTANDARD AppDomain.Unload(_appDomain); #endif } } script = $"Import-LocalizedData -BaseDirectory {parentDirectory} -FileName {psd1FileName} -BindingVariable ModuleMetadata; $ModuleMetadata.FunctionsToExport;"; cmdletResult = PowerShell.Create().AddScript(script).Invoke(); var functionCmdlets = cmdletResult.Select(c => c.ToString()).ToList(); foreach (var cmdlet in functionCmdlets) { var metadata = new CmdletMetadata(); metadata.VerbName = cmdlet.Split("-")[0]; metadata.NounName = cmdlet.Split("-")[1]; allCmdlets.Add(metadata); } ValidateHelpRecords(allCmdlets, helpFiles, helpLogger); ValidateHelpMarkdown(helpFolder, helpFiles, helpLogger); Directory.SetCurrentDirectory(savedDirectory); }
private void AnalyzeMamlHelp( IEnumerable <string> scopes, string directory, ReportLogger <HelpIssue> helpLogger, List <string> processedHelpFiles, string savedDirectory) { var commandAssemblies = Directory.EnumerateFiles(directory, "*.Commands.*.dll") .Where(f => IsAssemblyFile(f) && !File.Exists(f + "-Help.xml")); foreach (var orphanedAssembly in commandAssemblies) { helpLogger.LogRecord(new HelpIssue() { Assembly = orphanedAssembly, Description = string.Format("{0} has no matching help file", orphanedAssembly), Severity = 0, Remediation = string.Format("Make sure a dll Help file for {0} exists and it is " + "being copied to the output directory.", orphanedAssembly), Target = orphanedAssembly, HelpFile = orphanedAssembly + "-Help.xml", ProblemId = MissingHelpFile }); } var helpFiles = Directory.EnumerateFiles(directory, "*.dll-Help.xml") .Where(f => !processedHelpFiles.Contains(Path.GetFileName(f), StringComparer.OrdinalIgnoreCase)).ToList(); if (!helpFiles.Any()) { return; } Directory.SetCurrentDirectory(directory); foreach (var helpFile in helpFiles) { var cmdletFile = helpFile.Substring(0, helpFile.Length - "-Help.xml".Length); var helpFileName = Path.GetFileName(helpFile); var cmdletFileName = Path.GetFileName(cmdletFile); if (!File.Exists(cmdletFile)) { continue; } processedHelpFiles.Add(helpFileName); helpLogger.Decorator.AddDecorator(h => { h.HelpFile = helpFileName; h.Assembly = cmdletFileName; }, "Cmdlet"); // TODO: Remove IfDef #if NETSTANDARD var proxy = new CmdletLoader(); #else var proxy = EnvironmentHelpers.CreateProxy <CmdletLoader>(directory, out _appDomain); #endif var module = proxy.GetModuleMetadata(cmdletFile); var cmdlets = module.Cmdlets; var helpRecords = CmdletHelpParser.GetHelpTopics(helpFile, helpLogger); ValidateHelpRecords(cmdlets, helpRecords, helpLogger); helpLogger.Decorator.Remove("Cmdlet"); // TODO: Remove IfDef code #if !NETSTANDARD AppDomain.Unload(_appDomain); #endif } Directory.SetCurrentDirectory(savedDirectory); }
public abstract bool Export(ReportLogger reportLogger);
/// <summary> /// Compares the metadata of parameter sets with the same name for any breaking changes. /// /// Breaking changes for parameter sets include /// - Removing a parameter set /// - Making an optional parameter mandatory /// - Changing the position of a parameter /// - A parameter that previously could get its value from the pipeline no longer does /// - A parameter that previously could get its value from the pipeline by property name no longer does /// - A parameter has been removed from the parameter set /// </summary> /// <param name="cmdlet">Reference to the cmdlet whose parameter sets are being checked.</param> /// <param name="oldParameterSets">The list of parameter sets from the old (serialized) metadata.</param> /// <param name="newParameterSets">The list of parameter sets from the new metadata</param> /// <param name="issueLogger">ReportLogger that will keep track of the issues found.</param> public void CompareParameterSetMetadata( CmdletMetadata cmdlet, List <ParameterSetMetadata> oldParameterSets, List <ParameterSetMetadata> newParameterSets, ReportLogger <BreakingChangeIssue> issueLogger) { // This dictionary will map a parameter set name to the corresponding metadata Dictionary <string, ParameterSetMetadata> parameterSetDictionary = new Dictionary <string, ParameterSetMetadata>(); // Add each parameter set to the dictionary foreach (var newParameterSet in newParameterSets) { parameterSetDictionary.Add(newParameterSet.Name, newParameterSet); } // For each parameter set in the old metadata, see if it has been // added to the dictionary (exists in the new metadata) foreach (var oldParameterSet in oldParameterSets) { bool foundMatch = false; // Find matching parameter set foreach (var newParameterSet in newParameterSets) { Dictionary <string, Parameter> parameterDictionary = new Dictionary <string, Parameter>(); foreach (var parameter in newParameterSet.Parameters) { parameterDictionary.Add(parameter.ParameterMetadata.Name, parameter); foreach (var alias in parameter.ParameterMetadata.AliasList) { parameterDictionary.Add(alias, parameter); } } // Check if set has minimum parameters required to match bool minimumRequired = true; foreach (var parameter in oldParameterSet.Parameters) { if (!parameterDictionary.ContainsKey(parameter.ParameterMetadata.Name)) { minimumRequired = false; break; } else { var newParameter = parameterDictionary[parameter.ParameterMetadata.Name]; if (!parameter.Mandatory && newParameter.Mandatory || parameter.Position >= 0 && parameter.Position != newParameter.Position || parameter.ValueFromPipeline && !newParameter.ValueFromPipeline || parameter.ValueFromPipelineByPropertyName && !newParameter.ValueFromPipelineByPropertyName) { minimumRequired = false; break; } } } if (!minimumRequired) { continue; } parameterDictionary = new Dictionary <string, Parameter>(); foreach (var parameter in oldParameterSet.Parameters) { parameterDictionary.Add(parameter.ParameterMetadata.Name, parameter); foreach (var alias in parameter.ParameterMetadata.AliasList) { parameterDictionary.Add(alias, parameter); } } // Check if set has any additional mandatory parameters bool foundAdditional = false; foreach (var parameter in newParameterSet.Parameters) { if (parameterDictionary.ContainsKey(parameter.ParameterMetadata.Name)) { continue; } if (parameter.Mandatory) { foundAdditional = true; break; } } if (!foundAdditional) { foundMatch = true; break; } } if (!foundMatch) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.RemovedParameterSet, description: string.Format(Properties.Resources.RemovedParameterSetDescription, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.RemovedParameterSetRemediation, oldParameterSet.Name, cmdlet.Name)); } } }
private void AnalyzeMarkdownHelp( IEnumerable <string> scopes, string directory, ReportLogger <HelpIssue> helpLogger, List <string> processedHelpFiles, string savedDirectory) { var helpFolder = Directory.EnumerateDirectories(directory, "help").FirstOrDefault(); var service = Path.GetFileName(directory); if (helpFolder == null) { helpLogger.LogRecord(new HelpIssue() { Assembly = service, Description = string.Format("{0} has no matching help folder", service), Severity = 0, Remediation = string.Format("Make sure a help folder for {0} exists and it is " + "being copied to the output directory.", service), Target = service, HelpFile = service + "/folder", ProblemId = MissingHelpFile }); return; } var helpFiles = Directory.EnumerateFiles(helpFolder, "*.md").Select(f => Path.GetFileNameWithoutExtension(f)).ToList(); if (helpFiles.Any()) { Directory.SetCurrentDirectory(directory); var manifestFiles = Directory.EnumerateFiles(directory, "*.psd1").ToList(); if (manifestFiles.Count > 1) { manifestFiles = manifestFiles.Where(f => Path.GetFileName(f).IndexOf(service) >= 0).ToList(); } if (manifestFiles.Count == 0) { return; } var psd1 = manifestFiles.FirstOrDefault(); var parentDirectory = Directory.GetParent(psd1).FullName; var psd1FileName = Path.GetFileName(psd1); IEnumerable <string> nestedModules = null; List <string> requiredModules = null; PowerShell powershell = PowerShell.Create(); powershell.AddScript("Import-LocalizedData -BaseDirectory " + parentDirectory + " -FileName " + psd1FileName + " -BindingVariable ModuleMetadata; $ModuleMetadata.NestedModules; $ModuleMetadata.RequiredModules | % { $_[\"ModuleName\"] };"); var cmdletResult = powershell.Invoke(); nestedModules = cmdletResult.Where(c => c.ToString().StartsWith(".")).Select(c => c.ToString().Substring(2)); requiredModules = cmdletResult.Where(c => !c.ToString().StartsWith(".")).Select(c => c.ToString()).ToList(); if (nestedModules.Any()) { Directory.SetCurrentDirectory(directory); requiredModules = requiredModules.Join(scopes, module => 1, dir => 1, (module, dir) => Path.Combine(dir, module)) .Where(f => Directory.Exists(f)) .ToList(); requiredModules.Add(directory); List <CmdletMetadata> allCmdlets = new List <CmdletMetadata>(); foreach (var nestedModule in nestedModules) { var assemblyFile = Directory.GetFiles(parentDirectory, nestedModule, SearchOption.AllDirectories).FirstOrDefault(); if (File.Exists(assemblyFile)) { var assemblyFileName = Path.GetFileName(assemblyFile); helpLogger.Decorator.AddDecorator((h) => { h.HelpFile = assemblyFileName; h.Assembly = assemblyFileName; }, "Cmdlet"); processedHelpFiles.Add(assemblyFileName); var proxy = EnvironmentHelpers.CreateProxy <CmdletLoader>(directory, out _appDomain); var module = proxy.GetModuleMetadata(assemblyFile, requiredModules); var cmdlets = module.Cmdlets; allCmdlets.AddRange(cmdlets); helpLogger.Decorator.Remove("Cmdlet"); AppDomain.Unload(_appDomain); } } ValidateHelpRecords(allCmdlets, helpFiles, helpLogger); } Directory.SetCurrentDirectory(savedDirectory); } }
/// <summary> /// Compare two types by recursively checking their properties and property /// types, making sure that nothing has been removed or changed. /// </summary> /// <param name="cmdlet">The cmdlet metadata currently being checked.</param> /// <param name="oldType">The type metadata from the old (serialized) assembly.</param> /// <param name="newType">The type metadata from the new assembly.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> public void CompareTypeMetadata( CmdletBreakingChangeMetadata cmdlet, TypeMetadata oldType, TypeMetadata newType, ReportLogger <BreakingChangeIssue> issueLogger) { // For each property in the old assembly type, find the corresponding // property in the new assembly type foreach (var oldProperty in oldType.Properties.Keys) { if (newType.Properties.ContainsKey(oldProperty)) { var oldPropertyType = oldType.Properties[oldProperty]; var newPropertyType = newType.Properties[oldProperty]; var oldTypeMetadata = _oldTypeDictionary[oldPropertyType]; var newTypeMetadata = _newTypeDictionary[newPropertyType]; // Define variables for logging int problemId = ProblemIds.BreakingChangeProblemId.ChangedElementType; string description = string.Format(Properties.Resources.ChangedElementTypeDescription, oldProperty, oldTypeMetadata.ElementType, newTypeMetadata.ElementType); string remediation = string.Format(Properties.Resources.ChangedElementTypeRemediation, oldProperty, oldTypeMetadata.ElementType); // If the type is an array, check for any breaking changes if (IsElementType(cmdlet, oldTypeMetadata, newTypeMetadata, problemId, description, remediation, issueLogger)) { continue; } string target = string.Format("property {0}", oldProperty); // If the type is a generic, check for any breaking changes if (IsGenericType(cmdlet, oldTypeMetadata, newTypeMetadata, target, issueLogger)) { continue; } // If the types are the same, compare their properties if (oldPropertyType.Equals(newPropertyType, StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this type, run this // method on the type if (!_typeSet.Contains(oldPropertyType)) { _typeSet.Add(oldPropertyType); CompareTypeMetadata(cmdlet, oldTypeMetadata, newTypeMetadata, issueLogger); } } else { // If the type of the property has been changed, log an issue issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedPropertyType, description: string.Format(Properties.Resources.ChangedPropertyTypeDescription, oldProperty, oldType.Name, oldPropertyType, newPropertyType), remediation: string.Format(Properties.Resources.ChangedPropertyTypeRemediation, oldProperty, oldPropertyType)); } } else { // If the property has been removed, log an issue issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.RemovedProperty, description: string.Format(Properties.Resources.RemovedPropertyDescription, oldProperty, oldType.Name), remediation: string.Format(Properties.Resources.RemovedPropertyRemediation, oldProperty, oldType.Name)); } } }
/// <summary> /// Compares the metadata of parameter sets with the same name for any breaking changes. /// /// Breaking changes for parameter sets include /// - Removing a parameter set /// - Making an optional parameter mandatory /// - Changing the position of a parameter /// - A parameter that previously could get its value from the pipeline no longer does /// - A parameter that previously could get its value from the pipeline by property name no longer does /// - A parameter has been removed from the parameter set /// </summary> /// <param name="cmdlet">Reference to the cmdlet whose parameter sets are being checked.</param> /// <param name="oldParameterSets">The list of parameter sets from the old (serialized) metadata.</param> /// <param name="newParameterSets">The list of parameter sets from the new metadata</param> /// <param name="issueLogger">ReportLogger that will keep track of the issues found.</param> public void CompareParameterSetMetadata( CmdletBreakingChangeMetadata cmdlet, List <ParameterSetMetadata> oldParameterSets, List <ParameterSetMetadata> newParameterSets, ReportLogger <BreakingChangeIssue> issueLogger) { // This dictionary will map a parameter set name to the corresponding metadata Dictionary <string, ParameterSetMetadata> parameterSetDictionary = new Dictionary <string, ParameterSetMetadata>(); // Add each parameter set to the dictionary foreach (var newParameterSet in newParameterSets) { parameterSetDictionary.Add(newParameterSet.Name, newParameterSet); } // For each parameter set in the old metadata, see if it has been // added to the dictionary (exists in the new metadata) foreach (var oldParameterSet in oldParameterSets) { if (parameterSetDictionary.ContainsKey(oldParameterSet.Name)) { var newParameterSet = parameterSetDictionary[oldParameterSet.Name]; // This dictionary will map a parameter to the corresponding Parameter object Dictionary <string, Parameter> parameterDictionary = new Dictionary <string, Parameter>(); // For each parameter in the parameter set, add its name and alias to the dictionary foreach (var newParameter in newParameterSet.Parameters) { if (!parameterDictionary.ContainsKey(newParameter.ParameterMetadata.Name)) { parameterDictionary.Add(newParameter.ParameterMetadata.Name, newParameter); } foreach (var alias in newParameter.ParameterMetadata.AliasList) { if (!parameterDictionary.ContainsKey(alias)) { parameterDictionary.Add(alias, newParameter); } } } // For each parameter in the old metadata, see if it has been // added to the dictionary (exists in the new metadata) foreach (var oldParameter in oldParameterSet.Parameters) { if (parameterDictionary.ContainsKey(oldParameter.ParameterMetadata.Name)) { var newParameter = parameterDictionary[oldParameter.ParameterMetadata.Name]; // If the parameter was optional in the old assembly and // mandatory in the new assembly, log an issue if (!oldParameter.Mandatory && newParameter.Mandatory) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.MandatoryParameter, description: string.Format(Properties.Resources.MandatoryParameterDescription, oldParameter.ParameterMetadata.Name, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.MandatoryParameterRemediation, oldParameter.ParameterMetadata.Name, oldParameterSet.Name)); } // If the parameter had a position and it has changed in the // new assembly, log an issue if (oldParameter.Position >= 0 && oldParameter.Position != newParameter.Position) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.PositionChange, description: string.Format(Properties.Resources.PositionChangeDescription, oldParameter.ParameterMetadata.Name, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.PositionChangeRemediation, oldParameter.ParameterMetadata.Name, oldParameterSet.Name)); } // If the parameter can no longer get its value from // the pipeline, log an issue if (oldParameter.ValueFromPipeline && !newParameter.ValueFromPipeline) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ValueFromPipeline, description: string.Format(Properties.Resources.RemovedValueFromPipelineDescription, oldParameter.ParameterMetadata.Name, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.RemovedValueFromPipelineRemediation, oldParameter.ParameterMetadata.Name, oldParameterSet.Name)); } // If the parameter can no longer get its value from // the pipeline by property name, log an issue if (oldParameter.ValueFromPipelineByPropertyName && !newParameter.ValueFromPipelineByPropertyName) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ValueFromPipelineByPropertyName, description: string.Format(Properties.Resources.RemovedValueFromPipelineByPropertyNameDescription, oldParameter.ParameterMetadata.Name, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.RemovedValueFromPipelineByPropertyNameRemediation, oldParameter.ParameterMetadata.Name, oldParameterSet.Name)); } } // If the parameter cannot be found, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.RemovedParameterFromParameterSet, description: string.Format(Properties.Resources.RemovedParameterFromParameterSetDescription, oldParameter.ParameterMetadata.Name, cmdlet.Name, oldParameterSet.Name), remediation: string.Format(Properties.Resources.RemovedParameterFromParameterSetRemediation, oldParameter.ParameterMetadata.Name, oldParameterSet.Name)); } } } // If the parameter set cannot be found, and the parameter set // was not the default (no parameter set) name, log an issue else if (!parameterSetDictionary.ContainsKey(oldParameterSet.Name) && !oldParameterSet.Name.Equals("__AllParameterSets")) { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.RemovedParameterSet, description: string.Format(Properties.Resources.RemovedParameterSetDescription, oldParameterSet.Name, cmdlet.Name), remediation: string.Format(Properties.Resources.RemovedParameterSetRemediation, oldParameterSet.Name, cmdlet.Name)); } } }
public static void Run() { if (!CoreDataLib.IsLive()) { List <ExportItem> runList = Get.GetAllRunItems(); foreach (ExportItem exportItem in runList) { ReportLogger reportLogger = new ReportLogger(exportItem.ExportItemName); try { //exportItem.Export(reportLogger); if (exportItem.ExportItemName == "LCH_FullStock_HotelOnly_HC_ENG") { exportItem.Export(reportLogger); //LchFullStockImagesEngTsmExportItem expItem = new LchFullStockImagesEngTsmExportItem(exportItem); //expItem.Export(reportLogger); } //exportItem.Export(reportLogger); //if (exportItem.ExportItemName.Contains("LCH_FullStock_HotelOnly_ENG_100R")) //{ // exportItem.Export(reportLogger); //} reportLogger.EndLog(); } catch (Exception e) { reportLogger.EndLog(e); } } //Parallel.ForEach(runList, currentExportItem => //{ // ReportLogger reportLogger = new ReportLogger(currentExportItem.ExportItemName); // try // { // reportLogger.StartLog(currentExportItem.ExportItemName); // currentExportItem.Export(reportLogger); // reportLogger.EndLog(); // } // catch (Exception e) // { // reportLogger.EndLog(e); // Emailer.SendEmail("*****@*****.**", "CoreDataReportService", "MainProcess->Run", e); // } //}); } else { List <ExportItem> runList = Get.GetRunItems(DateTime.Now.Hour); Parallel.ForEach(runList, currentExportItem => { ReportLogger reportLogger = new ReportLogger(currentExportItem.ExportItemName); try { reportLogger.StartLog(currentExportItem.ExportItemName); currentExportItem.Export(reportLogger); reportLogger.EndLog(); } catch (Exception e) { reportLogger.EndLog(e); Emailer.SendEmail("*****@*****.**", "CoreDataReportService", "MainProcess->Run", e); } }); } }
protected override void OnStop() { ReportLogger.AddMessage("CoreData Report Service", "Stopped"); }
public Dictionary <string, object> Post(string type, [FromForm] long id, [FromForm] string sessionid) { Dictionary <string, object> response = new Dictionary <string, object>(); if (!Program.users.TryGetValue(sessionid, out User user) && user.mod > 0) { response.Add("status", 1); response.Add("msg", "Invalid session"); return(response); } if (user.banned) { response.Add("status", 4); response.Add("msg", "You are banned from doing this"); return(response); } string column; string table; switch (type) { case "thread": column = "threadid"; table = "threads"; break; case "comment": column = "commentid"; table = "comments"; break; case "user": column = "uid"; table = "users"; break; default: response.Add("status", 2); response.Add("msg", "Invalid report type"); return(response); } SqlConnection con = new SqlConnection(Program.Configuration["connectionStrings:splashConString"]); SqlCommand command = new SqlCommand("UPDATE " + table + " SET reported = 0 WHERE " + column + " = @id;", con); command.Parameters.AddWithValue("id", id); con.Open(); if (command.ExecuteNonQuery() > 0) { ReportLogger.LogAction(type, ReportLogger.RELEASE, id, user.uid); response.Add("status", 0); response.Add("msg", "Reports cleared"); } else { response.Add("status", 5); response.Add("msg", "Internal error occured"); } con.Close(); return(response); }
/// <summary> /// Checks if the type of the output is an array or a generic, and makes sure there are no breaking changes. /// If the type is not an array or a generic, it proceeds with the normal type checking with CompareTypeMetadata. /// </summary> /// <param name="cmdlet">The cmdlet whose output metadata is being checked for breaking changes.</param> /// <param name="oldTypeMetadata">The type metadata from the old (serialized) assembly.</param> /// <param name="newTypeMetadata">The type metadata from the new assembly.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> public void CheckOutputType( CmdletBreakingChangeMetadata cmdlet, TypeMetadata oldTypeMetadata, TypeMetadata newTypeMetadata, ReportLogger <BreakingChangeIssue> issueLogger) { // Check if the type is an array if (oldTypeMetadata.ElementType != null && newTypeMetadata.ElementType != null) { // Check if the element of the array is the same in the old and new metadata if (oldTypeMetadata.ElementType.Equals(newTypeMetadata.ElementType, StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this element type, // run this method on the type if (!_typeSet.Contains(oldTypeMetadata.ElementType)) { _typeSet.Add(oldTypeMetadata.ElementType); var oldElementType = _oldTypeDictionary[oldTypeMetadata.ElementType]; var newElementType = _newTypeDictionary[newTypeMetadata.ElementType]; CompareTypeMetadata(cmdlet, oldElementType, newElementType, issueLogger); } } // If the element type has changed, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedOutputElementType, description: string.Format(Properties.Resources.ChangedOutputElementTypeDescription, oldTypeMetadata.ElementType, newTypeMetadata.ElementType), remediation: string.Format(Properties.Resources.ChangedOutputElementTypeRemediation, oldTypeMetadata.ElementType)); } return; } // Check if the type is a generic if (oldTypeMetadata.GenericTypeArguments.Count > 0 && newTypeMetadata.GenericTypeArguments.Count > 0) { // Check if the generic type has changed if (oldTypeMetadata.Name.Equals(newTypeMetadata.Name, StringComparison.OrdinalIgnoreCase)) { // Check if the number of generic type arguments is the same if (oldTypeMetadata.GenericTypeArguments.Count == newTypeMetadata.GenericTypeArguments.Count) { // For each element in the generic type arguments list, make sure that the types // are the same for (int idx = 0; idx < oldTypeMetadata.GenericTypeArguments.Count; idx++) { if (oldTypeMetadata.GenericTypeArguments[idx].Equals(newTypeMetadata.GenericTypeArguments[idx], StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this generic type argument, // run this method on the type if (!_typeSet.Contains(oldTypeMetadata.GenericTypeArguments[idx])) { _typeSet.Add(oldTypeMetadata.GenericTypeArguments[idx]); var oldElementType = _oldTypeDictionary[oldTypeMetadata.GenericTypeArguments[idx]]; var newElementType = _newTypeDictionary[newTypeMetadata.GenericTypeArguments[idx]]; CompareTypeMetadata(cmdlet, oldElementType, newElementType, issueLogger); } } // If the generic type arguments aren't the same, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedOutputGenericTypeArgument, description: string.Format(Properties.Resources.ChangedOutputGenericTypeArgumentDescription, oldTypeMetadata.GenericTypeArguments[idx], newTypeMetadata.GenericTypeArguments[idx]), remediation: string.Format(Properties.Resources.ChangedOutputGenericTypeArgumentRemediation, oldTypeMetadata.GenericTypeArguments[idx])); } } } // If the number of generic type arguments is different, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.DifferentOutputGenericTypeArgumentSize, description: string.Format(Properties.Resources.DifferentOutputGenericTypeArgumentSizeDescription, oldTypeMetadata.Name, oldTypeMetadata.GenericTypeArguments.Count, newTypeMetadata.GenericTypeArguments.Count), remediation: string.Format(Properties.Resources.DifferentOutputGenericTypeArgumentSizeRemediation, oldTypeMetadata.Name, oldTypeMetadata.GenericTypeArguments.Count)); } } // If the generic type has changed, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedOutputGenericType, description: string.Format(Properties.Resources.ChangedOutputGenericTypeDescription, oldTypeMetadata.Name, newTypeMetadata.Name), remediation: string.Format(Properties.Resources.ChangedOutputGenericTypeRemediation, oldTypeMetadata.Name)); } return; } CompareTypeMetadata(cmdlet, oldTypeMetadata, newTypeMetadata, issueLogger); }
private void ValidateHelpMarkdown(string helpFolder, IList <string> helpRecords, ReportLogger <HelpIssue> helpLogger) { foreach (var helpMarkdown in helpRecords) { var file = Path.Combine(helpFolder, helpMarkdown + ".md"); var content = File.ReadAllText(file); try { var parser = new MarkdownParser(); var transformer = new ModelTransformerVersion2(); var markdownModel = parser.ParseString(new[] { content }); var model = transformer.NodeModelToMamlModel(markdownModel).FirstOrDefault(); } catch (Exception ex) { HelpIssue issue = new HelpIssue { Target = helpMarkdown, Severity = 1, ProblemId = PlatyPSSchemaViolation, Description = "Help content doesn't conform to PlatyPS Schema definition", Remediation = string.Format("No.") }; helpLogger.LogRecord(issue); Console.Error.WriteLine($"Failed to parse {file} by PlatyPS, {ex.Message}"); } } }
/// <summary> /// Check whether there exist lenient mandatory equal in the cmdlet /// Lenient mandatory equal means for two parameter set, one parameter set's mandatory parameters can /// be found in another parameter set whether as mandatory or optional. /// If all these two parameter set are not defualt, it may cause confusion. /// </summary> public void ValidateParameterSetWithLenientMandatoryEqual(CmdletMetadata cmdlet, ReportLogger <SignatureIssue> issueLogger) { var defaultParameterSet = cmdlet.DefaultParameterSet; foreach (var parameterSet1 in cmdlet.ParameterSets) { foreach (var parameterSet2 in cmdlet.ParameterSets) { if (!parameterSet1.Equals(parameterSet2) && cmdlet.DefaultParameterSetName != parameterSet1.Name && cmdlet.DefaultParameterSetName != parameterSet2.Name && parameterSet1.Name.CompareTo(parameterSet2.Name) > 0) { if (parameterSet1.AllMandatoryParemeterLenientEquals(parameterSet2) && !IsParameterSetIntersectionCoveredByDefault(parameterSet1, parameterSet2, defaultParameterSet)) { issueLogger.LogSignatureIssue( cmdlet: cmdlet, severity: 1, problemId: SignatureProblemId.ParameterSetWithLenientMandatoryEqual, description: string.Format( "Parameter set '{0}' and '{1}' of cmdlet '{2}', for all mandatory parameters in {0} " + "we can find mandatory and optional parameter in {1}, and all mandatory parameter in " + "{1} can find the corresponding mandatory parameter in {0}, " + "and both of them are not default parameter set which may cause confusion.", parameterSet1.Name, parameterSet2.Name, cmdlet.Name), remediation: "Merge these parameter sets into one parameter set."); } } } } }
/// <summary> /// Compare two types by recursively checking their properties and property /// types, making sure that nothing has been removed or changed. /// </summary> /// <param name="cmdlet">The cmdlet metadata currently being checked.</param> /// <param name="oldType">The type metadata from the old (serialized) assembly.</param> /// <param name="newType">The type metadata from the new assembly.</param> /// <param name="issueLogger">ReportLogger that will keep track of issues found.</param> public void CompareTypeMetadata( CmdletBreakingChangeMetadata cmdlet, TypeMetadata oldType, TypeMetadata newType, ReportLogger <BreakingChangeIssue> issueLogger) { // For each property in the old assembly type, find the corresponding // property in the new assembly type foreach (var oldProperty in oldType.Properties.Keys) { if (newType.Properties.ContainsKey(oldProperty)) { var oldPropertyType = oldType.Properties[oldProperty]; var newPropertyType = newType.Properties[oldProperty]; var oldTypeMetadata = _oldTypeDictionary[oldPropertyType]; var newTypeMetadata = _newTypeDictionary[newPropertyType]; // Check if the type is an array if (oldTypeMetadata.ElementType != null && newTypeMetadata.ElementType != null) { // Check if the element of the array is the same in the old and new metadata if (oldTypeMetadata.ElementType.Equals(newTypeMetadata.ElementType, StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this element type, // run this method on the type if (!_typeSet.Contains(oldTypeMetadata.ElementType)) { _typeSet.Add(oldTypeMetadata.ElementType); var oldElementType = _oldTypeDictionary[oldTypeMetadata.ElementType]; var newElementType = _newTypeDictionary[newTypeMetadata.ElementType]; CompareTypeMetadata(cmdlet, oldElementType, newElementType, issueLogger); } } // If the element type has changed, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedElementType, description: string.Format(Properties.Resources.ChangedElementTypeDescription, oldProperty, oldTypeMetadata.ElementType, newTypeMetadata.ElementType), remediation: string.Format(Properties.Resources.ChangedElementTypeRemediation, oldProperty, oldTypeMetadata.ElementType)); } continue; } // Check if the type is a generic if (oldTypeMetadata.GenericTypeArguments.Count > 0 && newTypeMetadata.GenericTypeArguments.Count > 0) { // Check if the generic type has changed if (oldTypeMetadata.Name.Equals(newTypeMetadata.Name, StringComparison.OrdinalIgnoreCase)) { // Check if the number of generic type arguments is the same if (oldTypeMetadata.GenericTypeArguments.Count == newTypeMetadata.GenericTypeArguments.Count) { // For each element in the generic type arguments list, make sure that the types // are the same for (int idx = 0; idx < oldTypeMetadata.GenericTypeArguments.Count; idx++) { if (oldTypeMetadata.GenericTypeArguments[idx].Equals(newTypeMetadata.GenericTypeArguments[idx], StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this generic type argument, // run this method on the type if (!_typeSet.Contains(oldTypeMetadata.GenericTypeArguments[idx])) { _typeSet.Add(oldTypeMetadata.GenericTypeArguments[idx]); var oldElementType = _oldTypeDictionary[oldTypeMetadata.GenericTypeArguments[idx]]; var newElementType = _newTypeDictionary[newTypeMetadata.GenericTypeArguments[idx]]; CompareTypeMetadata(cmdlet, oldElementType, newElementType, issueLogger); } } // If the generic type arguments aren't the same, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedGenericTypeArgument, description: string.Format(Properties.Resources.ChangedGenericTypeArgumentDescription, oldProperty, oldTypeMetadata.GenericTypeArguments[idx], newTypeMetadata.GenericTypeArguments[idx]), remediation: string.Format(Properties.Resources.ChangedGenericTypeArgumentRemediation, oldProperty, oldTypeMetadata.GenericTypeArguments[idx])); } } } // If the number of generic type arguments is different, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.DifferentGenericTypeArgumentSize, description: string.Format(Properties.Resources.DifferentGenericTypeArgumentSizeDescription, oldTypeMetadata.Name, oldProperty, oldTypeMetadata.GenericTypeArguments.Count, newTypeMetadata.GenericTypeArguments.Count), remediation: string.Format(Properties.Resources.DifferentGenericTypeArgumentSizeRemediation, oldTypeMetadata.Name, oldTypeMetadata.GenericTypeArguments.Count)); } } // If the generic type has changed, log an issue else { issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedGenericType, description: string.Format(Properties.Resources.ChangedGenericTypeDescription, oldProperty, oldTypeMetadata.Name, newTypeMetadata.Name), remediation: string.Format(Properties.Resources.ChangedGenericTypeRemediation, oldProperty, oldTypeMetadata.Name)); } continue; } // If the types are the same, compare their properties if (oldPropertyType.Equals(newPropertyType, StringComparison.OrdinalIgnoreCase)) { // If we have not previously seen this type, run this // method on the type if (!_typeSet.Contains(oldPropertyType)) { _typeSet.Add(oldPropertyType); CompareTypeMetadata(cmdlet, oldTypeMetadata, newTypeMetadata, issueLogger); } } else { // If the type of the property has been changed, log an issue issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.ChangedPropertyType, description: string.Format(Properties.Resources.ChangedPropertyTypeDescription, oldProperty, oldType.Name, oldPropertyType, newPropertyType), remediation: string.Format(Properties.Resources.ChangedPropertyTypeRemediation, oldProperty, oldPropertyType)); } } else { // If the property has been removed, log an issue issueLogger.LogBreakingChangeIssue( cmdlet: cmdlet, severity: 0, problemId: ProblemIds.BreakingChangeProblemId.RemovedProperty, description: string.Format(Properties.Resources.RemovedPropertyDescription, oldProperty, oldType.Name), remediation: string.Format(Properties.Resources.RemovedPropertyRemediation, oldProperty, oldType.Name)); } } }
/// <summary> /// Check whether there exist mandatory equal in the cmdlet. /// Mandatory equal means two parameter set has exactly the same mandatory parameters. /// If all these two parameter set are not defualt, it may cause confusion. /// An example: https://github.com/Azure/azure-powershell/issues/10954 /// </summary> public void ValidateParameterSetWithMandatoryEqual(CmdletMetadata cmdlet, ReportLogger <SignatureIssue> issueLogger) { var defaultParameterSet = cmdlet.DefaultParameterSet; List <HashSet <string> > mandatoryEqualSetList = new List <HashSet <string> >(); foreach (var parameterSet1 in cmdlet.ParameterSets) { foreach (var parameterSet2 in cmdlet.ParameterSets) { if (!parameterSet1.Equals(parameterSet2) && cmdlet.DefaultParameterSetName != parameterSet1.Name && cmdlet.DefaultParameterSetName != parameterSet2.Name) { if (parameterSet1.AllMandatoryParemeterEquals(parameterSet2) && !IsParameterSetIntersectionCoveredByDefault(parameterSet1, parameterSet2, defaultParameterSet)) { var isExistInSet = false; foreach (var mandatoryEqualSet in mandatoryEqualSetList) { if (mandatoryEqualSet.Contains(parameterSet1.Name) || mandatoryEqualSet.Contains(parameterSet2.Name)) { mandatoryEqualSet.Add(parameterSet1.Name); mandatoryEqualSet.Add(parameterSet2.Name); isExistInSet = true; break; } } if (!isExistInSet) { HashSet <string> newSet = new HashSet <string>(); newSet.Add(parameterSet1.Name); newSet.Add(parameterSet2.Name); mandatoryEqualSetList.Add(newSet); } } } } } if (mandatoryEqualSetList.Count > 0) { foreach (var mandatoryEqualSet in mandatoryEqualSetList) { string mandatoryEqualSetNames = ""; foreach (var mandatoryEqualSetName in mandatoryEqualSet) { if (mandatoryEqualSetNames != "") { mandatoryEqualSetNames += ", "; } mandatoryEqualSetNames += "'" + mandatoryEqualSetName + "'"; } issueLogger.LogSignatureIssue( cmdlet: cmdlet, severity: 1, problemId: SignatureProblemId.ParameterSetWithStrictMandatoryEqual, description: string.Format( "Parameter set {0} of cmdlet '{1}' have the same mandatory parameters, " + "and both of them are not default parameter set which may cause confusion.", mandatoryEqualSetNames, cmdlet.Name), remediation: "Merge these parameter sets into one parameter set."); } } }