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