/// <summary> /// Tries to find a completion handler given for the current AST node. /// </summary> /// <remarks> /// Note that in order for this function to work correctly, the <see cref="m_completionInformation"/> list must /// remain sorted by "starting syntax kind" and then by the "longest" parent kind list as /// the longest chains are checked first, then smaller chains, and so on, to find the best /// handler for the job. /// </remarks> private bool TryFindCompletionHandlerForNode(CompletionState completionState, out SymbolCompletionHandler symbolHandler, out CompletionItemCompletionHandler completionHandler, out INode completionNode) { symbolHandler = null; completionHandler = null; completionNode = null; foreach (var completionInfo in m_completionInformation) { if (completionInfo.StartingSyntaxKind == completionState.StartingNode.Kind) { symbolHandler = completionInfo.SymbolCompletionHandler; completionHandler = completionInfo.CompletionItemCompletionHandler; completionNode = completionState.StartingNode; // If we don't have any parent kinds, then we are done. if (completionInfo.ParentKinds.IsNullOrEmpty()) { return(true); } // Walk up the parent kinds and make sure that our node has // the correct type of parent. foreach (var parentKind in completionInfo.ParentKinds) { completionNode = (completionNode.Parent?.Kind == parentKind) ? completionNode.Parent : null; if (completionNode == null) { break; } } // If at this point, we still have a completion node, then we are good to go as we have matched // the longest parent kind list. if (completionNode != null) { if (completionInfo.ShouldRunHandler == null || completionInfo.ShouldRunHandler(completionState, completionNode)) { return(true); } } } } return(false); }
/// <nodoc/> private void AddSymbolCompletionHandlerInformation(SyntaxKind startingSyntaxKind, SymbolCompletionHandler completionHandler, params SyntaxKind[] parentKinds) { m_completionInformation.Add(new CompletionInformation { StartingSyntaxKind = startingSyntaxKind, ParentKinds = parentKinds.ToList(), SymbolCompletionHandler = completionHandler, ShouldRunHandler = (state, node) => true, }); }