private async void RetriggerAsync(bool force) { _lastTyped = DateTime.Now; int delay = force ? 50 : _delay; // Don't leave "stale" completion session up while the user is typing, or else we could // get completion from a stale session. ICompletionSession completionSession = _broker.GetSessions(_textView).FirstOrDefault(); if (completionSession != null && completionSession.Properties.TryGetProperty <bool>(RetriggerCompletion, out bool retrigger) && retrigger) { completionSession.Dismiss(); } await System.Threading.Tasks.Task.Delay(delay); // Prevents retriggering from happening while typing fast if (_lastTyped.AddMilliseconds(delay) > DateTime.Now) { return; } // Completion may have gotten invoked via by Web Editor OnPostTypeChar(). Don't invoke again, or else we get flikering completion list // TODO:Review the design here post-preview 4 and make sure this completion controller doesn't clash with Web Editors JSON completion controller completionSession = _broker.GetSessions(_textView).FirstOrDefault(); if (completionSession != null && completionSession.Properties.TryGetProperty <bool>(RetriggerCompletion, out retrigger)) { return; } var doc = JSONEditorDocument.FromTextBuffer(_textView.TextDataModel.DocumentBuffer); if (doc == null) { return; } JSONParseItem parseItem = JsonHelpers.GetItemBeforePosition(_textView.Caret.Position.BufferPosition, doc.JSONDocument); if (parseItem == null) { return; } JSONMember member = parseItem.FindType <JSONMember>(); if (member == null || (!member.UnquotedNameText.Equals(ManifestConstants.Library) && !member.UnquotedNameText.Equals(ManifestConstants.Destination) && member.UnquotedValueText?.Length <= 1)) { return; } JSONObject parent = parseItem.FindType <JSONObject>(); if (JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { VsHelpers.DTE.ExecuteCommand("Edit.ListMembers"); } }
public bool HasSuggestedActions(ITextView textView, ITextBuffer textBuffer, int caretPosition, JSONParseItem parseItem) { if (!DocumentService.TryGetTextDocument(textView.TextBuffer, out var doc)) { return(false); } JSONObject parent = parseItem.FindType <JSONObject>(); if (!(parent?.Parent is JSONArrayElement) || !parent.IsValid) { return(false); } if (!JsonHelpers.TryGetInstallationState(parent, out InstallationState)) { return(false); } ConfigFilePath = doc.FilePath; LibraryObject = parent; return(!string.IsNullOrEmpty(InstallationState.Name)); }
protected override IEnumerable <JSONCompletionEntry> GetEntries(JSONCompletionContext context) { var member = context.ContextItem as JSONMember; if (member == null || member.UnquotedNameText != ManifestConstants.Library) { yield break; } var parent = member.Parent as JSONObject; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } var dependencies = Dependencies.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } // member.Value is null when there is no value yet, e.g. when typing a space at "library":| // where | represents caret position. In this case, set caretPosition to "1" to short circuit execution of this function // and return no entries (member.UnquotedValueText will be empty string in that case). int caretPosition = member.Value != null ? context.Session.TextView.Caret.Position.BufferPosition - member.Value.Start - 1 : 1; if (caretPosition > member.UnquotedValueText.Length) { yield break; } Task <CompletionSet> task = catalog.GetLibraryCompletionSetAsync(member.UnquotedValueText, caretPosition); int count = 0; if (!context.Session.Properties.ContainsProperty(CompletionController.RetriggerCompletion)) { context.Session.Properties.AddProperty(CompletionController.RetriggerCompletion, true); } if (task.IsCompleted) { CompletionSet set = task.Result; int start = member.Value.Start; ITrackingSpan trackingSpan = context.Snapshot.CreateTrackingSpan(start + 1 + set.Start, set.Length, SpanTrackingMode.EdgeInclusive); if (set.Completions != null) { foreach (CompletionItem item in set.Completions) { string insertionText = item.InsertionText.Replace("\\\\", "\\").Replace("\\", "\\\\"); ImageMoniker moniker = item.DisplayText.EndsWith("/") || item.DisplayText.EndsWith("\\") ? _folderIcon : _libraryIcon; yield return(new SimpleCompletionEntry(item.DisplayText, insertionText, item.Description, moniker, trackingSpan, context.Session, ++count)); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, KnownMonikers.Loading, context.Session)); task.ContinueWith((a) => { if (!context.Session.IsDismissed) { CompletionSet set = task.Result; int start = member.Value.Start; ITrackingSpan trackingSpan = context.Snapshot.CreateTrackingSpan(start + 1 + set.Start, set.Length, SpanTrackingMode.EdgeExclusive); if (set.Completions != null) { var results = new List <JSONCompletionEntry>(); foreach (CompletionItem item in set.Completions) { string insertionText = item.InsertionText.Replace("\\", "\\\\"); ImageMoniker moniker = item.DisplayText.EndsWith("/") || item.DisplayText.EndsWith("\\") ? _folderIcon : _libraryIcon; results.Add(new SimpleCompletionEntry(item.DisplayText, insertionText, item.Description, moniker, trackingSpan, context.Session, ++count)); } UpdateListEntriesSync(context, results); } } }); } }
protected override IEnumerable <JSONCompletionEntry> GetEntries(JSONCompletionContext context) { var member = context.ContextItem as JSONMember; if (member == null || member.UnquotedNameText != ManifestConstants.Library) { yield break; } var parent = member.Parent as JSONObject; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } var dependencies = Dependencies.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } // member.Value is null when there is no value yet, e.g. when typing a space at "library":| // where | represents caret position. In this case, set caretPosition to "1" to short circuit execution of this function // and return no entries (member.UnquotedValueText will be empty string in that case). int caretPosition = member.Value != null ? context.Session.TextView.Caret.Position.BufferPosition - member.Value.Start - 1 : 1; if (caretPosition > member.UnquotedValueText.Length) { yield break; } Task <CompletionSet> task = catalog.GetLibraryCompletionSetAsync(member.UnquotedValueText, caretPosition); int count = 0; if (!context.Session.Properties.ContainsProperty(CompletionController.RetriggerCompletion)) { context.Session.Properties.AddProperty(CompletionController.RetriggerCompletion, true); } if (task.IsCompleted) { CompletionSet completionSet = task.Result; if (completionSet.Completions != null) { List <JSONCompletionEntry> results = GetCompletionList(member, context, completionSet, count); foreach (JSONCompletionEntry completionEntry in results) { yield return(completionEntry); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, string.Empty, KnownMonikers.Loading, context.Session)); task.ContinueWith((a) => { if (!context.Session.IsDismissed) { CompletionSet completionSet = task.Result; if (completionSet.Completions != null) { List <JSONCompletionEntry> results = GetCompletionList(member, context, completionSet, count); UpdateListEntriesSync(context, results); } } }); } }
protected override IEnumerable <JsonCompletionEntry> GetEntries(JsonCompletionContext context) { MemberNode member = context.ContextNode.FindType <MemberNode>(); if (member == null || member.UnquotedNameText != "files") { yield break; } var parent = member.Parent as ObjectNode; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } if (string.IsNullOrEmpty(state.Name)) { yield break; } var dependencies = _dependenciesFactory.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } Task <ILibrary> task = catalog.GetLibraryAsync(state.Name, state.Version, CancellationToken.None); FrameworkElement presenter = GetPresenter(context); IEnumerable <string> usedFiles = GetUsedFiles(context); if (task.IsCompleted) { if (!(task.Result is ILibrary library)) { yield break; } foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageSource glyph = WpfUtil.GetIconForFile(presenter, file, out bool isThemeIcon); yield return(new SimpleCompletionEntry(file, glyph, context.Session)); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, string.Empty, KnownMonikers.Loading, context.Session)); _ = task.ContinueWith(async(t) => { await VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!(t.Result is ILibrary library)) { return; } if (!context.Session.IsDismissed) { var results = new List <JsonCompletionEntry>(); foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageSource glyph = WpfUtil.GetIconForFile(presenter, file, out bool isThemeIcon); results.Add(new SimpleCompletionEntry(file, glyph, context.Session)); } } UpdateListEntriesSync(context, results); } }, TaskScheduler.Default); } }
protected override IEnumerable <JSONCompletionEntry> GetEntries(JSONCompletionContext context) { var member = context.ContextItem as JSONMember; if (member == null || member.UnquotedNameText != "id") { yield break; } var parent = member.Parent as JSONObject; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } var dependencies = Dependencies.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } int caretPosition = context.Session.TextView.Caret.Position.BufferPosition - member.Value.Start - 1; if (caretPosition > member.UnquotedValueText.Length) { yield break; } Task <CompletionSet> task = catalog.GetLibraryCompletionSetAsync(member.UnquotedValueText, caretPosition); int count = 0; if (task.IsCompleted) { CompletionSet set = task.Result; int start = member.Value.Start; ITrackingSpan trackingSpan = context.Snapshot.CreateTrackingSpan(start + 1 + set.Start, set.Length, SpanTrackingMode.EdgeInclusive); if (set.Completions != null) { foreach (CompletionItem item in set.Completions) { string insertionText = item.InsertionText.Replace("\\\\", "\\").Replace("\\", "\\\\"); ImageMoniker moniker = item.DisplayText.EndsWith("/") || item.DisplayText.EndsWith("\\") ? _folderIcon : _libraryIcon; yield return(new SimpleCompletionEntry(item.DisplayText, insertionText, item.Description, moniker, trackingSpan, context.Session, ++count)); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, KnownMonikers.Loading, context.Session)); task.ContinueWith((a) => { if (!context.Session.IsDismissed) { CompletionSet set = task.Result; int start = member.Value.Start; ITrackingSpan trackingSpan = context.Snapshot.CreateTrackingSpan(start + 1 + set.Start, set.Length, SpanTrackingMode.EdgeExclusive); if (set.Completions != null) { var results = new List <JSONCompletionEntry>(); foreach (CompletionItem item in set.Completions) { string insertionText = item.InsertionText.Replace("\\", "\\\\"); ImageMoniker moniker = item.DisplayText.EndsWith("/") || item.DisplayText.EndsWith("\\") ? _folderIcon : _libraryIcon; results.Add(new SimpleCompletionEntry(item.DisplayText, insertionText, item.Description, moniker, trackingSpan, context.Session, ++count)); } UpdateListEntriesSync(context, results); } } }); } }
protected override IEnumerable <JSONCompletionEntry> GetEntries(JSONCompletionContext context) { JSONMember member = context.ContextItem.FindType <JSONMember>(); if (member == null || member.UnquotedNameText != "files") { yield break; } var parent = member.Parent as JSONObject; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } if (string.IsNullOrEmpty(state.LibraryId)) { yield break; } var dependencies = Dependencies.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } Task <ILibrary> task = catalog.GetLibraryAsync(state.LibraryId, CancellationToken.None); FrameworkElement presenter = GetPresenter(context); IEnumerable <string> usedFiles = GetUsedFiles(context); if (task.IsCompleted) { if (!(task.Result is ILibrary library)) { yield break; } foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageSource glyph = WpfUtil.GetIconForFile(presenter, file, out bool isThemeIcon); yield return(new SimpleCompletionEntry(file, glyph, context.Session)); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, KnownMonikers.Loading, context.Session)); task.ContinueWith((a) => { if (!(task.Result is ILibrary library)) { return; } if (!context.Session.IsDismissed) { var results = new List <JSONCompletionEntry>(); foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageSource glyph = WpfUtil.GetIconForFile(presenter, file, out bool isThemeIcon); results.Add(new SimpleCompletionEntry(file, glyph, context.Session)); } } UpdateListEntriesSync(context, results); } }); } }