Exemplo n.º 1
0
        static async Task Main(string[] args)
        {
            // Attempt to set the version of MSBuild.
            var visualStudioInstances = MSBuildLocator.QueryVisualStudioInstances().ToArray();
            var instance = visualStudioInstances.Length == 1
                           // If there is only one instance of MSBuild on this machine, set that as the one to use.
                ? visualStudioInstances[0]
                           // Handle selecting the version of MSBuild you want to use.
                : SelectVisualStudioInstance(visualStudioInstances);

            Console.WriteLine($"Using MSBuild at '{instance.MSBuildPath}' to load projects.");

            // NOTE: Be sure to register an instance with the MSBuildLocator
            //       before calling MSBuildWorkspace.Create()
            //       otherwise, MSBuildWorkspace won't MEF compose.
            MSBuildLocator.RegisterInstance(instance);

            using (var workspace = MSBuildWorkspace.Create())
            {
                // Print message for WorkspaceFailed event to help diagnosing project load failures.
                workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);

                var solutionPath = args[0];
                Console.WriteLine($"Loading solution '{solutionPath}'");

                // Attach progress reporter so we print projects as they are loaded.
                var solution = await workspace.OpenSolutionAsync(solutionPath, new ConsoleProgressReporter());

                var solutionName = Path.GetFileNameWithoutExtension(solutionPath);

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

                var nodes = new Dictionary <long, Node>();
                var edges = new Dictionary <long, EdgeNode>();

                foreach (var project in solution.Projects.Where(p => !p.Name.Contains("Test")))
                {
                    foreach (var document in project.Documents)//.Where(d=>!d.Name.Contains("Dummy")))
                    {
                        var        collector = new CodeWalker(document.FilePath, document.Name, nodes, edges);
                        SyntaxTree tree      = CSharpSyntaxTree.ParseText(await document.GetTextAsync());
                        var        root      = (CompilationUnitSyntax)tree.GetRoot();
                        collector.Visit(root);
                    }
                }
                // Save Data files
                new Exporter(nodes, edges)
                //.ExportJson(solutionName)
                //.ExportNeo4J(solutionName)
                .ExportCsv(solutionName);
            }
        }
        /// <summary>
        /// Renders the C# code text to the specified <see cref="TextWriter" />.
        /// </summary>
        /// <remarks>
        /// The version of the <c>Render</c> method does all of the work because the other versions ultimately call this one. The
        /// steps involved are:
        /// <list type="number">
        /// <item><description>
        ///     The code text is parsed to produce a <c>SyntaxTree</c>
        /// </description></item>
        /// <item><description>
        ///     A compilation unit is created from the <c>SyntaxTree</c> and <c>MetadataReferences</c> properties and from that
        ///     the <c>SemanticModel</c> is initialized. Note that renderers that are only interested in the syntax need not
        ///     access the semantic mode, but the HTML renderer does need this information to determine if an identifier represents
        ///     a symbol that should be (color) formatted.
        /// </description></item>
        /// <item><description>
        ///     The <c>SyntaxVisiting</c> event is handled by invoking the <c>Callback</c> passing the <c>SyntaxTreeElement</c>
        ///     object and <c>VisitingState</c> enumeration value encapsulated in the <c>SyntaxVisitingEventArgs</c> object.
        ///     Concrete implementations due the actual rendering from the callback delegate.
        /// </description></item>
        /// <item><description>
        ///     Any prefix text is recovered using the <c>GetPrefixText</c> method and is written to the <c>Writer</c>.
        /// </description></item>
        /// <item><description>
        ///     The syntax tree root node is passed to the <c>SyntaxWalker.Visit</c> method (really the overridden
        ///     <c>SyntaxVisitor.Visit</c> method. This causes the callback delegate to be called as the tree is traversed. From
        ///     the callback delegate, concrete implementations can write to the <c>Writer</c> to render the nodes, tokens and
        ///     trivia that make up the syntax tree.
        /// </description></item>
        /// <item><description>
        ///     Finally, any postfix text is recovered using the <c>GetPostfixText</c> method and is written to the <c>Writer</c>.
        /// </description></item>
        /// </list>
        /// </remarks>
        /// <param name="writer">The <c>TextWriter</c> which contains the rendered code. It is the responsibility of the
        /// caller to dispose of the <paramref name="writer" /> when it is no longer needed. </param>
        /// <param name="codeText">The code text as a <see cref="string" /> instance.</param>
        /// <exception cref="ArgumentNullException">if <paramref name="writer"/> is null.</exception>
        public virtual void Render(TextWriter writer, string codeText)
        {
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer), "A non-null TextWriter is required.");
            }

            Writer     = writer;
            SyntaxTree = CSharpSyntaxTree.ParseText(codeText ?? string.Empty);

            // TODO: Formatting no longer provides a extension method on nodes. Move the entire functionality to another namespace.
            // if (FormatCode)
            // {
            //     IFormattingResult formattingResult = SyntaxTree.GetRoot().Format(FormattingOptions.GetDefaultOptions());
            //     CompilationUnitSyntax formattedRoot = (CompilationUnitSyntax)formattingResult.GetFormattedRoot();
            //     SyntaxTree = SyntaxTree.Create(formattedRoot);
            // }
            Compilation compilation = CSharpCompilation.Create("CoreRenderer",
                                                               syntaxTrees: new List <SyntaxTree> {
                SyntaxTree
            },
                                                               references: MetadataReferences);

            SemanticModel = compilation.GetSemanticModel(SyntaxTree);

            CodeWalker walker = new CodeWalker();

            walker.SyntaxVisiting += (s, e) =>
            {
                if (Callback != null)
                {
                    Callback(e.SyntaxTreeElement, e.State);
                }
            };

            Writer.Write(GetPrefixText());
            walker.Visit(SyntaxTree.GetRoot());
            Writer.Write(GetPostfixText());
        }