public virtual CompletionStartData InitializeCompletion(CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token) { var reason = ConvertReason(trigger.Reason, trigger.Character); if (reason == null) { return(CompletionStartData.DoesNotParticipateInCompletion); } var spine = XmlParser.GetSpineParser(triggerLocation); LoggingService.LogDebug( "Attempting completion for state '{0}'x{1}, character='{2}', trigger='{3}'", spine.CurrentState, spine.CurrentStateLength, trigger.Character, trigger ); var(kind, length) = XmlCompletionTriggering.GetTrigger(spine, reason.Value, trigger.Character); if (kind != XmlCompletionTrigger.None) { return(new CompletionStartData(CompletionParticipation.ProvidesItems, new SnapshotSpan(triggerLocation.Snapshot, triggerLocation.Position - length, length))); } //TODO: closing tag completion after typing > return(CompletionStartData.DoesNotParticipateInCompletion); }
public async virtual Task <CompletionContext> GetCompletionContextAsync( IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableToSpan, CancellationToken token) { var reason = ConvertReason(trigger.Reason, trigger.Character); if (reason == null) { return(CompletionContext.Empty); } var parser = BackgroundParser <TResult> .GetParser <TParser> ((ITextBuffer2)triggerLocation.Snapshot.TextBuffer); var spine = parser.GetSpineParser(triggerLocation); var(kind, _) = await Task.Run(() => XmlCompletionTriggering.GetTrigger(spine, reason.Value, trigger.Character), token).ConfigureAwait(false); if (kind != XmlCompletionTrigger.None) { List <XObject> nodePath = GetNodePath(spine, triggerLocation.Snapshot); switch (kind) { case XmlCompletionTrigger.Element: case XmlCompletionTrigger.ElementWithBracket: //TODO: if it's on the first line and there's no XML declaration, add <"?xml version=\"1.0\" encoding=\"{encoding}\" ?>"; //TODO: if it's on the first or second line and there's no DTD declaration, add the DTDs, or at least <!DOCTYPE //TODO: add closing tags // AddCloseTag (list, spine.Nodes); //TODO: add snippets // MonoDevelop.Ide.CodeTemplates.CodeTemplateService.AddCompletionDataForFileName (DocumentContext.Name, list); return(await GetElementCompletionsAsync(session, triggerLocation, nodePath, kind == XmlCompletionTrigger.ElementWithBracket, token)); case XmlCompletionTrigger.Attribute: IAttributedXObject attributedOb = (spine.Nodes.Peek() as IAttributedXObject) ?? spine.Nodes.Peek(1) as IAttributedXObject; return(await GetAttributeCompletionsAsync(session, triggerLocation, nodePath, attributedOb, GetExistingAttributes (spine, triggerLocation.Snapshot, attributedOb), token)); case XmlCompletionTrigger.AttributeValue: if (spine.Nodes.Peek() is XAttribute att && spine.Nodes.Peek(1) is IAttributedXObject attributedObject) { return(await GetAttributeValueCompletionsAsync(session, triggerLocation, nodePath, attributedObject, att, token)); } break; case XmlCompletionTrigger.Entity: return(await GetEntityCompletionsAsync(session, triggerLocation, nodePath, token)); case XmlCompletionTrigger.DocType: case XmlCompletionTrigger.DeclarationOrCDataOrComment: return(await GetDeclarationCompletionsAsync(session, triggerLocation, nodePath, token)); } } return(CompletionContext.Empty); }
public async virtual Task <CompletionContext> GetCompletionContextAsync( IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableToSpan, CancellationToken token) { var reason = ConvertReason(trigger.Reason, trigger.Character); if (reason == null) { return(CompletionContext.Empty); } var parser = XmlParser.GetSpineParser(triggerLocation); // FIXME: cache the value from InitializeCompletion somewhere? var(kind, _) = XmlCompletionTriggering.GetTrigger(parser, reason.Value, trigger.Character); if (kind != XmlCompletionTrigger.None) { List <XObject> nodePath = parser.GetNodePath(triggerLocation.Snapshot); session.Properties.AddProperty(typeof(XmlCompletionTrigger), kind); switch (kind) { case XmlCompletionTrigger.Element: case XmlCompletionTrigger.ElementWithBracket: // if we're completing an existing element, remove it from the path // so we don't get completions for its children instead if (nodePath.Count > 0) { if (nodePath[nodePath.Count - 1] is XElement leaf && leaf.Name.Length == applicableToSpan.Length) { nodePath.RemoveAt(nodePath.Count - 1); } } //TODO: if it's on the first or second line and there's no DTD declaration, add the DTDs, or at least <!DOCTYPE //TODO: add snippets // MonoDevelop.Ide.CodeTemplates.CodeTemplateService.AddCompletionDataForFileName (DocumentContext.Name, list); return(await GetElementCompletionsAsync(session, triggerLocation, nodePath, kind == XmlCompletionTrigger.ElementWithBracket, token)); case XmlCompletionTrigger.Attribute: IAttributedXObject attributedOb = (parser.Spine.Peek() as IAttributedXObject) ?? parser.Spine.Peek(1) as IAttributedXObject; parser.Clone().AdvanceUntilEnded((XObject)attributedOb, triggerLocation.Snapshot, 1000); var attributes = attributedOb.Attributes.ToDictionary(StringComparer.OrdinalIgnoreCase); return(await GetAttributeCompletionsAsync(session, triggerLocation, nodePath, attributedOb, attributes, token)); case XmlCompletionTrigger.AttributeValue: if (parser.Spine.Peek() is XAttribute att && parser.Spine.Peek(1) is IAttributedXObject attributedObject) { return(await GetAttributeValueCompletionsAsync(session, triggerLocation, nodePath, attributedObject, att, token)); } break; case XmlCompletionTrigger.Entity: return(await GetEntityCompletionsAsync(session, triggerLocation, nodePath, token)); case XmlCompletionTrigger.DocType: case XmlCompletionTrigger.DeclarationOrCDataOrComment: return(await GetDeclarationCompletionsAsync(session, triggerLocation, nodePath, token)); } } return(CompletionContext.Empty); }