示例#1
0
        public static Dictionary <string, CheckData> BuildIdToChecksMap(string csvFile, Func <CheckData, bool> predicate)
        {
            var checkDataList = CsvOperations.ParseCheckDatas(csvFile).Where(predicate).ToList();

            var result = new Dictionary <string, CheckData>();

            for (int i = 0; i < checkDataList.Count; ++i)
            {
                var checkData = checkDataList[i];
                Debug.Assert(!result.ContainsKey(checkData.Id));
                // a hidden ID used for codefix purpose only
                if (checkData.Id == "RS0021")
                {
                    continue;
                }
                // convert short description to readableID for those missing it
                if (checkData.Name.Trim().Equals(@"#N/A"))
                {
                    checkData.Name = Utilities.ConvertStringToPascalCase(checkData.Title);
                }

                if (string.IsNullOrWhiteSpace(checkData.Category))
                {
                    checkData.Category = "NoCetegory";
                }

                result[checkData.Id] = checkData;
            }
            return(result);
        }
示例#2
0
        public static void Main(string[] args)
        {
            _masterCsvFile     = args[0];
            _messageCsvFile    = args[1];
            _templateDirectory = args[2];
            _targetDirectory   = args[3];

            if (args.Length != 4)
            {
                Console.WriteLine("Usage: IncrementalGenerator <RuleInventory CSV file> <FxCop Messages CSV file> <Template Files Directory> <Target Directory>");
            }

            if (!Directory.Exists(_targetDirectory))
            {
                Console.WriteLine("ERROR: target directory doesn't exist: " + _targetDirectory);
                Console.WriteLine("       (SolutionGenerator could be used to generate all files from scratch)");
                return;
            }

            _sourceFilesDirectory = Path.Combine(_targetDirectory, "src");
            if (!Directory.Exists(_sourceFilesDirectory))
            {
                throw new ArgumentException($"Error: {_sourceFilesDirectory} doesn't exist.");
            }

            // Build the list of checks from the rule inventory spreadsheet
            var allChecks = Utilities.BuildIdToChecksMap(_masterCsvFile,
                                                         c => c.Port == PortStatus.Yes && (c.RevisedPriority == Priority.High || c.OriginalPriority == Priority.High));

            // reorg the dictionary by check name
            Dictionary <string, CheckData> allChecksByName = new Dictionary <string, CheckData>();

            foreach (var pair in allChecks)
            {
                Debug.Assert(!allChecksByName.ContainsKey(pair.Value.Name), $"Error: Duplicate check name found: {pair.Value.Name}");
                allChecksByName[pair.Value.Name] = pair.Value;
            }

            // Read core project files of existing analyzers and build a list of already implemented rules.
            // We assume all the existing analyzers follow the naming convention.
            var existingChecksByName = GetExistingChecksFromCoreProjects(_targetDirectory, allChecksByName);

            // generate a list of existing analyzer projects
            var existingAnalyzers = new HashSet <string>();

            foreach (var analyzer in existingChecksByName.Select(c => c.Value.AnalyzerProject))
            {
                existingAnalyzers.Add(analyzer);
            }

            // Build the list of checks that doesn't exist in target directory.
            var newChecksToAdd    = new Dictionary <string, CheckData>();
            var newChecksToCreate = new Dictionary <string, CheckData>();

            foreach (var check in allChecksByName)
            {
                if (existingChecksByName.ContainsKey(check.Key))
                {
                    continue;
                }
                if (!existingAnalyzers.Contains(check.Value.AnalyzerProject))
                {
                    newChecksToCreate[check.Value.Id] = check.Value;
                }
                else
                {
                    newChecksToAdd[check.Value.Id] = check.Value;
                }
            }

            // Add FxCop messages
            CsvOperations.ParseCheckMessages(_messageCsvFile, newChecksToAdd);

            // rebuild the data, organized by analyzer project
            var newChecksToAddByAnalyzer = Utilities.BuildAnalyzerToChecksMap(newChecksToAdd.Values);

            // generate new files and insert them to existing projects
            foreach (var pair in newChecksToAddByAnalyzer)
            {
                var analyzer = pair.Key;
                var checks   = pair.Value;

                AddNewChecksToCoreProject(analyzer, checks);
                AddNewChecksToCSharpProject(analyzer, checks);
                AddNewChecksToVisualBasicProject(analyzer, checks);
                AddNewChecksToUnitTestsProject(analyzer, checks);
                AddNewStringsToResxFile(analyzer, checks);
            }
            Console.WriteLine("Added checks:");
            foreach (var pair in newChecksToAddByAnalyzer)
            {
                Console.WriteLine($"\t{pair.Key}");
                foreach (var check in pair.Value)
                {
                    Console.WriteLine($"\t\t{check.Id}");
                }
            }

            if (newChecksToCreate.Count > 0)
            {
                if (!Directory.Exists(_templateDirectory))
                {
                    Console.WriteLine("ERROR: Template files directory doesn't exist: " + _templateDirectory);
                    return;
                }
                CsvOperations.ParseCheckMessages(_messageCsvFile, newChecksToCreate);
                var newChecksToCreateByAnalyzer = Utilities.BuildAnalyzerToChecksMap(newChecksToCreate.Values);

                // create new projects
                var projectGuids = new Dictionary <string, Dictionary <string, string> >();
                var categories   = new Dictionary <string, IEnumerable <string> >();
                foreach (var pair in newChecksToCreateByAnalyzer)
                {
                    categories[pair.Key] = Utilities.GetCategories(pair.Value);
                }

                Utilities.EmitAnalyzerProjects(newChecksToCreateByAnalyzer, _targetDirectory, _templateDirectory, categories, projectGuids);

                Console.WriteLine("Created checks:");
                foreach (var pair in newChecksToCreateByAnalyzer)
                {
                    Console.WriteLine($"\t{pair.Key}");
                    foreach (var check in pair.Value)
                    {
                        Console.WriteLine($"\t\t{check.Id}");
                    }
                }
            }
        }
