Пример #1
0
        private async Task <ISymbol> FindMethod(RoslynNode roslynNode, int lineNumber)
        {
            if (!IsInstanceInitialized())
            {
                throw new Exception($"Class was not initialized. Make sure to call {nameof(Initialize)} first.");
            }

            var text = await roslynNode.SyntaxTree.GetTextAsync().ConfigureAwait(false);

            if (lineNumber < 0 || lineNumber > text.Lines.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(lineNumber));
            }

            var textSpan = text.Lines[lineNumber].Span;
            var root     = await roslynNode.SyntaxTree.GetRootAsync().ConfigureAwait(false);

            var node         = root.FindNode(textSpan);
            var methodSyntax = node.AncestorsAndSelf().OfType <MethodDeclarationSyntax>().FirstOrDefault();

            if (methodSyntax == null)
            {
                return(null);
            }

            var semanticModel = roslynNode.ProjectCompilation.GetSemanticModel(roslynNode.SyntaxTree, true);
            var methodSymbol  = semanticModel.GetDeclaredSymbol(methodSyntax);

            return(methodSymbol);
        }
Пример #2
0
        private async Task <ISymbol> FindMethod(RoslynNode roslynNode, string methodName)
        {
            if (!IsInstanceInitialized())
            {
                throw new Exception($"Class was not initialized. Make sure to call {nameof(Initialize)} first.");
            }

            if (string.IsNullOrWhiteSpace(methodName))
            {
                throw new ArgumentNullException(nameof(methodName));
            }

            var syntaxNode = await roslynNode.SyntaxTree.GetRootAsync().ConfigureAwait(false);

            var methodSyntax = syntaxNode.DescendantNodes()
                               .OfType <MethodDeclarationSyntax>()
                               .Where(x => x.Identifier.ValueText.Equals(methodName, StringComparison.InvariantCultureIgnoreCase))
                               .SingleOrDefault();

            if (methodSyntax == null)
            {
                return(null);
            }

            var semanticModel = roslynNode.ProjectCompilation.GetSemanticModel(roslynNode.SyntaxTree, true);
            var methodSymbol  = semanticModel.GetDeclaredSymbol(methodSyntax);

            return(methodSymbol);
        }
Пример #3
0
        private async Task <IEnumerable <ISymbol> > FindReferencedMethod(ISymbol startSymbol, Func <ISymbol, bool> filter = null)
        {
            var references = await SymbolFinder.FindReferencesAsync(startSymbol, _solution).ConfigureAwait(false);

            var tasks = references
                        .SelectMany(r =>
            {
                return(r.Locations.Select(async x =>
                {
                    var compilation = await x.Document.Project.GetCompilationAsync().ConfigureAwait(false);
                    var node = new RoslynNode()
                    {
                        Project = x.Document.Project,
                        ProjectCompilation = compilation,
                        SyntaxTree = x.Location.SourceTree
                    };

                    return await FindMethod(node, x.Location.GetLineSpan().Span.Start.Line).ConfigureAwait(false);
                }));
            });

            var symbols = await Task.WhenAll(tasks.ToArray()).ConfigureAwait(false);

            if (filter != null)
            {
                return(symbols.Where(filter));
            }
            else
            {
                return(symbols);
            }
        }
Пример #4
0
        private async Task <bool> TryAddCategoryToTestMethod(RoslynNode roslynNode, ISymbol method, string category, bool recursive)
        {
            if (method == null)
            {
                throw new ArgumentNullException(nameof(method));
            }

            IEnumerable <ISymbol> testMethods;

            if (!HasAttribute(method, ATTRIBUTE_TEST_METHOD))
            {
                if (recursive == true)
                {
                    testMethods = await FindReferencedTestMethods(method).ConfigureAwait(false);
                }
                else
                {
                    testMethods = Array.Empty <ISymbol>();
                }
            }
            else
            {
                testMethods = new ISymbol[] { method };
            }

            foreach (var testMethod in testMethods)
            {
                var attrArgument = SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(category)));
                var attrList     = SyntaxFactory.AttributeList(
                    SyntaxFactory.SingletonSeparatedList(
                        SyntaxFactory.Attribute(
                            SyntaxFactory.IdentifierName(ATTRIBUTE_TEST_CATEGORY),
                            SyntaxFactory.AttributeArgumentList(
                                SyntaxFactory.SeparatedList(new[] { attrArgument })
                                )
                            )
                        )
                    );

                // We do know that methds only can be declared once, but for the sake of
                // completeness, let's assume that can have more than one declaration (because partial classes can)
                foreach (var declaration in testMethod.DeclaringSyntaxReferences)
                {
                    var node = declaration.GetSyntax();
                    var methodDeclaration = node as MethodDeclarationSyntax;
                    var newAttributesList = methodDeclaration.AttributeLists.Add(attrList);

                    var newNode = declaration.SyntaxTree.GetRoot().ReplaceNode(
                        methodDeclaration,
                        methodDeclaration.WithAttributeLists(newAttributesList)
                        );

                    var documentId = roslynNode.Project.GetDocumentId(declaration.SyntaxTree);
                    if (documentId != null)
                    {
                        _solution = _solution.WithDocumentSyntaxRoot(documentId, newNode);
                    }
                    else
                    {
                        _logger.Debug($"Document not found for '{declaration.SyntaxTree.FilePath}' for project '{roslynNode.Project.Name}'. Skiping declaration.");
                    }
                }
            }

            return(testMethods.Any());
        }