예제 #1
0
        public void summaryScales()
        {
            string programDir = srcDir + "\\ExprData\\sourcecode";
            string summaryDir = srcDir + "\\ExprData\\summaryScales";

            if (!Directory.Exists(summaryDir))
            {
                Directory.CreateDirectory(summaryDir);
            }
            int           sumFiles   = 0;
            int           sumClasses = 0;
            int           sumMethods = 0;
            int           sumLines   = 0;
            StringBuilder sb_files   = new StringBuilder();
            StringBuilder sb_classes = new StringBuilder();
            StringBuilder sb_methods = new StringBuilder();
            StringBuilder sb_lines   = new StringBuilder();

            foreach (var proPath in Directory.GetDirectories(programDir))
            {
                string proName = proPath.Split('\\').Last();

                Console.WriteLine("Summary " + proName + "...");

                int countFiles            = 0;
                int countClasses          = 0;
                int countMethods          = 0;
                int countLines            = 0;
                HashSet <string> filePath = new HashSet <string>();
                foreach (var slnPath in Common.scanCSharpSln(proPath))
                {
                    var msWorkspace = MSBuildWorkspace.Create();
                    var sol         = msWorkspace.OpenSolutionAsync(slnPath).Result;
                    foreach (var pro in sol.Projects)
                    {
                        foreach (var doc in pro.Documents)
                        {
                            if (filePath.Contains(doc.FilePath))
                            {
                                continue;
                            }
                            filePath.Add(doc.FilePath);
                            countFiles++;
                            var rootNode    = doc.GetSyntaxRootAsync().Result;
                            var classNodes  = rootNode.DescendantNodes().OfType <ClassDeclarationSyntax>();
                            var methodNodes = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>();
                            countClasses += classNodes.Count();
                            countMethods += methodNodes.Count();
                            var text = doc.GetTextAsync().Result.ToString();
                            countLines += text.Split('\n').Length;
                        }
                    }
                }
                sumFiles   += countFiles;
                sumClasses += countClasses;
                sumMethods += countMethods;
                sumLines   += countLines;

                sb_files.AppendLine(proName + "\t" + countFiles);
                sb_classes.AppendLine(proName + "\t" + countClasses);
                sb_methods.AppendLine(proName + "\t" + countMethods);
                sb_lines.AppendLine(proName + "\t" + countLines);
            }
            File.WriteAllText(summaryDir + "\\Files.txt", sb_files.ToString());
            File.WriteAllText(summaryDir + "\\Classes.txt", sb_classes.ToString());
            File.WriteAllText(summaryDir + "\\Methods.txt", sb_methods.ToString());
            File.WriteAllText(summaryDir + "\\Lines.txt", sb_lines.ToString());
            StringBuilder sb1 = new StringBuilder();

            sb1.AppendLine("Files\t\t" + sumFiles);
            sb1.AppendLine("Classes\t\t" + sumClasses);
            sb1.AppendLine("Methods\t\t" + sumMethods);
            sb1.AppendLine("Lines\t\t" + sumLines);
            File.WriteAllText(summaryDir + "\\Sum.txt", sb1.ToString());
        }