示例#3
0
        static void Main(string[] args)
        {
            _masterCsvFile   = args[0];
            _messageCsvFile  = args[1];
            _sourceDirectory = args[2];
            _outputDirectory = args[3];

            _projectGuids = new Dictionary <string, Dictionary <string, string> >();

            bool force = false;

            if (args.Length == 5 && args[4].Equals("/force"))
            {
                force = true;
            }

            if (Directory.Exists(_outputDirectory))
            {
                if (!force)
                {
                    Console.WriteLine("ERROR: can't overwrite existing directory: " + _outputDirectory);
                    Console.WriteLine("       pass /force on the command-line to delete and regenerate this content.");
                    return;
                }
                Directory.Delete(_outputDirectory, true);
            }

            CopyStarterFilesToOutputLocation(_sourceDirectory, _outputDirectory);

            // TODOS: add priorization data

            // Build a global list of checks. This operation ensures
            // no check id is reused between any entries
            Dictionary <string, CheckData> checks = Utilities.BuildIdToChecksMap(_masterCsvFile, c => c.Port == PortStatus.Yes || c.Port == PortStatus.Ported);

            // Add FxCop resolutions as messages for checks ported from FxCop
            CsvOperations.ParseCheckMessages(_messageCsvFile, checks);

            // Now we will rebuild the data, organizing it by project
            Dictionary <string, List <CheckData> > analyzers = Utilities.BuildAnalyzerToChecksMap(checks.Values);

            _categories = new Dictionary <string, IEnumerable <string> >();
            foreach (var pair in analyzers)
            {
                _categories[pair.Key] = Utilities.GetCategories(pair.Value);
            }

            // Emit projects associated with each analyzer. These include a core project, a C#
            // project (for C#-specific AST analyzers), a VB project (ditto) and test project
            Utilities.EmitAnalyzerProjects(analyzers, _outputDirectory, _sourceDirectory, _categories, _projectGuids);

            // TODO emit table that can be published as wiki page to track porting progress
            // EmitWikiTable(analyzers);

            EmitAnalyzerVersionsTargetsFile(analyzers);

            EmitNuGetPackagingProjFile(analyzers);

            EmitBuildAndTestProjFile(analyzers);

            EmitSolution(analyzers);

            Console.WriteLine("Done");
        }