// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { /// /// Main class for Autocomplete functionality /// public class AutoCompleteService { #region Singleton Instance Implementation /// /// Singleton service instance /// private static Lazy instance = new Lazy(() => new AutoCompleteService()); /// /// Gets the singleton service instance /// public static AutoCompleteService Instance { get { return instance.Value; } } /// /// Default, parameterless constructor. /// TODO: Figure out how to make this truely singleton even with dependency injection for tests /// public AutoCompleteService() { } #endregion /// /// Gets the current autocomplete candidate list /// public IEnumerable AutoCompleteList { get; private set; } public void InitializeService(ServiceHost serviceHost) { // Register a callback for when a connection is created ConnectionService.Instance.RegisterOnConnectionTask(UpdateAutoCompleteCache); } /// /// Update the cached autocomplete candidate list when the user connects to a database /// TODO: Update with refactoring/async /// /// public async Task UpdateAutoCompleteCache(DbConnection connection) { DbCommand command = connection.CreateCommand(); command.CommandText = "SELECT name FROM sys.tables"; command.CommandTimeout = 15; command.CommandType = CommandType.Text; var reader = await command.ExecuteReaderAsync(); List results = new List(); while (await reader.ReadAsync()) { results.Add(reader[0].ToString()); } AutoCompleteList = results; await Task.FromResult(0); } /// /// Return the completion item list for the current text position /// /// public CompletionItem[] GetCompletionItems(TextDocumentPosition textDocumentPosition) { var completions = new List(); int i = 0; // the completion list will be null is user not connected to server if (this.AutoCompleteList != null) { foreach (var autoCompleteItem in this.AutoCompleteList) { // convert the completion item candidates into CompletionItems completions.Add(new CompletionItem() { Label = autoCompleteItem, Kind = CompletionItemKind.Keyword, Detail = autoCompleteItem + " details", Documentation = autoCompleteItem + " documentation", TextEdit = new TextEdit { NewText = autoCompleteItem, Range = new Range { Start = new Position { Line = textDocumentPosition.Position.Line, Character = textDocumentPosition.Position.Character }, End = new Position { Line = textDocumentPosition.Position.Line, Character = textDocumentPosition.Position.Character + 5 } } } }); // only show 50 items if (++i == 50) { break; } } } return completions.ToArray(); } } }