public SignatureHelp GetSignatureHelp(Position position, PageInfoStore store) { var node = TraceNode(position); Node lastNode = null; while (node != null) { switch (node) { case Template template: var templateName = MwParserUtility.NormalizeTitle(template.Name); if (string.IsNullOrEmpty(templateName)) { return(null); } // i.e. redirect target var redirectSource = store.TryGetTransclusionPageInfo(templateName); if (redirectSource == null) { return(null); } var templateInfo = store.ResolveRedirectTarget(redirectSource); if (templateInfo == null) { templateInfo = redirectSource; redirectSource = null; } var help = new SignatureHelp { Signatures = new[] { templateInfo.ToSignatureInformation(redirectSource) }, ActiveSignature = 0, ActiveParameter = -1, }; if (lastNode is TemplateArgument arg) { // Magic Words are always positional, while it can fake "named arguments" if (templateInfo.Type == PageType.MagicWord) { var pos = template.Arguments.IndexOf(arg); help.ActiveParameter = pos; } else { var argName = arg.ArgumentName(); help.ActiveParameter = templateInfo.Arguments.IndexOf(p => p.Name == argName); } } return(help); case WikiLink wikiLink: return(null); } lastNode = node; node = node.ParentNode; } return(null); }
GetCompletionItems(Position position, PageInfoStore store) { var innermostNode = TraceNode(position); var innermostPlainText = innermostNode as PlainText; var node = innermostNode; Node lastNode = null; // ... when the innermostPlainText is also the first node of all parent nodes var isSimpleIdentifier = innermostPlainText != null; var lastNodeIsSimpleIdentifier = isSimpleIdentifier; // Trace the node from innermost to outermost. while (node != null) { lastNodeIsSimpleIdentifier = isSimpleIdentifier; isSimpleIdentifier = isSimpleIdentifier && (node is PlainText || lastNode.PreviousNode == null); switch (node) { case Template template: if (lastNodeIsSimpleIdentifier && lastNode == template.Name) { var enteredName = MwParserUtility.NormalizeTitle(GetTypedLhsText(innermostPlainText, position)); return(store.GetTransclusionCompletionItems(enteredName), true); } return(null, false); case TemplateArgument argument: // Do not show auto-completion for obvious argument values. if (lastNodeIsSimpleIdentifier && ( lastNode == argument.Name || // | abc$ = def argument.Name == null && lastNode == argument.Value // Anonymous argument, or unfinished argument name )) { var template = (Template)argument.ParentNode; var templateInfo = store.TryGetTransclusionPageInfo(MwParserUtility.NormalizeTitle(template.Name)); return(templateInfo.Arguments .Select(a => new CompletionItem(a.Name, CompletionItemKind.Property, a.Summary, a.Name + "=")), false); } return(null, false); case WikiLink wikiLink: if (lastNodeIsSimpleIdentifier && lastNode == wikiLink.Target) { var enteredName = MwParserUtility.NormalizeTitle(GetTypedLhsText(innermostPlainText, position)); return(store.GetWikiLinkCompletionItems(enteredName), true); } return(null, false); } lastNode = node; node = node.ParentNode; } return(null, false); }
public SessionState(ClientProxy clientProxy, ILoggerFactory loggerFactory) { this.loggerFactory = loggerFactory; if (clientProxy == null) { throw new ArgumentNullException(nameof(clientProxy)); } ClientProxy = clientProxy; logger = loggerFactory.CreateLogger <SessionState>(); PageInfoStore.LoadLocalStore(); }
/// <summary> /// Infers linked/transcluded pages information, and stores it into global store. /// </summary> public int InferTemplateInformation(PageInfoStore store) { if (store == null) { throw new ArgumentNullException(nameof(store)); } // template, argument var dict = new Dictionary <string, Dictionary <string, TemplateArgumentInfo> >(); foreach (var template in _Root.EnumDescendants().OfType <Template>()) { if (template.IsMagicWord) { continue; } var name = template.Name?.ToString(); if (string.IsNullOrEmpty(name)) { continue; } name = MwParserUtility.NormalizeTitle(name); if (name.Contains('{') || name.Contains('}')) { continue; } name = Utility.ExpandTransclusionTitle(name); // Start to infer it. if (!dict.TryGetValue(name, out var parameters)) { if (store.ContainsPageInfo(name)) { continue; } parameters = new Dictionary <string, TemplateArgumentInfo>(); dict.Add(name, parameters); } foreach (var p in template.Arguments.EnumNameArgumentPairs()) { if (parameters.ContainsKey(p.Key)) { continue; } // TODO: Insert documentation here. parameters.Add(p.Key, new TemplateArgumentInfo(p.Key, null)); } } foreach (var p in dict) { var isTemplate = Utility.IsTemplateTitle(p.Key); string transclusionName; if (isTemplate) { Debug.Assert(p.Key.StartsWith("Template:")); transclusionName = p.Key.Substring(9); } else { transclusionName = ":" + p.Key; } store.UpdatePageInfo(new PageInfo(p.Key, transclusionName, null, Prompts.InferredPageInfo, p.Value.OrderBy(p1 => p1.Key, TemplateArgumentNameComparer.Default) .Select(p1 => p1.Value).ToArray(), isTemplate ? PageType.Template : PageType.Page, true)); } return(dict.Count); }