private async Task<GraphNode> AddLinkedNodeForType(Project project, INamedTypeSymbol namedType, GraphBuilder graphBuilder, IEnumerable<SyntaxTree> syntaxTrees) { // If this named type is contained in a parent type, then just link farther up if (namedType.ContainingType != null) { var parentTypeNode = await AddLinkedNodeForType(project, namedType.ContainingType, graphBuilder, syntaxTrees).ConfigureAwait(false); var typeNode = await graphBuilder.AddNodeForSymbolAsync(namedType, relatedNode: parentTypeNode).ConfigureAwait(false); graphBuilder.AddLink(parentTypeNode, GraphCommonSchema.Contains, typeNode); return typeNode; } else { // From here, we can link back up to the containing project item var typeNode = await graphBuilder.AddNodeForSymbolAsync(namedType, contextProject: project, contextDocument: null).ConfigureAwait(false); foreach (var tree in syntaxTrees) { var document = project.Solution.GetDocument(tree); Contract.ThrowIfNull(document); var documentNode = graphBuilder.AddNodeForDocument(document); graphBuilder.AddLink(documentNode, GraphCommonSchema.Contains, typeNode); } return typeNode; } }
private async Task ProcessProjectAsync(Project project, GraphBuilder graphBuilder, CancellationToken cancellationToken) { var cacheService = project.Solution.Services.CacheService; if (cacheService != null) { using (cacheService.EnableCaching(project.Id)) { var results = await FindNavigableSourceSymbolsAsync(project, cancellationToken).ConfigureAwait(false); foreach (var result in results) { cancellationToken.ThrowIfCancellationRequested(); var symbol = result.Item1; if (symbol is INamedTypeSymbol) { await AddLinkedNodeForType(project, (INamedTypeSymbol)symbol, graphBuilder, symbol.DeclaringSyntaxReferences.Select(d => d.SyntaxTree)).ConfigureAwait(false); } else { await AddLinkedNodeForMemberAsync(project, symbol, graphBuilder).ConfigureAwait(false); } } } } }
private static async Task AddImplementedSymbols(GraphBuilder graphBuilder, GraphNode node, IEnumerable<ISymbol> implementedSymbols) { foreach (var interfaceType in implementedSymbols) { var interfaceTypeNode = await graphBuilder.AddNodeForSymbolAsync(interfaceType, relatedNode: node).ConfigureAwait(false); graphBuilder.AddLink(node, CodeLinkCategories.Implements, interfaceTypeNode); } }
public static async Task<GraphBuilder> CreateForInputNodesAsync(Solution solution, IEnumerable<GraphNode> inputNodes, CancellationToken cancellationToken) { var builder = new GraphBuilder(solution, cancellationToken); foreach (var inputNode in inputNodes) { if (inputNode.HasCategory(CodeNodeCategories.File)) { builder.PopulateMapsForFileInputNode(inputNode); } else if (!inputNode.HasCategory(CodeNodeCategories.SourceLocation)) { await builder.PopulateMapsForSymbolInputNodeAsync(inputNode).ConfigureAwait(false); } } return builder; }
private async Task <GraphNode> AddLinkedNodeForMemberAsync(Project project, ISymbol member, GraphBuilder graphBuilder) { Contract.ThrowIfNull(member.ContainingType); var trees = member.DeclaringSyntaxReferences.Select(d => d.SyntaxTree); var parentTypeNode = await AddLinkedNodeForType(project, member.ContainingType, graphBuilder, trees).ConfigureAwait(false); var memberNode = await graphBuilder.AddNodeForSymbolAsync(member, relatedNode : parentTypeNode).ConfigureAwait(false); graphBuilder.AddLink(parentTypeNode, GraphCommonSchema.Contains, memberNode); return(memberNode); }
private async Task <GraphNode> AddLinkedNodeForType(Project project, INamedTypeSymbol namedType, GraphBuilder graphBuilder, IEnumerable <SyntaxTree> syntaxTrees) { // If this named type is contained in a parent type, then just link farther up if (namedType.ContainingType != null) { var parentTypeNode = await AddLinkedNodeForType(project, namedType.ContainingType, graphBuilder, syntaxTrees).ConfigureAwait(false); var typeNode = await graphBuilder.AddNodeForSymbolAsync(namedType, relatedNode : parentTypeNode).ConfigureAwait(false); graphBuilder.AddLink(parentTypeNode, GraphCommonSchema.Contains, typeNode); return(typeNode); } else { // From here, we can link back up to the containing project item var typeNode = await graphBuilder.AddNodeForSymbolAsync(namedType, contextProject : project, contextDocument : null).ConfigureAwait(false); foreach (var tree in syntaxTrees) { var document = project.Solution.GetDocument(tree); Contract.ThrowIfNull(document); var documentNode = graphBuilder.AddNodeForDocument(document); graphBuilder.AddLink(documentNode, GraphCommonSchema.Contains, typeNode); } return(typeNode); } }
public ProgressionNavigateToSearchCallback(IGraphContext context, GraphBuilder graphBuilder) { _context = context; _graphBuilder = graphBuilder; }
public async Task <GraphBuilder> GetGraphAsync( Solution solution, IGraphContext context, CancellationToken cancellationToken ) { var graphBuilder = await GraphBuilder .CreateForInputNodesAsync(solution, context.InputNodes, cancellationToken) .ConfigureAwait(false); foreach (var node in context.InputNodes) { var symbol = graphBuilder.GetSymbol(node); if (!(symbol is INamedTypeSymbol namedType)) { continue; } if (namedType.TypeKind == TypeKind.Class) { var derivedTypes = await SymbolFinder .FindDerivedClassesArrayAsync( namedType, solution, transitive : false, cancellationToken : cancellationToken ) .ConfigureAwait(false); foreach (var derivedType in derivedTypes) { var symbolNode = await graphBuilder .AddNodeAsync(derivedType, relatedNode : node) .ConfigureAwait(false); graphBuilder.AddLink(symbolNode, CodeLinkCategories.InheritsFrom, node); } } else if (namedType.TypeKind == TypeKind.Interface) { var implementingClassesAndStructs = await SymbolFinder .FindImplementationsArrayAsync( namedType, solution, transitive : false, cancellationToken : cancellationToken ) .ConfigureAwait(false); var derivedInterfaces = await SymbolFinder .FindDerivedInterfacesArrayAsync( namedType, solution, transitive : false, cancellationToken : cancellationToken ) .ConfigureAwait(false); foreach ( var derivedType in implementingClassesAndStructs.Concat(derivedInterfaces) ) { var symbolNode = await graphBuilder .AddNodeAsync(derivedType, relatedNode : node) .ConfigureAwait(false); graphBuilder.AddLink(symbolNode, CodeLinkCategories.InheritsFrom, node); } } } return(graphBuilder); }
private async Task<GraphNode> AddLinkedNodeForMemberAsync(Project project, ISymbol member, GraphBuilder graphBuilder) { Contract.ThrowIfNull(member.ContainingType); var trees = member.DeclaringSyntaxReferences.Select(d => d.SyntaxTree); var parentTypeNode = await AddLinkedNodeForType(project, member.ContainingType, graphBuilder, trees).ConfigureAwait(false); var memberNode = await graphBuilder.AddNodeForSymbolAsync(member, relatedNode: parentTypeNode).ConfigureAwait(false); graphBuilder.AddLink(parentTypeNode, GraphCommonSchema.Contains, memberNode); return memberNode; }
public async Task <GraphBuilder> GetGraphAsync(Solution solution, IGraphContext context, CancellationToken cancellationToken) { var graphBuilder = await GraphBuilder.CreateForInputNodesAsync(solution, context.InputNodes, cancellationToken).ConfigureAwait(false); foreach (var node in context.InputNodes) { if (!cancellationToken.IsCancellationRequested) { var symbolAndProjectId = graphBuilder.GetSymbolAndProjectId(node); if (symbolAndProjectId.Symbol != null) { var containsChildren = SymbolContainment.GetContainedSymbols(symbolAndProjectId).Any(); graphBuilder.AddDeferredPropertySet(node, DgmlNodeProperties.ContainsChildren, containsChildren); } else if (node.HasCategory(CodeNodeCategories.File)) { var document = graphBuilder.GetContextDocument(node); if (document != null) { var childNodes = await SymbolContainment.GetContainedSyntaxNodesAsync(document, cancellationToken).ConfigureAwait(false); graphBuilder.AddDeferredPropertySet(node, DgmlNodeProperties.ContainsChildren, childNodes.Any()); } else { var uri = node.Id.GetNestedValueByName <Uri>(CodeGraphNodeIdName.File); if (uri != null) { // Since a solution load is not yet completed, there is no document available to answer this query. // The solution explorer presumes that if somebody doesn't answer for a file, they never will. // See Providers\GraphContextAttachedCollectionSource.cs for more. Therefore we should answer by setting // ContainsChildren property to either true or false, so any following updates will be tractable. // We will set it to false since the solution explorer assumes the default for this query response is 'false'. // Todo: we may need fallback to check if this node actually represents a C# or VB language // even when its extension fails to say so. One option would be to call DTEWrapper.IsRegisteredForLangService, // which may not be called here however since deadlock could happen. // The Uri returned by `GetNestedValueByName()` above isn't necessarily absolute and the `OriginalString` is // the only property that doesn't throw if the UriKind is relative, so `OriginalString` must be used instead // of `AbsolutePath`. var path = uri.OriginalString; // Recorded in https://github.com/dotnet/roslyn/issues/27805, we // have seen crashes because the URI in the graph node has the // following form, including the quotes (which are invalid path // characters): // C:\path\to\"some path\App.config" // So we avoid calling Path.GetExtension here. Alternatively, we // could check for illegal path characters directly first, but then // that check would actually happen twice because GetExtension will // also perform the check. if (path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".vb", StringComparison.OrdinalIgnoreCase)) { graphBuilder.AddDeferredPropertySet(node, DgmlNodeProperties.ContainsChildren, false); } } } } } } return(graphBuilder); }
private static void ProcessGraphTasks(GraphBuilder[] graphBuilders, IGraphContext context) { // Perform the actual graph transaction using (var transaction = new GraphTransactionScope()) { // Remove any links that may have been added by a previous population. We don't // remove nodes to maintain node identity, matching the behavior of the old // providers. context.Graph.Links.Clear(); foreach (var graphBuilder in graphBuilders) { graphBuilder.ApplyToGraph(context.Graph); context.OutputNodes.AddAll(graphBuilder.CreatedNodes); } transaction.Complete(); } }