예제 #2
0
        private async Task LoadSolutionAsync()
        {
            var roslynRoot   = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
            var solutionPath = Path.Combine(roslynRoot, "Compilers.sln");

            if (!File.Exists(solutionPath))
            {
                throw new ArgumentException("Couldn't find Compilers.sln");
            }

            Console.WriteLine("Found Compilers.sln: " + Process.GetCurrentProcess().Id);

            var assemblies = MSBuildMefHostServices.DefaultAssemblies
                             .Add(typeof(AnalyzerRunnerHelper).Assembly)
                             .Add(typeof(FindReferencesBenchmarks).Assembly);
            var services = MefHostServices.Create(assemblies);

            _workspace = MSBuildWorkspace.Create(new Dictionary <string, string>
            {
                // Use the latest language version to force the full set of available analyzers to run on the project.
                { "LangVersion", "preview" },
            }, services);

            if (_workspace == null)
            {
                throw new ArgumentException("Couldn't create workspace");
            }

            _workspace.TryApplyChanges(_workspace.CurrentSolution.WithOptions(_workspace.Options
                                                                              .WithChangedOption(StorageOptions.Database, StorageDatabase.SQLite)));

            Console.WriteLine("Opening roslyn.  Attach to: " + Process.GetCurrentProcess().Id);

            var start = DateTime.Now;

            _solution = await _workspace.OpenSolutionAsync(solutionPath, progress : null, CancellationToken.None);

            Console.WriteLine("Finished opening roslyn: " + (DateTime.Now - start));

            // Force a storage instance to be created.  This makes it simple to go examine it prior to any operations we
            // perform, including seeing how big the initial string table is.
            var storageService = _workspace.Services.GetPersistentStorageService(_workspace.CurrentSolution.Options);

            if (storageService == null)
            {
                throw new ArgumentException("Couldn't get storage service");
            }

            using (var storage = await storageService.GetStorageAsync(SolutionKey.ToSolutionKey(_workspace.CurrentSolution), CancellationToken.None))
            {
                Console.WriteLine("Sucessfully got persistent storage instance");
            }

            // There might be multiple projects with this name.  That's ok.  FAR goes and finds all the linked-projects
            // anyways  to perform the search on all the equivalent symbols from them.  So the end perf cost is the
            // same.
            var project = _solution.Projects.First(p => p.AssemblyName == "Microsoft.CodeAnalysis");

            start = DateTime.Now;
            var compilation = await project.GetCompilationAsync();

            Console.WriteLine("Time to get first compilation: " + (DateTime.Now - start));
            _type = compilation.GetTypeByMetadataName("Microsoft.CodeAnalysis.SyntaxToken");
            if (_type == null)
            {
                throw new Exception("Couldn't find type");
            }
        }
예제 #3
0
        private Solution LoadSolution(string solutionFilePath, IDictionary <string, string> properties = null)
        {
            var ws = MSBuildWorkspace.Create(properties);

            return(ws.OpenSolutionAsync(solutionFilePath).Result);
        }
예제 #4
0
 public void Cleanup()
 {
     _workspace?.Dispose();
     _workspace = null;
     _solution  = null;
 }
예제 #5
0
 public DiagramGenerator(string solutionPath, MSBuildWorkspace workspace)
 {
     _solution = workspace.OpenSolutionAsync(solutionPath).Result;
 }
예제 #6
0
        private static async Task Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
#if DEBUG
                args = new[] { @"..\..\..\..\.." };
#else
                args = new string[] { Environment.CurrentDirectory };
#endif
            }

            string rootPath = args[0];

            StringComparer comparer = StringComparer.InvariantCulture;

            var metadata = new RoslynatorMetadata(rootPath);

            ImmutableArray <AnalyzerMetadata>           analyzers             = metadata.Analyzers;
            ImmutableArray <AnalyzerMetadata>           codeAnalysisAnalyzers = metadata.CodeAnalysisAnalyzers;
            ImmutableArray <AnalyzerMetadata>           formattingAnalyzers   = metadata.FormattingAnalyzers;
            ImmutableArray <RefactoringMetadata>        refactorings          = metadata.Refactorings;
            ImmutableArray <CodeFixMetadata>            codeFixes             = metadata.CodeFixes;
            ImmutableArray <CompilerDiagnosticMetadata> compilerDiagnostics   = metadata.CompilerDiagnostics;

            WriteAllText(
                @"..\docs\Options.md",
                MarkdownGenerator.CreateListOfAnalyzerOptions(metadata));

            WriteAnalyzersReadMe(@"Analyzers\README.md", analyzers, "Roslynator.Analyzers");

            WriteAnalyzersReadMe(@"CodeAnalysis.Analyzers\README.md", codeAnalysisAnalyzers, "Roslynator.CodeAnalysis.Analyzers");

            WriteAnalyzersReadMe(@"Formatting.Analyzers\README.md", formattingAnalyzers, "Roslynator.Formatting.Analyzers");
