Example #1
0
        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);
                }
            }