Exemple #1
0
        private async void OnRunUnusedSolutionAnalysis()
        {
            var solutionNode = RootNodes?.OfType <SolutionNode>().FirstOrDefault();

            if (solutionNode == null)
            {
                return;
            }
            var solution      = solutionNode.Solution;
            var documentNodes = GetAllSelectedDocumentNodes(RootNodes).ToArray();
            var documentSet   = documentNodes.Select(n => n.Document).ToImmutableHashSet();
            int currentSymbol = 0;

            StatusText       = $"{currentSymbol}/{documentSet.Count}";
            StatusPercentage = 0;
            var interrestingSymbols = new ConcurrentBag <NodeBase>();

            await ForEachDocument(documentNodes, async documentNode =>
            {
                var document            = documentNode.Document;
                var documentsExceptSelf = documentSet.Except(new[] { document });
                var model = await document.GetSemanticModelAsync();
                var root  = await document.GetSyntaxRootAsync();
                var documentReferences = new List <NodeBase>();
                foreach (var node in root.DescendantNodesAndSelf(n => !(n is ClassDeclarationSyntax) && !(n is InterfaceDeclarationSyntax)).OfType <TypeDeclarationSyntax>())
                {
                    var symbol = model.GetDeclaredSymbol(node);
                    if (DontCareAboutThis(symbol))
                    {
                        continue;
                    }
                    // exclude the current document to limit the search to "external" references;
                    // this assumes one class per file (otherwise results will be missing)
                    IEnumerable <ReferencedSymbol> allReferenceSymbols;
                    // sometimes, FindReferencesAsync throws an InvalidOperationException telling us that
                    // "we should never reach here".
                    // assuming this has to do with not being thread safe or so, we'll just try again.
                    int retryCount = 3;
                    while (true)
                    {
                        try
                        {
                            allReferenceSymbols = await SymbolFinder.FindReferencesAsync(symbol, solution, documentsExceptSelf);
                            break;
                        }
                        catch (InvalidOperationException)
                        {
                        }
                        if (retryCount-- > 0)
                        {
                            return;
                        }
                    }
                    // it will still return matches inside the document (since there are members inside it),
                    // but their locations will be empty.
                    // TODO: search all documents and simply exclude the ones from the same class
                    //        to allow more than one class per file.
                    var referenceSymbols = allReferenceSymbols.Where(r => r.Locations.Any()).ToArray();
                    var reference        = new ReferenceSymbolNode(symbol, referenceSymbols);
                    documentReferences.Add(reference);
                    if (reference.ReferenceCount < 2)
                    {
                        interrestingSymbols.Add(reference);
                    }
                }
                // keep all existing nodes, except the reference nodes from a previous run
                documentNode.ChildNodes = documentNode.ChildNodes.Except(documentNode.ChildNodes.OfType <ReferenceSymbolNode>()).Concat(documentReferences).ToArray();
                IncrementStatus(documentSet, ref currentSymbol);
            });

            AnalysisResults = interrestingSymbols.ToArray();

            StatusText       = "Done.";
            StatusPercentage = 0;
        }