#if !DEBUG
            VisualStudioInstance instance = MSBuildLocator.QueryVisualStudioInstances().First(f => f.Version.Major == 16);

            MSBuildLocator.RegisterInstance(instance);

            using (MSBuildWorkspace workspace = MSBuildWorkspace.Create())
            {
                workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);

                string solutionPath = Path.Combine(rootPath, "Roslynator.sln");

                Console.WriteLine($"Loading solution '{solutionPath}'");

                Solution solution = await workspace.OpenSolutionAsync(solutionPath).ConfigureAwait(false);

                Console.WriteLine($"Finished loading solution '{solutionPath}'");

                RoslynatorInfo roslynatorInfo = await RoslynatorInfo.Create(solution).ConfigureAwait(false);

                IOrderedEnumerable <SourceFile> sourceFiles = analyzers
                                                              .Concat(codeAnalysisAnalyzers)
                                                              .Concat(formattingAnalyzers)
                                                              .Select(f => new SourceFile(f.Id, roslynatorInfo.GetAnalyzerFilesAsync(f.Identifier).Result))
                                                              .Concat(refactorings
                                                                      .Select(f => new SourceFile(f.Id, roslynatorInfo.GetRefactoringFilesAsync(f.Identifier).Result)))
                                                              .OrderBy(f => f.Id);

                MetadataFile.SaveSourceFiles(sourceFiles, @"..\SourceFiles.xml");
            }
#endif
            WriteAnalyzerMarkdowns(codeAnalysisAnalyzers, new (string, string)[] { ("Roslynator.CodeAnalysis.Analyzers", "https://www.nuget.org/packages/Roslynator.CodeAnalysis.Analyzers") });
