コード例 #1
0
        public override Compilation Rewrite(CompilationRewriterContext context)
        {
            var compilation = context.Compilation;

            // Transform compilation

            return(compilation);
        }
コード例 #2
0
        public override Compilation Rewrite(CompilationRewriterContext context)
        {
            var compilation = context.Compilation;

            foreach (var syntaxTree in compilation.SyntaxTrees)
            {
                var methods = syntaxTree.FindMethodsAndCtors().ToList();
                if (methods.Count > 0)
                {
                    var newRoot = syntaxTree.GetRoot().ReplaceNodes(syntaxTree.FindMethodsAndCtors(), (originalNode, _) => RewriteMethodWithNullGuard(originalNode));
                    context.ExportRewrittenDocument(syntaxTree, newRoot);

                    compilation = compilation.ReplaceSyntaxTree(syntaxTree, newRoot.SyntaxTree);
                }
            }

            return(compilation);
        }
 public override Compilation Rewrite(CompilationRewriterContext context) =>
 Rewrite(context.Compilation, context.ReportDiagnostic);
コード例 #4
0
        public override Compilation Rewrite(CompilationRewriterContext context)
        {
            var compilation = context.Compilation;

            // Look for Emtry{pomt
            var tokenSrc = new CancellationTokenSource();
            var symbol   = compilation.GetEntryPoint(tokenSrc.Token);

            if (symbol == null)
            {
                context.ReportDiagnostic(Diagnostic.Create(ThisDescriptor, Location.None, "Main entry point not found"));
                return(compilation);
            }

            // Fetch the method
            var syntaxReference = symbol.DeclaringSyntaxReferences.First();

            var mainTree       = syntaxReference.SyntaxTree;
            var root           = mainTree.GetRoot();
            var originalMethod = (MethodDeclarationSyntax)syntaxReference.GetSyntax();
            var newMethod      = originalMethod;

            SyntaxNode firstLocationNode = null;

            // Transform ExpressionBody into simple Body
            if (originalMethod.Body == null && originalMethod.ExpressionBody != null)
            {
                // Remove trailing ; of the expression body method
                var newSemiColonToken = Token(originalMethod.SemicolonToken.LeadingTrivia, SyntaxKind.None, originalMethod.SemicolonToken.TrailingTrivia);

                // Transform Expression body into a simple body
                firstLocationNode = originalMethod.ExpressionBody.Expression;
                newMethod         = originalMethod.WithSemicolonToken(newSemiColonToken).WithExpressionBody(null).WithBody(Block(SingletonList <StatementSyntax>(ExpressionStatement(originalMethod.ExpressionBody.Expression))));
            }
            else if (originalMethod.Body != null)
            {
                firstLocationNode = originalMethod.Body.Statements.FirstOrDefault();
            }

            if (newMethod.Body == null)
            {
                context.ReportDiagnostic(Diagnostic.Create(ThisDescriptor, Location.None, "Main entry point empty"));
                return(compilation);
            }

            // Calculate the line of the first statement
            int nextLine = 0;

            if (firstLocationNode != null)
            {
                nextLine = firstLocationNode.GetLocation().GetLineSpan().StartLinePosition.Line + 1;
            }
            else
            {
                // Otherwise take whatever trailing trivia the body has
                var trailingTrivia = newMethod.Body.GetTrailingTrivia();
                if (trailingTrivia.Count > 0)
                {
                    nextLine = trailingTrivia[0].GetLocation().GetLineSpan().StartLinePosition.Line + 1;
                }
                else
                {
                    // TODO: No line found?
                }
            }

            // Create the following code (done with https://roslynquoter.azurewebsites.net)
            //#line hidden
            //System.Console.WriteLine("Hello World from Conan!");
            //#line 9
            // TODO: Check if the following code is the most optimal way to manipulate efficiently the Compilation/Syntaxtrees

            var helloWorldFromConan = ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            IdentifierName(Identifier("System")),
                            IdentifierName("Console")),
                        IdentifierName("WriteLine")))
                .WithArgumentList(
                    ArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                LiteralExpression(
                                    SyntaxKind.StringLiteralExpression,
                                    Literal("Hello World from Conan!")))))))
                                      // #line number
                                      .WithTrailingTrivia(TriviaList(Trivia(LineDirectiveTrivia(Literal(nextLine), true))))
                                      .NormalizeWhitespace();

            // #line default
            var leadingTrivias = newMethod.GetLeadingTrivia();

            leadingTrivias = leadingTrivias.Insert(0, LineDirectiveHidden());
            leadingTrivias = leadingTrivias.Insert(0, CarriageReturnLineFeed);
            newMethod      = newMethod.WithLeadingTrivia(leadingTrivias);

            var statements = newMethod.Body.Statements;

            statements = statements.Insert(0, helloWorldFromConan);
            newMethod  = newMethod.WithBody(newMethod.Body.WithStatements(statements));

            var newRoot = root.ReplaceNode(originalMethod, newMethod);

            // Replace the syntax tree
            compilation = compilation.ReplaceSyntaxTree(mainTree, newRoot.SyntaxTree);

            // Just store the file on the disk (but it is not used by the debugger, as we are directly working on the original file)
            var newMainFile = context.GetOutputFilePath("NewMain");

            System.IO.File.WriteAllText(newMainFile, newRoot.ToFullString());

            context.ReportDiagnostic(Diagnostic.Create(ThisDescriptor, Location.None, $"Main method successfuly modified by the HelloWorld Conan Plugin (See modified file at: {newMainFile})"));

            return(compilation);
        }
コード例 #5
0
 /// <summary>
 ///     Convienient method used to log information in the output window.
 /// </summary>
 public static void ReportDiagnostic(this CompilationRewriterContext context, object message) =>
 context.ReportDiagnostic(Diagnostic.Create(ThisDescriptor, Location.None, message));
コード例 #6
0
        /// <summary>
        ///     Store the rewritten document on the disk for debugging purpose only,
        ///     as we are directly working on the original file.
        /// </summary>
        public static void ExportRewrittenDocument(this CompilationRewriterContext context, SyntaxTree syntaxTree, SyntaxNode rootNode)
        {
            var newMainFile = context.GetOutputFilePath("Conan." + Path.GetFileNameWithoutExtension(syntaxTree.FilePath));

            File.WriteAllText(newMainFile, rootNode.ToFullString());
        }