Exemplo n.º 1
0
        public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
        {
            NamespaceDeclarationSyntax namespaceDeclaration = node.Ancestors().OfType <NamespaceDeclarationSyntax>().FirstOrDefault();

            node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);

            var classTemplates = new List <AopTemplate>();

            var globalTemplates = _templateService.GetGlobalTemplates(_filePath, namespaceDeclaration?.Name?.ToString(), node.Identifier.ToString());

            classTemplates.AddRange(globalTemplates.Where(w => w.Action == Action));
            classTemplates.ForEach(s => s.AppliedTo = AopTemplateApplied.Class);

            string className = node.Identifier.ToString();

            Console.Out.WriteLine("Class:  " + className);

            if (BuilderSettings.Verbosity > 2)
            {
                Console.Out.WriteLine("Old code:");
                Console.Out.WriteLine(node.ToFullString());
            }

            AopRewriter.AddTemplatesFromAttributes(classTemplates, Action, node.AttributeLists, AopTemplateAction.Methods);

            ClassDeclarationSyntax result = AopRewriter.ProcessTemplates <ClassDeclarationSyntax>(_templateService, classTemplates, node, node);

            return(result);
        }
        protected override string InternalProcessFile(string sourcePath, string sourceCode)
        {
            // step 1. process comments
            string newSourceCode = ProcessAspectComments(sourceCode);

            SyntaxTree tree = CSharpSyntaxTree.ParseText(newSourceCode);

            AopWalker walker = GetClassTemplates(tree);

            // step 2. rewrite source code for classes
            {
                var classRewriter = new AopClassRewriter(sourcePath, this);

                SyntaxNode newNode = classRewriter.Visit(tree.GetRoot());
                newSourceCode = newNode.ToFullString();

                tree = CSharpSyntaxTree.ParseText(newSourceCode);
            }

            // step 3. rewrite source code for methods and properties
            {
                var rewriter = new AopRewriter(sourcePath, this, walker.ClassTemplates);

                SyntaxNode newNode = tree.GetRoot();

                var methodNames = newNode.DescendantNodes().OfType <MethodDeclarationSyntax>().Select(s => s.Identifier.ValueText);

                foreach (string methodName in methodNames)
                {
                    MethodDeclarationSyntax method = newNode.DescendantNodes().OfType <MethodDeclarationSyntax>().FirstOrDefault(w => w.Identifier.ValueText == methodName);
                    if (method == null)
                    {
                        continue;
                    }

                    foreach (AopTemplate template in rewriter.GetMethodTemplates(method))
                    {
                        method = newNode.DescendantNodes().OfType <MethodDeclarationSyntax>().FirstOrDefault(w => w.Identifier.ValueText == methodName);
                        if (method == null)
                        {
                            continue;
                        }

                        template.AppliedTo = AopTemplateApplied.Method;
                        SyntaxNode[] result = rewriter.VisitMethodDeclaration(method, template);

                        newNode = newNode.ReplaceNode(method, result);
                    }
                }

                var propertyNames = newNode.DescendantNodes().OfType <PropertyDeclarationSyntax>().Select(s => s.Identifier.ValueText);

                foreach (string propertyName in propertyNames)
                {
                    PropertyDeclarationSyntax property = newNode.DescendantNodes().OfType <PropertyDeclarationSyntax>().FirstOrDefault(w => w.Identifier.ValueText == propertyName);
                    if (property == null)
                    {
                        continue;
                    }

                    foreach (AopTemplate template in rewriter.GetPropertyTemplates(property))
                    {
                        property = newNode.DescendantNodes().OfType <PropertyDeclarationSyntax>().FirstOrDefault(w => w.Identifier.ValueText == propertyName);
                        if (property == null)
                        {
                            continue;
                        }

                        template.AppliedTo = AopTemplateApplied.Property;
                        SyntaxNode[] result = rewriter.VisitPropertyDeclaration(property, template);

                        newNode = newNode.ReplaceNode(property, result);
                    }
                }

                newSourceCode = newNode.ToFullString();


                tree = CSharpSyntaxTree.ParseText(newSourceCode);
            }

            // step 4. rewrite source code for using blocks
            {
                var rewriter = new AopUsingRewriter();

                SyntaxNode newNode = rewriter.Visit(tree.GetRoot());

                newSourceCode = newNode.ToFullString();

                tree = CSharpSyntaxTree.ParseText(newSourceCode);
            }

            // step 5. rewrite source code for postprocessing classes templates
            {
                var classRewriter = new AopClassRewriter(sourcePath, this)
                {
                    Action = AopTemplateAction.PostProcessingClasses
                };

                SyntaxNode newNode = classRewriter.Visit(tree.GetRoot());
                newSourceCode = newNode.ToFullString();
            }

            // step 6: cleanup AopTemplate attributes and using
            {
                tree = CSharpSyntaxTree.ParseText(newSourceCode);

                SyntaxNode node = tree.GetRoot();

                {
                    AttributeListSyntax oldNode;
                    while ((oldNode = node.DescendantNodes().OfType <AttributeListSyntax>().FirstOrDefault(w => w.Attributes.Any(a => a.Name.ToFullString() == "AopTemplate"))) != null)
                    {
                        node = node.RemoveNode(oldNode, SyntaxRemoveOptions.KeepLeadingTrivia);
                    }
                }

                {
                    UsingDirectiveSyntax oldNode;
                    while ((oldNode = node.DescendantNodes().OfType <UsingDirectiveSyntax>().FirstOrDefault(w => w.Name.ToFullString() == "AOP.Common")) != null)
                    {
                        node = node.RemoveNode(oldNode, SyntaxRemoveOptions.KeepLeadingTrivia);
                    }
                }

                // make sure the class has all required usings
                if (_requiredUsings.Count > 0)
                {
                    for (int i = 0; i < _requiredUsings.Count; i++)
                    {
                        _requiredUsings[i] = _requiredUsings[i].Trim(';');
                    }

                    foreach (UsingDirectiveSyntax usingNode in node.DescendantNodes().OfType <UsingDirectiveSyntax>())
                    {
                        string usingName = usingNode.Name.ToFullString();
                        if (_requiredUsings.Contains(usingName))
                        {
                            _requiredUsings.Remove(usingName);
                        }
                    }

                    SyntaxNode insertNode  = node.ChildNodes().LastOrDefault(w => w.Kind() == SyntaxKind.UsingDirective);
                    bool       insertAfter = true;

                    if (insertNode == null)
                    {
                        insertNode  = node.ChildNodes().First();
                        insertAfter = false;
                    }

                    foreach (string requiredUsing in _requiredUsings)
                    {
                        var usingNode = new List <SyntaxNode>()
                        {
                            SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(requiredUsing))
                        };

                        if (insertAfter)
                        {
                            node = node.InsertNodesAfter(insertNode, usingNode);
                        }
                        else
                        {
                            node = node.InsertNodesBefore(insertNode, usingNode);
                        }
                    }
                }

                newSourceCode = node.NormalizeWhitespace().ToFullString();
            }

            return(newSourceCode);
        }