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); }
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); }
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); } }
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()); }