Esempio n. 1
0
        /// <inheritdoc />
        protected override void Initialize(CSharpCompilation oldCompilation, CancellationToken _)
        {
            OptimizationLevel      compilationConfiguration = oldCompilation.Options.OptimizationLevel;
            DebugCometaryAttribute attribute = Attribute;

            if (compilationConfiguration == OptimizationLevel.Debug && !attribute.RunInDebug)
            {
                return;
            }
            if (compilationConfiguration == OptimizationLevel.Release && !attribute.RunInRelease)
            {
                return;
            }

            string typeName = attribute.MainClassName ?? DebugCometaryAttribute.DefaultMainClassName;

            if (Assembly.GetEntryAssembly().GetType(typeName) != null)
            {
                return;
            }

            CSharpCompilation EditCompilation(CSharpCompilation compilation, CancellationToken cancellationToken)
            {
                CSharpCompilationOptions options    = compilation.Options;
                CSharpCompilationOptions newOptions = options
                                                      .WithOutputKind(OutputKind.ConsoleApplication)
                                                      .WithMainTypeName(typeName);

                // - Make the compilation an application, allowing its execution.
                // - Redirect the entry point to the automatically generated class.
                compilation = compilation.WithOptions(newOptions);

                // Create the entry point:
                string errorFile = Path.GetTempFileName();

                CSharpSyntaxTree      generatedSyntaxTree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(GetSourceText(attribute.DisplayEndOfCompilationMessage, errorFile), cancellationToken: cancellationToken);
                CompilationUnitSyntax generatedRoot       = generatedSyntaxTree.GetCompilationUnitRoot(cancellationToken);

                ClassDeclarationSyntax classSyntax         = (ClassDeclarationSyntax)generatedRoot.Members.Last();
                ClassDeclarationSyntax originalClassSyntax = classSyntax;

                // Edit the generated syntax's name, if needed.
                if (typeName != DebugCometaryAttribute.DefaultMainClassName)
                {
                    classSyntax = classSyntax.WithIdentifier(F.Identifier(typeName));
                }

                // Change the filename and arguments.
                SyntaxList <MemberDeclarationSyntax> members = classSyntax.Members;

                FieldDeclarationSyntax WithValue(FieldDeclarationSyntax node, string value)
                {
                    VariableDeclaratorSyntax variableSyntax = node.Declaration.Variables[0];
                    LiteralExpressionSyntax  valueSyntax    = F.LiteralExpression(
                        SyntaxKind.StringLiteralExpression,
                        F.Literal(value)
                        );

                    return(node.WithDeclaration(
                               node.Declaration.WithVariables(node.Declaration.Variables.Replace(
                                                                  variableSyntax, variableSyntax.WithInitializer(F.EqualsValueClause(valueSyntax))
                                                                  ))
                               ));
                }

                FieldDeclarationSyntax WithBoolean(FieldDeclarationSyntax node, bool value)
                {
                    VariableDeclaratorSyntax variableSyntax = node.Declaration.Variables[0];
                    LiteralExpressionSyntax  valueSyntax    = F.LiteralExpression(value ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);

                    return(node.WithDeclaration(
                               node.Declaration.WithVariables(node.Declaration.Variables.Replace(
                                                                  variableSyntax, variableSyntax.WithInitializer(F.EqualsValueClause(valueSyntax))
                                                                  ))
                               ));
                }

                for (int i = 0; i < members.Count; i++)
                {
                    FieldDeclarationSyntax field = members[i] as FieldDeclarationSyntax;

                    if (field == null)
                    {
                        continue;
                    }

                    string fieldName = field.Declaration.Variables[0].Identifier.Text;

                    switch (fieldName)
                    {
                    case "References":
                        field = WithValue(field, string.Join(";", compilation.References.OfType <PortableExecutableReference>().Select(x => x.FilePath)));
                        break;

                    case "Files":
                        field = WithValue(field, string.Join(";", compilation.SyntaxTrees.Select(x => x.FilePath)));
                        break;

                    case "AssemblyName":
                        field = WithValue(field, compilation.AssemblyName);
                        break;

                    case "ErrorFile":
                        field = WithValue(field, errorFile);
                        break;

                    case "Written":
                        field = WithBoolean(field, OutputAllTreesAttribute.Instance != null);
                        break;

                    case "BreakAtEnd":
                        field = WithBoolean(field, attribute.DisplayEndOfCompilationMessage);
                        break;

                    case "BreakAtStart":
                        field = WithBoolean(field, attribute.BreakDuringStart);
                        break;

                    default:
                        continue;
                    }

                    members = members.Replace(members[i], field);
                }

                // Return the modified compilation.
                return(compilation.AddSyntaxTrees(
                           generatedSyntaxTree
                           .WithCometaryOptions(this)
                           .WithRoot(
                               generatedRoot.WithMembers(generatedRoot.Members.Replace(originalClassSyntax, classSyntax.WithMembers(members))
                                                         )
                               )
                           ));
            }

            CompilationPipeline += EditCompilation;
        }
Esempio n. 2
0
 internal DebuggingEditor(DebugCometaryAttribute attribute)
 {
     Attribute = attribute;
 }