예제 #7
0
        private static async Task MainAsync(string[] args, CancellationToken cancellationToken)
        {
            // A valid call must have at least one parameter (a solution file). Optionally it can include /all or /id:SAXXXX.
            if (args.Length < 1)
            {
                PrintHelp();
            }
            else
            {
                bool applyChanges = args.Contains("/apply");
                if (applyChanges)
                {
                    if (!args.Contains("/fixall"))
                    {
                        Console.Error.WriteLine("Error: /apply can only be used with /fixall");
                        return;
                    }
                }

                MSBuildLocator.RegisterDefaults();

                Stopwatch stopwatch = Stopwatch.StartNew();
                var       analyzers = GetAllAnalyzers();

                analyzers = FilterAnalyzers(analyzers, args).ToImmutableArray();

                if (analyzers.Length == 0)
                {
                    PrintHelp();
                    return;
                }

                var properties = new Dictionary <string, string>
                {
                    // This property ensures that XAML files will be compiled in the current AppDomain
                    // rather than a separate one. Any tasks isolated in AppDomains or tasks that create
                    // AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
                    { "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
                };

                MSBuildWorkspace workspace    = MSBuildWorkspace.Create();
                string           solutionPath = args.SingleOrDefault(i => !i.StartsWith("/", StringComparison.Ordinal));
                Solution         solution     = await workspace.OpenSolutionAsync(solutionPath, cancellationToken : cancellationToken).ConfigureAwait(false);

                Console.WriteLine($"Loaded solution in {stopwatch.ElapsedMilliseconds}ms");

                if (args.Contains("/stats"))
                {
                    List <Project> csharpProjects = solution.Projects.Where(i => i.Language == LanguageNames.CSharp).ToList();

                    Console.WriteLine("Number of projects:\t\t" + csharpProjects.Count);
                    Console.WriteLine("Number of documents:\t\t" + csharpProjects.Sum(x => x.DocumentIds.Count));

                    var statistics = await GetAnalyzerStatisticsAsync(csharpProjects, cancellationToken).ConfigureAwait(true);

                    Console.WriteLine("Number of syntax nodes:\t\t" + statistics.NumberofNodes);
                    Console.WriteLine("Number of syntax tokens:\t" + statistics.NumberOfTokens);
                    Console.WriteLine("Number of syntax trivia:\t" + statistics.NumberOfTrivia);
                }

                stopwatch.Restart();

                bool force = args.Contains("/force");

                var diagnostics = await GetAnalyzerDiagnosticsAsync(solution, analyzers, force, cancellationToken).ConfigureAwait(true);

                var allDiagnostics = diagnostics.SelectMany(i => i.Value).ToImmutableArray();

                Console.WriteLine($"Found {allDiagnostics.Length} diagnostics in {stopwatch.ElapsedMilliseconds}ms");

                bool testDocuments = args.Contains("/editperf") || args.Any(arg => arg.StartsWith("/editperf:"));
                if (testDocuments)
                {
                    Func <string, bool> documentMatch = _ => true;
                    string matchArg = args.FirstOrDefault(arg => arg.StartsWith("/editperf:"));
                    if (matchArg != null)
                    {
                        Regex expression = new Regex(matchArg.Substring("/editperf:".Length), RegexOptions.Compiled | RegexOptions.IgnoreCase);
                        documentMatch = documentPath => expression.IsMatch(documentPath);
                    }

                    int    iterations    = 10;
                    string iterationsArg = args.FirstOrDefault(arg => arg.StartsWith("/edititer:"));
                    if (iterationsArg != null)
                    {
                        iterations = int.Parse(iterationsArg.Substring("/edititer:".Length));
                    }

                    var projectPerformance  = new Dictionary <ProjectId, double>();
                    var documentPerformance = new Dictionary <DocumentId, DocumentAnalyzerPerformance>();
                    foreach (var projectId in solution.ProjectIds)
                    {
                        Project project = solution.GetProject(projectId);
                        if (project.Language != LanguageNames.CSharp)
                        {
                            continue;
                        }

                        foreach (var documentId in project.DocumentIds)
                        {
                            var document = project.GetDocument(documentId);
                            if (!documentMatch(document.FilePath))
                            {
                                continue;
                            }

                            var currentDocumentPerformance = await TestDocumentPerformanceAsync(analyzers, project, documentId, iterations, force, cancellationToken).ConfigureAwait(false);

                            Console.WriteLine($"{document.FilePath ?? document.Name}: {currentDocumentPerformance.EditsPerSecond:0.00}");
                            documentPerformance.Add(documentId, currentDocumentPerformance);
                        }

                        double sumOfDocumentAverages = documentPerformance.Where(x => x.Key.ProjectId == projectId).Sum(x => x.Value.EditsPerSecond);
                        double documentCount         = documentPerformance.Where(x => x.Key.ProjectId == projectId).Count();
                        if (documentCount > 0)
                        {
                            projectPerformance[project.Id] = sumOfDocumentAverages / documentCount;
                        }
                    }

                    var slowestFiles = documentPerformance.OrderBy(pair => pair.Value.EditsPerSecond).GroupBy(pair => pair.Key.ProjectId);
                    Console.WriteLine("Slowest files in each project:");
                    foreach (var projectGroup in slowestFiles)
                    {
                        Console.WriteLine($"  {solution.GetProject(projectGroup.Key).Name}");
                        foreach (var pair in projectGroup.Take(5))
                        {
                            var document = solution.GetDocument(pair.Key);
                            Console.WriteLine($"    {document.FilePath ?? document.Name}: {pair.Value.EditsPerSecond:0.00}");
                        }
                    }

                    foreach (var projectId in solution.ProjectIds)
                    {
                        double averageEditsInProject;
                        if (!projectPerformance.TryGetValue(projectId, out averageEditsInProject))
                        {
                            continue;
                        }

                        Project project = solution.GetProject(projectId);
                        Console.WriteLine($"{project.Name} ({project.DocumentIds.Count} documents): {averageEditsInProject:0.00} edits per second");
                    }
                }

                foreach (var group in allDiagnostics.GroupBy(i => i.Id).OrderBy(i => i.Key, StringComparer.OrdinalIgnoreCase))
                {
                    Console.WriteLine($"  {group.Key}: {group.Count()} instances");

                    // Print out analyzer diagnostics like AD0001 for analyzer exceptions
                    if (group.Key.StartsWith("AD", StringComparison.Ordinal))
                    {
                        foreach (var item in group)
                        {
                            Console.WriteLine(item);
                        }
                    }
                }

                string logArgument = args.FirstOrDefault(x => x.StartsWith("/log:"));
                if (logArgument != null)
                {
                    string fileName = logArgument.Substring(logArgument.IndexOf(':') + 1);
                    WriteDiagnosticResults(diagnostics.SelectMany(i => i.Value.Select(j => Tuple.Create(i.Key, j))).ToImmutableArray(), fileName);
                }

                if (args.Contains("/codefixes"))
                {
                    await TestCodeFixesAsync(stopwatch, solution, allDiagnostics, cancellationToken).ConfigureAwait(true);
                }

                if (args.Contains("/fixall"))
                {
                    await TestFixAllAsync(stopwatch, solution, diagnostics, applyChanges, cancellationToken).ConfigureAwait(true);
                }
            }
        }
예제 #8
0
        private static async Task <int> Main(string[] args)
        {
            // TODO: Figure out why `dotnet run` from generateapis.sh is sending 6 args instead of 3 as in: arg1 arg2 arg3 arg1 arg2 arg3
            if (args.Length < 3)
            {
                Console.WriteLine("Arguments: <project file> <api client name> <user client name>");
                return(1);
            }

            var projectFile    = args[0];
            var apiClientName  = args[1];
            var userClientName = args[2];

            var workspace = MSBuildWorkspace.Create(new Dictionary <string, string> {
                ["TargetFramework"] = "net45"
            });

            Project project;

            try
            {
                project = await workspace.OpenProjectAsync(projectFile);
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine($"Could not find project file {projectFile}");
                return(2);
            }

            var compilation = await project.GetCompilationAsync();

            var symbols = compilation.GetSymbolsWithName(name => name == apiClientName, SymbolFilter.Type).ToList();

            if (symbols.Count != 1)
            {
                Console.WriteLine($"Could not find type {apiClientName}");

                var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToList();
                if (errors.Count != 0)
                {
                    Console.WriteLine($"Errors: {errors.Count}, first error: {errors[0]}");
                }
                return(2);
            }

            var apiClientSymbol = (INamedTypeSymbol)symbols[0];

            // Find the API client from a generated file (there should be only one).
            var generatedApiClientSyntax = apiClientSymbol.DeclaringSyntaxReferences
                                           .Select(syntaxReference => syntaxReference.GetSyntax())
                                           .Cast <ClassDeclarationSyntax>()
                                           .SingleOrDefault(
                syntax => syntax.SyntaxTree.GetRoot().GetLeadingTrivia().ToFullString().Contains("// Generated code. DO NOT EDIT!"));

            if (generatedApiClientSyntax == null)
            {
                Console.WriteLine($"Could not find an auto-generated file containing the {apiClientName} definition");
                return(3);
            }

            var syntaxTree                              = generatedApiClientSyntax.SyntaxTree;
            var semanticModel                           = compilation.GetSemanticModel(syntaxTree);
            var generator                               = SyntaxGenerator.GetGenerator(project.GetDocument(syntaxTree));
            var requestMethodRewriter                   = new RequestMethodRewriter(semanticModel);
            var nonRequestMethodRewriter                = new ClientMethodRewriter(semanticModel);
            var requestMethodToImplRewriter             = new RequestMethodToImplRewriter();
            var convertToAsyncCancellationTokenOverload = new ConvertToAsyncCancellationTokenOverloadRewriter();

            var userClientSyntax =
                (ClassDeclarationSyntax)generator.ClassDeclaration(
                    userClientName,
                    accessibility: Accessibility.Public,
                    modifiers: DeclarationModifiers.Partial)
                .WithLeadingTrivia(generatedApiClientSyntax.GetLeadingTrivia());
            var userClientImplSyntax =
                (ClassDeclarationSyntax)generator.ClassDeclaration(
                    userClientName + "Impl",
                    accessibility: Accessibility.Public,
                    modifiers: DeclarationModifiers.Sealed | DeclarationModifiers.Partial,
                    baseType: ParseTypeName(userClientName))
                .WithLeadingTrivia(generatedApiClientSyntax.GetLeadingTrivia());

            // Copy the request methods from the API client with the user client. We only require these to be copied since
            // we already have handwritten flattening overloads to change ByteString to BigtableByteString.
            foreach (var methodSyntax in generatedApiClientSyntax.Members.OfType <MethodDeclarationSyntax>())
            {
                var method = semanticModel.GetDeclaredSymbol(methodSyntax);
                if (method.DeclaredAccessibility != Accessibility.Public ||
                    method.Parameters.IsEmpty)
                {
                    continue;
                }

                if (method.Parameters.Length == 2 &&
                    method.Parameters[0].Type.Name.EndsWith("Request"))
                {
                    var clientMethod = (MethodDeclarationSyntax)requestMethodRewriter.Visit(methodSyntax);
                    userClientSyntax = userClientSyntax.AddMembers(clientMethod);

                    if (method.Parameters[1].Type.Name.EndsWith(nameof(CallSettings)))
                    {
                        var clientImplMethod = (MethodDeclarationSyntax)requestMethodToImplRewriter.Visit(clientMethod);

                        if (s_customStreamMethods.TryGetValue(method.Name, out var customStreamMethodInfo) &&
                            customStreamMethodInfo.SplitSyncAndAsync)
                        {
                            var asyncMethod = clientMethod.ToAsync();
                            userClientSyntax = userClientSyntax.AddMembers(asyncMethod);

                            var asyncMethodWithCancellationToken = (MethodDeclarationSyntax)convertToAsyncCancellationTokenOverload.Visit(asyncMethod);
                            userClientSyntax = userClientSyntax.AddMembers(asyncMethodWithCancellationToken);

                            var clientImplSyncMethod = clientImplMethod.WithBodySafe(
                                Task().Member(nameof(System.Threading.Tasks.Task.Run))
                                .Invoke(Lambda(asyncMethod.Invoke(clientImplMethod.ParameterList.AsArguments())))
                                .Member(nameof(gax::TaskExtensions.ResultWithUnwrappedExceptions)).Invoke());
                            userClientImplSyntax = userClientImplSyntax.AddMembers(clientImplSyncMethod);

                            var clientImplAsyncMethod = clientImplMethod.ToAsync();
                            userClientImplSyntax = userClientImplSyntax.AddMembers(clientImplAsyncMethod);
                        }
                        else
                        {
                            userClientImplSyntax = userClientImplSyntax.AddMembers(clientImplMethod);
                        }
                    }
                }
                else if (
                    method.Name != "Create" &&
                    method.Name != "CreateAsync" &&
                    !s_customStreamMethods.ContainsKey(method.Name) &&
                    !method.Parameters.Any(p => p.Type.Name == "ByteString"))
                {
                    // TODO: We could also have this remap to BigtableByteString automatically, but we currently
                    //       have some validations for most methods with ByteStrings which I think we's lose by
                    //       autogenerating at the moment.
                    // For any other methods which aren't custom streaming methods and which don't use ByteString,
                    // which we remap to BigtableByteString, copy them (with some small fix ups) into the generated
                    // client.
                    userClientSyntax = userClientSyntax.AddMembers(
                        (MethodDeclarationSyntax)nonRequestMethodRewriter.Visit(methodSyntax));
                }
            }

            // Create a CompilationUnitSyntax from the Usings node of the original file, which will also contain the
            // copyright notice and generated code warnings in its leading trivia.
            // We also need a using directive for GAX, so that we can use ResultWithUnwrappedExceptions.
            var usings = syntaxTree.GetCompilationUnitRoot().Usings
                         .Add(UsingDirective(ParseName(typeof(gax::TaskExtensions).Namespace)));
            var compilationUnit = CompilationUnit().WithUsings(usings);

            // Add in the namespace with the ...Client and ...ClientImpl classes.
            compilationUnit = compilationUnit.AddMembers(
                (NamespaceDeclarationSyntax)generator.NamespaceDeclaration(
                    apiClientSymbol.ContainingNamespace.ToDisplayString(),
                    userClientSyntax,
                    userClientImplSyntax));

            // Use idiomatic formatting for the project.
            compilationUnit =
                (CompilationUnitSyntax)Formatter.Format(
                    compilationUnit,
                    workspace,
                    workspace.Options.WithChangedOption(FormattingOptions.NewLine, LanguageNames.CSharp, "\n"));

            var resultText = compilationUnit.ToFullString();

            try
            {
                var resultPath = Path.Combine(Path.GetDirectoryName(projectFile), $"{userClientName}.cs");
                File.WriteAllText(resultPath, resultText);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Could not write the auto-generated {userClientName}:\n{e}");
                return(4);
            }
            return(0);
        }
예제 #9
0
 protected void AssertFailures(MSBuildWorkspace workspace, params string[] expectedFailures)
 {
     AssertEx.Equal(expectedFailures, workspace.Diagnostics.Where(d => d.Kind == WorkspaceDiagnosticKind.Failure).Select(d => d.Message));
 }
예제 #10
0
 static PlantUMLDiagramGenerator()
 {
     MSBuildLocator.RegisterDefaults();
     workspace = MSBuildWorkspace.Create();
 }
예제 #11
0
        public static async Task <int> FormatWorkspaceAsync(ILogger logger, string solutionOrProjectPath, bool isSolution, bool logAllWorkspaceWarnings, bool saveFormattedFiles, CancellationToken cancellationToken)
        {
            logger.LogInformation(string.Format(Resources.Formatting_code_files_in_workspace_0, solutionOrProjectPath));

            logger.LogTrace(Resources.Loading_workspace);

            var loggedWarningCount = 0;
            var exitCode           = 1;
            var workspaceStopwatch = Stopwatch.StartNew();

            var properties = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                // This property ensures that XAML files will be compiled in the current AppDomain
                // rather than a separate one. Any tasks isolated in AppDomains or tasks that create
                // AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
                { "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
            };

            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            using (var workspace = MSBuildWorkspace.Create(properties))
            {
                workspace.WorkspaceFailed += LogWorkspaceWarnings;

                var projectPath = string.Empty;
                if (isSolution)
                {
                    await workspace.OpenSolutionAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    await workspace.OpenProjectAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);

                    projectPath = solutionOrProjectPath;
                }

                logger.LogTrace(Resources.Workspace_loaded_in_0_ms, workspaceStopwatch.ElapsedMilliseconds);
                workspaceStopwatch.Restart();

                int fileCount;
                int filesFormatted;
                (exitCode, fileCount, filesFormatted) = await FormatFilesInWorkspaceAsync(logger, workspace, projectPath, codingConventionsManager, saveFormattedFiles, cancellationToken).ConfigureAwait(false);

                logger.LogDebug(Resources.Formatted_0_of_1_files_in_2_ms, filesFormatted, fileCount, workspaceStopwatch.ElapsedMilliseconds);
            }

            logger.LogInformation(Resources.Format_complete);

            return(exitCode);

            void LogWorkspaceWarnings(object sender, WorkspaceDiagnosticEventArgs args)
            {
                if (args.Diagnostic.Kind == WorkspaceDiagnosticKind.Failure)
                {
                    return;
                }

                logger.LogWarning(args.Diagnostic.Message);

                if (!logAllWorkspaceWarnings)
                {
                    loggedWarningCount++;

                    if (loggedWarningCount == MaxLoggedWorkspaceWarnings)
                    {
                        logger.LogWarning(Resources.Maximum_number_of_workspace_warnings_to_log_has_been_reached_Set_the_verbosity_option_to_the_diagnostic_level_to_see_all_warnings);
                        ((MSBuildWorkspace)sender).WorkspaceFailed -= LogWorkspaceWarnings;
                    }
                }
            }
        }
