private static async Task AddItemsFromAssignmentAsync(Document document, SyntaxNode lhsNode, OperationCollector collector, CancellationToken cancellationToken) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var operation = semanticModel.GetOperation(lhsNode, cancellationToken); if (operation is null) { return; } IAssignmentOperation?assignmentOperation = null; while (assignmentOperation is null && operation is not null) { assignmentOperation = operation as IAssignmentOperation; operation = operation.Parent; } if (assignmentOperation is null) { return; } await collector.VisitAsync(assignmentOperation, cancellationToken).ConfigureAwait(false); }
private static async Task TrackMethodSymbolAsync(IMethodSymbol methodSymbol, OperationCollector collector, CancellationToken cancellationToken) { var hasAnyOutData = HasAValueReturn(methodSymbol) || HasAnOutOrRefParam(methodSymbol); if (!hasAnyOutData) { // With no out data, there's nothing to do here return; } // TODO: Use DFA to find meaningful returns? https://github.com/dotnet/roslyn-analyzers/blob/9e5f533cbafcc5579e4d758bc9bde27b7611ca54/docs/Writing%20dataflow%20analysis%20based%20analyzers.md if (HasAValueReturn(methodSymbol)) { foreach (var location in methodSymbol.GetDefinitionLocationsToShow()) { if (location.SourceTree is null) { continue; } var node = location.FindNode(cancellationToken); var sourceDoc = collector.Solution.GetRequiredDocument(location.SourceTree); var syntaxFacts = sourceDoc.GetRequiredLanguageService <ISyntaxFactsService>(); var semanticModel = await sourceDoc.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var operation = semanticModel.GetOperation(node, cancellationToken); // In VB the parent node contains the operation (IBlockOperation) instead of the one returned // by the symbol location. if (operation is null && node.Parent is not null) { operation = semanticModel.GetOperation(node.Parent, cancellationToken); } if (operation is null) { continue; } await collector.VisitAsync(operation, cancellationToken).ConfigureAwait(false); } } if (HasAnOutOrRefParam(methodSymbol)) { foreach (var outOrRefParam in methodSymbol.Parameters.Where(p => p.IsRefOrOut())) { if (!outOrRefParam.IsFromSource()) { continue; } await TrackVariableReferencesAsync(outOrRefParam, collector, cancellationToken).ConfigureAwait(false); } }