예제 #12
0
 public SolutionData(Solution solution, MSBuildWorkspace buildWorkspace, SolutionConfiguration configuration)
 {
     Configuration = configuration;
     Workspace     = buildWorkspace;
     Solution      = solution;
 }
예제 #13
0
        static async Task <List <KeyValuePair <IMethodSymbol, List <EnumUse> > > > Run(string[] args)
        {
            var securityUsagesCache = new Dictionary <ISymbol, List <EnumUse> >();

            // load and compile the solution
            string solutionPath = args[0];
            var    msWorkspace  = MSBuildWorkspace.Create();
            var    solution     = await msWorkspace.OpenSolutionAsync(solutionPath);

            var compiles = solution.Projects.ToDictionary(i => i, i => i.GetCompilationAsync().Result);

            // find all 'Controller's in the web project
            var webProject  = solution.Projects.Single(i => i.Name.EndsWith("Web"));
            var webCompile  = compiles[webProject];
            var controllers = webCompile.GetSymbolsWithName(i => i.EndsWith("Controller")).OfType <INamedTypeSymbol>().ToList();

            var data = new List <KeyValuePair <IMethodSymbol, List <EnumUse> > >();

            foreach (var controller in controllers)
            {
                var actions = controller.GetMembers().OfType <IMethodSymbol>().Where(i => i.DeclaredAccessibility == Accessibility.Public && i.MethodKind == MethodKind.Ordinary).ToList();
                foreach (var action in actions)
                {
                    var usages = await GetSecurityUsages(action);

                    data.Add(new KeyValuePair <IMethodSymbol, List <EnumUse> >(action, usages));
                }
            }
            return(data);

            async Task <List <EnumUse> > GetSecurityUsages(ISymbol method)
            {
                List <EnumUse> list;

                if (securityUsagesCache.TryGetValue(method, out list))
                {
                    return(list);
                }

                // load empty value to avoid recursion issues
                securityUsagesCache.Add(method, new List <EnumUse>());
                try
                {
                    list = await RawGetSecurityUsages(method);

                    securityUsagesCache[method] = list; // replace empty value
                    return(list);
                }
                catch
                {
                    // remove dummy value so we'll retry later
                    securityUsagesCache.Remove(method);
                    throw;
                }
            }

            async Task <List <EnumUse> > RawGetSecurityUsages(ISymbol method)
            {
                //Console.WriteLine($"Checking {method}");
                var usages = new List <EnumUse>();
                var x      = (IMethodSymbol)await SymbolFinder.FindSourceDefinitionAsync(method, solution);

                if (null == x)
                {
                    return(usages);
                }
                var proj = solution.GetProject(x.ContainingAssembly);

                if (null == proj)
                {
                    return(usages);
                }
                var compiled = compiles[proj];

                foreach (var reference in x.DeclaringSyntaxReferences)
                {
                    var node = await reference.GetSyntaxAsync();

                    var model = compiled.GetSemanticModel(node.SyntaxTree);

                    var uses = node.DescendantNodesAndSelf().OfType <MemberAccessExpressionSyntax>()
                               .Where(i => i.Expression is IdentifierNameSyntax && i.Expression.ToString() == "SecurityComponentEnum")
                               .Where(i => !i.AncestorsAndSelf().OfType <AttributeSyntax>().Any())
                    ;
                    foreach (var use in uses)
                    {
                        var nearestInvoke = use.AncestorsAndSelf().OfType <InvocationExpressionSyntax>().FirstOrDefault();
                        if (null != nearestInvoke)
                        {
                            // point to attach debugger to figure out how to deal with multi-line stuff
                            if (nearestInvoke.ToString().Contains("\n"))
                            {
                            }
                        }
                        usages.Add(new EnumUse
                        {
                            Method = method,
                            Call   = nearestInvoke ?? (SyntaxNode)use,
                            Use    = use
                        });
                    }
                    var calls = node.DescendantNodesAndSelf().OfType <InvocationExpressionSyntax>().ToList();
                    foreach (var call in calls)
                    {
                        var callTarget = model.GetSymbolInfo(call);
                        foreach (var candidate in callTarget.CandidateSymbols)
                        {
                            // it seems like we should be able to call SymbolFinder.FindImplementationsAsync directly on candidate, but I get no results
                            //   so instead, we call it on the type, then find members with the right name.
                            //   this means we recurse to *all* overloads...
                            var classes = await SymbolFinder.FindImplementationsAsync(candidate.ContainingType, solution);

                            foreach (ITypeSymbol cls in classes)
                            {
                                foreach (var implementation in cls.GetMembers(candidate.Name))
                                {
                                    usages.AddRange(await GetSecurityUsages(implementation));
                                }
                            }
                            usages.AddRange(await GetSecurityUsages(candidate));
                        }
                    }
                }

                return(usages);
            }
        }
예제 #14
0
 public Tern(MSBuildWorkspace workspace, string projectFilePath)
 {
     _workspace       = workspace;
     _projectFilePath = projectFilePath;
 }